From 91b645d0fee2d25047a6104728d38043e3e53ee9 Mon Sep 17 00:00:00 2001 From: cxl Date: Sun, 15 Mar 2015 16:51:28 +0000 Subject: [PATCH] .uppdev git-svn-id: svn://ultimatepp.org/upp/trunk@8271 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- uppdev/FileHexView/FileHexView.upp | 10 + uppdev/FileHexView/init | 5 + uppdev/FileHexView/main.cpp | 109 + uppdev/cpp/cpp.h | 2 +- uppdev/cpp/main.cpp | 4 +- uppdev/plugin/astyle/ASBeautifier.cpp | 1975 ------ uppdev/plugin/astyle/ASEnhancer.cpp | 489 -- uppdev/plugin/astyle/ASFormatter.cpp | 2204 ------ uppdev/plugin/astyle/ASResource.cpp | 395 -- uppdev/plugin/astyle/ASStringTools.cpp | 86 - uppdev/plugin/astyle/ASStringTools.hpp | 58 - uppdev/plugin/astyle/astyle.h | 504 -- uppdev/plugin/astyle/astyle.upp | 12 - uppdev/plugin/astyle/astyle_main.cpp | 1138 ---- uppdev/plugin/astyle/init | 4 - uppdev/plugin/cairo/Cairo.h | 223 - uppdev/plugin/cairo/CairoCtrl.h | 264 - uppdev/plugin/cairo/CairoDraw.cpp | 259 - uppdev/plugin/cairo/CairoDraw.h | 51 - uppdev/plugin/cairo/CairoPattern.h | 185 - uppdev/plugin/cairo/CairoUpp.cpp | 390 -- uppdev/plugin/cairo/cairo-version.h | 8 - uppdev/plugin/cairo/cairo.upp | 27 - uppdev/plugin/cairo/cairolib.c | 92 - uppdev/plugin/cairo/cairolibwin32.c | 8 - uppdev/plugin/cairo/init | 6 - .../lib/cairo-analysis-surface-private.h | 76 - .../plugin/cairo/lib/cairo-analysis-surface.c | 988 --- uppdev/plugin/cairo/lib/cairo-arc-private.h | 57 - uppdev/plugin/cairo/lib/cairo-arc.c | 292 - uppdev/plugin/cairo/lib/cairo-array.c | 492 -- .../plugin/cairo/lib/cairo-atomic-private.h | 104 - uppdev/plugin/cairo/lib/cairo-atomic.c | 96 - uppdev/plugin/cairo/lib/cairo-base85-stream.c | 132 - .../plugin/cairo/lib/cairo-bentley-ottmann.c | 1935 ------ uppdev/plugin/cairo/lib/cairo-beos.h | 60 - uppdev/plugin/cairo/lib/cairo-cache-private.h | 126 - uppdev/plugin/cairo/lib/cairo-cache.c | 363 - uppdev/plugin/cairo/lib/cairo-cff-subset.c | 2289 ------- uppdev/plugin/cairo/lib/cairo-clip-private.h | 136 - uppdev/plugin/cairo/lib/cairo-clip.c | 858 --- uppdev/plugin/cairo/lib/cairo-color.c | 175 - .../plugin/cairo/lib/cairo-compiler-private.h | 162 - uppdev/plugin/cairo/lib/cairo-debug.c | 75 - .../plugin/cairo/lib/cairo-deflate-stream.c | 149 - uppdev/plugin/cairo/lib/cairo-deprecated.h | 138 - .../plugin/cairo/lib/cairo-directfb-surface.c | 1932 ------ uppdev/plugin/cairo/lib/cairo-directfb.h | 67 - uppdev/plugin/cairo/lib/cairo-features.h | 28 - uppdev/plugin/cairo/lib/cairo-fixed-private.h | 244 - .../cairo/lib/cairo-fixed-type-private.h | 70 - uppdev/plugin/cairo/lib/cairo-fixed.c | 39 - .../cairo/lib/cairo-font-face-twin-data.c | 1030 --- .../plugin/cairo/lib/cairo-font-face-twin.c | 209 - uppdev/plugin/cairo/lib/cairo-font-face.c | 776 --- uppdev/plugin/cairo/lib/cairo-font-options.c | 406 -- .../plugin/cairo/lib/cairo-freelist-private.h | 71 - uppdev/plugin/cairo/lib/cairo-freelist.c | 73 - uppdev/plugin/cairo/lib/cairo-ft-font.c | 2746 -------- uppdev/plugin/cairo/lib/cairo-ft-private.h | 70 - uppdev/plugin/cairo/lib/cairo-ft.h | 75 - uppdev/plugin/cairo/lib/cairo-glitz-private.h | 41 - uppdev/plugin/cairo/lib/cairo-glitz-surface.c | 2495 ------- uppdev/plugin/cairo/lib/cairo-glitz.h | 57 - .../plugin/cairo/lib/cairo-gstate-private.h | 71 - uppdev/plugin/cairo/lib/cairo-gstate.c | 1858 ----- uppdev/plugin/cairo/lib/cairo-hash-private.h | 88 - uppdev/plugin/cairo/lib/cairo-hash.c | 576 -- uppdev/plugin/cairo/lib/cairo-hull.c | 222 - uppdev/plugin/cairo/lib/cairo-image-surface.c | 1388 ---- uppdev/plugin/cairo/lib/cairo-lzw.c | 403 -- .../plugin/cairo/lib/cairo-malloc-private.h | 141 - uppdev/plugin/cairo/lib/cairo-matrix.c | 863 --- .../cairo/lib/cairo-meta-surface-private.h | 190 - uppdev/plugin/cairo/lib/cairo-meta-surface.c | 1010 --- uppdev/plugin/cairo/lib/cairo-misc.c | 669 -- .../cairo/lib/cairo-mutex-impl-private.h | 239 - .../cairo/lib/cairo-mutex-list-private.h | 59 - uppdev/plugin/cairo/lib/cairo-mutex-private.h | 67 - .../cairo/lib/cairo-mutex-type-private.h | 187 - uppdev/plugin/cairo/lib/cairo-mutex.c | 82 - uppdev/plugin/cairo/lib/cairo-os2-private.h | 77 - uppdev/plugin/cairo/lib/cairo-os2-surface.c | 1351 ---- uppdev/plugin/cairo/lib/cairo-os2.h | 88 - .../cairo/lib/cairo-output-stream-private.h | 176 - uppdev/plugin/cairo/lib/cairo-output-stream.c | 707 -- .../cairo/lib/cairo-paginated-private.h | 167 - .../lib/cairo-paginated-surface-private.h | 72 - .../cairo/lib/cairo-paginated-surface.c | 693 -- uppdev/plugin/cairo/lib/cairo-path-bounds.c | 174 - uppdev/plugin/cairo/lib/cairo-path-fill.c | 239 - .../cairo/lib/cairo-path-fixed-private.h | 80 - uppdev/plugin/cairo/lib/cairo-path-fixed.c | 896 --- uppdev/plugin/cairo/lib/cairo-path-private.h | 57 - uppdev/plugin/cairo/lib/cairo-path-stroke.c | 1522 ----- uppdev/plugin/cairo/lib/cairo-path.c | 482 -- uppdev/plugin/cairo/lib/cairo-pattern.c | 2528 ------- .../cairo/lib/cairo-pdf-operators-private.h | 165 - uppdev/plugin/cairo/lib/cairo-pdf-operators.c | 1450 ---- .../cairo/lib/cairo-pdf-surface-private.h | 171 - uppdev/plugin/cairo/lib/cairo-pdf-surface.c | 4996 -------------- uppdev/plugin/cairo/lib/cairo-pdf.h | 68 - uppdev/plugin/cairo/lib/cairo-pen.c | 491 -- uppdev/plugin/cairo/lib/cairo-png.c | 708 -- uppdev/plugin/cairo/lib/cairo-polygon.c | 149 - uppdev/plugin/cairo/lib/cairo-private.h | 57 - .../cairo/lib/cairo-ps-surface-private.h | 100 - uppdev/plugin/cairo/lib/cairo-ps-surface.c | 3337 --------- uppdev/plugin/cairo/lib/cairo-ps.h | 114 - uppdev/plugin/cairo/lib/cairo-quartz-font.c | 840 --- .../cairo/lib/cairo-quartz-image-surface.c | 286 - uppdev/plugin/cairo/lib/cairo-quartz-image.h | 59 - .../plugin/cairo/lib/cairo-quartz-private.h | 104 - .../plugin/cairo/lib/cairo-quartz-surface.c | 2752 -------- uppdev/plugin/cairo/lib/cairo-quartz.h | 82 - uppdev/plugin/cairo/lib/cairo-rectangle.c | 225 - .../cairo/lib/cairo-reference-count-private.h | 62 - .../plugin/cairo/lib/cairo-region-private.h | 117 - uppdev/plugin/cairo/lib/cairo-region.c | 221 - .../cairo/lib/cairo-scaled-font-private.h | 119 - .../lib/cairo-scaled-font-subsets-private.h | 640 -- .../cairo/lib/cairo-scaled-font-subsets.c | 1077 --- uppdev/plugin/cairo/lib/cairo-scaled-font.c | 2569 ------- .../plugin/cairo/lib/cairo-skiplist-private.h | 116 - uppdev/plugin/cairo/lib/cairo-skiplist.c | 485 -- uppdev/plugin/cairo/lib/cairo-slope.c | 108 - uppdev/plugin/cairo/lib/cairo-spline.c | 287 - uppdev/plugin/cairo/lib/cairo-stroke-style.c | 103 - .../cairo/lib/cairo-supported-features.h | 21 - .../lib/cairo-surface-fallback-private.h | 131 - .../plugin/cairo/lib/cairo-surface-fallback.c | 1301 ---- .../plugin/cairo/lib/cairo-surface-private.h | 105 - uppdev/plugin/cairo/lib/cairo-surface.c | 2697 -------- .../cairo/lib/cairo-svg-surface-private.h | 74 - uppdev/plugin/cairo/lib/cairo-svg-surface.c | 2611 ------- uppdev/plugin/cairo/lib/cairo-svg.h | 82 - uppdev/plugin/cairo/lib/cairo-system.c | 97 - uppdev/plugin/cairo/lib/cairo-traps.c | 713 -- .../cairo/lib/cairo-truetype-subset-private.h | 199 - .../plugin/cairo/lib/cairo-truetype-subset.c | 1338 ---- .../plugin/cairo/lib/cairo-type1-fallback.c | 887 --- uppdev/plugin/cairo/lib/cairo-type1-private.h | 51 - uppdev/plugin/cairo/lib/cairo-type1-subset.c | 1405 ---- .../lib/cairo-type3-glyph-surface-private.h | 84 - .../cairo/lib/cairo-type3-glyph-surface.c | 528 -- uppdev/plugin/cairo/lib/cairo-types-private.h | 345 - uppdev/plugin/cairo/lib/cairo-unicode.c | 421 -- .../cairo/lib/cairo-user-font-private.h | 46 - uppdev/plugin/cairo/lib/cairo-user-font.c | 843 --- uppdev/plugin/cairo/lib/cairo-version.c | 88 - uppdev/plugin/cairo/lib/cairo-version.h | 14 - .../plugin/cairo/lib/cairo-wideint-private.h | 277 - .../cairo/lib/cairo-wideint-type-private.h | 149 - uppdev/plugin/cairo/lib/cairo-wideint.c | 860 --- uppdev/plugin/cairo/lib/cairo-win32-font.c | 2156 ------ .../cairo/lib/cairo-win32-printing-surface.c | 1653 ----- uppdev/plugin/cairo/lib/cairo-win32-private.h | 194 - uppdev/plugin/cairo/lib/cairo-win32-surface.c | 2134 ------ uppdev/plugin/cairo/lib/cairo-win32.h | 112 - uppdev/plugin/cairo/lib/cairo-xcb-surface.c | 2551 ------- uppdev/plugin/cairo/lib/cairo-xcb-xrender.h | 63 - uppdev/plugin/cairo/lib/cairo-xcb.h | 73 - uppdev/plugin/cairo/lib/cairo-xlib-display.c | 525 -- uppdev/plugin/cairo/lib/cairo-xlib-private.h | 168 - uppdev/plugin/cairo/lib/cairo-xlib-screen.c | 504 -- .../cairo/lib/cairo-xlib-surface-private.h | 109 - uppdev/plugin/cairo/lib/cairo-xlib-surface.c | 4075 ----------- uppdev/plugin/cairo/lib/cairo-xlib-visual.c | 185 - .../cairo/lib/cairo-xlib-xrender-private.h | 1090 --- uppdev/plugin/cairo/lib/cairo-xlib-xrender.h | 66 - uppdev/plugin/cairo/lib/cairo-xlib.h | 100 - uppdev/plugin/cairo/lib/cairo.c | 3833 ----------- uppdev/plugin/cairo/lib/cairo.h | 2328 ------- uppdev/plugin/cairo/lib/cairoint.h | 2539 ------- .../cairo/lib/check-has-hidden-symbols.c | 3 - uppdev/plugin/cairo/lib/check-link.c | 24 - .../plugin/cairo/lib/test-fallback-surface.c | 234 - .../plugin/cairo/lib/test-fallback-surface.h | 50 - uppdev/plugin/cairo/lib/test-meta-surface.c | 334 - uppdev/plugin/cairo/lib/test-meta-surface.h | 50 - .../plugin/cairo/lib/test-paginated-surface.c | 330 - .../plugin/cairo/lib/test-paginated-surface.h | 52 - uppdev/plugin/libfetch/Makefile | 75 - uppdev/plugin/libfetch/fetch.3 | 667 -- uppdev/plugin/libfetch/ftp.errors | 47 - uppdev/plugin/libfetch/http.errors | 45 - uppdev/plugin/libfetch/lib/common.c | 784 --- uppdev/plugin/libfetch/lib/common.h | 146 - uppdev/plugin/libfetch/lib/fetch.c | 446 -- uppdev/plugin/libfetch/lib/fetch.h | 162 - uppdev/plugin/libfetch/lib/file.c | 156 - uppdev/plugin/libfetch/lib/ftp.c | 1020 --- uppdev/plugin/libfetch/lib/http.c | 1192 ---- uppdev/plugin/libfetch/libfetch.upp | 11 - uppdev/plugin/lzo/init | 3 - uppdev/plugin/lzo/lib/COPYING | 339 - uppdev/plugin/lzo/lib/README.LZO | 123 - uppdev/plugin/lzo/lib/lzoconf.h | 444 -- uppdev/plugin/lzo/lib/lzodefs.h | 2998 -------- uppdev/plugin/lzo/lib/minilzo.c | 6053 ----------------- uppdev/plugin/lzo/lib/minilzo.h | 94 - uppdev/plugin/lzo/lzo.cpp | 37 - uppdev/plugin/lzo/lzo.h | 16 - uppdev/plugin/lzo/lzo.upp | 8 - uppdev/plugin/pixman/init | 3 - .../pixman/lib/pixman-access-accessors.c | 3 - uppdev/plugin/pixman/lib/pixman-access.c | 1986 ------ uppdev/plugin/pixman/lib/pixman-arm-simd.c | 407 -- uppdev/plugin/pixman/lib/pixman-arm-simd.h | 94 - uppdev/plugin/pixman/lib/pixman-combine32.c | 1273 ---- uppdev/plugin/pixman/lib/pixman-combine32.h | 217 - uppdev/plugin/pixman/lib/pixman-combine64.c | 1273 ---- uppdev/plugin/pixman/lib/pixman-combine64.h | 217 - .../pixman/lib/pixman-compose-accessors.c | 4 - uppdev/plugin/pixman/lib/pixman-compose.c | 596 -- .../plugin/pixman/lib/pixman-compute-region.c | 242 - .../plugin/pixman/lib/pixman-edge-accessors.c | 4 - uppdev/plugin/pixman/lib/pixman-edge-imp.h | 154 - uppdev/plugin/pixman/lib/pixman-edge.c | 331 - uppdev/plugin/pixman/lib/pixman-image.c | 828 --- uppdev/plugin/pixman/lib/pixman-matrix.c | 625 -- uppdev/plugin/pixman/lib/pixman-mmx.c | 3025 -------- uppdev/plugin/pixman/lib/pixman-mmx.h | 320 - uppdev/plugin/pixman/lib/pixman-pict.c | 2290 ------- uppdev/plugin/pixman/lib/pixman-private.h | 804 --- uppdev/plugin/pixman/lib/pixman-region.c | 2129 ------ uppdev/plugin/pixman/lib/pixman-region16.c | 83 - uppdev/plugin/pixman/lib/pixman-region32.c | 73 - uppdev/plugin/pixman/lib/pixman-source.c | 709 -- uppdev/plugin/pixman/lib/pixman-sse2.c | 4717 ------------- uppdev/plugin/pixman/lib/pixman-sse2.h | 358 - uppdev/plugin/pixman/lib/pixman-timer.c | 66 - .../pixman/lib/pixman-transformed-accessors.c | 3 - uppdev/plugin/pixman/lib/pixman-transformed.c | 615 -- uppdev/plugin/pixman/lib/pixman-trap.c | 284 - uppdev/plugin/pixman/lib/pixman-utils.c | 581 -- uppdev/plugin/pixman/lib/pixman-version.h | 50 - uppdev/plugin/pixman/lib/pixman-vmx.c | 1064 --- uppdev/plugin/pixman/lib/pixman-vmx.h | 308 - uppdev/plugin/pixman/lib/pixman.h | 901 --- uppdev/plugin/pixman/pixman.upp | 10 - uppdev/plugin/pixman/pixmanlib1.c | 17 - uppdev/plugin/pixman/pixmanlib2.c | 9 - uppdev/plugin/pixman/pixmanlib3.c | 5 - uppdev/plugin/pixman/pixmanlib4.c | 6 - uppdev/plugin/png/Copying | 21 - uppdev/plugin/png/init | 8 - uppdev/plugin/png/lib/CHANGES | 1995 ------ uppdev/plugin/png/lib/INSTALL | 199 - uppdev/plugin/png/lib/KNOWNBUG | 21 - uppdev/plugin/png/lib/LICENSE | 109 - uppdev/plugin/png/lib/README | 263 - uppdev/plugin/png/lib/example.c | 814 --- uppdev/plugin/png/lib/libpng-1.2.22.txt | 2851 -------- uppdev/plugin/png/lib/libpng.3 | 3600 ---------- uppdev/plugin/png/lib/libpngpf.3 | 274 - uppdev/plugin/png/lib/png.5 | 73 - uppdev/plugin/png/lib/png.c | 798 --- uppdev/plugin/png/lib/png.h | 3540 ---------- uppdev/plugin/png/lib/pngconf.h | 1483 ---- uppdev/plugin/png/lib/pngerror.c | 341 - uppdev/plugin/png/lib/pnggccrd.c | 101 - uppdev/plugin/png/lib/pngget.c | 901 --- uppdev/plugin/png/lib/pngmem.c | 608 -- uppdev/plugin/png/lib/pngpread.c | 1584 ----- uppdev/plugin/png/lib/pngread.c | 1472 ---- uppdev/plugin/png/lib/pngrio.c | 167 - uppdev/plugin/png/lib/pngrtran.c | 4284 ------------ uppdev/plugin/png/lib/pngrutil.c | 3163 --------- uppdev/plugin/png/lib/pngset.c | 1246 ---- uppdev/plugin/png/lib/pngtest.c | 1553 ----- uppdev/plugin/png/lib/pngtrans.c | 662 -- uppdev/plugin/png/lib/pngvcrd.c | 1 - uppdev/plugin/png/lib/pngwio.c | 234 - uppdev/plugin/png/lib/pngwrite.c | 1514 ----- uppdev/plugin/png/lib/pngwtran.c | 572 -- uppdev/plugin/png/lib/pngwutil.c | 2792 -------- uppdev/plugin/png/png.h | 50 - uppdev/plugin/png/png.upp | 60 - uppdev/plugin/png/pnglib.c | 24 - uppdev/plugin/png/pngreg.icpp | 9 - uppdev/plugin/png/pngupp.cpp | 497 -- 282 files changed, 127 insertions(+), 187329 deletions(-) create mode 100644 uppdev/FileHexView/FileHexView.upp create mode 100644 uppdev/FileHexView/init create mode 100644 uppdev/FileHexView/main.cpp delete mode 100644 uppdev/plugin/astyle/ASBeautifier.cpp delete mode 100644 uppdev/plugin/astyle/ASEnhancer.cpp delete mode 100644 uppdev/plugin/astyle/ASFormatter.cpp delete mode 100644 uppdev/plugin/astyle/ASResource.cpp delete mode 100644 uppdev/plugin/astyle/ASStringTools.cpp delete mode 100644 uppdev/plugin/astyle/ASStringTools.hpp delete mode 100644 uppdev/plugin/astyle/astyle.h delete mode 100644 uppdev/plugin/astyle/astyle.upp delete mode 100644 uppdev/plugin/astyle/astyle_main.cpp delete mode 100644 uppdev/plugin/astyle/init delete mode 100644 uppdev/plugin/cairo/Cairo.h delete mode 100644 uppdev/plugin/cairo/CairoCtrl.h delete mode 100644 uppdev/plugin/cairo/CairoDraw.cpp delete mode 100644 uppdev/plugin/cairo/CairoDraw.h delete mode 100644 uppdev/plugin/cairo/CairoPattern.h delete mode 100644 uppdev/plugin/cairo/CairoUpp.cpp delete mode 100644 uppdev/plugin/cairo/cairo-version.h delete mode 100644 uppdev/plugin/cairo/cairo.upp delete mode 100644 uppdev/plugin/cairo/cairolib.c delete mode 100644 uppdev/plugin/cairo/cairolibwin32.c delete mode 100644 uppdev/plugin/cairo/init delete mode 100644 uppdev/plugin/cairo/lib/cairo-analysis-surface-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-analysis-surface.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-arc-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-arc.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-array.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-atomic-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-atomic.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-base85-stream.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-bentley-ottmann.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-beos.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-cache-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-cache.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-cff-subset.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-clip-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-clip.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-color.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-compiler-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-debug.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-deflate-stream.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-deprecated.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-directfb-surface.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-directfb.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-features.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-fixed-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-fixed-type-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-fixed.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-font-face-twin-data.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-font-face-twin.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-font-face.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-font-options.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-freelist-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-freelist.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-ft-font.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-ft-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-ft.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-glitz-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-glitz-surface.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-glitz.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-gstate-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-gstate.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-hash-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-hash.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-hull.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-image-surface.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-lzw.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-malloc-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-matrix.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-meta-surface-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-meta-surface.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-misc.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-mutex-impl-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-mutex-list-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-mutex-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-mutex-type-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-mutex.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-os2-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-os2-surface.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-os2.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-output-stream-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-output-stream.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-paginated-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-paginated-surface-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-paginated-surface.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-path-bounds.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-path-fill.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-path-fixed-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-path-fixed.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-path-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-path-stroke.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-path.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-pattern.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-pdf-operators-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-pdf-operators.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-pdf-surface-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-pdf-surface.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-pdf.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-pen.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-png.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-polygon.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-ps-surface-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-ps-surface.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-ps.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-quartz-font.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-quartz-image-surface.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-quartz-image.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-quartz-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-quartz-surface.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-quartz.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-rectangle.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-reference-count-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-region-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-region.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-scaled-font-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-scaled-font-subsets-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-scaled-font-subsets.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-scaled-font.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-skiplist-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-skiplist.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-slope.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-spline.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-stroke-style.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-supported-features.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-surface-fallback-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-surface-fallback.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-surface-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-surface.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-svg-surface-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-svg-surface.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-svg.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-system.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-traps.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-truetype-subset-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-truetype-subset.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-type1-fallback.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-type1-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-type1-subset.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-type3-glyph-surface-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-type3-glyph-surface.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-types-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-unicode.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-user-font-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-user-font.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-version.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-version.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-wideint-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-wideint-type-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-wideint.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-win32-font.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-win32-printing-surface.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-win32-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-win32-surface.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-win32.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-xcb-surface.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-xcb-xrender.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-xcb.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-xlib-display.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-xlib-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-xlib-screen.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-xlib-surface-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-xlib-surface.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-xlib-visual.c delete mode 100644 uppdev/plugin/cairo/lib/cairo-xlib-xrender-private.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-xlib-xrender.h delete mode 100644 uppdev/plugin/cairo/lib/cairo-xlib.h delete mode 100644 uppdev/plugin/cairo/lib/cairo.c delete mode 100644 uppdev/plugin/cairo/lib/cairo.h delete mode 100644 uppdev/plugin/cairo/lib/cairoint.h delete mode 100644 uppdev/plugin/cairo/lib/check-has-hidden-symbols.c delete mode 100644 uppdev/plugin/cairo/lib/check-link.c delete mode 100644 uppdev/plugin/cairo/lib/test-fallback-surface.c delete mode 100644 uppdev/plugin/cairo/lib/test-fallback-surface.h delete mode 100644 uppdev/plugin/cairo/lib/test-meta-surface.c delete mode 100644 uppdev/plugin/cairo/lib/test-meta-surface.h delete mode 100644 uppdev/plugin/cairo/lib/test-paginated-surface.c delete mode 100644 uppdev/plugin/cairo/lib/test-paginated-surface.h delete mode 100644 uppdev/plugin/libfetch/Makefile delete mode 100644 uppdev/plugin/libfetch/fetch.3 delete mode 100644 uppdev/plugin/libfetch/ftp.errors delete mode 100644 uppdev/plugin/libfetch/http.errors delete mode 100644 uppdev/plugin/libfetch/lib/common.c delete mode 100644 uppdev/plugin/libfetch/lib/common.h delete mode 100644 uppdev/plugin/libfetch/lib/fetch.c delete mode 100644 uppdev/plugin/libfetch/lib/fetch.h delete mode 100644 uppdev/plugin/libfetch/lib/file.c delete mode 100644 uppdev/plugin/libfetch/lib/ftp.c delete mode 100644 uppdev/plugin/libfetch/lib/http.c delete mode 100644 uppdev/plugin/libfetch/libfetch.upp delete mode 100644 uppdev/plugin/lzo/init delete mode 100644 uppdev/plugin/lzo/lib/COPYING delete mode 100644 uppdev/plugin/lzo/lib/README.LZO delete mode 100644 uppdev/plugin/lzo/lib/lzoconf.h delete mode 100644 uppdev/plugin/lzo/lib/lzodefs.h delete mode 100644 uppdev/plugin/lzo/lib/minilzo.c delete mode 100644 uppdev/plugin/lzo/lib/minilzo.h delete mode 100644 uppdev/plugin/lzo/lzo.cpp delete mode 100644 uppdev/plugin/lzo/lzo.h delete mode 100644 uppdev/plugin/lzo/lzo.upp delete mode 100644 uppdev/plugin/pixman/init delete mode 100644 uppdev/plugin/pixman/lib/pixman-access-accessors.c delete mode 100644 uppdev/plugin/pixman/lib/pixman-access.c delete mode 100644 uppdev/plugin/pixman/lib/pixman-arm-simd.c delete mode 100644 uppdev/plugin/pixman/lib/pixman-arm-simd.h delete mode 100644 uppdev/plugin/pixman/lib/pixman-combine32.c delete mode 100644 uppdev/plugin/pixman/lib/pixman-combine32.h delete mode 100644 uppdev/plugin/pixman/lib/pixman-combine64.c delete mode 100644 uppdev/plugin/pixman/lib/pixman-combine64.h delete mode 100644 uppdev/plugin/pixman/lib/pixman-compose-accessors.c delete mode 100644 uppdev/plugin/pixman/lib/pixman-compose.c delete mode 100644 uppdev/plugin/pixman/lib/pixman-compute-region.c delete mode 100644 uppdev/plugin/pixman/lib/pixman-edge-accessors.c delete mode 100644 uppdev/plugin/pixman/lib/pixman-edge-imp.h delete mode 100644 uppdev/plugin/pixman/lib/pixman-edge.c delete mode 100644 uppdev/plugin/pixman/lib/pixman-image.c delete mode 100644 uppdev/plugin/pixman/lib/pixman-matrix.c delete mode 100644 uppdev/plugin/pixman/lib/pixman-mmx.c delete mode 100644 uppdev/plugin/pixman/lib/pixman-mmx.h delete mode 100644 uppdev/plugin/pixman/lib/pixman-pict.c delete mode 100644 uppdev/plugin/pixman/lib/pixman-private.h delete mode 100644 uppdev/plugin/pixman/lib/pixman-region.c delete mode 100644 uppdev/plugin/pixman/lib/pixman-region16.c delete mode 100644 uppdev/plugin/pixman/lib/pixman-region32.c delete mode 100644 uppdev/plugin/pixman/lib/pixman-source.c delete mode 100644 uppdev/plugin/pixman/lib/pixman-sse2.c delete mode 100644 uppdev/plugin/pixman/lib/pixman-sse2.h delete mode 100644 uppdev/plugin/pixman/lib/pixman-timer.c delete mode 100644 uppdev/plugin/pixman/lib/pixman-transformed-accessors.c delete mode 100644 uppdev/plugin/pixman/lib/pixman-transformed.c delete mode 100644 uppdev/plugin/pixman/lib/pixman-trap.c delete mode 100644 uppdev/plugin/pixman/lib/pixman-utils.c delete mode 100644 uppdev/plugin/pixman/lib/pixman-version.h delete mode 100644 uppdev/plugin/pixman/lib/pixman-vmx.c delete mode 100644 uppdev/plugin/pixman/lib/pixman-vmx.h delete mode 100644 uppdev/plugin/pixman/lib/pixman.h delete mode 100644 uppdev/plugin/pixman/pixman.upp delete mode 100644 uppdev/plugin/pixman/pixmanlib1.c delete mode 100644 uppdev/plugin/pixman/pixmanlib2.c delete mode 100644 uppdev/plugin/pixman/pixmanlib3.c delete mode 100644 uppdev/plugin/pixman/pixmanlib4.c delete mode 100644 uppdev/plugin/png/Copying delete mode 100644 uppdev/plugin/png/init delete mode 100644 uppdev/plugin/png/lib/CHANGES delete mode 100644 uppdev/plugin/png/lib/INSTALL delete mode 100644 uppdev/plugin/png/lib/KNOWNBUG delete mode 100644 uppdev/plugin/png/lib/LICENSE delete mode 100644 uppdev/plugin/png/lib/README delete mode 100644 uppdev/plugin/png/lib/example.c delete mode 100644 uppdev/plugin/png/lib/libpng-1.2.22.txt delete mode 100644 uppdev/plugin/png/lib/libpng.3 delete mode 100644 uppdev/plugin/png/lib/libpngpf.3 delete mode 100644 uppdev/plugin/png/lib/png.5 delete mode 100644 uppdev/plugin/png/lib/png.c delete mode 100644 uppdev/plugin/png/lib/png.h delete mode 100644 uppdev/plugin/png/lib/pngconf.h delete mode 100644 uppdev/plugin/png/lib/pngerror.c delete mode 100644 uppdev/plugin/png/lib/pnggccrd.c delete mode 100644 uppdev/plugin/png/lib/pngget.c delete mode 100644 uppdev/plugin/png/lib/pngmem.c delete mode 100644 uppdev/plugin/png/lib/pngpread.c delete mode 100644 uppdev/plugin/png/lib/pngread.c delete mode 100644 uppdev/plugin/png/lib/pngrio.c delete mode 100644 uppdev/plugin/png/lib/pngrtran.c delete mode 100644 uppdev/plugin/png/lib/pngrutil.c delete mode 100644 uppdev/plugin/png/lib/pngset.c delete mode 100644 uppdev/plugin/png/lib/pngtest.c delete mode 100644 uppdev/plugin/png/lib/pngtrans.c delete mode 100644 uppdev/plugin/png/lib/pngvcrd.c delete mode 100644 uppdev/plugin/png/lib/pngwio.c delete mode 100644 uppdev/plugin/png/lib/pngwrite.c delete mode 100644 uppdev/plugin/png/lib/pngwtran.c delete mode 100644 uppdev/plugin/png/lib/pngwutil.c delete mode 100644 uppdev/plugin/png/png.h delete mode 100644 uppdev/plugin/png/png.upp delete mode 100644 uppdev/plugin/png/pnglib.c delete mode 100644 uppdev/plugin/png/pngreg.icpp delete mode 100644 uppdev/plugin/png/pngupp.cpp diff --git a/uppdev/FileHexView/FileHexView.upp b/uppdev/FileHexView/FileHexView.upp new file mode 100644 index 000000000..751f7b112 --- /dev/null +++ b/uppdev/FileHexView/FileHexView.upp @@ -0,0 +1,10 @@ +uses + CtrlLib, + HexView; + +file + main.cpp; + +mainconfig + "" = "GUI SSE2"; + diff --git a/uppdev/FileHexView/init b/uppdev/FileHexView/init new file mode 100644 index 000000000..2f8ccc9e9 --- /dev/null +++ b/uppdev/FileHexView/init @@ -0,0 +1,5 @@ +#ifndef _FileHexView_icpp_init_stub +#define _FileHexView_icpp_init_stub +#include "CtrlLib/init" +#include "HexView/init" +#endif diff --git a/uppdev/FileHexView/main.cpp b/uppdev/FileHexView/main.cpp new file mode 100644 index 000000000..7a80d0528 --- /dev/null +++ b/uppdev/FileHexView/main.cpp @@ -0,0 +1,109 @@ +#include +#include + +using namespace Upp; + +class FileHexView : public HexView, private LRUCache::Maker { +public: + virtual int Byte(int64 addr); + + virtual int64 Key() const; + virtual int Make(String& object) const; + +private: + FileIn file; + int64 blk; + + LRUCache cache; + + enum { BLKSHIFT = 14, BLKSIZE = 1 << BLKSHIFT }; + +public: + void Open(const char *path); +}; + +int64 FileHexView::Key() const +{ + return blk; +} + +int FileHexView::Make(String& object) const +{ + FileIn& in = const_cast(file); + in.Seek(blk * FileHexView::BLKSIZE); + object = in.Get(FileHexView::BLKSIZE); + return 1; +} + +int FileHexView::Byte(int64 addr) +{ + blk = addr >> BLKSHIFT; + String h = cache.Get(*this); + cache.Shrink(10); // cache only 10 blocks (~150 KB) + int ii = addr & (BLKSIZE - 1); + return ii < h.GetCount() ? (byte)h[ii] : 0; +} + +void FileHexView::Open(const char *path) +{ + file.Open(path); + SetTotal(file.GetSize()); +} + + +bool FileIsBinary(const char *path) +{ + FileIn in(path); + if(in) { + String data = in.Get(150000); + data.Cat('\n'); + const char *end = data.End(); + int le = -1; + const char *s = data; + while(s < end) { + int c = (byte)*s; + if(c < 32) { + if(c == '\r') { + if(s[1] != '\n' || le == 0) + return true; + le = 1; + s += 2; + } + else + if(c == '\n') { + if(le == 1) + return true; + s++; + } + else + if(c == '\t') + s++; + else + return true; + } + else + s++; + } + } + return false; +} + +GUI_APP_MAIN +{ +/* FindFile ff("c:/xxx/*.*"); + while(ff) { + if(ff.IsFile()) + DLOG(ff.GetName() << " " << FileIsBinary(ff.GetPath())); + ff.Next(); + } + return; +*/ + FileHexView view; +// view.Open("C:/Users/cxl/WinBase.pp"); + view.Open("N:/Exodus.Gods.and.Kings.2014.1080p.WEB-DL.DD5.1.H264-RARBG/Exodus.Gods.and.Kings.2014.1080p.WEB-DL.DD5.1.H264-RARBG.mkv"); + + TopWindow win; + win.Add(view.SizePos()); + + win.Run(); +} diff --git a/uppdev/cpp/cpp.h b/uppdev/cpp/cpp.h index 6846cfd44..ac4fcf7e7 100644 --- a/uppdev/cpp/cpp.h +++ b/uppdev/cpp/cpp.h @@ -41,7 +41,7 @@ struct Cpp { Index header; VectorMap macro0; VectorMap macro; - Index notmacro; + Index notmacro; // speed optimization Index usedmacro; void SyncSet(); diff --git a/uppdev/cpp/main.cpp b/uppdev/cpp/main.cpp index eab603d5f..fbd139544 100644 --- a/uppdev/cpp/main.cpp +++ b/uppdev/cpp/main.cpp @@ -68,8 +68,8 @@ CONSOLE_APP_MAIN // Test("C:/Program Files/Microsoft SDKs/Windows/v7.1/Include/WinBase.h"); Test("C:/Program Files (x86)/Microsoft Visual Studio 9.0/VC/include/string.h"); // Test("C:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\Vc\\Include\\string.h"); - Test("C:/Program Files (x86)/Microsoft Visual Studio 10.0/VC/include/vector"); - return; +// Test("C:/Program Files (x86)/Microsoft Visual Studio 10.0/VC/include/vector"); +// return; Cpp x; x.filedir = GetFileFolder(GetDataFile("x")); x.include_path = "C:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\Vc\\Include;C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\Include;C:\\OpenSSL-Win32\\include;C:\\u\\pgsql\\include;C:\\u\\OpenSSL-Win32\\include"; diff --git a/uppdev/plugin/astyle/ASBeautifier.cpp b/uppdev/plugin/astyle/ASBeautifier.cpp deleted file mode 100644 index 9f0f5e4b3..000000000 --- a/uppdev/plugin/astyle/ASBeautifier.cpp +++ /dev/null @@ -1,1975 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * - * ASBeautifier.cpp - * - * This file is a part of "Artistic Style" - an indentation and - * reformatting tool for C, C++, C# and Java source files. - * http://astyle.sourceforge.net - * - * The "Artistic Style" project, including all files needed to - * compile it, is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later - * version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this project; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - */ - - /* - 2008-01-26 Patches by Massimo Del Fedele : - - modified sources to use Ultimate++ containers instead std:: ones - - fixed memory leaks based on bug report 1804791 submitted by Eran Ifrah - - modified to work with unicode - */ -#include "astyle.h" - - -#define INIT_CONTAINER(container, value) {if ( (container) != NULL ) delete (container); (container) = (value); } -#define DELETE_CONTAINER(container) {if ( (container) != NULL ) delete (container); } - - -namespace astyle -{ -Vector ASBeautifier::headers; -Vector ASBeautifier::nonParenHeaders; -Vector ASBeautifier::preBlockStatements; -Vector ASBeautifier::assignmentOperators; -Vector ASBeautifier::nonAssignmentOperators; - - -/* - * initialize the static vars - */ -void ASBeautifier::initStatic() -{ - static int beautifierFileType = 9; // initialized with an invalid type - - if (fileType == beautifierFileType) // don't build unless necessary - return; - - beautifierFileType = fileType; - - headers.clear(); - nonParenHeaders.clear(); - assignmentOperators.clear(); - nonAssignmentOperators.clear(); - preBlockStatements.clear(); - - ASResource::buildHeaders(headers, fileType, true); - ASResource::buildNonParenHeaders(nonParenHeaders, fileType, true); - ASResource::buildAssignmentOperators(assignmentOperators); - ASResource::buildNonAssignmentOperators(nonAssignmentOperators); - ASResource::buildPreBlockStatements(preBlockStatements); - -// cout << "beaut" << endl; -} - -/** - * ASBeautifier's constructor - */ -ASBeautifier::ASBeautifier() -{ - waitingBeautifierStack = NULL; - activeBeautifierStack = NULL; - waitingBeautifierStackLengthStack = NULL; - activeBeautifierStackLengthStack = NULL; - - headerStack = NULL; - tempStacks = NULL; - blockParenDepthStack = NULL; - blockStatementStack = NULL; - parenStatementStack = NULL; - bracketBlockStateStack = NULL; - inStatementIndentStack = NULL; - inStatementIndentStackSizeStack = NULL; - parenIndentStack = NULL; - sourceIterator = NULL; - - isMinimalConditinalIndentSet = false; - shouldForceTabIndentation = false; - - setSpaceIndentation(4); - setMaxInStatementIndentLength(40); - setClassIndent(false); - setSwitchIndent(false); - setCaseIndent(false); - setBlockIndent(false); - setBracketIndent(false); - setNamespaceIndent(false); - setLabelIndent(false); - setEmptyLineFill(false); - fileType = C_TYPE; - setCStyle(); - setPreprocessorIndent(false); -} - -/** - * ASBeautifier's copy constructor - */ -ASBeautifier::ASBeautifier(const ASBeautifier &other) -{ - waitingBeautifierStack = NULL; - activeBeautifierStack = NULL; - waitingBeautifierStackLengthStack = NULL; - activeBeautifierStackLengthStack = NULL; - - headerStack = new WithDeepCopy >; - *headerStack <<= *other.headerStack; - - tempStacks = new WithDeepCopy*> >; - WithDeepCopy*> >::iterator iter; - for (iter = other.tempStacks->begin(); - iter != other.tempStacks->end(); - ++iter) - { - WithDeepCopy > *newVec = new WithDeepCopy >; - *newVec = **iter; - tempStacks->push_back(newVec); - } - blockParenDepthStack = new WithDeepCopy >; - *blockParenDepthStack = *other.blockParenDepthStack; - - blockStatementStack = new WithDeepCopy >; - *blockStatementStack = *other.blockStatementStack; - - parenStatementStack = new WithDeepCopy >; - *parenStatementStack = *other.parenStatementStack; - - bracketBlockStateStack = new WithDeepCopy >; - *bracketBlockStateStack = *other.bracketBlockStateStack; - - inStatementIndentStack = new WithDeepCopy >; - *inStatementIndentStack = *other.inStatementIndentStack; - - inStatementIndentStackSizeStack = new WithDeepCopy >; - *inStatementIndentStackSizeStack = *other.inStatementIndentStackSizeStack; - - parenIndentStack = new WithDeepCopy >; - *parenIndentStack = *other.parenIndentStack; - - sourceIterator = other.sourceIterator; - - // protected variables - fileType = other.fileType; - isCStyle = other.isCStyle; - isJavaStyle = other.isJavaStyle; - isSharpStyle = other.isSharpStyle; - - // variables set by ASFormatter - // must also be updated in preprocessor - inLineNumber = other.inLineNumber; - outLineNumber = other.outLineNumber; - lineCommentNoBeautify = other.lineCommentNoBeautify; - isNonInStatementArray = other.isNonInStatementArray; - - // private variables - indentString = other.indentString; - currentHeader = other.currentHeader; - previousLastLineHeader = other.previousLastLineHeader; - immediatelyPreviousAssignmentOp = other.immediatelyPreviousAssignmentOp; - probationHeader = other.probationHeader; - isInQuote = other.isInQuote; - isInComment = other.isInComment; - isInCase = other.isInCase; - isInQuestion = other.isInQuestion; - isInStatement = other.isInStatement; - isInHeader = other.isInHeader; - isInOperator = other.isInOperator; - isInTemplate = other.isInTemplate; - isInDefine = other.isInDefine; - isInDefineDefinition = other.isInDefineDefinition; - classIndent = other.classIndent; - isInClassHeader = other.isInClassHeader; - isInClassHeaderTab = other.isInClassHeaderTab; - switchIndent = other.switchIndent; - caseIndent = other.caseIndent; - namespaceIndent = other.namespaceIndent; - bracketIndent = other.bracketIndent; - blockIndent = other.blockIndent; - labelIndent = other.labelIndent; - preprocessorIndent = other.preprocessorIndent; - isInConditional = other.isInConditional; - isMinimalConditinalIndentSet = other.isMinimalConditinalIndentSet; - shouldForceTabIndentation = other.shouldForceTabIndentation; - emptyLineFill = other.emptyLineFill; - backslashEndsPrevLine = other.backslashEndsPrevLine; - blockCommentNoIndent = other.blockCommentNoIndent; - blockCommentNoBeautify = other.blockCommentNoBeautify; - previousLineProbationTab = other.previousLineProbationTab; - minConditionalIndent = other.minConditionalIndent; - parenDepth = other.parenDepth; - indentLength = other.indentLength; - blockTabCount = other.blockTabCount; - leadingWhiteSpaces = other.leadingWhiteSpaces; - maxInStatementIndent = other.maxInStatementIndent; - templateDepth = other.templateDepth; - prevFinalLineSpaceTabCount = other.prevFinalLineSpaceTabCount; - prevFinalLineTabCount = other.prevFinalLineTabCount; - defineTabCount = other.defineTabCount; - quoteChar = other.quoteChar; - prevNonSpaceCh = other.prevNonSpaceCh; - currentNonSpaceCh = other.currentNonSpaceCh; - currentNonLegalCh = other.currentNonLegalCh; - prevNonLegalCh = other.prevNonLegalCh; -} - -/** - * ASBeautifier's destructor - */ -ASBeautifier::~ASBeautifier() -{ - DELETE_CONTAINER(headerStack); - DELETE_CONTAINER(blockParenDepthStack); - DELETE_CONTAINER(blockStatementStack); - DELETE_CONTAINER(parenStatementStack); - DELETE_CONTAINER(bracketBlockStateStack); - DELETE_CONTAINER(inStatementIndentStack); - DELETE_CONTAINER(inStatementIndentStackSizeStack); - DELETE_CONTAINER(parenIndentStack); - - //this two were missing... - DELETE_CONTAINER(waitingBeautifierStackLengthStack); - DELETE_CONTAINER(activeBeautifierStackLengthStack); - - //the correct way to release tempStacks, waitingBeautifierStack and activeBeautifierStack - if(tempStacks) - { - Vector< Vector* >::iterator iter = tempStacks->begin(); - for(; iter != tempStacks->end(); iter++) - delete *iter; - tempStacks->clear(); - delete tempStacks; - tempStacks = NULL; - } - - if(waitingBeautifierStack) - { - Vector::iterator iter = waitingBeautifierStack->begin(); - for(; iter != waitingBeautifierStack->end(); iter++) - delete *iter; - waitingBeautifierStack->clear(); - delete waitingBeautifierStack; - waitingBeautifierStack = NULL; - } - - if(activeBeautifierStack) - { - Vector::iterator iter = activeBeautifierStack->begin(); - for(; iter != activeBeautifierStack->end(); iter++) - delete *iter; - activeBeautifierStack->clear(); - delete activeBeautifierStack; - activeBeautifierStack = NULL; - } -} - -/** - * initialize the ASBeautifier. - * - * init() should be called every time a ABeautifier object is to start - * beautifying a NEW source file. - * init() recieves a pointer to a DYNAMICALLY CREATED ASSourceIterator object - * that will be used to iterate through the source code. This object will be - * deleted during the ASBeautifier's destruction, and thus should not be - * deleted elsewhere. - * - * @param iter a pointer to the DYNAMICALLY CREATED ASSourceIterator object. - */ -void ASBeautifier::init(ASSourceIterator *iter) -{ - sourceIterator = iter; - init(); -} - -/** - * initialize the ASBeautifier. - */ -void ASBeautifier::init() -{ - initStatic(); - - INIT_CONTAINER(waitingBeautifierStack, new Vector); - INIT_CONTAINER(activeBeautifierStack, new Vector); - - INIT_CONTAINER(waitingBeautifierStackLengthStack, new Vector); - INIT_CONTAINER(activeBeautifierStackLengthStack, new Vector); - - INIT_CONTAINER(headerStack, new WithDeepCopy >); - INIT_CONTAINER(tempStacks, new WithDeepCopy*> >); - tempStacks->push_back(new Vector); - - INIT_CONTAINER(blockParenDepthStack, new WithDeepCopy >); - INIT_CONTAINER(blockStatementStack, new WithDeepCopy >); - INIT_CONTAINER(parenStatementStack, new WithDeepCopy >); - - INIT_CONTAINER(bracketBlockStateStack, new WithDeepCopy >); - bracketBlockStateStack->push_back(true); - - INIT_CONTAINER(inStatementIndentStack, new WithDeepCopy >); - INIT_CONTAINER(inStatementIndentStackSizeStack, new WithDeepCopy >); - inStatementIndentStackSizeStack->push_back(0); - INIT_CONTAINER(parenIndentStack, new WithDeepCopy >); - - immediatelyPreviousAssignmentOp = NULL; - previousLastLineHeader = NULL; - currentHeader = NULL; - - isInQuote = false; - isInComment = false; - isInStatement = false; - isInCase = false; - isInQuestion = false; - isInClassHeader = false; - isInClassHeaderTab = false; - isInHeader = false; - isInOperator = false; - isInTemplate = false; - isInConditional = false; - templateDepth = 0; - parenDepth = 0; - blockTabCount = 0; - leadingWhiteSpaces = 0; - prevNonSpaceCh = '{'; - currentNonSpaceCh = '{'; - prevNonLegalCh = '{'; - currentNonLegalCh = '{'; - quoteChar = ' '; - prevFinalLineSpaceTabCount = 0; - prevFinalLineTabCount = 0; - probationHeader = NULL; - backslashEndsPrevLine = false; - isInDefine = false; - isInDefineDefinition = false; - defineTabCount = 0; - lineCommentNoBeautify = false; - blockCommentNoIndent = false; - blockCommentNoBeautify = false; - previousLineProbationTab = false; - isNonInStatementArray = false; - inLineNumber = -1; // for debugging - outLineNumber = 0; // for debugging -} - -/** - * set indentation style to C/C++. - */ -void ASBeautifier::setCStyle() -{ - fileType = C_TYPE; - isCStyle = true; - isJavaStyle = false; - isSharpStyle = false; -} - -/** - * set indentation style to Java. - */ -void ASBeautifier::setJavaStyle() -{ - fileType = JAVA_TYPE; - isJavaStyle = true; - isCStyle = false; - isSharpStyle = false; -} - -/** - * set indentation style to C#. - */ -void ASBeautifier::setSharpStyle() -{ - fileType = SHARP_TYPE; - isSharpStyle = true; - isCStyle = false; - isJavaStyle = false; -} - -/** - * indent using one tab per indentation - */ -void ASBeautifier::setTabIndentation(int length, bool forceTabs) -{ - indentString = "\t"; - indentLength = length; - shouldForceTabIndentation = forceTabs; - - if (!isMinimalConditinalIndentSet) - minConditionalIndent = indentLength * 2; -} - -/** - * indent using a number of spaces per indentation. - * - * @param length number of spaces per indent. - */ -void ASBeautifier::setSpaceIndentation(int length) -{ - indentString = WString(' ', length); - indentLength = length; - - if (!isMinimalConditinalIndentSet) - minConditionalIndent = indentLength * 2; -} - -/** - * set the maximum indentation between two lines in a multi-line statement. - * - * @param max maximum indentation length. - */ -void ASBeautifier::setMaxInStatementIndentLength(int max) -{ - maxInStatementIndent = max; -} - -/** - * set the minimum indentation between two lines in a multi-line condition. - * - * @param min minimal indentation length. - */ -void ASBeautifier::setMinConditionalIndentLength(int min) -{ - minConditionalIndent = min; - isMinimalConditinalIndentSet = true; -} - -/** - * set the state of the bracket indentation option. If true, brackets will - * be indented one additional indent. - * - * @param state state of option. - */ -void ASBeautifier::setBracketIndent(bool state) -{ - bracketIndent = state; -} - -/** - * set the state of the block indentation option. If true, entire blocks - * will be indented one additional indent, similar to the GNU indent style. - * - * @param state state of option. - */ -void ASBeautifier::setBlockIndent(bool state) -{ - if (state) - setBracketIndent(false); // so that we don't have both bracket and block indent - blockIndent = state; -} - -/** - * set the state of the class indentation option. If true, C++ class - * definitions will be indented one additional indent. - * - * @param state state of option. - */ -void ASBeautifier::setClassIndent(bool state) -{ - classIndent = state; -} - -/** - * set the state of the switch indentation option. If true, blocks of 'switch' - * statements will be indented one additional indent. - * - * @param state state of option. - */ -void ASBeautifier::setSwitchIndent(bool state) -{ - switchIndent = state; -} - -/** - * set the state of the case indentation option. If true, lines of 'case' - * statements will be indented one additional indent. - * - * @param state state of option. - */ -void ASBeautifier::setCaseIndent(bool state) -{ - caseIndent = state; -} - -/** - * set the state of the namespace indentation option. - * If true, blocks of 'namespace' statements will be indented one - * additional indent. Otherwise, NO indentation will be added. - * - * @param state state of option. - */ -void ASBeautifier::setNamespaceIndent(bool state) -{ - namespaceIndent = state; -} - -/** - * set the state of the label indentation option. - * If true, labels will be indented one indent LESS than the - * current indentation level. - * If false, labels will be flushed to the left with NO - * indent at all. - * - * @param state state of option. - */ -void ASBeautifier::setLabelIndent(bool state) -{ - labelIndent = state; -} - -/** - * set the state of the preprocessor indentation option. - * If true, multiline #define statements will be indented. - * - * @param state state of option. - */ -void ASBeautifier::setPreprocessorIndent(bool state) -{ - preprocessorIndent = state; -} - -/** - * set the state of the empty line fill option. - * If true, empty lines will be filled with the whitespace. - * of their previous lines. - * If false, these lines will remain empty. - * - * @param state state of option. - */ -void ASBeautifier::setEmptyLineFill(bool state) -{ - emptyLineFill = state; -} - -/** - * get the number of spaces per indent - * - * @return value of indentLength option. -*/ -int ASBeautifier::getIndentLength(void) -{ - return indentLength; -} - -/** - * get the char used for indentation, space or tab - * - * @return the char used for indentation. - */ -WString ASBeautifier::getIndentString(void) -{ - return indentString; -} - -/** - * get the state of the case indentation option. If true, lines of 'case' - * statements will be indented one additional indent. - * - * @return state of caseIndent option. - */ -bool ASBeautifier::getCaseIndent(void) -{ - return caseIndent; -} - -/** - * get C style identifier. - * If true, a C source is being indented. - * - * @return state of isCStyle option. - */ -bool ASBeautifier::getCStyle(void) -{ - return isCStyle; -} - -/** - * get Java style identifier. - * If true, a Java source is being indented. - * - * @return state of isJavaStyle option. - */ -bool ASBeautifier::getJavaStyle(void) -{ - return isJavaStyle; -} - -/** - * get C# style identifier. - * If true, a C# source is being indented. - * - * @return state of isSharpStyle option. - */ -bool ASBeautifier::getSharpStyle(void) -{ - return isSharpStyle; -} - -/** - * get the state of the empty line fill option. - * If true, empty lines will be filled with the whitespace. - * of their previous lines. - * If false, these lines will remain empty. - * - * @return state of emptyLineFill option. - */ -bool ASBeautifier::getEmptyLineFill(void) -{ - return emptyLineFill; -} - -/** - * check if there are any indented lines ready to be read by nextLine() - * - * @return are there any indented lines ready? - */ -bool ASBeautifier::hasMoreLines() const -{ - return sourceIterator->hasMoreLines(); -} - -/** - * get the next indented line. - * - * @return indented line. - */ -WString ASBeautifier::nextLine() -{ - return beautify(sourceIterator->nextLine()); -} - -/** - * beautify a line of source code. - * every line of source code in a source code file should be sent - * one after the other to the beautify method. - * - * @return the indented line. - * @param originalLine the original unindented line. - */ -WString ASBeautifier::beautify(const WString &originalLine) -{ - WString line; - bool isInLineComment = false; - bool lineStartsInComment = false; - bool isInClass = false; - bool isInSwitch = false; - bool isImmediatelyAfterConst = false; - bool isSpecialChar = false; - char ch = ' '; - char prevCh; - WString outBuffer; // the newly idented line is bufferd here - int tabCount = 0; - const WString *lastLineHeader = NULL; - bool closingBracketReached = false; - int spaceTabCount = 0; - char tempCh; - int headerStackSize = headerStack->GetCount(); - bool shouldIndentBrackettedLine = true; - int lineOpeningBlocksNum = 0; - int lineClosingBlocksNum = 0; - bool previousLineProbation = (probationHeader != NULL); - int i; - - currentHeader = NULL; - lineStartsInComment = isInComment; - blockCommentNoBeautify = blockCommentNoIndent; - previousLineProbationTab = false; - outLineNumber++; - - // handle and remove white spaces around the line: - // If not in comment, first find out size of white space before line, - // so that possible comments starting in the line continue in - // relation to the preliminary white-space. - if (!isInComment) - { - int strlen = originalLine.GetCount(); - leadingWhiteSpaces = 0; - - for (int j = 0; j < strlen && isWhiteSpace(originalLine[j]); j++) - { - if (originalLine[j] == '\t') - leadingWhiteSpaces += indentLength; - else - leadingWhiteSpaces++; - } - line = trim(originalLine); - } - else - { - // convert leading tabs to spaces - WString spaceTabs(' ', indentLength); - WString newLine = originalLine; - int strlen = newLine.GetCount(); - - for (int j=0; j < leadingWhiteSpaces && j < strlen; j++) - { - if (newLine[j] == '\t') - { - ASString_Replace(newLine, j, 1, spaceTabs); - strlen = newLine.GetCount(); - } - } - - // trim the comment leaving the new leading whitespace - int trimSize = 0; - strlen = newLine.GetCount(); - - while (trimSize < strlen - && trimSize < leadingWhiteSpaces - && isWhiteSpace(newLine[trimSize])) - trimSize++; - - - while (trimSize < strlen && isWhiteSpace(newLine[strlen-1])) - strlen--; - - line = newLine.Mid(trimSize, strlen); - int trimEnd = ASString_Find_Last_Not_Of(line, " \t"); - if (trimEnd >= 0) - { - int spacesToDelete = line.GetCount() - 1 - trimEnd; - if (spacesToDelete > 0) - line.Remove(trimEnd + 1, spacesToDelete); - } - } - - - if (line.GetCount() == 0) - { - if (backslashEndsPrevLine) // must continue to clear variables - line = " "; - else if (emptyLineFill) - return preLineWS(prevFinalLineSpaceTabCount, prevFinalLineTabCount); - else - return line; - } - - // handle preprocessor commands - - if (isCStyle && !isInComment && (line[0] == '#' || backslashEndsPrevLine)) - { - if (line[0] == '#') - { - WString preproc = trim(line.Mid(1)); - - // When finding a multi-lined #define statement, the original beautifier - // 1. sets its isInDefineDefinition flag - // 2. clones a new beautifier that will be used for the actual indentation - // of the #define. This clone is put into the activeBeautifierStack in order - // to be called for the actual indentation. - // The original beautifier will have isInDefineDefinition = true, isInDefine = false - // The cloned beautifier will have isInDefineDefinition = true, isInDefine = true - if (preprocessorIndent && preproc.Mid(0, 6) == WString("define") && *line.Last() == '\\') - { - if (!isInDefineDefinition) - { - ASBeautifier *defineBeautifier; - - // this is the original beautifier - isInDefineDefinition = true; - - // push a new beautifier into the active stack - // this beautifier will be used for the indentation of this define - defineBeautifier = new ASBeautifier(*this); - activeBeautifierStack->push_back(defineBeautifier); - } - else - { - // the is the cloned beautifier that is in charge of indenting the #define. - isInDefine = true; - } - } - else if (preproc.Mid(0, 2) == WString("if")) - { - // push a new beautifier into the stack - waitingBeautifierStackLengthStack->push_back(waitingBeautifierStack->GetCount()); - activeBeautifierStackLengthStack->push_back(activeBeautifierStack->GetCount()); - waitingBeautifierStack->push_back(new ASBeautifier(*this)); - } - else if (preproc.Mid(0, 4) == WString("else")) - { - if (waitingBeautifierStack && !waitingBeautifierStack->IsEmpty()) - { - // MOVE current waiting beautifier to active stack. - activeBeautifierStack->push_back(waitingBeautifierStack->back()); - waitingBeautifierStack->pop_back(); - } - } - else if (preproc.Mid(0, 4) == WString("elif")) - { - if (waitingBeautifierStack && !waitingBeautifierStack->IsEmpty()) - { - // append a COPY current waiting beautifier to active stack, WITHOUT deleting the original. - activeBeautifierStack->push_back(new ASBeautifier(*(waitingBeautifierStack->back()))); - } - } - else if (preproc.Mid(0, 5) == WString("endif")) - { - int stackLength; - ASBeautifier *beautifier; - - if (waitingBeautifierStackLengthStack && !waitingBeautifierStackLengthStack->IsEmpty()) - { - stackLength = waitingBeautifierStackLengthStack->back(); - waitingBeautifierStackLengthStack->pop_back(); - while ((int) waitingBeautifierStack->GetCount() > stackLength) - { - beautifier = waitingBeautifierStack->back(); - waitingBeautifierStack->pop_back(); - delete beautifier; - } - } - - if (!activeBeautifierStackLengthStack->IsEmpty()) - { - stackLength = activeBeautifierStackLengthStack->back(); - activeBeautifierStackLengthStack->pop_back(); - while ((int) activeBeautifierStack->GetCount() > stackLength) - { - beautifier = activeBeautifierStack->back(); - activeBeautifierStack->pop_back(); - delete beautifier; - } - } - } - } - - // check if the last char is a backslash - if (line.GetCount() > 0) - backslashEndsPrevLine = (line[line.GetCount() - 1] == '\\'); - else - backslashEndsPrevLine = false; - - // check if this line ends a multi-line #define - // if so, use the #define's cloned beautifier for the line's indentation - // and then remove it from the active beautifier stack and delete it. - if (!backslashEndsPrevLine && isInDefineDefinition && !isInDefine) - { - WString beautifiedLine; - ASBeautifier *defineBeautifier; - - isInDefineDefinition = false; - defineBeautifier = activeBeautifierStack->back(); - activeBeautifierStack->pop_back(); - - beautifiedLine = defineBeautifier->beautify(line); - delete defineBeautifier; - return beautifiedLine; - } - - // unless this is a multi-line #define, return this precompiler line as is. - if (!isInDefine && !isInDefineDefinition) - return originalLine; - } - - // if there exists any worker beautifier in the activeBeautifierStack, - // then use it instead of me to indent the current line. - // variables set by ASFormatter must be updated. - if (!isInDefine && activeBeautifierStack != NULL && !activeBeautifierStack->IsEmpty()) - { - activeBeautifierStack->back()->inLineNumber = inLineNumber; - activeBeautifierStack->back()->outLineNumber = outLineNumber; - activeBeautifierStack->back()->lineCommentNoBeautify = lineCommentNoBeautify; - activeBeautifierStack->back()->isNonInStatementArray = isNonInStatementArray; - return activeBeautifierStack->back()->beautify(line); - } - - // calculate preliminary indentation based on data from past lines - if (!inStatementIndentStack->IsEmpty()) - spaceTabCount = inStatementIndentStack->back(); - - - for (i = 0; i < (int) headerStackSize; i++) - { - isInClass = false; - - if (blockIndent || (!(i > 0 && (*headerStack)[i-1] != &AS_OPEN_BRACKET - && (*headerStack)[i] == &AS_OPEN_BRACKET))) - ++tabCount; - - if (!isJavaStyle && !namespaceIndent && i >= 1 - && (*headerStack)[i-1] == &AS_NAMESPACE - && (*headerStack)[i] == &AS_OPEN_BRACKET) - --tabCount; - - if (isCStyle && i >= 1 - && (*headerStack)[i-1] == &AS_CLASS - && (*headerStack)[i] == &AS_OPEN_BRACKET) - { - if (classIndent) - ++tabCount; - isInClass = true; - } - - // is the switchIndent option is on, indent switch statements an additional indent. - else if (switchIndent && i > 1 && - (*headerStack)[i-1] == &AS_SWITCH && - (*headerStack)[i] == &AS_OPEN_BRACKET - ) - { - ++tabCount; - isInSwitch = true; - } - - } - - if (!lineStartsInComment - && isCStyle - && isInClass - && classIndent - && headerStackSize >= 2 - && (*headerStack)[headerStackSize-2] == &AS_CLASS - && (*headerStack)[headerStackSize-1] == &AS_OPEN_BRACKET - && line[0] == '}') - --tabCount; - - else if (!lineStartsInComment - && isInSwitch - && switchIndent - && headerStackSize >= 2 - && (*headerStack)[headerStackSize-2] == &AS_SWITCH - && (*headerStack)[headerStackSize-1] == &AS_OPEN_BRACKET - && line[0] == '}') - --tabCount; - - if (isInClassHeader) - { - isInClassHeaderTab = true; - tabCount += 2; - } - - if (isInConditional) - { - --tabCount; - } - - - // parse characters in the current line. - - for (i = 0; i < (int) line.GetCount(); i++) - { - tempCh = line[i]; - - prevCh = ch; - ch = tempCh; - -// outBuffer.append(1, ch); - outBuffer.Cat(ch); - - if (isWhiteSpace(ch)) - continue; - - // check for utf8 characters - // isalnum() will display an assert message in debug if not bypassed here - if (ch < 0) - continue; - - // handle special characters (i.e. backslash+character such as \n, \t, ...) - if (isSpecialChar) - { - isSpecialChar = false; - continue; - } - if (!(isInComment || isInLineComment) && line.Mid(i, 2) == WString("\\\\")) - { - outBuffer.Cat('\\'); - i++; - continue; - } - if (!(isInComment || isInLineComment) && ch == '\\') - { - isSpecialChar = true; - continue; - } - - // handle quotes (such as 'x' and "Hello Dolly") - if (!(isInComment || isInLineComment) && (ch == '"' || ch == '\'')) - if (!isInQuote) - { - quoteChar = ch; - isInQuote = true; - } - else if (quoteChar == ch) - { - isInQuote = false; - isInStatement = true; - continue; - } - if (isInQuote) - continue; - - // handle comments - - if (!(isInComment || isInLineComment) && line.Mid(i, 2) == WString("//")) - { - isInLineComment = true; - outBuffer.Cat('/'); - i++; - continue; - } - else if (!(isInComment || isInLineComment) && line.Mid(i, 2) == WString("/*")) - { - isInComment = true; - outBuffer.Cat('*'); - i++; - int j = ASString_Find_First_Not_Of(line, " \t"); - if (line.Mid(j, 2) != WString("/*")) // does line start with comment? - blockCommentNoIndent = true; // if no, cannot indent continuation lines - continue; - } - else if ((isInComment || isInLineComment) && line.Mid(i, 2) == WString("*/")) - { - isInComment = false; - outBuffer.Cat('/'); - i++; - blockCommentNoIndent = false; // ok to indent next comment - continue; - } - - if (isInComment || isInLineComment) - continue; - - // if we have reached this far then we are NOT in a comment or String of special character... - - if (probationHeader != NULL) - { - if (((probationHeader == &AS_STATIC || probationHeader == &AS_CONST) && ch == '{') - || (probationHeader == &AS_SYNCHRONIZED && ch == '(')) - { - // insert the probation header as a new header - isInHeader = true; - headerStack->push_back(probationHeader); - - // handle the specific probation header - isInConditional = (probationHeader == &AS_SYNCHRONIZED); - if (probationHeader == &AS_CONST) - isImmediatelyAfterConst = true; - - isInStatement = false; - // if the probation comes from the previous line, then indent by 1 tab count. - if (previousLineProbation && ch == '{') - { - tabCount++; - previousLineProbationTab = true; - } - previousLineProbation = false; - } - - // dismiss the probation header - probationHeader = NULL; - } - - prevNonSpaceCh = currentNonSpaceCh; - currentNonSpaceCh = ch; - if (!isLegalNameChar(ch) && ch != ',' && ch != ';') - { - prevNonLegalCh = currentNonLegalCh; - currentNonLegalCh = ch; - } - - if (isInHeader) - { - isInHeader = false; - currentHeader = headerStack->back(); - } - else - currentHeader = NULL; - - if (isCStyle && isInTemplate - && (ch == '<' || ch == '>') - && findHeader(line, i, nonAssignmentOperators) == NULL) - { - if (ch == '<') - { - ++templateDepth; - } - else if (ch == '>') - { - if (--templateDepth <= 0) - { - if (isInTemplate) - ch = ';'; - else - ch = 't'; - isInTemplate = false; - templateDepth = 0; - } - } - } - - // handle parenthesies - if (ch == '(' || ch == '[' || ch == ')' || ch == ']') - { - if (ch == '(' || ch == '[') - { - if (parenDepth == 0) - { - parenStatementStack->push_back(isInStatement); - isInStatement = true; - } - parenDepth++; - - inStatementIndentStackSizeStack->push_back(inStatementIndentStack->GetCount()); - - if (currentHeader != NULL) - registerInStatementIndent(line, i, spaceTabCount, minConditionalIndent/*indentLength*2*/, true); - else - registerInStatementIndent(line, i, spaceTabCount, 0, true); - } - else if (ch == ')' || ch == ']') - { - parenDepth--; - if (parenDepth == 0) - { - isInStatement = parenStatementStack->back(); - parenStatementStack->pop_back(); - ch = ' '; - - isInConditional = false; - } - - if (!inStatementIndentStackSizeStack->IsEmpty()) - { - int previousIndentStackSize = inStatementIndentStackSizeStack->back(); - inStatementIndentStackSizeStack->pop_back(); - while (previousIndentStackSize < (int) inStatementIndentStack->GetCount()) - inStatementIndentStack->pop_back(); - - if (!parenIndentStack->IsEmpty()) - { - int poppedIndent = parenIndentStack->back(); - parenIndentStack->pop_back(); - - if (i == 0) - spaceTabCount = poppedIndent; - } - } - } - - continue; - } - - - if (ch == '{') - { - bool isBlockOpener; - // first, check if '{' is a block-opener or an static-array opener - isBlockOpener = ((prevNonSpaceCh == '{' && bracketBlockStateStack->back()) - || prevNonSpaceCh == '}' - || prevNonSpaceCh == ')' - || prevNonSpaceCh == ';' - || peekNextChar(line, i) == '{' - || isNonInStatementArray - || isInClassHeader -// || isBlockOpener - || isImmediatelyAfterConst - || (isInDefine && - (prevNonSpaceCh == '(' - || prevNonSpaceCh == '_' - || isalnum(prevNonSpaceCh)))); - - isInClassHeader = false; - if (!isBlockOpener && currentHeader != NULL) - { - for (int n = 0; n < nonParenHeaders.GetCount(); n++) - if (currentHeader == nonParenHeaders[n]) - { - isBlockOpener = true; - break; - } - } - bracketBlockStateStack->push_back(isBlockOpener); - if (!isBlockOpener) - { - inStatementIndentStackSizeStack->push_back(inStatementIndentStack->GetCount()); - registerInStatementIndent(line, i, spaceTabCount, 0, true); - parenDepth++; - if (i == 0) - shouldIndentBrackettedLine = false; - - continue; - } - - // this bracket is a block opener... - - ++lineOpeningBlocksNum; -// if (isInClassHeader) -// isInClassHeader = false; - - if (isInClassHeaderTab) - { - isInClassHeaderTab = false; - // decrease tab count if bracket is broken - int firstChar = ASString_Find_First_Not_Of(line, " \t"); - if(firstChar >= 0) - if (line[firstChar] == '{' && (int) firstChar == i) - tabCount -= 2; - } - - // do not allow inStatementIndent - should occur for Java files only - if (inStatementIndentStack->GetCount() > 0) - { - spaceTabCount = 0; - inStatementIndentStack->back() = 0; - } - - blockParenDepthStack->push_back(parenDepth); - blockStatementStack->push_back(isInStatement); - - inStatementIndentStackSizeStack->push_back(inStatementIndentStack->GetCount()); - if (inStatementIndentStack->GetCount() > 0) - inStatementIndentStack->back() = 0; - - blockTabCount += isInStatement ? 1 : 0; - parenDepth = 0; - isInStatement = false; - - tempStacks->push_back(new Vector); - headerStack->push_back(&AS_OPEN_BRACKET); - lastLineHeader = &AS_OPEN_BRACKET; - - continue; - } - - //check if a header has been reached - if (isWhiteSpace(prevCh)) - { - bool isIndentableHeader = true; - const WString *newHeader = findHeader(line, i, headers); - if (newHeader != NULL) - { - // if we reached here, then this is a header... - isInHeader = true; - - Vector *lastTempStack; - if (tempStacks->IsEmpty()) - lastTempStack = NULL; - else - lastTempStack = tempStacks->back(); - - // if a new block is opened, push a new stack into tempStacks to hold the - // future list of headers in the new block. - - // take care of the special case: 'else if (...)' - if (newHeader == &AS_IF && lastLineHeader == &AS_ELSE) - { - headerStack->pop_back(); - } - - // take care of 'else' - else if (newHeader == &AS_ELSE) - { - if (lastTempStack != NULL) - { - int indexOfIf = indexOf(*lastTempStack, &AS_IF); - if (indexOfIf != -1) - { - // recreate the header list in headerStack up to the previous 'if' - // from the temporary snapshot stored in lastTempStack. - int restackSize = lastTempStack->GetCount() - indexOfIf - 1; - for (int r = 0; r < restackSize; r++) - { - headerStack->push_back(lastTempStack->back()); - lastTempStack->pop_back(); - } - if (!closingBracketReached) - tabCount += restackSize; - } - /* - * If the above if is not true, i.e. no 'if' before the 'else', - * then nothing beautiful will come out of this... - * I should think about inserting an Exception here to notify the caller of this... - */ - } - } - - // check if 'while' closes a previous 'do' - else if (newHeader == &AS_WHILE) - { - if (lastTempStack != NULL) - { - int indexOfDo = indexOf(*lastTempStack, &AS_DO); - if (indexOfDo != -1) - { - // recreate the header list in headerStack up to the previous 'do' - // from the temporary snapshot stored in lastTempStack. - int restackSize = lastTempStack->GetCount() - indexOfDo - 1; - for (int r = 0; r < restackSize; r++) - { - headerStack->push_back(lastTempStack->back()); - lastTempStack->pop_back(); - } - if (!closingBracketReached) - tabCount += restackSize; - } - } - } - // check if 'catch' closes a previous 'try' or 'catch' - else if (newHeader == &AS_CATCH || newHeader == &AS_FINALLY) - { - if (lastTempStack != NULL) - { - int indexOfTry = indexOf(*lastTempStack, &AS_TRY); - if (indexOfTry == -1) - indexOfTry = indexOf(*lastTempStack, &AS_CATCH); - if (indexOfTry != -1) - { - // recreate the header list in headerStack up to the previous 'try' - // from the temporary snapshot stored in lastTempStack. - int restackSize = lastTempStack->GetCount() - indexOfTry - 1; - for (int r = 0; r < restackSize; r++) - { - headerStack->push_back(lastTempStack->back()); - lastTempStack->pop_back(); - } - - if (!closingBracketReached) - tabCount += restackSize; - } - } - } - else if (newHeader == &AS_CASE) - { - isInCase = true; - --tabCount; - } - else if (newHeader == &AS_DEFAULT) - { - isInCase = true; - --tabCount; - } - else if (newHeader == &AS_STATIC - || newHeader == &AS_SYNCHRONIZED - || (newHeader == &AS_CONST && isCStyle)) - { - if (!headerStack->IsEmpty() && - (headerStack->back() == &AS_STATIC - || headerStack->back() == &AS_SYNCHRONIZED - || headerStack->back() == &AS_CONST)) - { - isIndentableHeader = false; - } - else - { - isIndentableHeader = false; - probationHeader = newHeader; - } - } - else if (newHeader == &AS_CONST) - { - isIndentableHeader = false; - } - else if (newHeader == &AS_TEMPLATE) - { - if (isCStyle) - isInTemplate = true; - isIndentableHeader = false; - } - - - if (isIndentableHeader) - { - headerStack->push_back(newHeader); - isInStatement = false; - if (indexOf(nonParenHeaders, newHeader) == -1) - { - isInConditional = true; - } - lastLineHeader = newHeader; - } - else - isInHeader = false; - - outBuffer.Cat(newHeader->Mid(1)); - i += newHeader->GetCount() - 1; - - continue; - } - } - - if (isCStyle && !isalpha(prevCh) - && line.Mid(i, 8) == WString("operator") && !isalnum(line[i+8])) - { - isInOperator = true; - outBuffer.Cat(AS_OPERATOR.Mid(1)); - i += 7; - continue; - } - - // "new" operator is a pointer, not a calculation - if (!isalpha(prevCh) - && line.Mid(i, 3) == WString("new") && !isalnum(line[i+3])) - { - if (prevNonSpaceCh == '=' && isInStatement && !inStatementIndentStack->IsEmpty()) - inStatementIndentStack->back() = 0; - } - - if (ch == '?') - isInQuestion = true; - - - // special handling of 'case' statements - if (ch == ':') - { - if ((int) line.GetCount() > i + 1 && line[i+1] == ':') // look for :: - { - ++i; - outBuffer.Cat(':'); - ch = ' '; - continue; - } - - else if (isInQuestion) - { - isInQuestion = false; - } - - else if (isCStyle && isInClass && prevNonSpaceCh != ')') - { - --tabCount; - // found a 'private:' or 'public:' inside a class definition - // so do nothing special - } - - else if (!isJavaStyle && isInClassHeader) - { - // found a 'class A : public B' definition - // so do nothing special - } - - else if (isJavaStyle && lastLineHeader == &AS_FOR) - { - // found a java for-each statement - // so do nothing special - } - - else if (isCStyle && prevNonSpaceCh == ')') - { - isInClassHeader = true; - if (i == 0) - tabCount += 2; - } - else - { - currentNonSpaceCh = ';'; // so that brackets after the ':' will appear as block-openers - if (isInCase) - { - isInCase = false; - ch = ';'; // from here on, treat char as ';' - } - - - else // is in a label (e.g. 'label1:') - { - if (labelIndent) - --tabCount; // unindent label by one indent - else - tabCount = 0; // completely flush indent to left - } - - - - } - } - - if ((ch == ';' || (parenDepth > 0 && ch == ',')) && !inStatementIndentStackSizeStack->IsEmpty()) - while ((int) inStatementIndentStackSizeStack->back() + (parenDepth > 0 ? 1 : 0) - < (int) inStatementIndentStack->GetCount()) - inStatementIndentStack->pop_back(); - - - // handle ends of statements - if ((ch == ';' && parenDepth == 0) || ch == '}'/* || (ch == ',' && parenDepth == 0)*/) - { - if (ch == '}') - { - // first check if this '}' closes a previous block, or a static array... - if (!bracketBlockStateStack->IsEmpty()) - { - bool bracketBlockState = bracketBlockStateStack->back(); - bracketBlockStateStack->pop_back(); - if (!bracketBlockState) - { - if (!inStatementIndentStackSizeStack->IsEmpty()) - { - // this bracket is a static array - - int previousIndentStackSize = inStatementIndentStackSizeStack->back(); - inStatementIndentStackSizeStack->pop_back(); - while (previousIndentStackSize < (int) inStatementIndentStack->GetCount()) - inStatementIndentStack->pop_back(); - parenDepth--; - if (i == 0) - shouldIndentBrackettedLine = false; - - if (!parenIndentStack->IsEmpty()) - { - int poppedIndent = parenIndentStack->back(); - parenIndentStack->pop_back(); - if (i == 0) - spaceTabCount = poppedIndent; - } - } - continue; - } - } - - // this bracket is block closer... - - ++lineClosingBlocksNum; - - if (!inStatementIndentStackSizeStack->IsEmpty()) - inStatementIndentStackSizeStack->pop_back(); - - if (!blockParenDepthStack->IsEmpty()) - { - parenDepth = blockParenDepthStack->back(); - blockParenDepthStack->pop_back(); - isInStatement = blockStatementStack->back(); - blockStatementStack->pop_back(); - - if (isInStatement) - blockTabCount--; - } - - closingBracketReached = true; - int headerPlace = indexOf(*headerStack, &AS_OPEN_BRACKET); - if (headerPlace != -1) - { - const WString *popped = headerStack->back(); - while (popped != &AS_OPEN_BRACKET) - { - headerStack->pop_back(); - popped = headerStack->back(); - } - headerStack->pop_back(); - - if (!tempStacks->IsEmpty()) - { - Vector *temp = tempStacks->back(); - tempStacks->pop_back(); - delete temp; - } - } - - - ch = ' '; // needed due to cases such as '}else{', so that headers ('else' tn tih case) will be identified... - } - - /* - * Create a temporary snapshot of the current block's header-list in the - * uppermost inner stack in tempStacks, and clear the headerStack up to - * the begining of the block. - * Thus, the next future statement will think it comes one indent past - * the block's '{' unless it specifically checks for a companion-header - * (such as a previous 'if' for an 'else' header) within the tempStacks, - * and recreates the temporary snapshot by manipulating the tempStacks. - */ - if (!tempStacks->back()->IsEmpty()) - while (!tempStacks->back()->IsEmpty()) - tempStacks->back()->pop_back(); - while (!headerStack->IsEmpty() && headerStack->back() != &AS_OPEN_BRACKET) - { - tempStacks->back()->push_back(headerStack->back()); - headerStack->pop_back(); - } - - if (parenDepth == 0 && ch == ';') - isInStatement = false; - - previousLastLineHeader = NULL; - isInClassHeader = false; - isInQuestion = false; - - continue; - } - - - // check for preBlockStatements ONLY if not within parenthesies - // (otherwise 'struct XXX' statements would be wrongly interpreted...) - if (isWhiteSpace(prevCh) && !isInTemplate && parenDepth == 0) - { - const WString *newHeader = findHeader(line, i, preBlockStatements); - if (newHeader != NULL) - { - isInClassHeader = true; - outBuffer.Cat(newHeader->Mid(1)); - i += newHeader->GetCount() - 1; - headerStack->push_back(newHeader); - } - } - - // Handle operators - - immediatelyPreviousAssignmentOp = NULL; - - // Check if an operator has been reached. - const WString *foundAssignmentOp = findHeader(line, i, assignmentOperators, false); - if (foundAssignmentOp == &AS_RETURN) - foundAssignmentOp = findHeader(line, i, assignmentOperators, true); - const WString *foundNonAssignmentOp = findHeader(line, i, nonAssignmentOperators, false); - - // Since findHeader's boundry checking was not used above, it is possible - // that both an assignment op and a non-assignment op where found, - // e.g. '>>' and '>>='. If this is the case, treat the LONGER one as the - // found operator. - if (foundAssignmentOp != NULL && foundNonAssignmentOp != NULL) - if (foundAssignmentOp->GetCount() < foundNonAssignmentOp->GetCount()) - foundAssignmentOp = NULL; - else - foundNonAssignmentOp = NULL; - - if (foundNonAssignmentOp != NULL) - { - if (foundNonAssignmentOp->GetCount() > 1) - { - outBuffer.Cat(foundNonAssignmentOp->Mid(1)); - i += foundNonAssignmentOp->GetCount() - 1; - } - } - - else if (foundAssignmentOp != NULL) - { - if (foundAssignmentOp->GetCount() > 1) - { - outBuffer.Cat(foundAssignmentOp->Mid(1)); - i += foundAssignmentOp->GetCount() - 1; - } - - if (!isInOperator && !isInTemplate && !isNonInStatementArray) - { - registerInStatementIndent(line, i, spaceTabCount, 0, false); - immediatelyPreviousAssignmentOp = foundAssignmentOp; - isInStatement = true; - } - } - - if (isInOperator) - isInOperator = false; - } - - // handle special cases of unindentation: - - /* - * if '{' doesn't follow an immediately previous '{' in the headerStack - * (but rather another header such as "for" or "if", then unindent it - * by one indentation relative to its block. - */ - - if (!lineStartsInComment - && !blockIndent - && outBuffer.GetCount() > 0 - && outBuffer[0] == '{' - && !(lineOpeningBlocksNum > 0 && lineOpeningBlocksNum == lineClosingBlocksNum) - && !(headerStack->GetCount() > 1 && (*headerStack)[headerStack->GetCount()-2] == &AS_OPEN_BRACKET) - && shouldIndentBrackettedLine) - --tabCount; - - else if (!lineStartsInComment - && outBuffer.GetCount() > 0 - && outBuffer[0] == '}' - && shouldIndentBrackettedLine) - --tabCount; - - // correctly indent one-line-blocks... - else if (!lineStartsInComment - && outBuffer.GetCount() > 0 - && lineOpeningBlocksNum > 0 - && lineOpeningBlocksNum == lineClosingBlocksNum - && previousLineProbationTab) - --tabCount; //lineOpeningBlocksNum - (blockIndent ? 1 : 0); - - if (tabCount < 0) - tabCount = 0; - - // take care of extra bracket indentatation option... - if (bracketIndent && outBuffer.GetCount() > 0 && shouldIndentBrackettedLine) - if (outBuffer[0] == '{' || outBuffer[0] == '}') - tabCount++; - - - if (isInDefine) - { - if (outBuffer[0] == '#') - { - WString preproc = trim(outBuffer.Mid(1)); - - if (preproc.Mid(0, 6) == WString("define")) - { - if (!inStatementIndentStack->IsEmpty() - && inStatementIndentStack->back() > 0) - { - defineTabCount = tabCount; - } - else - { - defineTabCount = tabCount - 1; - tabCount--; - } - } - } - - tabCount -= defineTabCount; - } - - if (tabCount < 0) - tabCount = 0; - if (lineCommentNoBeautify || blockCommentNoBeautify) - tabCount = spaceTabCount = 0; - - // finally, insert indentations into begining of line - - prevFinalLineSpaceTabCount = spaceTabCount; - prevFinalLineTabCount = tabCount; - - if (shouldForceTabIndentation) - { - tabCount += spaceTabCount / indentLength; - spaceTabCount = spaceTabCount % indentLength; - } - - outBuffer = preLineWS(spaceTabCount, tabCount) + outBuffer; - - if (lastLineHeader != NULL) - previousLastLineHeader = lastLineHeader; - - return outBuffer; -} - - -WString ASBeautifier::preLineWS(int spaceTabCount, int tabCount) -{ - WString ws; - - for (int i = 0; i < tabCount; i++) - ws += indentString; - - while ((spaceTabCount--) > 0) - ws += WString(" "); - - return ws; - -} - -/** - * register an in-statement indent. - */ -void ASBeautifier::registerInStatementIndent(const WString &line, int i, int spaceTabCount, - int minIndent, bool updateParenStack) -{ - int inStatementIndent; - int remainingCharNum = line.GetCount() - i; - int nextNonWSChar = getNextProgramCharDistance(line, i); - - // if indent is around the last char in the line, indent instead 2 spaces from the previous indent - if (nextNonWSChar == remainingCharNum) - { - int previousIndent = spaceTabCount; - if (!inStatementIndentStack->IsEmpty()) - previousIndent = inStatementIndentStack->back(); - - inStatementIndentStack->push_back(/*2*/ indentLength + previousIndent); - if (updateParenStack) - parenIndentStack->push_back(previousIndent); - return; - } - - if (updateParenStack) - parenIndentStack->push_back(i + spaceTabCount); - - inStatementIndent = i + nextNonWSChar + spaceTabCount; - - if (i + nextNonWSChar < minIndent) - inStatementIndent = minIndent + spaceTabCount; - - if (i + nextNonWSChar > maxInStatementIndent) - inStatementIndent = indentLength * 2 + spaceTabCount; - - if (!inStatementIndentStack->IsEmpty() && - inStatementIndent < inStatementIndentStack->back()) - inStatementIndent = inStatementIndentStack->back(); - - if (isNonInStatementArray) - inStatementIndent = 0; - - inStatementIndentStack->push_back(inStatementIndent); -} - -/** - * get distance to the next non-white sspace, non-comment character in the line. - * if no such character exists, return the length remaining to the end of the line. - */ -int ASBeautifier::getNextProgramCharDistance(const WString &line, int i) -{ - bool inComment = false; - int remainingCharNum = line.GetCount() - i; - int charDistance; - char ch; - - for (charDistance = 1; charDistance < remainingCharNum; charDistance++) - { - ch = line[i + charDistance]; - if (inComment) - { - if (line.Mid(i + charDistance, 2) == WString("*/")) - { - charDistance++; - inComment = false; - } - continue; - } - else if (isWhiteSpace(ch)) - continue; - else if (ch == '/') - { - if (line.Mid(i + charDistance, 2) == WString("//")) - return remainingCharNum; - else if (line.Mid(i + charDistance, 2) == WString("/*")) - { - charDistance++; - inComment = true; - } - } - else - return charDistance; - } - - return charDistance; -} - - -/** - * check if a specific line position contains a header, out of several possible headers. - * - * @return a pointer to the found header. if no header was found then return NULL. - */ -const WString *ASBeautifier::findHeader(const WString &line, int i, const Vector &possibleHeaders, bool checkBoundry) -{ - int maxHeaders = possibleHeaders.GetCount(); - // const WString *header = NULL; - int p; - - for (p = 0; p < maxHeaders; p++) - { - const WString *header = possibleHeaders[p]; - - if (line.Mid(i, header->GetCount()) == *header) - { - // check that this is a header and not a part of a longer word - // (e.g. not at its begining, not at its middle...) - - int lineLength = line.GetCount(); - int headerEnd = i + header->GetCount(); - char startCh = (*header)[0]; // first char of header - char endCh = 0; // char just after header - char prevCh = 0; // char just before header - - if (headerEnd < lineLength) - { - endCh = line[headerEnd]; - } - if (i > 0) - { - prevCh = line[i-1]; - } - - if (!checkBoundry) - { - return header; - } - else if (prevCh != 0 - && isLegalNameChar(startCh) - && isLegalNameChar(prevCh)) - { - return NULL; - } - else if (headerEnd >= lineLength - || !isLegalNameChar(startCh) - || !isLegalNameChar(endCh)) - { - return header; - } - else - { - return NULL; - } - } - } - - return NULL; -} - -/** - * find the index number of a string element in a container of strings - * - * @return the index number of element in the ocntainer. -1 if element not found. - * @param container a vector of strings. - * @param element the element to find . - */ -int ASBeautifier::indexOf(Vector &container, const WString *element) -{ -/* Vector::const_iterator where; - where = find(container.begin(), container.end(), element); - - if (where == container.end()) - return -1; - else - return (int) (where - container.begin()); -*/ - - return FindIndex(container, element); -} - -/** - * trim removes the white space surrounding a line. - * - * @return the trimmed line. - * @param str the line to trim. - */ -WString ASBeautifier::trim(const WString &str) -{ - - int start = 0; - int end = str.GetCount() - 1; - - while (start < end && isWhiteSpace(str[start])) - start++; - - while (start <= end && isWhiteSpace(str[end])) - end--; - -// WString returnStr(str, start, end + 1 - start); -// return returnStr; - return str.Mid(start, end+1-start); -} - -/** -* peek at the next unread character. -* -* @return the next unread character. -* @param line the line to check. -* @param i the current char position on the line. -*/ -char ASBeautifier::peekNextChar(WString &line, int i) -{ - char ch = ' '; - int peekNum = ASString_Find_First_Not_Of(line, " \t", i + 1); - - if (peekNum < 0) - return ch; - - ch = line[peekNum]; - - return ch; -} - - -} // end namespace astyle diff --git a/uppdev/plugin/astyle/ASEnhancer.cpp b/uppdev/plugin/astyle/ASEnhancer.cpp deleted file mode 100644 index 44bb82fd3..000000000 --- a/uppdev/plugin/astyle/ASEnhancer.cpp +++ /dev/null @@ -1,489 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * - * ASEnhancer.cpp - * - * This file is a part of "Artistic Style" - an indentation and - * reformatting tool for C, C++, C# and Java source files. - * http://astyle.sourceforge.net - * - * The "Artistic Style" project, including all files needed to - * compile it, is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later - * version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this project; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - */ - - /* - 2008-01-26 Patches by Massimo Del Fedele : - - modified sources to use Ultimate++ containers instead std:: ones - - fixed memory leaks based on bug report 1804791 submitted by Eran Ifrah - - modified to work with unicode - */ -// can trace only if NDEBUG is not defined -#ifndef NDEBUG -// #define TRACEswitch -// #define TRACEcase -// #define TRACEmisc -#endif - -#include "astyle.h" - -#include -#include -#include - -#ifdef TRACEswitch -#define TRswitch(a,b) *traceOut << lineNumber << a << b << endl; -#else -#define TRswitch(a,b) ((void)0) -#endif // TRACEswitch -#ifdef TRACEcase -#define TRcase(a,b) *traceOut << lineNumber << a << b << endl; -#else -#define TRcase(a,b) ((void)0) -#endif // TRACEcase -#ifdef TRACEmisc -#define TRmisc(a) *traceOut << lineNumber << a << endl; -#else -#define TRmisc(a) ((void)0) -#endif // TRACEmisc - - -namespace astyle -{ - -// ---------------------------- functions for ASEnhancer Class ------------------------------------- - -/** - * ASEnhancer constructor - */ -ASEnhancer::ASEnhancer() -{ - // variables are initialized by init() - traceOut = new StringStream; -} - -/** - * Destructor of ASEnhancer - * Display the TRACE entries. - */ -ASEnhancer::~ASEnhancer() -{ -#if defined(TRACEswitch) || defined(TRACEcase) || defined(TRACEmisc) - WString line; - WString msg = "TRACE Entries\n\n"; - char countLine[50]; - int count = 0; - - while (getline(*traceOut, line)) - { - msg += line + '\n'; - count++; - } - sprintf(countLine, "\n%d Entries", count); - msg += countLine; - // write a text file to "My Documents" (Windows) - char filename [_MAX_PATH + _MAX_FNAME + _MAX_EXT + 1]; // full path and filename - strcpy(filename, getenv("USERPROFILE")); - strcat(filename, "\\My Documents\\tracee.txt"); - ofstream outfile(filename); - outfile << msg; - outfile.close(); -#endif - delete traceOut; -} - -/** - * initialize the ASEnhancer. - * - * init() is called each time an ASFormatter object is initialized. - */ -void ASEnhancer::init(int _indentLength, - WString _indentString, - bool _isCStyle, - bool _isJavaStyle, - bool _isSharpStyle, - bool _caseIndent, - bool _emptyLineFill) -{ - // formatting variables from ASFormatter and ASBeautifier - indentLength = _indentLength; - if (_indentString[0] == '\t') - useTabs = true; - else - useTabs = false; - isCStyle = _isCStyle; - isJavaStyle = _isJavaStyle; - isSharpStyle = _isSharpStyle; - caseIndent = _caseIndent; - emptyLineFill = _emptyLineFill; - - // unindent variables - lineNumber = 0; - bracketCount = 0; - isInComment = false; - isInQuote = false; - switchDepth = 0; - lookingForCaseBracket = false; - unindentNextLine = false; - -#if defined(TRACEswitch) || defined(TRACEcase) || defined(TRACEmisc) - *traceOut << "New file -------------" << endl; -#endif -} - -/** - * additional formatting for line of source code. - * every line of source code in a source code file should be sent - * one after the other to this function. - * indents event tables - * unindents the case blocks - * - * @param line the original formatted line will be updated if necessary. - */ -void ASEnhancer::enhance(WString &line) -{ - static Array swVector; // stack Vector of switch variables - static switchVariables sw; // switch variables struct - - static bool nextLineIsEventTable; // begin event table is reached - static bool isInEventTable; // need to indent an event table - - bool isSpecialChar = false; - int lineLength; // length of the line being parsed - - lineNumber++; - lineLength = line.GetCount(); - - // check for beginning of event table - if (nextLineIsEventTable) - { - isInEventTable = true; - nextLineIsEventTable = false; - } - - if (lineLength == 0 - && ! isInEventTable - && ! emptyLineFill) - return; - - // test for unindent on attached brackets - if (unindentNextLine) - { - sw.unindentDepth++; - sw.unindentCase = true; - unindentNextLine = false; - TRcase(" unindent case ", sw.unindentDepth); - } - - // parse characters in the current line. - - for (int i = 0; i < lineLength; i++) - { - char ch = line[i]; - - // bypass whitespace - if (isWhiteSpaceX(ch)) - continue; - - // handle special characters (i.e. backslash+character such as \n, \t, ...) - if (isSpecialChar) - { - isSpecialChar = false; - continue; - } - if (!(isInComment) && line.Mid(i, 2) == WString("\\\\")) - { - i++; - continue; - } - if (!(isInComment) && ch == '\\') - { - isSpecialChar = true; - continue; - } - - // handle quotes (such as 'x' and "Hello Dolly") - if (!(isInComment) && (ch == '"' || ch == '\'')) - if (!isInQuote) - { - quoteChar = ch; - isInQuote = true; - } - else if (quoteChar == ch) - { - isInQuote = false; - continue; - } - - if (isInQuote) - continue; - - // handle comments - - if (!(isInComment) && line.Mid(i, 2) == WString("//")) - { - // check for windows line markers -//@@ CHECK !!!! if (line.Mid(i + 2, 1) > WString("\xf0")) - if (line.Mid(i + 2, 1) > WString("\xf0") && line.Mid(i + 2, 1) > WString("\xff")) - lineNumber--; - break; // finished with the line - } - else if (!(isInComment) && line.Mid(i, 2) == WString("/*")) - { - isInComment = true; - i++; - continue; - } - else if ((isInComment) && line.Mid(i, 2) == WString("*/")) - { - isInComment = false; - i++; - continue; - } - - if (isInComment) - continue; - - // if we have reached this far then we are NOT in a comment or String of special characters - - if (line[i] == '{') // if open bracket - bracketCount++; - - if (line[i] == '}') // if close bracket - bracketCount--; - - // ---------------- process event tables -------------------------------------- - - // check for event table begin - if (findKeyword(line, i, "BEGIN_EVENT_TABLE") - || findKeyword(line, i, "BEGIN_MESSAGE_MAP")) - nextLineIsEventTable = true; - - // check for event table end - if (findKeyword(line, i, "END_EVENT_TABLE") - || findKeyword(line, i, "END_MESSAGE_MAP")) - isInEventTable = false; - - // ---------------- process switch statements --------------------------------- - - if (findKeyword(line, i, "switch")) // if switch statement - { - switchDepth++; // bump switch depth - TRswitch(" switch ", switchDepth); - swVector.push_back(sw); // save current variables - sw.switchBracketCount = 0; - sw.unindentCase = false; // don't clear case until end of switch - i += 5; // bypass switch statement - continue; - } - - // just want switch statements from this point - - if (caseIndent || switchDepth == 0) // from here just want switch statements - continue; // get next char - - if (line[i] == '{') // if open bracket - { - sw.switchBracketCount++; - if (lookingForCaseBracket) // if 1st after case statement - { - sw.unindentCase = true; // unindenting this case - sw.unindentDepth++; // bump depth - lookingForCaseBracket = false; // not looking now - TRcase(" unindent case ", sw.unindentDepth); - } - continue; - } - - lookingForCaseBracket = false; // no opening bracket, don't indent - - if (line[i] == '}') // if close bracket - { - sw.switchBracketCount--; - if (sw.switchBracketCount == 0) // if end of switch statement - { - TRswitch(" endsw ", switchDepth); - switchDepth--; // one less switch - sw = swVector.back(); // restore sw struct - swVector.pop_back(); // remove last entry from stack - } - continue; - } - - // look for case or default header - - if (findKeyword(line, i, "case") || findKeyword(line, i, "default")) - { - if (sw.unindentCase) // if unindented last case - { - sw.unindentCase = false; // stop unindenting previous case - sw.unindentDepth--; // reduce depth - } - for (; i < lineLength; i++) // bypass colon - { - if (line[i] == ':') - if ((i + 1 < lineLength) && (line[i + 1] == ':')) - i++; // bypass scope resolution operator - else - break; - } - i++; - for (; i < lineLength; i++) // bypass whitespace - { - if (!(isWhiteSpaceX(line[i]))) - break; - } - if (i < lineLength) // check for bracket - { - if (line[i] == '{') // if bracket found - { - sw.switchBracketCount++; - unindentNextLine = true; // start unindenting on next line - continue; - } - } - lookingForCaseBracket = true; // bracket must be on next line - i--; // need to check for comments - continue; - } - } // end of for loop - - if (isInEventTable) // if need to indent - indentLine(line, 1); // do it - - if (sw.unindentDepth > 0) // if need to unindent - unindentLine(line, sw.unindentDepth); // do it -} - -/** - * indent a line by a given number of tabsets - * by inserting leading whitespace to the line argument. - * - * @param line a pointer to the line to indent. - * @param unindent the number of tabsets to insert. - * @return the number of characters inserted. - */ -int ASEnhancer::indentLine(WString &line, const int indent) const -{ - if (line.GetCount() == 0 - && ! emptyLineFill) - return 0; - - int charsToInsert; // number of chars to insert - - if (useTabs) // if formatted with tabs - { - charsToInsert = indent; // tabs to insert - line.Insert(0, WString('\t', charsToInsert)); // insert the tabs - } - else - { - charsToInsert = indent * indentLength; // compute chars to insert - line.Insert(0, WString('\t', charsToInsert)); // insert the tabs - } - - return charsToInsert; -} - -/** - * unindent a line by a given number of tabsets - * by erasing the leading whitespace from the line argument. - * - * @param line a pointer to the line to unindent. - * @param unindent the number of tabsets to erase. - * @return the number of characters erased. - */ -int ASEnhancer::unindentLine(WString &line, const int unindent) const -{ - int whitespace = ASString_Find_First_Not_Of(line, " \t"); - if (whitespace == -1) // if line is blank - whitespace = line.GetCount(); // must remove padding, if any - - if (whitespace == 0) - return 0; - - int charsToErase; // number of chars to erase - - if (useTabs) // if formatted with tabs - { - charsToErase = unindent; // tabs to erase - if (charsToErase <= whitespace) // if there is enough whitespace - line.Remove(0, charsToErase); // erase the tabs - else - charsToErase = 0; - } - else - { - charsToErase = unindent * indentLength; // compute chars to erase - if (charsToErase <= whitespace) // if there is enough whitespace - line.Remove(0, charsToErase); // erase the spaces - else - charsToErase = 0; - } - - return charsToErase; -} - -/** - * check if a specific line position contains a keyword. - * - * @return true if the word was found. false if the word was not found. - */ -bool ASEnhancer::findKeyword(const WString &line, int i, const char *keyword) const -{ - if (line.Mid(i, strlen(keyword)) == WString(keyword)) - { - // check that this is a header and not a part of a longer word - // (e.g. not at its begining, not at its middle...) - - int lineLength = line.GetCount(); - int wordEnd = i + strlen(keyword); - char startCh = keyword[0]; // first char of header - char endCh = 0; // char just after header - char prevCh = 0; // char just before header - - if (wordEnd < lineLength) - { - endCh = line[wordEnd]; - } - if (i > 0) - { - prevCh = line[i-1]; - } - - if (prevCh != 0 - && isLegalNameCharX(startCh) - && isLegalNameCharX(prevCh)) - { - return false; - } - else if (wordEnd >= lineLength - || !isLegalNameCharX(startCh) - || !isLegalNameCharX(endCh)) - { - return true; - } - else - { - return false; - } - } - - return false; -} - -} // end namespace astyle diff --git a/uppdev/plugin/astyle/ASFormatter.cpp b/uppdev/plugin/astyle/ASFormatter.cpp deleted file mode 100644 index d36ed7d60..000000000 --- a/uppdev/plugin/astyle/ASFormatter.cpp +++ /dev/null @@ -1,2204 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * - * ASFormatter.cpp - * - * This file is a part of "Artistic Style" - an indentation and - * reformatting tool for C, C++, C# and Java source files. - * http://astyle.sourceforge.net - * - * The "Artistic Style" project, including all files needed to - * compile it, is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later - * version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this project; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - */ - - /* - 2008-01-26 Patches by Massimo Del Fedele : - - modified sources to use Ultimate++ containers instead std:: ones - - fixed memory leaks based on bug report 1804791 submitted by Eran Ifrah - - modified to work with unicode - */ -#include "astyle.h" - -#include -#include -#include -#ifdef __VMS -#include -#else -#include -#endif - -// can trace only if NDEBUG is not defined -#ifndef NDEBUG -// #define TRACEunpad -// #define TRACEcomment -// #define TRACEheader -// #define TRACEbracket -// #define TRACEarray -#if defined(TRACEunpad) || defined(TRACEcomment) || defined(TRACEheader) \ -|| defined(TRACEbracket) || defined(TRACEarray) -ofstream *traceOutF; -#define TRACEF -#endif -#endif - -#ifdef TRACEunpad -#define TRunpad(a,b,c) if(b > 0 || c > 0) *traceOutF << outLineNumber << " " << b << a << c << endl -#else -#define TRunpad(a,b,c) ((void)0) -#endif - -#ifdef TRACEcomment -#define TRcomment(a) *traceOutF << outLineNumber << " " << a << endl -#else -#define TRcomment(a) ((void)0) -#endif - -#ifdef TRACEheader -#define TRxtra(a) *traceOutF << outLineNumber << " " << a << endl -#else -#define TRxtra(a) ((void)0) -#endif - -#ifdef TRACEbracket -#define TRbracket(a) *traceOutF << outLineNumber << " " << a << endl -#else -#define TRbracket(a) ((void)0) -#endif - -#ifdef TRACEarray -#define TRarray(a) *traceOutF << outLineNumber << " " << a << endl -#else -#define TRarray(a) ((void)0) -#endif - -#define INIT_CONTAINER(container, value) {if ( (container) != NULL ) delete (container); (container) = (value); } -#define DELETE_CONTAINER(container) {if ( (container) != NULL ) delete (container); } -#define IS_A(a,b) ( ((a) & (b)) == (b)) - -using namespace std; - -namespace astyle -{ -Vector ASFormatter::headers; -Vector ASFormatter::nonParenHeaders; -Vector ASFormatter::preDefinitionHeaders; -Vector ASFormatter::preCommandHeaders; -Vector ASFormatter::operators; -Vector ASFormatter::assignmentOperators; -Vector ASFormatter::castOperators; - -/** - * Constructor of ASFormatter - */ -ASFormatter::ASFormatter() -{ - preBracketHeaderStack = NULL; - bracketTypeStack = NULL; - parenStack = NULL; - lineCommentNoIndent = false; - sourceIterator = NULL; - bracketFormatMode = NONE_MODE; - shouldPadOperators = false; - shouldPadParensOutside = false; - shouldPadParensInside = false; - shouldUnPadParens = false; - shouldBreakOneLineBlocks = true; - shouldBreakOneLineStatements = true; - shouldConvertTabs = false; - shouldBreakBlocks = false; - shouldBreakClosingHeaderBlocks = false; - shouldBreakClosingHeaderBrackets = false; - shouldBreakElseIfs = false; -#ifdef TRACEF - // create a trace text file - WString filename = "tracef.txt"; - char* env = getenv("HOME"); - if (env != NULL) - filename = WString(env) + WString("/tracef.txt"); - else - { - env = getenv("USERPROFILE"); - if (env != NULL) - filename = WString(env) + WString("\\My Documents\\tracef.txt"); - else - { - cout << "\nCould not open tracef.txt\n" << endl; - exit(1); - } - } - traceOutF = new ofstream(filename.c_str()); -#endif -} - -/** - * Destructor of ASFormatter - */ -ASFormatter::~ASFormatter() -{ - DELETE_CONTAINER(preBracketHeaderStack); - DELETE_CONTAINER(bracketTypeStack); - DELETE_CONTAINER(parenStack); -#ifdef TRACEF - delete traceOutF; -#endif -} - -/** - * initialization of static data of ASFormatter. - */ -void ASFormatter::staticInit() -{ - static int formatterFileType = 9; // initialized with an invalid type - - if (fileType == formatterFileType) // don't build unless necessary - return; - - formatterFileType = fileType; - - headers.clear(); - nonParenHeaders.clear(); - assignmentOperators.clear(); - operators.clear(); - preDefinitionHeaders.clear(); - preCommandHeaders.clear(); - castOperators.clear(); - - ASResource::buildHeaders(headers, fileType); - ASResource::buildNonParenHeaders(nonParenHeaders, fileType); - ASResource::buildAssignmentOperators(assignmentOperators); - ASResource::buildOperators(operators); - ASResource::buildPreDefinitionHeaders(preDefinitionHeaders); - ASResource::buildPreCommandHeaders(preCommandHeaders); - ASResource::buildCastOperators(castOperators); -} - -/** - * initialize the ASFormatter. - * - * init() should be called every time a ASFormatter object is to start - * formatting a NEW source file. - * init() recieves a pointer to a DYNAMICALLY CREATED ASSourceIterator object - * that will be used to iterate through the source code. This object will be - * deleted during the ASFormatter's destruction, and thus should not be - * deleted elsewhere. - * - * @param iter a pointer to the DYNAMICALLY CREATED ASSourceIterator object. - */ -void ASFormatter::init(ASSourceIterator *si) -{ - staticInit(); - - ASBeautifier::init(si); - ASEnhancer::init(ASBeautifier::getIndentLength(), - ASBeautifier::getIndentString(), - ASBeautifier::getCStyle(), - ASBeautifier::getJavaStyle(), - ASBeautifier::getSharpStyle(), - ASBeautifier::getCaseIndent(), - ASBeautifier::getEmptyLineFill()); - sourceIterator = si; - - INIT_CONTAINER(preBracketHeaderStack, new Vector); - INIT_CONTAINER(bracketTypeStack, new Vector); - bracketTypeStack->push_back(NULL_TYPE); - INIT_CONTAINER(parenStack, new Vector); - parenStack->push_back(0); - - currentHeader = NULL; - currentLine = WString(""); - readyFormattedLine = WString(""); - formattedLine = ""; - currentChar = ' '; - previousChar = ' '; - previousCommandChar = ' '; - previousNonWSChar = ' '; - quoteChar = '"'; - charNum = 0; - spacePadNum = 0; - previousReadyFormattedLineLength = -1; - templateDepth = 0; - previousBracketType = NULL_TYPE; - previousOperator = NULL; - - isVirgin = true; - isInLineComment = false; - isInComment = false; - isInPreprocessor = false; - doesLineStartComment = false; - isInQuote = false; - isSpecialChar = false; - isNonParenHeader = true; - foundNamespaceHeader = false; - foundClassHeader = false; - foundPreDefinitionHeader = false; - foundPreCommandHeader = false; - foundCastOperator = false; - foundQuestionMark = false; - isInLineBreak = false; - endOfCodeReached = false; - isLineReady = false; - isPreviousBracketBlockRelated = true; - isInPotentialCalculation = false; - shouldReparseCurrentChar = false; - passedSemicolon = false; - passedColon = false; - isInTemplate = false; - isInBlParen = false; - shouldBreakLineAfterComments = false; - isImmediatelyPostComment = false; - isImmediatelyPostLineComment = false; - isImmediatelyPostEmptyBlock = false; - isImmediatelyPostPreprocessor = false; - - isPrependPostBlockEmptyLineRequested = false; - isAppendPostBlockEmptyLineRequested = false; - prependEmptyLine = false; - appendOpeningBracket = false; - - foundClosingHeader = false; - previousReadyFormattedLineLength = 0; - - isImmediatelyPostHeader = false; - isInHeader = false; -#ifdef TRACEF - // fileName will be empty if ASTYLE_LIB is defined - if (fileName.empty()) - *traceOutF << "new file" << endl; - else - *traceOutF << fileName << endl; -#endif -} - -/** - * get the next formatted line. - * - * @return formatted line. - */ - -WString ASFormatter::nextLine() -{ - // these are reset with each new line - const WString *newHeader; - bool isInVirginLine = isVirgin; - isCharImmediatelyPostComment = false; - isPreviousCharPostComment = false; - isCharImmediatelyPostLineComment = false; - isCharImmediatelyPostOpenBlock = false; - isCharImmediatelyPostCloseBlock = false; - isCharImmediatelyPostTemplate = false; - - while (!isLineReady) - { - if (shouldReparseCurrentChar) - shouldReparseCurrentChar = false; - else if (!getNextChar()) - { - breakLine(); - return beautify(readyFormattedLine); - } - else // stuff to do when reading a new character... - { - // make sure that a virgin '{' at the begining ofthe file will be treated as a block... - if (isInVirginLine && currentChar == '{') - previousCommandChar = '{'; - isPreviousCharPostComment = isCharImmediatelyPostComment; - isCharImmediatelyPostComment = false; - isCharImmediatelyPostTemplate = false; - } - - //if (inLineNumber >= 185) - // int x = 1; - - if (isInLineComment) - { - appendCurrentChar(); - - // explicitely break a line when a line comment's end is found. - if (charNum + 1 == (int) currentLine.GetCount()) - { - isInLineBreak = true; - isInLineComment = false; - isImmediatelyPostLineComment = true; - currentChar = 0; //make sure it is a neutral char. - } - continue; - } - else if (isInComment) - { - if (isSequenceReached("*/")) - { - isInComment = false; - isImmediatelyPostComment = true; - appendSequence(AS_CLOSE_COMMENT); - goForward(1); - } - else - appendCurrentChar(); - - continue; - } - - // not in line comment or comment - - else if (isInQuote) - { - if (isSpecialChar) - { - isSpecialChar = false; - appendCurrentChar(); - } - else if (currentChar == '\\') - { - isSpecialChar = true; - appendCurrentChar(); - } - else if (quoteChar == currentChar) - { - isInQuote = false; - appendCurrentChar(); - } - else - { - appendCurrentChar(); - } - - continue; - } - - // handle white space - needed to simplify the rest. - if (isWhiteSpace(currentChar) || isInPreprocessor) - { - appendCurrentChar(); - continue; - } - - /* not in MIDDLE of quote or comment or white-space of any type ... */ - - if (isSequenceReached("//")) - { - if (currentLine[charNum+2] == '\xf2') // check for windows line marker - isAppendPostBlockEmptyLineRequested = false; - isInLineComment = true; - // do not indent if in column 1 or 2 - if (lineCommentNoIndent == false) - { - if (charNum == 0) - lineCommentNoIndent = true; - else if (charNum == 1 && currentLine[0] == ' ') - lineCommentNoIndent = true; - } - // move comment if spaces were added or deleted - if (lineCommentNoIndent == false && spacePadNum != 0) - adjustComments(); - formattedLineCommentNum = formattedLine.GetCount(); - appendSequence(AS_OPEN_LINE_COMMENT); - goForward(1); - // explicitely break a line when a line comment's end is found. - if (charNum + 1 == (int) currentLine.GetCount()) - { - isInLineBreak = true; - isInLineComment = false; - isImmediatelyPostLineComment = true; - currentChar = 0; //make sure it is a neutral char. - } - continue; - } - else if (isSequenceReached("/*")) - { - isInComment = true; - if (spacePadNum != 0) - adjustComments(); - formattedLineCommentNum = formattedLine.GetCount(); - appendSequence(AS_OPEN_COMMENT); - goForward(1); - continue; - } - else if (currentChar == '"' || currentChar == '\'') - { - isInQuote = true; - quoteChar = currentChar; - appendCurrentChar(); - continue; - } - - /* not in quote or comment or white-space of any type ... */ - - // check if in preprocessor - // ** isInPreprocessor will be automatically reset at the begining - // of a new line in getnextChar() - if (currentChar == '#') - { - isInPreprocessor = true; - appendCurrentChar(); - continue; - } - - /* not in preprocessor ... */ - - if (isImmediatelyPostComment) - { - isImmediatelyPostComment = false; - isCharImmediatelyPostComment = true; - } - - if (isImmediatelyPostLineComment) - { - isImmediatelyPostLineComment = false; - isCharImmediatelyPostLineComment = true; - } - - if (shouldBreakLineAfterComments) - { - shouldBreakLineAfterComments = false; - shouldReparseCurrentChar = true; - breakLine(); - continue; - } - - // reset isImmediatelyPostHeader information - if (isImmediatelyPostHeader) - { - isImmediatelyPostHeader = false; - - // Make sure headers are broken from their succeeding blocks - // (e.g. - // if (isFoo) DoBar(); - // should become - // if (isFoo) - // DoBar; - // ) - // But treat else if() as a special case which should not be broken! - if (shouldBreakOneLineStatements) - { - // if may break 'else if()'s, then simply break the line - - if (shouldBreakElseIfs) - isInLineBreak = true; - } - } - - if (passedSemicolon) // need to break the formattedLine - { - passedSemicolon = false; - if (parenStack->back() == 0 && currentChar != ';') // allow ;; - { - // does a one-line statement have ending comments? - if (IS_A(bracketTypeStack->back(), SINGLE_LINE_TYPE)) - { - int blockEnd = ASString_ReverseFind(currentLine, AS_CLOSE_BRACKET); - assert(blockEnd != -1); - - // move ending comments to this formattedLine - if (isBeforeLineEndComment(blockEnd)) - { - int commentStart = ASString_Find_First_Not_Of(currentLine, " \t", blockEnd + 1); - assert(commentStart != -1); - assert((currentLine.Mid(commentStart, 2) == WString("//")) - || (currentLine.Mid(commentStart, 2) == WString("/*"))); - int commentLength = currentLine.GetCount() - commentStart; - int tabCount = getIndentLength(); - appendSpacePad(); - for (int i=1; iback() == 0 && !isBeforeComment()) - { - shouldReparseCurrentChar = true; - isInLineBreak = true; - continue; - } - } - - // Check if in template declaration, e.g. foo or foo - // If so, set isInTemplate to true - if (!isInTemplate && currentChar == '<') - { - int maxTemplateDepth = 0; - templateDepth = 0; - const WString *oper; - for (int i = charNum; - i < currentLine.GetCount(); - i += (oper ? oper->GetCount() : 1)) - { - oper = ASBeautifier::findHeader(currentLine, i, operators); - - if (oper == &AS_LS) - { - templateDepth++; - maxTemplateDepth++; - } - else if (oper == &AS_GR) - { - templateDepth--; - if (templateDepth == 0) - { - // this is a template! - isInTemplate = true; - templateDepth = maxTemplateDepth; - break; - } - } - else if (oper == &AS_COMMA // comma, e.g. A - || oper == &AS_BIT_AND // reference, e.g. A - || oper == &AS_MULT // pointer, e.g. A - || oper == &AS_COLON_COLON) // ::, e.g. std::string - { - continue; - } - else if (!isLegalNameChar(currentLine[i]) && !isWhiteSpace(currentLine[i])) - { - // this is not a template -> leave... - isInTemplate = false; - break; - } - } - } - - // handle parenthesies - if (currentChar == '(' || currentChar == '[' || (isInTemplate && currentChar == '<')) - { - parenStack->back()++; - if (currentChar == '[') - isInBlParen = true; - } - else if (currentChar == ')' || currentChar == ']' || (isInTemplate && currentChar == '>')) - { - parenStack->back()--; - if (isInTemplate && currentChar == '>') - { - templateDepth--; - if (templateDepth == 0) - { - isInTemplate = false; - isCharImmediatelyPostTemplate = true; - } - } - - // check if this parenthesis closes a header, e.g. if (...), while (...) - if (isInHeader && parenStack->back() == 0) - { - isInHeader = false; - isImmediatelyPostHeader = true; - } - if (currentChar == ']') - isInBlParen = false; - if (currentChar == ')') - foundCastOperator = false; - } - - // handle brackets - if (currentChar == '{' || currentChar == '}') - { - if (currentChar == '{') - { - BracketType newBracketType = getBracketType(); - foundNamespaceHeader = false; - foundClassHeader = false; - foundPreDefinitionHeader = false; - foundPreCommandHeader = false; - isInPotentialCalculation = false; - - bracketTypeStack->push_back(newBracketType); - preBracketHeaderStack->push_back(currentHeader); - currentHeader = NULL; - - isPreviousBracketBlockRelated = !IS_A(newBracketType, ARRAY_TYPE); - } - - // this must be done before the bracketTypeStack is popped - BracketType bracketType = bracketTypeStack->back(); - bool isOpeningArrayBracket = (IS_A(bracketType, ARRAY_TYPE) - && bracketTypeStack->size() >= 2 - && !IS_A((*bracketTypeStack)[bracketTypeStack->size()-2], ARRAY_TYPE) - ); - - if (currentChar == '}') - { - // if a request has been made to append a post block empty line, - // but the block exists immediately before a closing bracket, - // then there is not need for the post block empty line. - // - isAppendPostBlockEmptyLineRequested = false; - - if (!bracketTypeStack->IsEmpty()) - { - previousBracketType = bracketTypeStack->back(); - bracketTypeStack->pop_back(); - isPreviousBracketBlockRelated = !IS_A(bracketType, ARRAY_TYPE); - } - - if (!preBracketHeaderStack->IsEmpty()) - { - currentHeader = preBracketHeaderStack->back(); - preBracketHeaderStack->pop_back(); - } - else - currentHeader = NULL; - } - - // format brackets - if (IS_A(bracketType, ARRAY_TYPE)) - formatArrayBrackets(bracketType, isOpeningArrayBracket); - else - formatBrackets(bracketType); - continue; - } - - if (((previousCommandChar == '{' && isPreviousBracketBlockRelated) - || (previousCommandChar == '}' - && bracketFormatMode != NONE_MODE - && !isImmediatelyPostEmptyBlock - && isPreviousBracketBlockRelated - && !isPreviousCharPostComment // Fixes wrongly appended newlines after '}' immediately after comments - && peekNextChar() != ' ' - && !IS_A(previousBracketType, DEFINITION_TYPE) - && !(ASBeautifier::isJavaStyle && currentChar == ')')) - && !IS_A(bracketTypeStack->back(), DEFINITION_TYPE)) - && (shouldBreakOneLineBlocks - || !IS_A(bracketTypeStack->back(), SINGLE_LINE_TYPE))) - { - isCharImmediatelyPostOpenBlock = (previousCommandChar == '{'); - isCharImmediatelyPostCloseBlock = (previousCommandChar == '}'); - - //if (bracketFormatMode != NONE_MODE) - //{ - previousCommandChar = ' '; - isInLineBreak = true; - //} - } - - // reset block handling flags - isImmediatelyPostEmptyBlock = false; - - // look for headers - if (!isInTemplate) - { - if ((newHeader = findHeader(headers)) != NULL) - { - foundClosingHeader = false; - const WString *previousHeader; - - // recognize closing headers of do..while, if..else, try..catch..finally - if ((newHeader == &AS_ELSE && currentHeader == &AS_IF) - || (newHeader == &AS_WHILE && currentHeader == &AS_DO) - || (newHeader == &AS_CATCH && currentHeader == &AS_TRY) - || (newHeader == &AS_CATCH && currentHeader == &AS_CATCH) - || (newHeader == &AS_FINALLY && currentHeader == &AS_TRY) - || (newHeader == &AS_FINALLY && currentHeader == &AS_CATCH)) - foundClosingHeader = true; - - previousHeader = currentHeader; - currentHeader = newHeader; - - // If in ATTACH or LINUX bracket modes, attach closing headers (e.g. 'else', 'catch') - // to their preceding bracket, - // But do not perform the attachment if the shouldBreakClosingHeaderBrackets is set! - if (!shouldBreakClosingHeaderBrackets - && foundClosingHeader - && (bracketFormatMode == ATTACH_MODE || bracketFormatMode == BDAC_MODE) - && (shouldBreakOneLineBlocks || !IS_A(previousBracketType, SINGLE_LINE_TYPE)) - && previousNonWSChar == '}') - { - spacePadNum = 0; // don't count as padding - - int firstChar = ASString_Find_First_Not_Of(formattedLine, " \t"); - - if (firstChar >= 0) // if a blank line does not preceed this - { - isInLineBreak = false; - appendSpacePad(); - } - - if (shouldBreakBlocks) - isAppendPostBlockEmptyLineRequested = false; - } - - // If NONE bracket mode, leave closing headers as they are (e.g. 'else', 'catch') - if (foundClosingHeader && bracketFormatMode == NONE_MODE && previousCommandChar == '}') - { - if (lineBeginsWith('}')) // is closing bracket broken? - { - isInLineBreak = false; - appendSpacePad(); - } - - if (shouldBreakBlocks) - isAppendPostBlockEmptyLineRequested = false; - } - - if (foundClosingHeader && bracketFormatMode == BREAK_MODE && previousCommandChar == '}') - breakLine(); - - //Check if a template definition as been reached, e.g. template - //if (newHeader == &AS_TEMPLATE) - //{ - // isInTemplate = true; - //} - - // check if the found header is non-paren header - isNonParenHeader = (find(nonParenHeaders.begin(), nonParenHeaders.end(), - newHeader) != nonParenHeaders.end()); - - appendSequence(*currentHeader); - goForward(currentHeader->GetCount() - 1); - // if a paren-header is found add a space after it, if needed - // this checks currentLine, appendSpacePad() checks formattedLine - if (!isNonParenHeader && charNum < (int) currentLine.GetCount() && !isWhiteSpace(currentLine[charNum+1])) - appendSpacePad(); - - // Signal that a header has been reached - // *** But treat a closing while() (as in do...while) - // as if it where NOT a header since a closing while() - // should never have a block after it! - if (!(foundClosingHeader && currentHeader == &AS_WHILE)) - { - isInHeader = true; - if (isNonParenHeader) - { - isImmediatelyPostHeader = true; - isInHeader = false; - } - } - - if (currentHeader == &AS_IF && previousHeader == &AS_ELSE) - isInLineBreak = false; - - if (shouldBreakBlocks) - { - if (previousHeader == NULL - && !foundClosingHeader - && !isCharImmediatelyPostOpenBlock) - { - isPrependPostBlockEmptyLineRequested = true; - } - - if (currentHeader == &AS_ELSE - || currentHeader == &AS_CATCH - || currentHeader == &AS_FINALLY - || foundClosingHeader) - { - isPrependPostBlockEmptyLineRequested = false; - } - - if (shouldBreakClosingHeaderBlocks - && isCharImmediatelyPostCloseBlock) - { - isPrependPostBlockEmptyLineRequested = true; - } - - } - - continue; - } - else if ((newHeader = findHeader(preDefinitionHeaders)) != NULL - && parenStack->back() == 0) - { - if (newHeader == &AS_NAMESPACE) - foundNamespaceHeader = true; - if (newHeader == &AS_CLASS) - foundClassHeader = true; - foundPreDefinitionHeader = true; - appendSequence(*newHeader); - goForward(newHeader->GetCount() - 1); - - if (shouldBreakBlocks) - isPrependPostBlockEmptyLineRequested = true; - - continue; - } - else if ((newHeader = findHeader(preCommandHeaders)) != NULL) - { - if (ASBeautifier::isJavaStyle - || (*newHeader == AS_CONST && previousCommandChar == ')') // 'const' member functions is a command bracket - || *newHeader == AS_EXTERN) - foundPreCommandHeader = true; - appendSequence(*newHeader); - goForward(newHeader->GetCount() - 1); - - continue; - } - else if ((newHeader = findHeader(castOperators)) != NULL) - { - foundCastOperator = true; - appendSequence(*newHeader); - goForward(newHeader->GetCount() - 1); - - continue; - } - - } - - if (isInLineBreak) // OK to break line here - breakLine(); - - if (previousNonWSChar == '}' || currentChar == ';') - { - if (shouldBreakOneLineStatements && currentChar == ';' - && (shouldBreakOneLineBlocks || !IS_A(bracketTypeStack->back(), SINGLE_LINE_TYPE)) - //&& (! bracketFormatMode == NONE_MODE) - ) - { - passedSemicolon = true; - } - - if (shouldBreakBlocks && currentHeader != NULL && parenStack->back() == 0) - { - isAppendPostBlockEmptyLineRequested = true; - } - - if (currentChar != ';') - currentHeader = NULL; - - foundQuestionMark = false; - foundNamespaceHeader = false; - foundClassHeader = false; - foundPreDefinitionHeader = false; - foundPreCommandHeader = false; - foundCastOperator = false; - isInPotentialCalculation = false; - isNonInStatementArray = false; - } - - if (currentChar == ':' - && shouldBreakOneLineStatements - && !foundQuestionMark // not in a ... ? ... : ... sequence - && !foundPreDefinitionHeader // not in a definition block (e.g. class foo : public bar - && previousCommandChar != ')' // not immediately after closing paren of a method header, e.g. ASFormatter::ASFormatter(...) : ASBeautifier(...) - && previousChar != ':' // not part of '::' - && peekNextChar() != ':') // not part of '::' - { - passedColon = true; - if (shouldBreakBlocks) - isPrependPostBlockEmptyLineRequested = true; - } - - if (currentChar == '?') - foundQuestionMark = true; - - // determine if this is a potential calculation - newHeader = findHeader(operators); - - if (newHeader != NULL) - { - if (!isInPotentialCalculation) - { - if (find(assignmentOperators.begin(), assignmentOperators.end(), newHeader) - != assignmentOperators.end()) - { - char peekedChar = peekNextChar(); - isInPotentialCalculation = (newHeader != &AS_RETURN - && !(newHeader == &AS_EQUAL && peekedChar == '*') - && !(newHeader == &AS_EQUAL && peekedChar == '&')); - } - } - } - else - { - // the following are not calculations - if (currentLine.Mid(charNum, 3) == WString("new") && !isLegalNameChar(currentLine[charNum+3])) - isInPotentialCalculation = false; - } - - if (shouldPadOperators && newHeader != NULL) - { - padOperators(newHeader); - continue; - } - - if ((shouldPadParensOutside || shouldPadParensInside || shouldUnPadParens) - && (currentChar == '(' || currentChar == ')')) - { - padParens(); - continue; - } - - appendCurrentChar(); - } // end of while loop * end of while loop * end of while loop * end of while loop - - // return a beautified (i.e. correctly indented) line. - - WString beautifiedLine; - int readyFormattedLineLength = trim(readyFormattedLine).GetCount(); - - if (prependEmptyLine // prepend a blank line before this formatted line - && readyFormattedLineLength > 0 - && previousReadyFormattedLineLength > 0) - { - isLineReady = true; // signal that a readyFormattedLine is still waiting - beautifiedLine = beautify(""); - previousReadyFormattedLineLength = 0; - } - else // format the current formatted line - { - isLineReady = false; - beautifiedLine = beautify(readyFormattedLine); - previousReadyFormattedLineLength = readyFormattedLineLength; - lineCommentNoBeautify = lineCommentNoIndent; - lineCommentNoIndent = false; - if (appendOpeningBracket) // insert bracket after this formatted line - { - appendOpeningBracket = false; - isLineReady = true; // signal that a readyFormattedLine is still waiting - readyFormattedLine = "{"; - isPrependPostBlockEmptyLineRequested = false; // next line should not be empty - } - } - - prependEmptyLine = false; - enhance(beautifiedLine); // call the enhancer function - return beautifiedLine; -} - - -/** -* check if there are any indented lines ready to be read by nextLine() -* -* @return are there any indented lines ready? -*/ -bool ASFormatter::hasMoreLines() const -{ - return !endOfCodeReached; -} - -/** - * set the bracket formatting mode. - * options: - * astyle::NONE_MODE no formatting of brackets. - * astyle::ATTACH_MODE Java, K&R style bracket placement. - * astyle::BREAK_MODE ANSI C/C++ style bracket placement. - * - * @param mode the bracket formatting mode. - */ -void ASFormatter::setBracketFormatMode(BracketMode mode) -{ - bracketFormatMode = mode; -} - -/** - * set closing header bracket breaking mode - * options: - * true brackets just before closing headers (e.g. 'else', 'catch') - * will be broken, even if standard brackets are attached. - * false closing header brackets will be treated as standard brackets. - * - * @param state the closing header bracket breaking mode. - */ -void ASFormatter::setBreakClosingHeaderBracketsMode(bool state) -{ - shouldBreakClosingHeaderBrackets = state; -} - -/** - * set 'else if()' breaking mode - * options: - * true 'else' headers will be broken from their succeeding 'if' headers. - * false 'else' headers will be attached to their succeeding 'if' headers. - * - * @param state the 'else if()' breaking mode. - */ -void ASFormatter::setBreakElseIfsMode(bool state) -{ - shouldBreakElseIfs = state; -} - -/** - * set operator padding mode. - * options: - * true statement operators will be padded with spaces around them. - * false statement operators will not be padded. - * - * @param state the padding mode. - */ -void ASFormatter::setOperatorPaddingMode(bool state) -{ - shouldPadOperators = state; -} - -/** -* set parenthesis outside padding mode. -* options: -* true statement parenthesiss will be padded with spaces around them. -* false statement parenthesiss will not be padded. -* -* @param state the padding mode. -*/ -void ASFormatter::setParensOutsidePaddingMode(bool state) -{ - shouldPadParensOutside = state; -} - -/** -* set parenthesis inside padding mode. -* options: -* true statement parenthesis will be padded with spaces around them. -* false statement parenthesis will not be padded. -* -* @param state the padding mode. -*/ -void ASFormatter::setParensInsidePaddingMode(bool state) -{ - shouldPadParensInside = state; -} - -/** -* set parenthesis unpadding mode. -* options: -* true statement parenthesis will be unpadded with spaces removed around them. -* false statement parenthesis will not be unpadded. -* -* @param state the padding mode. -*/ -void ASFormatter::setParensUnPaddingMode(bool state) -{ - shouldUnPadParens = state; -} - -/** - * set option to break/not break one-line blocks - * - * @param state true = break, false = don't break. - */ -void ASFormatter::setBreakOneLineBlocksMode(bool state) -{ - shouldBreakOneLineBlocks = state; -} - -/** - * set option to break/not break lines consisting of multiple statements. - * - * @param state true = break, false = don't break. - */ -void ASFormatter::setSingleStatementsMode(bool state) -{ - shouldBreakOneLineStatements = state; -} - -/** - * set option to convert tabs to spaces. - * - * @param state true = convert, false = don't convert. - */ -void ASFormatter::setTabSpaceConversionMode(bool state) -{ - shouldConvertTabs = state; -} - - -/** - * set option to break unrelated blocks of code with empty lines. - * - * @param state true = convert, false = don't convert. - */ -void ASFormatter::setBreakBlocksMode(bool state) -{ - shouldBreakBlocks = state; -} - -/** - * set option to break closing header blocks of code (such as 'else', 'catch', ...) with empty lines. - * - * @param state true = convert, false = don't convert. - */ -void ASFormatter::setBreakClosingHeaderBlocksMode(bool state) -{ - shouldBreakClosingHeaderBlocks = state; -} - -/** - * jump over several characters. - * - * @param i the number of characters to jump over. - */ -void ASFormatter::goForward(int i) -{ - while (--i >= 0) - getNextChar(); -} - -/** -* peek at the next unread character. -* -* @return the next unread character. -*/ -char ASFormatter::peekNextChar() const -{ - char ch = ' '; - int peekNum = ASString_Find_First_Not_Of(currentLine, " \t", charNum + 1); - if (peekNum < 0) - return ch; - - ch = currentLine[peekNum]; - -// if (shouldConvertTabs && ch == '\t') -// ch = ' '; - - return ch; -} - -/** -* check if current placement is before a comment or line-comment -* -* @return is before a comment or line-comment. -*/ -bool ASFormatter::isBeforeComment() const -{ - bool foundComment = false; - int peekNum = ASString_Find_First_Not_Of(currentLine, " \t", charNum + 1); - if (peekNum < 0) - return foundComment; - - foundComment = (currentLine.Mid(peekNum, 2) == WString("/*") - || currentLine.Mid(peekNum, 2) == WString("//")); - - return foundComment; -} - -/** -* check if current placement is before a comment or line-comment -* if a block comment it must be at the end of the line -* -* @return is before a comment or line-comment. -*/ -bool ASFormatter::isBeforeLineEndComment(int startPos) const -{ - bool foundLineEndComment = false; - int peekNum = ASString_Find_First_Not_Of(currentLine, " \t", startPos + 1); - if (peekNum >= 0) - { - if (currentLine.Mid(peekNum, 2) == WString("//")) - foundLineEndComment = true; - else if (currentLine.Mid(peekNum, 2) == WString("/*")) - { - // comment must be closed on this line with nothing after it - int endNum = currentLine.Find("*/", peekNum + 2); - if (endNum >= 0) - if(ASString_Find_First_Not_Of(currentLine, " \t", endNum + 2) < 0) - foundLineEndComment = true; - - } - } - return foundLineEndComment; -} - - -/** -* get the next character, increasing the current placement in the process. -* the new character is inserted into the variable currentChar. -* -* @return whether succeded to recieve the new character. -*/ -bool ASFormatter::getNextChar() -{ - isInLineBreak = false; - previousChar = currentChar; - - if (!isWhiteSpace(currentChar)) - { - previousNonWSChar = currentChar; - if (!isInComment && !isInLineComment && !isInQuote - && !isImmediatelyPostComment - && !isImmediatelyPostLineComment - && !isSequenceReached("/*") - && !isSequenceReached("//")) - previousCommandChar = previousNonWSChar; - } - - int currentLineLength = currentLine.GetCount(); - - if (charNum + 1 < currentLineLength - && (!isWhiteSpace(peekNextChar()) || isInComment || isInLineComment)) - { - currentChar = currentLine[++charNum]; - - if (shouldConvertTabs && currentChar == '\t') - currentChar = ' '; - - return true; - } - else // end of line has been reached - { - if (sourceIterator->hasMoreLines()) - { - currentLine = sourceIterator->nextLine(); - spacePadNum = 0; - inLineNumber++; - - if (currentLine.GetCount() == 0) - { - currentLine = WString(" "); // a null is inserted if this is not done - } - - // unless reading in the first line of the file, - // break a new line. - if (!isVirgin) - isInLineBreak = true; - else - isVirgin = false; - - if (isInLineComment) - isImmediatelyPostLineComment = true; - isInLineComment = false; - - // check if is in preprocessor before line trimming - isImmediatelyPostPreprocessor = isInPreprocessor; - if (previousNonWSChar != '\\') - isInPreprocessor = false; - - trimNewLine(); - currentChar = currentLine[charNum]; - - if (shouldConvertTabs && currentChar == '\t') - currentChar = ' '; - - return true; - } - else - { - endOfCodeReached = true; - return false; - } - } -} - -/** -* jump over the leading white space in the current line, -* IF the line does not begin a comment or is in a preprocessor definition. -*/ -void ASFormatter::trimNewLine() -{ - int len = currentLine.GetCount(); - charNum = 0; - - if (isInComment || isInPreprocessor) - return; - - while (isWhiteSpace(currentLine[charNum]) && charNum + 1 < len) - ++charNum; - - doesLineStartComment = false; - if (isSequenceReached("/*")) - { - charNum = 0; - doesLineStartComment = true; - } -} - -/** - * append a character to the current formatted line. - * Unless disabled (via canBreakLine == false), first check if a - * line-break has been registered, and if so break the - * formatted line, and only then append the character into - * the next formatted line. - * - * @param ch the character to append. - * @param canBreakLine if true, a registered line-break - */ -void ASFormatter::appendChar(char ch, bool canBreakLine) -{ - if (canBreakLine && isInLineBreak) - breakLine(); - formattedLine.Cat(ch); -} - -/** - * append a string sequence to the current formatted line. - * Unless disabled (via canBreakLine == false), first check if a - * line-break has been registered, and if so break the - * formatted line, and only then append the sequence into - * the next formatted line. - * - * @param sequence the sequence to append. - * @param canBreakLine if true, a registered line-break - */ -void ASFormatter::appendSequence(const WString &sequence, bool canBreakLine) -{ - if (canBreakLine && isInLineBreak) - breakLine(); - formattedLine.Cat(sequence); -} - -/** - * append a space to the current formattedline, UNLESS the - * last character is already a white-space character. - */ -void ASFormatter::appendSpacePad() -{ - int len = formattedLine.GetCount(); - if (len > 0 && !isWhiteSpace(formattedLine[len-1])) - { - formattedLine.Cat(' '); - spacePadNum++; - } -} - -/** - * append a space to the current formattedline, UNLESS the - * next character is already a white-space character. - */ -void ASFormatter::appendSpaceAfter() -{ - int len = currentLine.GetCount(); - if (charNum + 1 < len && !isWhiteSpace(currentLine[charNum+1])) - { - formattedLine.Cat(' '); - spacePadNum++; - } -} - -/** - * register a line break for the formatted line. - */ -void ASFormatter::breakLine() -{ - isLineReady = true; - isInLineBreak = false; - spacePadNum = 0; - formattedLineCommentNum = -1; - - // queue an empty line prepend request if one exists - prependEmptyLine = isPrependPostBlockEmptyLineRequested; - - readyFormattedLine = formattedLine; - if (isAppendPostBlockEmptyLineRequested) - { - isAppendPostBlockEmptyLineRequested = false; - isPrependPostBlockEmptyLineRequested = true; - } - else - { - isPrependPostBlockEmptyLineRequested = false; - } - - formattedLine = ""; -} - -/** - * check if the currently reached open-bracket (i.e. '{') - * opens a: - * - a definition type block (such as a class or namespace), - * - a command block (such as a method block) - * - a static array - * this method takes for granted that the current character - * is an opening bracket. - * - * @return the type of the opened block. - */ -BracketType ASFormatter::getBracketType() const -{ - BracketType returnVal; - - if (foundPreDefinitionHeader) - { - returnVal = DEFINITION_TYPE; - if (foundNamespaceHeader) - returnVal = (BracketType)(returnVal | NAMESPACE_TYPE); - else if (foundClassHeader) - returnVal = (BracketType)(returnVal | CLASS_TYPE); - } - else - { - bool isCommandType = false; - - if (previousNonWSChar != '=') - isCommandType = (foundPreCommandHeader - || (currentHeader != NULL && isNonParenHeader) - || (previousCommandChar == ')') - || (previousCommandChar == ':' && !foundQuestionMark) - || (previousCommandChar == ';') - || ((previousCommandChar == '{' || previousCommandChar == '}') - && isPreviousBracketBlockRelated)); - - returnVal = (isCommandType ? COMMAND_TYPE : ARRAY_TYPE); - } - - if (isOneLineBlockReached()) - returnVal = (BracketType)(returnVal | SINGLE_LINE_TYPE); - - TRbracket(returnVal); - return returnVal; -} - -/** - * check if the currently reached '*' or '&' character is - * a pointer-or-reference symbol, or another operator. - * this method takes for granted that the current character - * is either a '*' or '&'. - * - * @return whether current character is a reference-or-pointer - */ -bool ASFormatter::isPointerOrReference() const -{ - bool isPR; - isPR = (!isInPotentialCalculation - || IS_A(bracketTypeStack->back(), DEFINITION_TYPE) - || (!isLegalNameChar(previousNonWSChar) - && previousNonWSChar != ')' - && previousNonWSChar != ']') - ); - - if (!isPR) - { - char nextChar = peekNextChar(); - isPR |= (!isWhiteSpace(nextChar) - && nextChar != '-' - && nextChar != '(' - && nextChar != '[' - && !isLegalNameChar(nextChar)); - } - - return isPR; -} - - -/** - * check if the currently reached '-' character is - * a unary minus - * this method takes for granted that the current character - * is a '-'. - * - * @return whether the current '-' is a unary minus. - */ -bool ASFormatter::isUnaryMinus() const -{ - return ((previousOperator == &AS_RETURN || !isalnum(previousCommandChar)) - && previousCommandChar != '.' - && previousCommandChar != ')' - && previousCommandChar != ']'); -} - - -/** - * check if the currently reached '-' or '+' character is - * part of an exponent, i.e. 0.2E-5. - * this method takes for granted that the current character - * is a '-' or '+'. - * - * @return whether the current '-' is in an exponent. - */ -bool ASFormatter::isInExponent() const -{ - int formattedLineLength = formattedLine.GetCount(); - if (formattedLineLength >= 2) - { - char prevPrevFormattedChar = formattedLine[formattedLineLength - 2]; - char prevFormattedChar = formattedLine[formattedLineLength - 1]; - - return ((prevFormattedChar == 'e' || prevFormattedChar == 'E') - && (prevPrevFormattedChar == '.' || isdigit(prevPrevFormattedChar))); - } - else - return false; -} - -/** - * check if a one-line bracket has been reached, - * i.e. if the currently reached '{' character is closed - * with a complimentry '}' elsewhere on the current line, - *. - * @return has a one-line bracket been reached? - */ -bool ASFormatter::isOneLineBlockReached() const -{ - bool isInComment = false; - bool isInQuote = false; - int bracketCount = 1; - int currentLineLength = currentLine.GetCount(); - char quoteChar = ' '; - - for (int i = charNum + 1; i < currentLineLength; ++i) - { - char ch = currentLine[i]; - - if (isInComment) - { - if (currentLine.Mid(i, 2) == WString("*/")) - { - isInComment = false; - ++i; - } - continue; - } - - if (ch == '\\') - { - ++i; - continue; - } - - if (isInQuote) - { - if (ch == quoteChar) - isInQuote = false; - continue; - } - - if (ch == '"' || ch == '\'') - { - isInQuote = true; - quoteChar = ch; - continue; - } - - if (currentLine.Mid(i, 2) == WString("//")) - break; - - if (currentLine.Mid(i, 2) == WString("/*")) - { - isInComment = true; - ++i; - continue; - } - - if (ch == '{') - ++bracketCount; - else if (ch == '}') - --bracketCount; - - if (bracketCount == 0) - return true; - } - - return false; -} - -/** - * check if one of a set of headers has been reached in the - * current position of the current line. - * - * @return a pointer to the found header. Or a NULL if no header has been reached. - * @param headers a vector of headers. - * @param checkBoundry - */ -const WString *ASFormatter::findHeader(const Vector &headers, bool checkBoundry) -{ - return ASBeautifier::findHeader(currentLine, charNum, headers, checkBoundry); -} - -/** - * check if a line begins with the specified character - * i.e. if the current line begins with a open bracket. - * - * @return true or false - */ -bool ASFormatter::lineBeginsWith(char charToCheck) const -{ - bool beginsWith = false; - int i = ASString_Find_First_Not_Of(currentLine, " \t"); - if (i >= 0) - if (currentLine[i] == charToCheck && (int) i == charNum) - beginsWith = true; - - return beginsWith; -} - -/** - * adjust comment position because of adding or deleting spaces - * the spaces are added or deleted to formattedLine - * spacePadNum contains the adjustment - */ -void ASFormatter::adjustComments(void) -{ - assert(spacePadNum != 0); - assert(currentLine.Mid(charNum, 2) == WString("//") - || currentLine.Mid(charNum, 2) == WString("/*")); - - - // block comment must be closed on this line with nothing after it - if (currentLine.Mid(charNum, 2) == WString("/*")) - { - int endNum = currentLine.Find("*/", charNum + 2); - if (endNum < 0) - return; - if(ASString_Find_First_Not_Of(currentLine, " \t", endNum + 2) >= 0) - return; - } - - int len = formattedLine.GetCount(); - // if spaces were removed, need to add spaces before the comment - if (spacePadNum < 0) - { - int adjust = -spacePadNum; // make the number positive - if (formattedLine[len-1] != '\t') // don't adjust if a tab - formattedLine.Cat(WString(' ', adjust)); -// else // comment out to avoid compiler warning -// adjust = 0; -// TRcomment(adjust); // trace macro - } - // if spaces were added, need to delete spaces before the comment, if possible - else if (spacePadNum > 0) - { - int adjust = spacePadNum; - if (ASString_Find_Last_Not_Of(formattedLine, " ") < len - adjust - 1 - && formattedLine[len-1] != '\t') // don't adjust a tab - formattedLine.Trim(len - adjust); - // the following are commented out to avoid a Borland compiler warning - //else - // adjust = 0; - TRcomment(-adjust); // trace macro - } -} - -/** - * append the current bracket inside the end of line comments - * currentChar contains the bracket, it will be appended to formattedLine - * formattedLineCommentNum is the comment location on formattedLine - */ -void ASFormatter::appendCharInsideComments(void) -{ - if (formattedLineCommentNum == -1 // does the comment start on the previous line? - || isBeforeComment()) // does a comment follow on this line? - { - appendCurrentChar(true); // don't attach - return; - } - assert(formattedLine.Mid(formattedLineCommentNum, 2) == WString("//") - || formattedLine.Mid(formattedLineCommentNum, 2) == WString("/*")); - - // find the previous non space char - int end = formattedLineCommentNum; - int beg = ASString_Find_Last_Not_Of(formattedLine, " \t", end-1); - if (beg < 0) // is the previous line comment only? - { - appendCurrentChar(true); // don't attach - return; - } - beg++; - - // insert the bracket - if (end - beg < 3) // is there room to insert? - formattedLine.Insert(beg, WString(' ', 3-end+beg)); - if (formattedLine[beg] == '\t') // don't pad with a tab - formattedLine.Insert(beg, ' '); - formattedLine.Set(beg+1, currentChar); -} - -/** - * add or remove space padding to operators - * currentChar contains the paren - * the operators and necessary padding will be appended to formattedLine - * the calling function should have a continue statement after calling this method - * - * @param *newOperator the operator to be padded - */ -void ASFormatter::padOperators(const WString *newOperator) -{ - assert (shouldPadOperators); - assert(newOperator != NULL); - - bool shouldPad = (newOperator != &AS_COLON_COLON - && newOperator != &AS_PAREN_PAREN - && newOperator != &AS_BLPAREN_BLPAREN - && newOperator != &AS_PLUS_PLUS - && newOperator != &AS_MINUS_MINUS - && newOperator != &AS_NOT - && newOperator != &AS_BIT_NOT - && newOperator != &AS_ARROW - && newOperator != &AS_OPERATOR - && newOperator != &AS_RETURN - && !(newOperator == &AS_MINUS && isInExponent()) - && !(newOperator == &AS_MINUS // check for negative number - && (previousNonWSChar == '(' - || previousNonWSChar == '=' - || previousNonWSChar == ',')) - && !(newOperator == &AS_PLUS && isInExponent()) - && previousOperator != &AS_OPERATOR - && !((newOperator == &AS_MULT || newOperator == &AS_BIT_AND) - && isPointerOrReference()) - && !(newOperator == &AS_MULT - && (previousNonWSChar == '.' - || previousNonWSChar == '>')) // check for -> - && !((isInTemplate || isCharImmediatelyPostTemplate) - && (newOperator == &AS_LS || newOperator == &AS_GR)) - ); - // pad before operator - if (shouldPad - && !isInBlParen - && !(newOperator == &AS_COLON && !foundQuestionMark) - && newOperator != &AS_SEMICOLON - && newOperator != &AS_COMMA) - appendSpacePad(); - appendSequence(*newOperator); - goForward(newOperator->GetCount() - 1); - - // since this block handles '()' and '[]', - // the parenStack must be updated here accordingly! - if (newOperator == &AS_PAREN_PAREN - || newOperator == &AS_BLPAREN_BLPAREN) - parenStack->back()--; - - currentChar = (*newOperator)[newOperator->GetCount() - 1]; - // pad after operator - // but do not pad after a '-' that is a unary-minus. - if (shouldPad - && !isInBlParen - && !isBeforeComment() - && !(newOperator == &AS_MINUS && isUnaryMinus()) - && (currentLine[charNum + 1] != ';') - && (currentLine.Mid(charNum + 1, 2) != WString("::"))) - appendSpaceAfter(); - - previousOperator = newOperator; - return; -} - -/** - * add or remove space padding to parens - * currentChar contains the paren - * the parens and necessary padding will be appended to formattedLine - * the calling function should have a continue statement after calling this method - */ -void ASFormatter::padParens(void) -{ - assert(shouldPadParensOutside || shouldPadParensInside || shouldUnPadParens); - assert (currentChar == '(' || currentChar == ')'); - - if (currentChar == '(') - { - int spacesOutsideToDelete = formattedLine.GetCount() - 1; - int spacesInsideToDelete = 0; - - // compute spaces outside the opening paren to delete - if (shouldUnPadParens) - { - char lastChar = ' '; - bool prevIsParenHeader = false; - int i = ASString_Find_Last_Not_Of(formattedLine, " \t"); - if (i >= 0) - { - int end = i; - spacesOutsideToDelete -= i; - lastChar = formattedLine[i]; - // was last word a paren header? - int start; // start of the previous word - for (start = i; start > 0; start--) - { - if (isLegalNameChar(formattedLine[start]) || formattedLine[start] == '*') - continue; - start++; - break; - } - WString prevWord = formattedLine.Mid(start, end-start+1); - // if previous word is a header, it will be a paren header - const WString *prevWordH = ASBeautifier::findHeader(formattedLine, start, headers); - if (prevWordH != NULL) - { - prevIsParenHeader = true; - TRxtra(*prevWordH); // trace macro - } - else if (prevWord == WString("return") // don't unpad return statements - || prevWord == WString("*")) // don't unpad multiply or pointer - { - prevIsParenHeader = true; - TRxtra(prevWord); // trace macro - } - // don't unpad variables - else if (prevWord == WString("bool") - || prevWord == WString("int") - || prevWord == WString("void") - || prevWord == WString("void*") - || (prevWord.GetCount() >= 6 // check end of word for _t - && prevWord.Mid(prevWord.GetCount()-2, 2) == WString("_t")) - || prevWord == WString("BOOL") - || prevWord == WString("DWORD") - || prevWord == WString("HWND") - || prevWord == WString("INT") - || prevWord == WString("LPSTR") - || prevWord == WString("VOID") - || prevWord == WString("LPVOID") - ) - { - prevIsParenHeader = true; - TRxtra(prevWord); // trace macro - } - } - // do not unpad operators, but leave them if already padded - if (shouldPadParensOutside || prevIsParenHeader) - spacesOutsideToDelete--; - else if (lastChar == '|' // check for || - || lastChar == '&' // check for && - || lastChar == ',' - || (lastChar == '>' && !foundCastOperator) - || lastChar == '<' - || lastChar == '?' - || lastChar == ':' - || lastChar == ';' - || lastChar == '=' - || lastChar == '+' - || lastChar == '-' - || (lastChar == '*' && isInPotentialCalculation) - || lastChar == '/' - || lastChar == '%') - spacesOutsideToDelete--; - - if (spacesOutsideToDelete > 0) - { - formattedLine.Remove(i + 1, spacesOutsideToDelete); - spacePadNum -= spacesOutsideToDelete; - } - } - - // pad open paren outside - char peekedCharOutside = peekNextChar(); - if (shouldPadParensOutside) - if (!(currentChar == '(' && peekedCharOutside == ')')) - appendSpacePad(); - - appendCurrentChar(); - - // unpad open paren inside - if (shouldUnPadParens) - { - int j = ASString_Find_First_Not_Of(currentLine, " \t", charNum + 1); - if (j >= 0) - spacesInsideToDelete = j - charNum - 1; - if (shouldPadParensInside) - spacesInsideToDelete--; - if (spacesInsideToDelete > 0) - { - currentLine.Remove(charNum + 1, spacesInsideToDelete); - spacePadNum -= spacesInsideToDelete; - } - } - - // pad open paren inside - char peekedCharInside = peekNextChar(); - if (shouldPadParensInside) - if (!(currentChar == '(' && peekedCharInside == ')')) - appendSpaceAfter(); - - TRunpad('(', spacesOutsideToDelete, spacesInsideToDelete); // trace macro - } - else if (currentChar == ')' /*|| currentChar == ']'*/) - { - int spacesOutsideToDelete = 0; - int spacesInsideToDelete = formattedLine.GetCount(); - - // unpad close paren inside - if (shouldUnPadParens) - { - int i = ASString_Find_Last_Not_Of(formattedLine, " \t"); - if (i >= 0) - spacesInsideToDelete = formattedLine.GetCount() - 1 - i; - if (shouldPadParensInside) - spacesInsideToDelete--; - if (spacesInsideToDelete > 0) - { - formattedLine.Remove(i + 1, spacesInsideToDelete); - spacePadNum -= spacesInsideToDelete; - } - } - - // pad close paren inside - if (shouldPadParensInside) - if (!(previousChar == '(' && currentChar == ')')) - appendSpacePad(); - - appendCurrentChar(); - - // unpad close paren outside - if (shouldUnPadParens) - { - // may have end of line comments - int j = ASString_Find_First_Not_Of(currentLine, " \t", charNum + 1); - if (j >= 0) - if (currentLine[j] == '[' || currentLine[j] == ']') - spacesOutsideToDelete = j - charNum - 1; - if (shouldPadParensOutside) - spacesOutsideToDelete--; -// spacesOutsideToDelete--; // always leave 1 space - - if (spacesOutsideToDelete > 0) - { - currentLine.Remove(charNum + 1, spacesOutsideToDelete); - spacePadNum -= spacesOutsideToDelete; - } - } - - // pad close paren outside - char peekedCharOutside = peekNextChar(); - if (shouldPadParensOutside) - if (peekedCharOutside != ';' - && peekedCharOutside != ',' - && peekedCharOutside != '.' - && peekedCharOutside != '-') // check for -> -// && !(currentChar == ']' && peekedCharOutside == '[')) - appendSpaceAfter(); - - TRunpad(')', spacesInsideToDelete, 0 /*spacesOutsideToDelete*/); // trace macro - } - return; -} - -/** - * format brackets as attached or broken - * currentChar contains the bracket - * the brackets will be appended to the current formattedLine or a new formattedLine as necessary - * the calling function should have a continue statement after calling this method - * - * @param bracketType the type of bracket to be formatted. - */ -void ASFormatter::formatBrackets(BracketType bracketType) -{ - assert(!IS_A(bracketType, ARRAY_TYPE)); - assert (currentChar == '{' || currentChar == '}'); - - if (currentChar == '{') - { - parenStack->push_back(0); - } - else if (currentChar == '}') - { - if (!parenStack->IsEmpty()) - { - parenStack->pop_back(); - } - } - - if (currentChar == '{') - { - bool bdacBreak = false; - // should a Linux bracket be broken? - if (bracketFormatMode == BDAC_MODE) - { - // always break a class - if (IS_A((*bracketTypeStack)[bracketTypeStack->size()-1], CLASS_TYPE)) - bdacBreak = true; - // break a namespace and the first bracket if a function - else if (bracketTypeStack->size() <= 2) - { - if (IS_A((*bracketTypeStack)[bracketTypeStack->size()-1], NAMESPACE_TYPE) - || IS_A((*bracketTypeStack)[bracketTypeStack->size()-1], COMMAND_TYPE)) - bdacBreak = true; - } - // break the first bracket after a namespace if a function - else if (IS_A((*bracketTypeStack)[bracketTypeStack->size()-2], NAMESPACE_TYPE)) - { - if (IS_A((*bracketTypeStack)[bracketTypeStack->size()-1], COMMAND_TYPE)) - bdacBreak = true; - } - // if not C style then break the first bracket after a class if a function - else if (!ASBeautifier::isCStyle) - { - if (IS_A((*bracketTypeStack)[bracketTypeStack->size()-2], CLASS_TYPE) - && IS_A((*bracketTypeStack)[bracketTypeStack->size()-1], COMMAND_TYPE)) - bdacBreak = true; - } - } - if (bracketFormatMode == ATTACH_MODE - || (bracketFormatMode == BDAC_MODE && !bdacBreak)) - { - // are there comments before the bracket? - if (isCharImmediatelyPostComment || isCharImmediatelyPostLineComment) - { - if ((shouldBreakOneLineBlocks || !IS_A(bracketType, SINGLE_LINE_TYPE)) - && peekNextChar() != '}') - appendCharInsideComments(); - else - appendCurrentChar(true); // don't attach - } - else if (previousCommandChar == '{' - || previousCommandChar == '}' - || previousCommandChar == ';') // '}' , ';' chars added for proper handling of '{' immediately after a '}' or ';' - { - appendCurrentChar(true); // don't attach - } - else - { - int firstChar = ASString_Find_First_Not_Of(formattedLine, " \t"); - if (firstChar < 0) // if a blank line preceeds this - appendCurrentChar(true); // don't attach - else if (shouldBreakOneLineBlocks - || !IS_A(bracketType, SINGLE_LINE_TYPE) - || peekNextChar() == '}') - { - appendSpacePad(); - appendCurrentChar(false); // OK to attach - } - else - appendCurrentChar(true); // don't attach - } - } - else if (bracketFormatMode == BREAK_MODE - || (bracketFormatMode == BDAC_MODE && bdacBreak)) - { - if (isBeforeComment()) - { - // do not break unless comment is at line end - if (isBeforeLineEndComment(charNum)) - { - currentChar = ' '; // remove bracket from current line - appendOpeningBracket = true; // append bracket to following line - } - } - else if (!IS_A(bracketType, SINGLE_LINE_TYPE)) - breakLine(); - else if (shouldBreakOneLineBlocks && peekNextChar() != '}') - breakLine(); - - appendCurrentChar(); - } - else if (bracketFormatMode == NONE_MODE) - { - if (lineBeginsWith('{')) // is opening bracket broken? - appendCurrentChar(true); - else - appendCurrentChar(false); - } - } - else if (currentChar == '}') - { - // mark state of immediately after empty block - // this state will be used for locating brackets that appear immedately AFTER an empty block (e.g. '{} \n}'). - if (previousCommandChar == '{') - isImmediatelyPostEmptyBlock = true; - - if ((!(previousCommandChar == '{' && isPreviousBracketBlockRelated)) // this '{' does not close an empty block - && (shouldBreakOneLineBlocks || !IS_A(bracketType, SINGLE_LINE_TYPE)) // astyle is allowed to break on line blocks - && (!(bracketFormatMode == NONE_MODE && IS_A(bracketType, SINGLE_LINE_TYPE))) - && !isImmediatelyPostEmptyBlock) // this '}' does not immediately follow an empty block - { - breakLine(); - appendCurrentChar(); - } - else - { - if (!isCharImmediatelyPostComment - && !(bracketFormatMode == NONE_MODE) - && !isImmediatelyPostEmptyBlock) - isInLineBreak = false; - - appendCurrentChar(); - - //if (!bracketFormatMode == NONE_MODE) - // if ((shouldBreakOneLineBlocks || !IS_A(bracketType, SINGLE_LINE_TYPE)) - // && !(currentChar == '}' && peekNextChar() == ';')) // fixes }; placed on separate lines - // shouldBreakLineAfterComments = true; - } - - if (shouldBreakBlocks) - { - isAppendPostBlockEmptyLineRequested = true; - } - } - return; -} - -/** - * format array brackets as attached or broken - * determine if the brackets can have an inStatement indent - * currentChar contains the bracket - * the brackets will be appended to the current formattedLine or a new formattedLine as necessary - * the calling function should have a continue statement after calling this method - * - * @param bracketType the type of bracket to be formatted, must be an ARRAY_TYPE. - * @param isOpeningArrayBracket indicates if this is the opening bracket for the array block. - */ -void ASFormatter::formatArrayBrackets(BracketType bracketType, bool isOpeningArrayBracket) -{ - assert(IS_A(bracketType, ARRAY_TYPE)); - assert (currentChar == '{' || currentChar == '}'); - - if (currentChar == '{') - { - // is this the first opening bracket in the array? - if (isOpeningArrayBracket) - { - if (bracketFormatMode == ATTACH_MODE || bracketFormatMode == BDAC_MODE) - { - // don't attach to a preprocessor directive - if (isImmediatelyPostPreprocessor) - appendCurrentChar(true); // don't attach - // are there comments before the bracket? - else if (isCharImmediatelyPostComment || isCharImmediatelyPostLineComment) - { - appendCharInsideComments(); - } - else - { - // if bracket is broken or not an assignment - if (lineBeginsWith('{') || previousNonWSChar != '=') - appendSpacePad(); - appendCurrentChar(false); // OK to attach - } - } - else if (bracketFormatMode == BREAK_MODE) - { - if (isWhiteSpace(peekNextChar())) - breakLine(); - else if (isBeforeComment()) - { - // do not break unless comment is at line end - if (isBeforeLineEndComment(charNum)) - { - currentChar = ' '; // remove bracket from current line - appendOpeningBracket = true; // append bracket to following line - } - } - appendCurrentChar(); - } - else if (bracketFormatMode == NONE_MODE) - { - if (lineBeginsWith('{')) // is opening bracket broken? - appendCurrentChar(); - else - appendCurrentChar(false); - } - } - else - appendCurrentChar(); // not the first opening bracket - don't change - - // if an opening bracket ends the line there will be no inStatement indent - char nextChar = peekNextChar(); - if (isWhiteSpace(nextChar) - || isBeforeLineEndComment(charNum) - || nextChar == '{') - isNonInStatementArray = true; - if (isNonInStatementArray) - TRarray('x'); - else - TRarray(' '); - - } - else if (currentChar == '}') - { - // does this close the first opening bracket in the array? - if (isOpeningArrayBracket && !IS_A(bracketType, SINGLE_LINE_TYPE) ) - { - breakLine(); - appendCurrentChar(); - } - else - appendCurrentChar(); - } -} - - -} // end namespace astyle diff --git a/uppdev/plugin/astyle/ASResource.cpp b/uppdev/plugin/astyle/ASResource.cpp deleted file mode 100644 index fc3e3fb7c..000000000 --- a/uppdev/plugin/astyle/ASResource.cpp +++ /dev/null @@ -1,395 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * - * ASResource.cpp - * - * This file is a part of "Artistic Style" - an indentation and - * reformatting tool for C, C++, C# and Java source files. - * http://astyle.sourceforge.net - * - * The "Artistic Style" project, including all files needed to - * compile it, is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later - * version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this project; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - */ - - /* - 2008-01-26 Patches by Massimo Del Fedele : - - modified sources to use Ultimate++ containers instead std:: ones - - fixed memory leaks based on bug report 1804791 submitted by Eran Ifrah - - modified to work with unicode - */ -#include "astyle.h" - - -namespace astyle -{ -const WString ASResource::AS_IF = WString("if"); -const WString ASResource::AS_ELSE = WString("else"); -const WString ASResource::AS_FOR = WString("for"); -const WString ASResource::AS_DO = WString("do"); -const WString ASResource::AS_WHILE = WString("while"); -const WString ASResource::AS_SWITCH = WString("switch"); -const WString ASResource::AS_CASE = WString("case"); -const WString ASResource::AS_DEFAULT = WString("default"); -const WString ASResource::AS_CLASS = WString("class"); -const WString ASResource::AS_STRUCT = WString("struct"); -const WString ASResource::AS_UNION = WString("union"); -const WString ASResource::AS_INTERFACE = WString("interface"); -const WString ASResource::AS_NAMESPACE = WString("namespace"); -const WString ASResource::AS_EXTERN = WString("extern"); -const WString ASResource::AS_PUBLIC = WString("public"); -const WString ASResource::AS_PROTECTED = WString("protected"); -const WString ASResource::AS_PRIVATE = WString("private"); -const WString ASResource::AS_STATIC = WString("static"); -const WString ASResource::AS_SYNCHRONIZED = WString("synchronized"); -const WString ASResource::AS_OPERATOR = WString("operator"); -const WString ASResource::AS_TEMPLATE = WString("template"); -const WString ASResource::AS_TRY = WString("try"); -const WString ASResource::AS_CATCH = WString("catch"); -const WString ASResource::AS_FINALLY = WString("finally"); -const WString ASResource::AS_THROWS = WString("throws"); -const WString ASResource::AS_CONST = WString("const"); - -const WString ASResource::AS_ASM = WString("asm"); - -const WString ASResource::AS_BAR_DEFINE = WString("#define"); -const WString ASResource::AS_BAR_INCLUDE = WString("#include"); -const WString ASResource::AS_BAR_IF = WString("#if"); -const WString ASResource::AS_BAR_EL = WString("#el"); -const WString ASResource::AS_BAR_ENDIF = WString("#endif"); - -const WString ASResource::AS_OPEN_BRACKET = WString("{"); -const WString ASResource::AS_CLOSE_BRACKET = WString("}"); -const WString ASResource::AS_OPEN_LINE_COMMENT = WString("//"); -const WString ASResource::AS_OPEN_COMMENT = WString("/*"); -const WString ASResource::AS_CLOSE_COMMENT = WString("*/"); - -const WString ASResource::AS_ASSIGN = WString("="); -const WString ASResource::AS_PLUS_ASSIGN = WString("+="); -const WString ASResource::AS_MINUS_ASSIGN = WString("-="); -const WString ASResource::AS_MULT_ASSIGN = WString("*="); -const WString ASResource::AS_DIV_ASSIGN = WString("/="); -const WString ASResource::AS_MOD_ASSIGN = WString("%="); -const WString ASResource::AS_OR_ASSIGN = WString("|="); -const WString ASResource::AS_AND_ASSIGN = WString("&="); -const WString ASResource::AS_XOR_ASSIGN = WString("^="); -const WString ASResource::AS_GR_GR_ASSIGN = WString(">>="); -const WString ASResource::AS_LS_LS_ASSIGN = WString("<<="); -const WString ASResource::AS_GR_GR_GR_ASSIGN = WString(">>>="); -const WString ASResource::AS_LS_LS_LS_ASSIGN = WString("<<<="); -const WString ASResource::AS_RETURN = WString("return"); - -const WString ASResource::AS_EQUAL = WString("=="); -const WString ASResource::AS_PLUS_PLUS = WString("++"); -const WString ASResource::AS_MINUS_MINUS = WString("--"); -const WString ASResource::AS_NOT_EQUAL = WString("!="); -const WString ASResource::AS_GR_EQUAL = WString(">="); -const WString ASResource::AS_GR_GR = WString(">>"); -const WString ASResource::AS_GR_GR_GR = WString(">>>"); -const WString ASResource::AS_LS_EQUAL = WString("<="); -const WString ASResource::AS_LS_LS = WString("<<"); -const WString ASResource::AS_LS_LS_LS = WString("<<<"); -const WString ASResource::AS_ARROW = WString("->"); -const WString ASResource::AS_AND = WString("&&"); -const WString ASResource::AS_OR = WString("||"); -const WString ASResource::AS_COLON_COLON = WString("::"); -const WString ASResource::AS_PAREN_PAREN = WString("()"); -const WString ASResource::AS_BLPAREN_BLPAREN = WString("[]"); - -const WString ASResource::AS_PLUS = WString("+"); -const WString ASResource::AS_MINUS = WString("-"); -const WString ASResource::AS_MULT = WString("*"); -const WString ASResource::AS_DIV = WString("/"); -const WString ASResource::AS_MOD = WString("%"); -const WString ASResource::AS_GR = WString(">"); -const WString ASResource::AS_LS = WString("<"); -const WString ASResource::AS_NOT = WString("!"); -const WString ASResource::AS_BIT_OR = WString("|"); -const WString ASResource::AS_BIT_AND = WString("&"); -const WString ASResource::AS_BIT_NOT = WString("~"); -const WString ASResource::AS_BIT_XOR = WString("^"); -const WString ASResource::AS_QUESTION = WString("?"); -const WString ASResource::AS_COLON = WString(":"); -const WString ASResource::AS_COMMA = WString(","); -const WString ASResource::AS_SEMICOLON = WString(";"); - -const WString ASResource::AS_FOREACH = WString("foreach"); -const WString ASResource::AS_LOCK = WString("lock"); -const WString ASResource::AS_UNSAFE = WString("unsafe"); -const WString ASResource::AS_FIXED = WString("fixed"); -const WString ASResource::AS_GET = WString("get"); -const WString ASResource::AS_SET = WString("set"); -const WString ASResource::AS_ADD = WString("add"); -const WString ASResource::AS_REMOVE = WString("remove"); - -const WString ASResource::AS_CONST_CAST = WString("const_cast"); -const WString ASResource::AS_DYNAMIC_CAST = WString("dynamic_cast"); -const WString ASResource::AS_REINTERPRET_CAST = WString("reinterpret_cast"); -const WString ASResource::AS_STATIC_CAST = WString("static_cast"); - - -/** - * Build the vector of assignment operators. - * Used by BOTH ASFormatter.cpp and ASBeautifier.cpp - * - * @param assignmentOperators a reference to the vector to be built. - */ -void ASResource::buildAssignmentOperators(Vector &assignmentOperators) -{ - assignmentOperators.push_back(&AS_ASSIGN); - assignmentOperators.push_back(&AS_PLUS_ASSIGN); - assignmentOperators.push_back(&AS_MINUS_ASSIGN); - assignmentOperators.push_back(&AS_MULT_ASSIGN); - assignmentOperators.push_back(&AS_DIV_ASSIGN); - assignmentOperators.push_back(&AS_MOD_ASSIGN); - assignmentOperators.push_back(&AS_OR_ASSIGN); - assignmentOperators.push_back(&AS_AND_ASSIGN); - assignmentOperators.push_back(&AS_XOR_ASSIGN); - - // Java - assignmentOperators.push_back(&AS_GR_GR_GR_ASSIGN); - assignmentOperators.push_back(&AS_GR_GR_ASSIGN); - assignmentOperators.push_back(&AS_LS_LS_ASSIGN); - - // Unknown - assignmentOperators.push_back(&AS_LS_LS_LS_ASSIGN); - - assignmentOperators.push_back(&AS_RETURN); -} - -/** - * Build the vector of C++ cast operators. - * Used by ONLY ASFormatter.cpp - * - * @param castOperators a reference to the vector to be built. - */ -void ASResource::buildCastOperators(Vector &castOperators) -{ - castOperators.push_back(&AS_CONST_CAST); - castOperators.push_back(&AS_DYNAMIC_CAST); - castOperators.push_back(&AS_REINTERPRET_CAST); - castOperators.push_back(&AS_STATIC_CAST); -} - -/** - * Build the vector of header words. - * Used by BOTH ASFormatter.cpp and ASBeautifier.cpp - * - * @param headers a reference to the vector to be built. - */ -void ASResource::buildHeaders(Vector &headers, int fileType, bool beautifier) -{ - headers.push_back(&AS_IF); - headers.push_back(&AS_ELSE); - headers.push_back(&AS_FOR); - headers.push_back(&AS_WHILE); - headers.push_back(&AS_DO); - headers.push_back(&AS_SWITCH); - headers.push_back(&AS_TRY); - headers.push_back(&AS_CATCH); - - if (beautifier) - { - headers.push_back(&AS_CASE); - headers.push_back(&AS_DEFAULT); - headers.push_back(&AS_CONST); - headers.push_back(&AS_STATIC); - headers.push_back(&AS_EXTERN); - headers.push_back(&AS_TEMPLATE); - } - - if (fileType == JAVA_TYPE) - { - headers.push_back(&AS_FINALLY); - headers.push_back(&AS_SYNCHRONIZED); - } - - if (fileType == SHARP_TYPE) - { - headers.push_back(&AS_FINALLY); - headers.push_back(&AS_FOREACH); - headers.push_back(&AS_LOCK); - headers.push_back(&AS_UNSAFE); - headers.push_back(&AS_FIXED); - headers.push_back(&AS_GET); - headers.push_back(&AS_SET); - headers.push_back(&AS_ADD); - headers.push_back(&AS_REMOVE); - } -} - -/** - * Build the vector of non-assignment operators. - * Used by ONLY ASBeautifier.cpp - * - * @param nonParenHeaders a reference to the vector to be built. - */ -void ASResource::buildNonAssignmentOperators(Vector &nonAssignmentOperators) -{ - nonAssignmentOperators.push_back(&AS_EQUAL); - nonAssignmentOperators.push_back(&AS_PLUS_PLUS); - nonAssignmentOperators.push_back(&AS_MINUS_MINUS); - nonAssignmentOperators.push_back(&AS_NOT_EQUAL); - nonAssignmentOperators.push_back(&AS_GR_EQUAL); - nonAssignmentOperators.push_back(&AS_GR_GR_GR); - nonAssignmentOperators.push_back(&AS_GR_GR); - nonAssignmentOperators.push_back(&AS_LS_EQUAL); - nonAssignmentOperators.push_back(&AS_LS_LS_LS); - nonAssignmentOperators.push_back(&AS_LS_LS); - nonAssignmentOperators.push_back(&AS_ARROW); - nonAssignmentOperators.push_back(&AS_AND); - nonAssignmentOperators.push_back(&AS_OR); -} - -/** - * Build the vector of header non-paren headers. - * Used by BOTH ASFormatter.cpp and ASBeautifier.cpp - * - * @param nonParenHeaders a reference to the vector to be built. - */ -void ASResource::buildNonParenHeaders(Vector &nonParenHeaders, int fileType, bool beautifier) -{ - nonParenHeaders.push_back(&AS_ELSE); - nonParenHeaders.push_back(&AS_DO); - nonParenHeaders.push_back(&AS_TRY); - - if (beautifier) - { - nonParenHeaders.push_back(&AS_CASE); - nonParenHeaders.push_back(&AS_DEFAULT); - nonParenHeaders.push_back(&AS_CONST); - nonParenHeaders.push_back(&AS_STATIC); - nonParenHeaders.push_back(&AS_EXTERN); - nonParenHeaders.push_back(&AS_TEMPLATE); - } - - if (fileType == JAVA_TYPE) - { - nonParenHeaders.push_back(&AS_FINALLY); - } - - if (fileType == SHARP_TYPE) - { - nonParenHeaders.push_back(&AS_FINALLY); - nonParenHeaders.push_back(&AS_UNSAFE); - nonParenHeaders.push_back(&AS_GET); - nonParenHeaders.push_back(&AS_SET); - nonParenHeaders.push_back(&AS_ADD); - nonParenHeaders.push_back(&AS_REMOVE); - } -} - -/** - * Build the vector of operators. - * Used by ONLY ASFormatter.cpp - * - * @param operators a reference to the vector to be built. - */ -void ASResource::buildOperators(Vector &operators) -{ - operators.push_back(&AS_PLUS_ASSIGN); - operators.push_back(&AS_MINUS_ASSIGN); - operators.push_back(&AS_MULT_ASSIGN); - operators.push_back(&AS_DIV_ASSIGN); - operators.push_back(&AS_MOD_ASSIGN); - operators.push_back(&AS_OR_ASSIGN); - operators.push_back(&AS_AND_ASSIGN); - operators.push_back(&AS_XOR_ASSIGN); - operators.push_back(&AS_EQUAL); - operators.push_back(&AS_PLUS_PLUS); - operators.push_back(&AS_MINUS_MINUS); - operators.push_back(&AS_NOT_EQUAL); - operators.push_back(&AS_GR_EQUAL); - operators.push_back(&AS_GR_GR_GR_ASSIGN); - operators.push_back(&AS_GR_GR_ASSIGN); - operators.push_back(&AS_GR_GR_GR); - operators.push_back(&AS_GR_GR); - operators.push_back(&AS_LS_EQUAL); - operators.push_back(&AS_LS_LS_LS_ASSIGN); - operators.push_back(&AS_LS_LS_ASSIGN); - operators.push_back(&AS_LS_LS_LS); - operators.push_back(&AS_LS_LS); - operators.push_back(&AS_ARROW); - operators.push_back(&AS_AND); - operators.push_back(&AS_OR); - operators.push_back(&AS_COLON_COLON); - operators.push_back(&AS_PLUS); - operators.push_back(&AS_MINUS); - operators.push_back(&AS_MULT); - operators.push_back(&AS_DIV); - operators.push_back(&AS_MOD); - operators.push_back(&AS_QUESTION); - operators.push_back(&AS_COLON); - operators.push_back(&AS_ASSIGN); - operators.push_back(&AS_LS); - operators.push_back(&AS_GR); - operators.push_back(&AS_NOT); - operators.push_back(&AS_BIT_OR); - operators.push_back(&AS_BIT_AND); - operators.push_back(&AS_BIT_NOT); - operators.push_back(&AS_BIT_XOR); - operators.push_back(&AS_OPERATOR); - operators.push_back(&AS_COMMA); - operators.push_back(&AS_RETURN); -} - -/** - * Build the vector of pre-block statements. - * Used by ONLY ASBeautifier.cpp - * - * @param preBlockStatements a reference to the vector to be built. - */ -void ASResource::buildPreBlockStatements(Vector &preBlockStatements) -{ - preBlockStatements.push_back(&AS_CLASS); - preBlockStatements.push_back(&AS_STRUCT); - preBlockStatements.push_back(&AS_UNION); - preBlockStatements.push_back(&AS_INTERFACE); - preBlockStatements.push_back(&AS_NAMESPACE); - preBlockStatements.push_back(&AS_THROWS); - preBlockStatements.push_back(&AS_EXTERN); -} - -/** - * Build the vector of pre-command headers. - * Used by ONLY ASFormatter.cpp - * - * @param preCommandHeaders a reference to the vector to be built. - */ -void ASResource::buildPreCommandHeaders(Vector &preCommandHeaders) -{ - preCommandHeaders.push_back(&AS_EXTERN); - preCommandHeaders.push_back(&AS_THROWS); - preCommandHeaders.push_back(&AS_CONST); -} - -/** - * Build the vector of pre-definition headers. - * Used by ONLY ASFormatter.cpp - * - * @param preDefinitionHeaders a reference to the vector to be built. - */ -void ASResource::buildPreDefinitionHeaders(Vector &preDefinitionHeaders) -{ - preDefinitionHeaders.push_back(&AS_CLASS); - preDefinitionHeaders.push_back(&AS_INTERFACE); - preDefinitionHeaders.push_back(&AS_NAMESPACE); - preDefinitionHeaders.push_back(&AS_STRUCT); -} - - -} // end namespace astyle diff --git a/uppdev/plugin/astyle/ASStringTools.cpp b/uppdev/plugin/astyle/ASStringTools.cpp deleted file mode 100644 index 3020f2557..000000000 --- a/uppdev/plugin/astyle/ASStringTools.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * - * astyle.h - * - * This file is a part of "Artistic Style" - an indentation and - * reformatting tool for C, C++, C# and Java source files. - * http://astyle.sourceforge.net - * - * The "Artistic Style" project, including all files needed to - * compile it, is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later - * version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this project; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - */ - - /* - 2008-01-26 Patches by Massimo Del Fedele : - - modified sources to use Ultimate++ containers instead std:: ones - - fixed memory leaks based on bug report 1804791 submitted by Eran Ifrah - - modified to work with unicode - */ -#include "ASStringTools.hpp" - -/////////////////////////////////////////////////////////////////////////////////////////// -// Replaces a chunk in a string with a new string -void ASString_Replace(WString &s, int Pos, int Len, WString const &newString) -{ - if(Pos < 0 || Pos >= s.GetCount()) - return; - s.Remove(Pos, Len); - s.Insert(Pos, newString); - -} // END ASString_Replace() - -/////////////////////////////////////////////////////////////////////////////////////////// -// Find first character in a string *not* contained in another string -int ASString_Find_First_Not_Of(WString const &s, WString const &Pattern, int pos) -{ - if(pos < 0 || pos >= s.GetCount()) - return -1; - int len = s.GetCount(); - while(pos < len && Pattern.Find(s[pos]) != -1) - pos++; - if(pos < len) - return pos; - else - return -1; - -} // END ASString_Find_First_Not_Of() - -/////////////////////////////////////////////////////////////////////////////////////////// -// Find last character in a string *not* contained in another string -int ASString_Find_Last_Not_Of(WString const &s, WString const &Pattern, int pos) -{ - if(pos < 0 || pos >= s.GetCount()) - pos = s.GetCount() -1; - while(pos > 0 && Pattern.Find(s[pos]) != -1) - pos--; - return pos; - -} // END ASString_Find_Last_Not_Of() - -/////////////////////////////////////////////////////////////////////////////////////////// -// Finds a substring starting at the end of a given string -int ASString_ReverseFind(WString const &s, WString const &Pattern) -{ - int pos = -1; - int k = 0; - while( (k = s.Find(Pattern, k)) >= 0) - pos = k++; - return pos; - -} // END ASString_ReverseFind() diff --git a/uppdev/plugin/astyle/ASStringTools.hpp b/uppdev/plugin/astyle/ASStringTools.hpp deleted file mode 100644 index 1a4cdd4ad..000000000 --- a/uppdev/plugin/astyle/ASStringTools.hpp +++ /dev/null @@ -1,58 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * - * astyle.h - * - * This file is a part of "Artistic Style" - an indentation and - * reformatting tool for C, C++, C# and Java source files. - * http://astyle.sourceforge.net - * - * The "Artistic Style" project, including all files needed to - * compile it, is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later - * version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this project; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - */ - - /* - 2008-01-26 Patches by Massimo Del Fedele : - - modified sources to use Ultimate++ containers instead std:: ones - - fixed memory leaks based on bug report 1804791 submitted by Eran Ifrah - - modified to work with unicode - */ -#ifndef __ASSTRINGTOOLS_HPP -#define __ASSTRINGTOOLS_HPP - -#include - -using namespace Upp; - -/////////////////////////////////////////////////////////////////////////////////////////// -// Replaces a chunk in a string with a new string -void ASString_Replace(WString &s, int Pos, int Len, WString const &newString); - -/////////////////////////////////////////////////////////////////////////////////////////// -// Find first character in a string *not* contained in another string -int ASString_Find_First_Not_Of(WString const &s, WString const &Pattern, int from = 0); - -/////////////////////////////////////////////////////////////////////////////////////////// -// Find last character in a string *not* contained in another string -int ASString_Find_Last_Not_Of(WString const &s, WString const &Pattern, int from = -1); - -/////////////////////////////////////////////////////////////////////////////////////////// -// Finds a substring starting at the end of a given string -int ASString_ReverseFind(WString const &s, WString const &Pattern); - -#endif diff --git a/uppdev/plugin/astyle/astyle.h b/uppdev/plugin/astyle/astyle.h deleted file mode 100644 index 4de51cca2..000000000 --- a/uppdev/plugin/astyle/astyle.h +++ /dev/null @@ -1,504 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * - * astyle.h - * - * This file is a part of "Artistic Style" - an indentation and - * reformatting tool for C, C++, C# and Java source files. - * http://astyle.sourceforge.net - * - * The "Artistic Style" project, including all files needed to - * compile it, is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later - * version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this project; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - */ - - /* - 2008-01-26 Patches by Massimo Del Fedele : - - modified sources to use Ultimate++ containers instead std:: ones - - fixed memory leaks based on bug report 1804791 submitted by Eran Ifrah - - modified to work with unicode - */ - -#ifndef ASTYLE_H -#define ASTYLE_H - -#include -#include "ASStringTools.hpp" - -// 4996 - secure version deprecation warnings for .NET 2005 -// 4267 - 64 bit signed/unsigned loss of data -#ifdef _MSC_VER -#pragma warning(disable: 4996) -#pragma warning(disable: 4267) -#endif - -namespace astyle -{ - -enum FileType { C_TYPE=0, JAVA_TYPE=1, SHARP_TYPE=2 }; - -/* The enums below are not recognized by 'vectors' in Microsoft Visual C++ - V5 when they are part of a namespace!!! Use Visual C++ V6 or higher. -*/ -enum BracketMode { NONE_MODE, ATTACH_MODE, BREAK_MODE, BDAC_MODE }; - -// added by Massimo Del Fedele - just an helper for dialog setup -enum ParenthesisPad { PAD_NONE, PAD_INSIDE, PAD_OUTSIDE, PAD_BOTH }; - -enum BracketType { NULL_TYPE = 0, - NAMESPACE_TYPE = 1, // also a DEFINITION_TYPE - CLASS_TYPE = 2, // also a DEFINITION_TYPE - DEFINITION_TYPE = 4, - COMMAND_TYPE = 8, - ARRAY_TYPE = 16, // arrays and enums - SINGLE_LINE_TYPE = 32 - }; -class ASSourceIterator -{ - public: - int eolWindows; - int eolLinux; - int eolMacOld; - char outputEOL[4]; // output end of line char - ASSourceIterator() { eolWindows = eolLinux = eolMacOld = 0; } - virtual ~ASSourceIterator() {} - virtual bool hasMoreLines() const = 0; - virtual WString nextLine() = 0; -}; - -class ASResource -{ - public: - void buildAssignmentOperators(Vector &assignmentOperators); - void buildCastOperators(Vector &castOperators); - void buildHeaders(Vector &headers, int fileType, bool beautifier=false); - void buildNonAssignmentOperators(Vector &nonAssignmentOperators); - void buildNonParenHeaders(Vector &nonParenHeaders, int fileType, bool beautifier=false); - void buildOperators(Vector &operators); - void buildPreBlockStatements(Vector &preBlockStatements); - void buildPreCommandHeaders(Vector &preCommandHeaders); - void buildPreDefinitionHeaders(Vector &preDefinitionHeaders); - - public: - static const WString AS_IF, AS_ELSE; - static const WString AS_DO, AS_WHILE; - static const WString AS_FOR; - static const WString AS_SWITCH, AS_CASE, AS_DEFAULT; - static const WString AS_TRY, AS_CATCH, AS_THROWS, AS_FINALLY; - static const WString AS_PUBLIC, AS_PROTECTED, AS_PRIVATE; - static const WString AS_CLASS, AS_STRUCT, AS_UNION, AS_INTERFACE, AS_NAMESPACE, AS_EXTERN; - static const WString AS_STATIC; - static const WString AS_CONST; - static const WString AS_SYNCHRONIZED; - static const WString AS_OPERATOR, AS_TEMPLATE; - static const WString AS_OPEN_BRACKET, AS_CLOSE_BRACKET; - static const WString AS_OPEN_LINE_COMMENT, AS_OPEN_COMMENT, AS_CLOSE_COMMENT; - static const WString AS_BAR_DEFINE, AS_BAR_INCLUDE, AS_BAR_IF, AS_BAR_EL, AS_BAR_ENDIF; - static const WString AS_RETURN; - static const WString AS_ASSIGN, AS_PLUS_ASSIGN, AS_MINUS_ASSIGN, AS_MULT_ASSIGN; - static const WString AS_DIV_ASSIGN, AS_MOD_ASSIGN, AS_XOR_ASSIGN, AS_OR_ASSIGN, AS_AND_ASSIGN; - static const WString AS_GR_GR_ASSIGN, AS_LS_LS_ASSIGN, AS_GR_GR_GR_ASSIGN, AS_LS_LS_LS_ASSIGN; - static const WString AS_EQUAL, AS_PLUS_PLUS, AS_MINUS_MINUS, AS_NOT_EQUAL, AS_GR_EQUAL, AS_GR_GR_GR, AS_GR_GR; - static const WString AS_LS_EQUAL, AS_LS_LS_LS, AS_LS_LS, AS_ARROW, AS_AND, AS_OR; - static const WString AS_COLON_COLON, AS_PAREN_PAREN, AS_BLPAREN_BLPAREN; - static const WString AS_PLUS, AS_MINUS, AS_MULT, AS_DIV, AS_MOD, AS_GR, AS_LS; - static const WString AS_NOT, AS_BIT_XOR, AS_BIT_OR, AS_BIT_AND, AS_BIT_NOT; - static const WString AS_QUESTION, AS_COLON, AS_SEMICOLON, AS_COMMA; - static const WString AS_ASM; - static const WString AS_FOREACH, AS_LOCK, AS_UNSAFE, AS_FIXED; - static const WString AS_GET, AS_SET, AS_ADD, AS_REMOVE; - static const WString AS_CONST_CAST, AS_DYNAMIC_CAST, AS_REINTERPRET_CAST, AS_STATIC_CAST; -}; - -class ASBeautifier : protected ASResource -{ - public: - ASBeautifier(); - virtual ~ASBeautifier(); - virtual void init(ASSourceIterator* iter); // pointer to dynamically created iterator. - void init(); - virtual bool hasMoreLines() const; - virtual WString nextLine(); - virtual WString beautify(const WString &line); - void setTabIndentation(int length = 4, bool forceTabs = false); - void setSpaceIndentation(int length = 4); - void setMaxInStatementIndentLength(int max); - void setMinConditionalIndentLength(int min); - void setClassIndent(bool state); - void setSwitchIndent(bool state); - void setCaseIndent(bool state); - void setBracketIndent(bool state); - void setBlockIndent(bool state); - void setNamespaceIndent(bool state); - void setLabelIndent(bool state); - void setCStyle(); - void setJavaStyle(); - void setSharpStyle(); - void setEmptyLineFill(bool state); - void setPreprocessorIndent(bool state); - int getIndentLength(void); - WString getIndentString(void); - bool getCaseIndent(void); - bool getCStyle(void); - bool getJavaStyle(void); - bool getSharpStyle(void); - bool getEmptyLineFill(void); - - protected: - int getNextProgramCharDistance(const WString &line, int i); -// bool isLegalNameChar(char ch) const; - const WString *findHeader(const WString &line, int i, - const Vector &possibleHeaders, - bool checkBoundry = true); - WString trim(const WString &str); - int indexOf(Vector &container, const WString *element); - int fileType; - bool isCStyle; - bool isJavaStyle; - bool isSharpStyle; - - // variables set by ASFormatter - must be updated in preprocessor - int inLineNumber; // for debugging - int outLineNumber; // for debugging - bool lineCommentNoBeautify; - bool isNonInStatementArray; - - private: - ASBeautifier(const ASBeautifier ©); - void operator=(ASBeautifier&); // not to be implemented - - void initStatic(); - void registerInStatementIndent(const WString &line, int i, int spaceTabCount, - int minIndent, bool updateParenStack); - WString preLineWS(int spaceTabCount, int tabCount); - - static Vector headers; - static Vector nonParenHeaders; - static Vector preBlockStatements; - static Vector assignmentOperators; - static Vector nonAssignmentOperators; - - ASSourceIterator *sourceIterator; - Vector *waitingBeautifierStack; - Vector *activeBeautifierStack; - Vector *waitingBeautifierStackLengthStack; - Vector *activeBeautifierStackLengthStack; - WithDeepCopy > *headerStack; - WithDeepCopy* > >*tempStacks; - WithDeepCopy > *blockParenDepthStack; - WithDeepCopy > *blockStatementStack; - WithDeepCopy >*parenStatementStack; - WithDeepCopy > *inStatementIndentStack; - WithDeepCopy > *inStatementIndentStackSizeStack; - WithDeepCopy > *parenIndentStack; - WithDeepCopy >*bracketBlockStateStack; - WString indentString; - const WString *currentHeader; - const WString *previousLastLineHeader; - const WString *immediatelyPreviousAssignmentOp; - const WString *probationHeader; - bool isInQuote; - bool isInComment; - bool isInCase; - bool isInQuestion; - bool isInStatement; - bool isInHeader; - bool isInOperator; - bool isInTemplate; - bool isInDefine; - bool isInDefineDefinition; - bool classIndent; - bool isInClassHeader; - bool isInClassHeaderTab; - bool switchIndent; - bool caseIndent; - bool namespaceIndent; - bool bracketIndent; - bool blockIndent; - bool labelIndent; - bool preprocessorIndent; - bool isInConditional; - bool isMinimalConditinalIndentSet; - bool shouldForceTabIndentation; - bool emptyLineFill; - bool backslashEndsPrevLine; - bool blockCommentNoIndent; - bool blockCommentNoBeautify; - bool previousLineProbationTab; - int minConditionalIndent; - int parenDepth; - int indentLength; - int blockTabCount; - int leadingWhiteSpaces; - int maxInStatementIndent; - int templateDepth; - int prevFinalLineSpaceTabCount; - int prevFinalLineTabCount; - int defineTabCount; - char quoteChar; - char prevNonSpaceCh; - char currentNonSpaceCh; - char currentNonLegalCh; - char prevNonLegalCh; - char peekNextChar(WString &line, int i); - - protected: // inline functions - // check if a specific character can be used in a legal variable/method/class name - inline bool isLegalNameChar(char ch) const { - return (isalnum(ch) || ch == '.' || ch == '_' || (isJavaStyle && ch == '$') || (isCStyle && ch == '~')); - } - - // check if a specific character is a whitespace character - inline bool isWhiteSpace(char ch) const { - return (ch == ' ' || ch == '\t'); - } -}; - - -class ASEnhancer -{ - public: - // functions - ASEnhancer(); - ~ASEnhancer(); - void init(int, WString, bool, bool, bool, bool, bool); - void enhance(WString &line); - - private: - // set by init function - int indentLength; - bool useTabs; - bool isCStyle; - bool isJavaStyle; - bool isSharpStyle; - bool caseIndent; - bool emptyLineFill; - - // parsing variables - int lineNumber; - bool isInQuote; - bool isInComment; - char quoteChar; - - // unindent variables - int bracketCount; - int switchDepth; - bool lookingForCaseBracket; - bool unindentNextLine; - - // StringStream for trace - StringStream *traceOut; - - private: // private functions - bool findKeyword(const WString &line, int i, const char *header) const; - int indentLine(WString &line, const int indent) const; - int unindentLine(WString &line, const int unindent) const; - - private: - // struct used by ParseFormattedLine function - // contains variables used to unindent the case blocks - struct switchVariables { - int switchBracketCount; - int unindentDepth; - bool unindentCase; - - switchVariables() { // constructor - switchBracketCount = 0; - unindentDepth = 0; - unindentCase = false; - } - }; - - private: // inline functions - // check if a specific character can be used in a legal variable/method/class name - inline bool isLegalNameCharX(char ch) const { - return (isalnum(ch) || ch == '.' || ch == '_' || (isJavaStyle && ch == '$') || (isCStyle && ch == '~')); - } - - // check if a specific character is a whitespace character - inline bool isWhiteSpaceX(char ch) const { - return (ch == ' ' || ch == '\t'); - } -}; - - -class ASFormatter : public ASBeautifier, private ASEnhancer -{ - public: - ASFormatter(); - virtual ~ASFormatter(); - virtual void init(ASSourceIterator* iter); - virtual bool hasMoreLines() const; - virtual WString nextLine(); - void setBracketFormatMode(BracketMode mode); - void setBreakClosingHeaderBracketsMode(bool state); - void setOperatorPaddingMode(bool mode); - void setParensOutsidePaddingMode(bool mode); - void setParensInsidePaddingMode(bool mode); - void setParensUnPaddingMode(bool state); - void setBreakOneLineBlocksMode(bool state); - void setSingleStatementsMode(bool state); - void setTabSpaceConversionMode(bool state); - void setBreakBlocksMode(bool state); - void setBreakClosingHeaderBlocksMode(bool state); - void setBreakElseIfsMode(bool state); - WString fileName; - - private: - void ASformatter(ASFormatter ©); // not to be imlpemented - void operator=(ASFormatter&); // not to be implemented - void staticInit(); - void goForward(int i); - void trimNewLine(); - char peekNextChar() const; - BracketType getBracketType() const; - bool getNextChar(); - bool isBeforeComment() const; - bool isBeforeLineEndComment(int startPos) const; - bool isPointerOrReference() const; - bool isUnaryMinus() const; - bool isInExponent() const; - bool isOneLineBlockReached() const; -// bool isNextCharWhiteSpace() const; - bool lineBeginsWith(char charToCheck) const; - void appendChar(char ch, bool canBreakLine = true); - void appendCharInsideComments(); - void appendSequence(const WString &sequence, bool canBreakLine = true); - void appendSpacePad(); - void appendSpaceAfter(); - void breakLine(); - void padOperators(const WString *newOperator); - void padParens(); - void formatBrackets(BracketType bracketType); - void formatArrayBrackets(BracketType bracketType, bool isOpeningArrayBracket); - void adjustComments(); - const WString *findHeader(const Vector &headers, bool checkBoundry = true); - - static Vector headers; - static Vector nonParenHeaders; - static Vector preDefinitionHeaders; - static Vector preCommandHeaders; - static Vector operators; - static Vector assignmentOperators; - static Vector castOperators; - - ASSourceIterator *sourceIterator; - Vector *preBracketHeaderStack; - Vector *bracketTypeStack; - Vector *parenStack; - WString readyFormattedLine; - WString currentLine; - WString formattedLine; - const WString *currentHeader; - const WString *previousOperator; // used ONLY by pad=oper - char currentChar; - char previousChar; - char previousNonWSChar; - char previousCommandChar; - char quoteChar; - int charNum; - int spacePadNum; - int templateDepth; - int traceFileNumber; - int formattedLineCommentNum; // comment location on formattedLine - int previousReadyFormattedLineLength; - BracketMode bracketFormatMode; - BracketType previousBracketType; - bool isVirgin; - bool shouldPadOperators; - bool shouldPadParensOutside; - bool shouldPadParensInside; - bool shouldUnPadParens; - bool shouldConvertTabs; - bool isInLineComment; - bool isInComment; - bool isInPreprocessor; - bool isInTemplate; // true both in template definitions (e.g. template) and template usage (e.g. F). - bool doesLineStartComment; - bool isInQuote; - bool isInBlParen; - bool isSpecialChar; - bool isNonParenHeader; - bool foundQuestionMark; - bool foundPreDefinitionHeader; - bool foundNamespaceHeader; - bool foundClassHeader; - bool foundPreCommandHeader; - bool foundCastOperator; - bool isInLineBreak; -// bool isInClosingBracketLineBreak; - bool endOfCodeReached; - bool lineCommentNoIndent; - bool isLineReady; - bool isPreviousBracketBlockRelated; - bool isInPotentialCalculation; - bool isCharImmediatelyPostComment; - bool isPreviousCharPostComment; - bool isCharImmediatelyPostLineComment; - bool isCharImmediatelyPostOpenBlock; - bool isCharImmediatelyPostCloseBlock; - bool isCharImmediatelyPostTemplate; - bool shouldBreakOneLineBlocks; - bool shouldReparseCurrentChar; - bool shouldBreakOneLineStatements; - bool shouldBreakLineAfterComments; - bool shouldBreakClosingHeaderBrackets; - bool shouldBreakElseIfs; - bool passedSemicolon; - bool passedColon; - bool isImmediatelyPostComment; - bool isImmediatelyPostLineComment; - bool isImmediatelyPostEmptyBlock; - bool isImmediatelyPostPreprocessor; - - bool shouldBreakBlocks; - bool shouldBreakClosingHeaderBlocks; - bool isPrependPostBlockEmptyLineRequested; - bool isAppendPostBlockEmptyLineRequested; - - bool prependEmptyLine; - bool appendOpeningBracket; - bool foundClosingHeader; - - bool isInHeader; - bool isImmediatelyPostHeader; - - private: // inline functions - // append the CURRENT character (curentChar)to the current formatted line. - inline void appendCurrentChar(bool canBreakLine = true) { - appendChar(currentChar, canBreakLine); - } - - // check if a specific sequence exists in the current placement of the current line - inline bool isSequenceReached(const char *sequence) const { -// return currentLine.compare(charNum, strlen(sequence), sequence) == 0; - return currentLine.Mid(charNum, strlen(sequence)) == WString(sequence); - } -}; - -} // end of namespace astyle - -// NEEDED FOR Upp::Vector<> -// marks enum BracketType as moveable so it can be used by Upp containers -namespace Upp -{ - NTL_MOVEABLE(astyle::BracketType); - -} // end namespace Upp - -#endif // closes ASTYLE_H - diff --git a/uppdev/plugin/astyle/astyle.upp b/uppdev/plugin/astyle/astyle.upp deleted file mode 100644 index e89c55823..000000000 --- a/uppdev/plugin/astyle/astyle.upp +++ /dev/null @@ -1,12 +0,0 @@ -uses - Core; - -file - ASStringTools.hpp, - ASStringTools.cpp, - astyle.h, - ASBeautifier.cpp, - ASEnhancer.cpp, - ASFormatter.cpp, - ASResource.cpp; - diff --git a/uppdev/plugin/astyle/astyle_main.cpp b/uppdev/plugin/astyle/astyle_main.cpp deleted file mode 100644 index 7d9515805..000000000 --- a/uppdev/plugin/astyle/astyle_main.cpp +++ /dev/null @@ -1,1138 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * - * astyle_main.cpp - * - * This file is a part of "Artistic Style" - an indentation and - * reformatting tool for C, C++, C# and Java source files. - * http://astyle.sourceforge.net - * - * The "Artistic Style" project, including all files needed to - * compile it, is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later - * version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this project; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - */ - -#include "astyle.h" - -#include -#include -#include -#include -#include - -#ifndef ASTYLE_LIB // for console build only -#if defined(_MSC_VER) || defined(__DMC__) -#include -#include -//#define utimbuf _utimbuf -//#define utime _utime -#else -#include -#include -#endif // end compiler checks -#endif // end ASTYLE_LIB - -// for G++ implementation of string.compare: -// compare((str), (place), (length)) instead of compare(place, length, str) -#if defined(__GNUC__) && __GNUC__ < 3 -#error - Use GNU C compiler release 3 or higher -#endif - -// for namespace problem in version 5.0 -#if defined(_MSC_VER) && _MSC_VER < 1200 // check for V6.0 -#error - Use Microsoft compiler version 6 or higher -#endif - -#ifdef _WIN32 -#define STDCALL __stdcall -#define EXPORT __declspec(dllexport) -#else -#define STDCALL -#define EXPORT -#endif - -#define IS_OPTION(arg,op) ((arg).compare(op)==0) -#define IS_OPTIONS(arg,a,b) (IS_OPTION((arg),(a)) || IS_OPTION((arg),(b))) - -#define GET_PARAM(arg,op) ((arg).substr(strlen(op))) -#define GET_PARAMS(arg,a,b) (isParamOption((arg),(a)) ? GET_PARAM((arg),(a)) : GET_PARAM((arg),(b))) - -using namespace astyle; - -const char* _version = "1.21"; - -// some compilers want this declared -bool parseOption(ASFormatter &formatter, const string &arg, const string &errorInfo); - -#ifdef ASTYLE_LIB -// GUI function pointers -typedef void (STDCALL *fpError)(int, char*); // pointer to callback error handler -typedef char* (STDCALL *fpAlloc)(unsigned long); // pointer to callback memory allocation -// GUI variables -stringstream *_err = NULL; -#else -// console variables -ostream *_err = &cerr; -bool _purgeOrigIn = false; -bool _preserveDate = false; -string _suffix = ".orig"; -stringstream _msg; // info messages are not printed until a file is read -#endif -bool _modeManuallySet = false; - - -// typename will be istringstream for GUI and istream otherwise -template -class ASStreamIterator : - public ASSourceIterator -{ - public: - ASStreamIterator(T *in); - virtual ~ASStreamIterator(); - bool hasMoreLines() const; - string nextLine(); - - private: - T * inStream; - string buffer; - bool inStreamEOF; -}; - -template -ASStreamIterator::ASStreamIterator(T *in) -{ - inStream = in; - buffer.reserve(200); - inStreamEOF = false; -} - - -template -ASStreamIterator::~ASStreamIterator() -{ -} - - -template -bool ASStreamIterator::hasMoreLines() const -{ - return !inStreamEOF; -} - - -/** - * read the input stream, delete any end of line characters, - * and build a string that contains the input line. - * - * @return string containing the next input line minus any end of line characters - */ -template -string ASStreamIterator::nextLine() -{ - char ch; - char LF = '\n'; - char CR = '\r'; - inStream->get(ch); - buffer.clear(); - - while (!inStream->eof() && ch != LF && ch != CR) - { - buffer.append(1, ch); - inStream->get(ch); - } - - if (inStream->eof()) - { - inStreamEOF = true; - return buffer; - } - - int peekch = inStream->peek(); - - if (ch == CR) // CR+LF is windows otherwise Mac OS 9 - { - if (peekch == LF) - { - inStream->get(); - eolWindows++; - } - else - eolMacOld++; - } - else // LF is Linux, allow for improbable LF/CR - { - if (peekch == CR) - { - inStream->get(); - eolWindows++; - } - else - eolLinux++; - } - - // set output end of line character - if (eolWindows >= eolLinux) - if (eolWindows >= eolMacOld) - strcpy(outputEOL, "\r\n"); // Windows (CR+LF) - else - strcpy(outputEOL, "\r"); // MacOld (CR) - else - if (eolLinux >= eolMacOld) - strcpy(outputEOL, "\n"); // Linux (LF) - else - strcpy(outputEOL, "\r"); // MacOld (CR) - - return buffer; -} - - -template -bool parseOptions(ASFormatter &formatter, - const ITER &optionsBegin, - const ITER &optionsEnd, - const string &errorInfo) -{ - ITER option; - bool ok = true; - string arg, subArg; - - for (option = optionsBegin; option != optionsEnd; ++option) - { - arg = *option; - - if (arg.compare(0, 2, "--") == 0) - ok &= parseOption(formatter, arg.substr(2), errorInfo); - else if (arg[0] == '-') - { - size_t i; - - for (i = 1; i < arg.length(); ++i) - { - if (isalpha(arg[i]) && i > 1) - { - ok &= parseOption(formatter, subArg, errorInfo); - subArg = ""; - } - subArg.append(1, arg[i]); - } - ok &= parseOption(formatter, subArg, errorInfo); - subArg = ""; - } - else - { - ok &= parseOption(formatter, arg, errorInfo); - subArg = ""; - } - } - return ok; -} - -void importOptions(istream &in, vector &optionsVector) -{ - char ch; - string currentToken; - - while (in) - { - currentToken = ""; - do - { - in.get(ch); - if (in.eof()) - break; - // treat '#' as line comments - if (ch == '#') - while (in) - { - in.get(ch); - if (ch == '\n') - break; - } - - // break options on spaces, tabs or new-lines - if (in.eof() || ch == ' ' || ch == '\t' || ch == '\n') - break; - else - currentToken.append(1, ch); - - } - while (in); - - if (currentToken.length() != 0) - optionsVector.push_back(currentToken); - } -} - -bool isParamOption(const string &arg, const char *option) -{ - bool retVal = arg.compare(0, strlen(option), option) == 0; - // if comparing for short option, 2nd char of arg must be numeric - if (retVal && strlen(option) == 1 && arg.length() > 1) - if (!isdigit(arg[1])) - retVal = false; - return retVal; -} - -void isOptionError(const string &arg, const string &errorInfo) -{ -#ifdef ASTYLE_LIB - if (_err->str().length() == 0) - { - (*_err) << errorInfo << endl; // need main error message - (*_err) << arg; // output the option in error - } - else - (*_err) << endl << arg; // put endl after previous option -#else - if (errorInfo.length() > 0) // to avoid a compiler warning - (*_err) << "Error in param: " << arg << endl; -#endif -} - -bool isParamOption(const string &arg, const char *option1, const char *option2) -{ - return isParamOption(arg, option1) || isParamOption(arg, option2); -} - - -bool parseOption(ASFormatter &formatter, const string &arg, const string &errorInfo) -{ - if ( IS_OPTION(arg, "style=ansi") ) - { - formatter.setSpaceIndentation(4); - formatter.setBracketFormatMode(BREAK_MODE); - formatter.setBracketIndent(false); - formatter.setClassIndent(false); - formatter.setSwitchIndent(false); - formatter.setNamespaceIndent(false); - } - else if ( IS_OPTION(arg, "style=gnu") ) - { - formatter.setSpaceIndentation(2); - formatter.setBracketFormatMode(BREAK_MODE); - formatter.setBlockIndent(true); - formatter.setClassIndent(false); - formatter.setSwitchIndent(false); - formatter.setNamespaceIndent(false); - } - else if ( IS_OPTION(arg, "style=java") ) - { -// formatter.setJavaStyle(); -// _modeManuallySet = true; - formatter.setSpaceIndentation(4); - formatter.setBracketFormatMode(ATTACH_MODE); - formatter.setBracketIndent(false); - formatter.setSwitchIndent(false); - } - else if ( IS_OPTION(arg, "style=kr") ) - { - //manuallySetCStyle(formatter); - formatter.setSpaceIndentation(4); - formatter.setBracketFormatMode(ATTACH_MODE); - formatter.setBracketIndent(false); - formatter.setClassIndent(false); - formatter.setSwitchIndent(false); - formatter.setNamespaceIndent(false); - } - else if ( IS_OPTION(arg, "style=linux") ) - { - formatter.setSpaceIndentation(8); - formatter.setBracketFormatMode(BDAC_MODE); - formatter.setBracketIndent(false); - formatter.setClassIndent(false); - formatter.setSwitchIndent(false); - formatter.setNamespaceIndent(false); - } - // must check for mode=cs before mode=c !!! - else if ( IS_OPTION(arg, "mode=cs") ) - { - formatter.setSharpStyle(); - _modeManuallySet = true; - } - else if ( IS_OPTION(arg, "mode=c") ) - { - formatter.setCStyle(); - _modeManuallySet = true; - } - else if ( IS_OPTION(arg, "mode=java") ) - { - formatter.setJavaStyle(); - _modeManuallySet = true; - } - else if ( isParamOption(arg, "t", "indent=tab=") ) - { - int spaceNum = 4; - string spaceNumParam = GET_PARAMS(arg, "t", "indent=tab="); - if (spaceNumParam.length() > 0) - spaceNum = atoi(spaceNumParam.c_str()); - if (spaceNum < 2 || spaceNum > 20) - isOptionError(arg, errorInfo); - else - formatter.setTabIndentation(spaceNum, false); - } - else if ( isParamOption(arg, "T", "force-indent=tab=") ) - { - int spaceNum = 4; - string spaceNumParam = GET_PARAMS(arg, "T", "force-indent=tab="); - if (spaceNumParam.length() > 0) - spaceNum = atoi(spaceNumParam.c_str()); - if (spaceNum < 2 || spaceNum > 20) - isOptionError(arg, errorInfo); - else - formatter.setTabIndentation(spaceNum, true); - } - else if ( IS_OPTION(arg, "indent=tab") ) - { - formatter.setTabIndentation(4); - } - else if ( isParamOption(arg, "s", "indent=spaces=") ) - { - int spaceNum = 4; - string spaceNumParam = GET_PARAMS(arg, "s", "indent=spaces="); - if (spaceNumParam.length() > 0) - spaceNum = atoi(spaceNumParam.c_str()); - if (spaceNum < 2 || spaceNum > 20) - isOptionError(arg, errorInfo); - else - formatter.setSpaceIndentation(spaceNum); - } - else if ( IS_OPTION(arg, "indent=spaces") ) - { - formatter.setSpaceIndentation(4); - } - else if ( isParamOption(arg, "m", "min-conditional-indent=") ) - { - int minIndent = 8; - string minIndentParam = GET_PARAMS(arg, "m", "min-conditional-indent="); - if (minIndentParam.length() > 0) - minIndent = atoi(minIndentParam.c_str()); - if (minIndent > 40) - isOptionError(arg, errorInfo); - else - formatter.setMinConditionalIndentLength(minIndent); - } - else if ( isParamOption(arg, "M", "max-instatement-indent=") ) - { - int maxIndent = 40; - string maxIndentParam = GET_PARAMS(arg, "M", "max-instatement-indent="); - if (maxIndentParam.length() > 0) - maxIndent = atoi(maxIndentParam.c_str()); - if (maxIndent > 80) - isOptionError(arg, errorInfo); - else - formatter.setMaxInStatementIndentLength(maxIndent); - } - else if ( IS_OPTIONS(arg, "B", "indent-brackets") ) - { - formatter.setBracketIndent(true); - } - else if ( IS_OPTIONS(arg, "G", "indent-blocks") ) - { - formatter.setBlockIndent(true); - } - else if ( IS_OPTIONS(arg, "N", "indent-namespaces") ) - { - formatter.setNamespaceIndent(true); - } - else if ( IS_OPTIONS(arg, "C", "indent-classes") ) - { - formatter.setClassIndent(true); - } - else if ( IS_OPTIONS(arg, "S", "indent-switches") ) - { - formatter.setSwitchIndent(true); - } - else if ( IS_OPTIONS(arg, "K", "indent-cases") ) - { - formatter.setCaseIndent(true); - } - else if ( IS_OPTIONS(arg, "L", "indent-labels") ) - { - formatter.setLabelIndent(true); - } - else if ( IS_OPTIONS(arg, "y", "brackets=break-closing") ) - { - formatter.setBreakClosingHeaderBracketsMode(true); - } - else if ( IS_OPTIONS(arg, "b", "brackets=break") ) - { - formatter.setBracketFormatMode(BREAK_MODE); - } - else if ( IS_OPTIONS(arg, "a", "brackets=attach") ) - { - formatter.setBracketFormatMode(ATTACH_MODE); - } - else if ( IS_OPTIONS(arg, "l", "brackets=linux") ) - { - formatter.setBracketFormatMode(BDAC_MODE); - } - else if ( IS_OPTIONS(arg, "O", "one-line=keep-blocks") ) - { - formatter.setBreakOneLineBlocksMode(false); - } - else if ( IS_OPTIONS(arg, "o", "one-line=keep-statements") ) - { - formatter.setSingleStatementsMode(false); - } - else if ( IS_OPTIONS(arg, "P", "pad=paren") ) - { - formatter.setParensOutsidePaddingMode(true); - formatter.setParensInsidePaddingMode(true); - } - else if ( IS_OPTIONS(arg, "d", "pad=paren-out") ) - { - formatter.setParensOutsidePaddingMode(true); - } - else if ( IS_OPTIONS(arg, "D", "pad=paren-in") ) - { - formatter.setParensInsidePaddingMode(true); - } - else if ( IS_OPTIONS(arg, "U", "unpad=paren") ) - { - formatter.setParensUnPaddingMode(true); - } - else if ( IS_OPTIONS(arg, "p", "pad=oper") ) - { - formatter.setOperatorPaddingMode(true); - } - else if ( IS_OPTIONS(arg, "E", "fill-empty-lines") ) - { - formatter.setEmptyLineFill(true); - } - else if ( IS_OPTIONS(arg, "w", "indent-preprocessor") ) - { - formatter.setPreprocessorIndent(true); - } - else if ( IS_OPTIONS(arg, "V", "convert-tabs") ) - { - formatter.setTabSpaceConversionMode(true); - } - else if ( IS_OPTIONS(arg, "F", "break-blocks=all") ) - { - formatter.setBreakBlocksMode(true); - formatter.setBreakClosingHeaderBlocksMode(true); - } - else if ( IS_OPTIONS(arg, "f", "break-blocks") ) - { - formatter.setBreakBlocksMode(true); - } - else if ( IS_OPTIONS(arg, "e", "break-elseifs") ) - { - formatter.setBreakElseIfsMode(true); - } -#ifdef ASTYLE_LIB - // End of options used by GUI - else - isOptionError(arg, errorInfo); -#else - // Options used by only console - else if ( IS_OPTIONS(arg, "n", "suffix=none") ) - { - _purgeOrigIn = true; - } - else if ( isParamOption(arg, "suffix=") ) - { - string suffixParam = GET_PARAM(arg, "suffix="); - if (suffixParam.length() > 0) - { - _suffix = suffixParam; -// if (_suffix[0] != '.') -// _suffix = '.' + _suffix; - } - } - else if ( IS_OPTIONS(arg, "Z", "preserve-date") ) - { - _preserveDate =true; - } - else if ( IS_OPTIONS(arg, "X", "errors-to-stdout") ) - { - _err = &cout; - } - else if ( IS_OPTIONS(arg, "v", "version") ) - { - (*_err) << "Artistic Style " << _version << endl; - exit(0); - } - else - { - (*_err) << errorInfo << arg << endl; - return false; // unknown option - } -#endif -// End of parseOption function - return true; //o.k. -} - - -#ifdef ASTYLE_LIB -// ************************* GUI functions ***************************************************** -/* - * IMPORTANT VC DLL linker must have the parameter /EXPORT:AStyleMain=_AStyleMain@16 - * /EXPORT:AStyleGetVersion=_AStyleGetVersion@0 - * For Dll only - "warning C4702: unreachable code" in the header - * is caused by using the Optimization options. - * /O2 Maximize speed - * /O1 Minimize size - * /Ob2 Inline Expansion - * This is a bug in the Microsoft compiler. The program runs about twice as fast - * with the options set. There haven't been any problems so far. -*/ -extern "C" EXPORT char* STDCALL - AStyleMain(const char* pSourceIn, // pointer to the source to be formatted - const char* pOptions, // pointer to AStyle options, separated by \n - fpError fpErrorHandler, // pointer to error handler function - fpAlloc fpMemoryAlloc) // pointer to memory allocation function -{ - if (fpErrorHandler == NULL) // cannot display a message if no error handler - return NULL; - - if (pSourceIn == NULL) - { - fpErrorHandler(101, "No pointer to source input"); - return NULL; - } - if (pOptions == NULL) - { - fpErrorHandler(102, "No pointer to AStyle options"); - return NULL; - } - if (fpMemoryAlloc == NULL) - { - fpErrorHandler(103, "No pointer to memory allocation function"); - return NULL; - } - - ASFormatter formatter; - - string arg; - vector optionsVector; - istringstream opt(pOptions); - _err = new stringstream; - _modeManuallySet = false; - - importOptions(opt, optionsVector); - - parseOptions(formatter, - optionsVector.begin(), - optionsVector.end(), - "Unknown Artistic Style options\n" - "The following options were not processed:"); - - if (_err->str().length() > 0) - fpErrorHandler(210, (char*) _err->str().c_str()); - - delete _err; - _err = NULL; - - istringstream in(pSourceIn); - ASStreamIterator streamIterator(&in); - ostringstream out; - formatter.init(&streamIterator); - - while (formatter.hasMoreLines()) - { - out << formatter.nextLine(); - out << streamIterator.outputEOL; - } - - unsigned long textSizeOut = out.str().length(); - char* pTextOut = fpMemoryAlloc(textSizeOut + 1); // call memory allocation function -// pTextOut = NULL; // for testing - if (pTextOut == NULL) - { - fpErrorHandler(110, "Allocation failure on output"); - return NULL; - } - - strcpy(pTextOut, out.str().c_str()); - - return pTextOut; -} - -extern "C" EXPORT const char* STDCALL AStyleGetVersion (void) -{ - return _version; -} - -#else - -void preserveFileDate(const char *oldFileName, const char *newFileName) -{ - struct stat stBuf; - bool statErr = false; - if (stat (oldFileName, &stBuf) == -1) - statErr = true; - else - { - struct utimbuf outBuf; - outBuf.actime = stBuf.st_atime; - // add 1 so RCS will recoginze a change - outBuf.modtime = stBuf.st_mtime + 1; - if (utime (newFileName, &outBuf) == -1) - statErr = true; - } - if (statErr) - (*_err) << " Could not preserve file date" << endl; -} - -bool stringEndsWith(const string &str, const string &suffix) -{ - int strIndex = (int) str.length() - 1; - int suffixIndex = (int) suffix.length() - 1; - - while (strIndex >= 0 && suffixIndex >= 0) - { - if (tolower(str[strIndex]) != tolower(suffix[suffixIndex])) - return false; - - --strIndex; - --suffixIndex; - } - - return true; -} - - -void error(const char *why, const char* what) -{ - (*_err) << why << ' ' << what << '\n' << endl; - exit(1); -} - - -void printHelp() -{ - (*_err) << endl; - (*_err) << " Artistic Style " << _version << endl; - (*_err) << " Maintained by: Jim Pattee\n"; - (*_err) << " Original Author: Tal Davidson\n"; - (*_err) << endl; - (*_err) << "Usage : astyle [options] Source1.cpp Source2.cpp [...]\n"; - (*_err) << " astyle [options] < Original > Beautified\n"; - (*_err) << endl; - (*_err) << "When indenting a specific file, the resulting indented file RETAINS the\n"; - (*_err) << "original file-name. The original pre-indented file is renamed, with a\n"; - (*_err) << "suffix of \".orig\" added to the original filename.\n"; - (*_err) << endl; - (*_err) << "By default, astyle is set up to indent C/C++/C#/Java files, with 4 spaces\n"; - (*_err) << "per indent, a maximal indentation of 40 spaces inside continuous statements,\n"; - (*_err) << "and NO formatting.\n"; - (*_err) << endl; - (*_err) << "Option's Format:\n"; - (*_err) << "----------------\n"; - (*_err) << " Long options (starting with '--') must be written one at a time.\n"; - (*_err) << " Short options (starting with '-') may be appended together.\n"; - (*_err) << " Thus, -bps4 is the same as -b -p -s4.\n"; - (*_err) << endl; - (*_err) << "Predefined Style Options:\n"; - (*_err) << "-------------------------\n"; - (*_err) << " --style=ansi\n"; - (*_err) << " ANSI style formatting/indenting.\n"; - (*_err) << endl; - (*_err) << " --style=gnu\n"; - (*_err) << " GNU style formatting/indenting.\n"; - (*_err) << endl; - (*_err) << " --style=kr\n"; - (*_err) << " Kernighan&Ritchie style formatting/indenting.\n"; - (*_err) << endl; - (*_err) << " --style=linux\n"; - (*_err) << " Linux mode (8 spaces per indent, break definition-block\n"; - (*_err) << " brackets but attach command-block brackets).\n"; - (*_err) << endl; - (*_err) << " --style=java\n"; - (*_err) << " Java mode, with standard java style formatting/indenting.\n"; - (*_err) << endl; - (*_err) << "Tab and Bracket Options:\n"; - (*_err) << "------------------------\n"; - (*_err) << " default indent option\n"; - (*_err) << " If no indentation option is set,\n"; - (*_err) << " the default option of 4 spaces will be used.\n"; - (*_err) << endl; - (*_err) << " --indent=spaces=# OR -s#\n"; - (*_err) << " Indent using # spaces per indent. Not specifying #\n"; - (*_err) << " will result in a default of 4 spaces per indent.\n"; - (*_err) << endl; - (*_err) << " --indent=tab OR --indent=tab=# OR -t OR -t#\n"; - (*_err) << " Indent using tab characters, assuming that each\n"; - (*_err) << " tab is # spaces long. Not specifying # will result\n"; - (*_err) << " in a default assumption of 4 spaces per tab.\n"; - (*_err) << endl; - (*_err) << " --force-indent=tab=# OR -T#\n"; - (*_err) << " Indent using tab characters, assuming that each\n"; - (*_err) << " tab is # spaces long. Force tabs to be used in areas\n"; - (*_err) << " Astyle would prefer to use spaces.\n"; - (*_err) << endl; - (*_err) << " default brackets option\n"; - (*_err) << " If no brackets option is set,\n"; - (*_err) << " the brackets will not be changed.\n"; - (*_err) << endl; - (*_err) << " --brackets=break OR -b\n"; - (*_err) << " Break brackets from pre-block code (i.e. ANSI C/C++ style).\n"; - (*_err) << endl; - (*_err) << " --brackets=attach OR -a\n"; - (*_err) << " Attach brackets to pre-block code (i.e. Java/K&R style).\n"; - (*_err) << endl; - (*_err) << " --brackets=linux OR -l\n"; - (*_err) << " Break definition-block brackets and attach command-block\n"; - (*_err) << " brackets.\n"; - (*_err) << endl; - (*_err) << " --brackets=break-closing OR -y\n"; - (*_err) << " Break brackets before closing headers (e.g. 'else', 'catch', ...).\n"; - (*_err) << " Should be appended to --brackets=attach or --brackets=linux.\n"; - (*_err) << endl; - (*_err) << "Indentation options:\n"; - (*_err) << "--------------------\n"; - (*_err) << " --indent-classes OR -C\n"; - (*_err) << " Indent 'class' blocks, so that the inner 'public:',\n"; - (*_err) << " 'protected:' and 'private: headers are indented in\n"; - (*_err) << " relation to the class block.\n"; - (*_err) << endl; - (*_err) << " --indent-switches OR -S\n"; - (*_err) << " Indent 'switch' blocks, so that the inner 'case XXX:'\n"; - (*_err) << " headers are indented in relation to the switch block.\n"; - (*_err) << endl; - (*_err) << " --indent-cases OR -K\n"; - (*_err) << " Indent case blocks from the 'case XXX:' headers.\n"; - (*_err) << " Case statements not enclosed in blocks are NOT indented.\n"; - (*_err) << endl; - (*_err) << " --indent-brackets OR -B\n"; - (*_err) << " Add extra indentation to '{' and '}' block brackets.\n"; - (*_err) << endl; - (*_err) << " --indent-blocks OR -G\n"; - (*_err) << " Add extra indentation entire blocks (including brackets).\n"; - (*_err) << endl; - (*_err) << " --indent-namespaces OR -N\n"; - (*_err) << " Indent the contents of namespace blocks.\n"; - (*_err) << endl; - (*_err) << " --indent-labels OR -L\n"; - (*_err) << " Indent labels so that they appear one indent less than\n"; - (*_err) << " the current indentation level, rather than being\n"; - (*_err) << " flushed completely to the left (which is the default).\n"; - (*_err) << endl; - (*_err) << " --indent-preprocessor OR -w\n"; - (*_err) << " Indent multi-line #define statements.\n"; - (*_err) << endl; - (*_err) << " --max-instatement-indent=# OR -M#\n"; - (*_err) << " Indent a maximal # spaces in a continuous statement,\n"; - (*_err) << " relative to the previous line.\n"; - (*_err) << endl; - (*_err) << " --min-conditional-indent=# OR -m#\n"; - (*_err) << " Indent a minimal # spaces in a continuous conditional\n"; - (*_err) << " belonging to a conditional header.\n"; - (*_err) << endl; - (*_err) << "Formatting options:\n"; - (*_err) << "-------------------\n"; - (*_err) << " --break-blocks OR -f\n"; - (*_err) << " Insert empty lines around unrelated blocks, labels, classes, ...\n"; - (*_err) << endl; - (*_err) << " --break-blocks=all OR -F\n"; - (*_err) << " Like --break-blocks, except also insert empty lines \n"; - (*_err) << " around closing headers (e.g. 'else', 'catch', ...).\n"; - (*_err) << endl; - (*_err) << " --break-elseifs OR -e\n"; - (*_err) << " Break 'else if()' statements into two different lines.\n"; - (*_err) << endl; - (*_err) << " --pad=oper OR -p\n"; - (*_err) << " Insert space paddings around operators.\n"; - (*_err) << endl; - (*_err) << " --pad=paren OR -P\n"; - (*_err) << " Insert space padding around parenthesis on both the outside\n"; - (*_err) << " and the inside.\n"; - (*_err) << endl; - (*_err) << " --pad=paren-out OR -d\n"; - (*_err) << " Insert space padding around parenthesis on the outside only.\n"; - (*_err) << endl; - (*_err) << " --pad=paren-in OR -D\n"; - (*_err) << " Insert space padding around parenthesis on the inside only.\n"; - (*_err) << endl; - (*_err) << " --unpad=paren OR -U\n"; - (*_err) << " Remove unnecessary space padding around parenthesis. This\n"; - (*_err) << " can be used in combination with the 'pad' options above.\n"; - (*_err) << endl; - (*_err) << " --one-line=keep-statements OR -o\n"; - (*_err) << " Don't break lines containing multiple statements into\n"; - (*_err) << " multiple single-statement lines.\n"; - (*_err) << endl; - (*_err) << " --one-line=keep-blocks OR -O\n"; - (*_err) << " Don't break blocks residing completely on one line.\n"; - (*_err) << endl; - (*_err) << " --convert-tabs OR -V\n"; - (*_err) << " Convert tabs to spaces.\n"; - (*_err) << endl; - (*_err) << " --fill-empty-lines OR -E\n"; - (*_err) << " Fill empty lines with the white space of their\n"; - (*_err) << " previous lines.\n"; - (*_err) << endl; - (*_err) << " --mode=c OR -c\n"; - (*_err) << " Indent a C, C++ or C# source file (this is the default).\n"; - (*_err) << endl; - (*_err) << " --mode=java OR -j\n"; - (*_err) << " Indent a Java(TM) source file.\n"; - (*_err) << endl; - (*_err) << "Other options:\n"; - (*_err) << "--------------\n"; - (*_err) << " --suffix=####\n"; - (*_err) << " Append the suffix #### instead of '.orig' to original filename.\n"; - (*_err) << endl; - (*_err) << " --suffix=none OR -n\n"; - (*_err) << " Do not retain a backup of the original file.\n"; - (*_err) << endl; - (*_err) << " --options=####\n"; - (*_err) << " Specify an options file #### to read and use.\n"; - (*_err) << endl; - (*_err) << " --options=none\n"; - (*_err) << " Disable the default options file.\n"; - (*_err) << " Only the command-line parameters will be used.\n"; - (*_err) << endl; - (*_err) << " --preserve-date OR -Z\n"; - (*_err) << " The date and time modified will not be changed in the formatted file.\n"; - (*_err) << endl; - (*_err) << " --errors-to-stdout OR -X\n"; - (*_err) << " Print errors and help information to standard-output rather than\n"; - (*_err) << " to standard-error.\n"; - (*_err) << endl; - (*_err) << " --version OR -v\n"; - (*_err) << " Print version number.\n"; - (*_err) << endl; - (*_err) << " --help OR -h OR -?\n"; - (*_err) << " Print this help message.\n"; - (*_err) << endl; - (*_err) << "Default options file:\n"; - (*_err) << "---------------------\n"; - (*_err) << " Artistic Style looks for a default options file in the\n"; - (*_err) << " following order:\n"; - (*_err) << " 1. The contents of the ARTISTIC_STYLE_OPTIONS environment\n"; - (*_err) << " variable if it exists.\n"; - (*_err) << " 2. The file called .astylerc in the directory pointed to by the\n"; - (*_err) << " HOME environment variable ( i.e. $HOME/.astylerc ).\n"; - (*_err) << " 3. The file called astylerc in the directory pointed to by the\n"; - (*_err) << " USERPROFILE environment variable ( i.e. %USERPROFILE%\\astylerc ).\n"; - (*_err) << " If a default options file is found, the options in this file\n"; - (*_err) << " will be parsed BEFORE the command-line options.\n"; - (*_err) << " Long options within the default option file may be written without\n"; - (*_err) << " the preliminary '--'.\n"; - (*_err) << endl; -} - -int main(int argc, char *argv[]) -{ - ASFormatter formatter; - vector fileNameVector; - vector optionsVector; - string optionsFileName = ""; - string arg; - bool ok = true; - bool shouldPrintHelp = false; - bool shouldParseOptionsFile = true; - - _modeManuallySet = false; - - _msg << "\nArtistic Style " << _version << endl; - // manage flags - for (int i = 1; i < argc; i++) - { - arg = string(argv[i]); - - if ( IS_OPTION(arg, "--options=none") ) - { - shouldParseOptionsFile = false; - } - else if ( isParamOption(arg, "--options=") ) - { - optionsFileName = GET_PARAM(arg, "--options="); - } - else if ( IS_OPTION(arg, "-h") - || IS_OPTION(arg, "--help") - || IS_OPTION(arg, "-?") ) - { - shouldPrintHelp = true; - } - else if (arg[0] == '-') - { - optionsVector.push_back(arg); - } - else // file-name - { - fileNameVector.push_back(arg); - } - } - - // parse options file - if (shouldParseOptionsFile) - { - if (optionsFileName.compare("") == 0) - { - char* env = getenv("ARTISTIC_STYLE_OPTIONS"); - if (env != NULL) - optionsFileName = string(env); - } - if (optionsFileName.compare("") == 0) - { - char* env = getenv("HOME"); - if (env != NULL) - optionsFileName = string(env) + string("/.astylerc"); - } - if (optionsFileName.compare("") == 0) - { - char* env = getenv("USERPROFILE"); - if (env != NULL) - optionsFileName = string(env) + string("/astylerc"); - } - - if (optionsFileName.compare("") != 0) - { - ifstream optionsIn(optionsFileName.c_str()); - if (optionsIn) - { - _msg << "Using default options file " << optionsFileName << endl; - vector fileOptionsVector; - importOptions(optionsIn, fileOptionsVector); - ok = parseOptions(formatter, - fileOptionsVector.begin(), - fileOptionsVector.end(), - string("Unknown option in default options file: ")); - } - - optionsIn.close(); - if (!ok) - { - (*_err) << "For help on options, type 'astyle -h' " << endl; - } - } - } - - // parse options from command line - - ok = parseOptions(formatter, - optionsVector.begin(), - optionsVector.end(), - string("Unknown command line option: ")); - if (!ok) - { - (*_err) << "For help on options, type 'astyle -h' \n" << endl; - exit(1); - } - - if (shouldPrintHelp) - { - printHelp(); - exit(0); - } - - // if no files have been given, use cin for input and cout for output - // this is used to format text for text editors like TextWrangler - // do NOT display any console messages when this branch is used - if (fileNameVector.empty()) - { - ASStreamIterator streamIterator(&cin); - - formatter.init(&streamIterator); - - while (formatter.hasMoreLines()) - { - cout << formatter.nextLine(); - if (formatter.hasMoreLines()) - cout << streamIterator.outputEOL; - } - cout.flush(); - } - else - { - // indent the given files - cout << _msg.str().c_str(); - clock_t startTime = clock(); - for (size_t i = 0; i < fileNameVector.size(); i++) - { - string originalFileName = fileNameVector[i]; - string inFileName = originalFileName + _suffix; - - remove(inFileName.c_str()); // remove the old .orig if present - - // check if the file is present before rename - ifstream inCheck(originalFileName.c_str()); - if (!inCheck) - error("Could not open input file", originalFileName.c_str()); - inCheck.close(); - - if (rename(originalFileName.c_str(), inFileName.c_str()) < 0) - error("Could not rename ", string(originalFileName + " to " + inFileName).c_str()); - - ifstream in(inFileName.c_str(), ios::binary); - if (!in) - error("Could not open input file", inFileName.c_str()); - - ofstream out(originalFileName.c_str(), ios::binary); - if (!out) - error("Could not open output file", originalFileName.c_str()); - - // Unless a specific language mode has been, set the language mode - // according to the file's suffix. - if (!_modeManuallySet) - { - if (stringEndsWith(originalFileName, string(".java"))) - formatter.setJavaStyle(); - else if (stringEndsWith(originalFileName, string(".cs"))) - formatter.setSharpStyle(); - else - formatter.setCStyle(); - } - // display file formatting message and save the filename - cout << "formatting " << originalFileName.c_str() << endl; - size_t fname = originalFileName.find_last_of("/\\"); - if (fname == string::npos) - fname = 0; - else - fname +=1; - formatter.fileName = originalFileName.substr(fname); - - ASStreamIterator streamIterator(&in); - formatter.init(&streamIterator); - - while (formatter.hasMoreLines()) - { - out << formatter.nextLine(); - // the last line does not get an eol - if (formatter.hasMoreLines()) - out << streamIterator.outputEOL; - } - out.flush(); - out.close(); - in.close(); - - // change date modified to original file date - if (_preserveDate) - preserveFileDate(inFileName.c_str(), originalFileName.c_str()); - - if (_purgeOrigIn) - remove(inFileName.c_str()); - } - // all files formatted - clock_t stopTime = clock(); - float secs = (float) (stopTime - startTime) / CLOCKS_PER_SEC; - // show tenths of a second if time is less than 20 seconds - cout.precision(2); - if (secs >= 100 || (secs >= 10 && secs < 20)) - cout.precision(3); - cout << "total time " << secs << " seconds" << endl; - cout.precision(0); - cout << endl; - } - return 0; -} - -#endif -// ************************* end of console functions ***************************************** diff --git a/uppdev/plugin/astyle/init b/uppdev/plugin/astyle/init deleted file mode 100644 index cb0d67960..000000000 --- a/uppdev/plugin/astyle/init +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef _plugin_astyle_icpp_init_stub -#define _plugin_astyle_icpp_init_stub -#include "Core/init" -#endif diff --git a/uppdev/plugin/cairo/Cairo.h b/uppdev/plugin/cairo/Cairo.h deleted file mode 100644 index 0c0bf3283..000000000 --- a/uppdev/plugin/cairo/Cairo.h +++ /dev/null @@ -1,223 +0,0 @@ -#ifndef _plugin_cairo_Cairo_h_ -#define _plugin_cairo_Cairo_h_ - -#include -#include - -#include "lib/cairo.h" -#include "lib/cairo-svg.h" -#include "lib/cairo-pdf.h" -#include "CairoPattern.h" - -NAMESPACE_UPP - -class Cairo : public NoCopy -{ -private: - cairo_surface_t *_surface; - cairo_t *_context; - int _width, _height; - - void DestroySurface() - { - if (_context != NULL) - { - cairo_status_t status = cairo_status(_context); - ASSERT_(status == CAIRO_STATUS_SUCCESS, cairo_status_to_string(status)); - cairo_destroy(_context); - } - - if (_surface != NULL) - cairo_surface_destroy(_surface); - } - -public: - Cairo() - : _surface(NULL), - _context(NULL) - { - } - - ~Cairo() - { - DestroySurface(); - } - - int GetWidth() { return _width; } - int GetHeight() { return _height; } - - void SetSurface(cairo_surface_t *surface, int width, int height); - void SetSurface(ImageBuffer &img); - void CreateSvgSurface(String const &filename, double widthInPoints = 595, double heightInPoints = 841); // DIN-A4 default size - void CreatePdfSurface(String const &filename, double widthInPoints = 595, double heightInPoints = 841); // DIN-A4 default size - - cairo_t *GetContext() - { - return _context; - } - - cairo_surface_t *GetSurface() - { - return _surface; - } - - bool HasContext() - { - return _context != NULL; - } - - void Clear(Color const &color) - { - SetSourceRGB(color); - Paint(); - } - - /*******************************************************************************************************/ - /************** TODO: remove the following 2 methods!!! Replace them with a dedicated font system ******/ - /*******************************************************************************************************/ - void DrawText(double x, double y, char const * const text, double size, Color ink) - { - cairo_t *context = GetContext(); - ASSERT(context != NULL); - - cairo_set_font_size(context, size); - - Save(); - - Translate(x, y + size); - - SetSourceRGB(ink); - cairo_show_text(context, text); - - NewPath(); - - Restore(); - } - - void DrawTextCenter(double x, double y, double width, char const * const text, double size, Color ink) - { - cairo_t *context = GetContext(); - ASSERT(context != NULL); - - cairo_set_font_size(context, size); - - // measure string - cairo_text_extents_t extents; - cairo_text_extents(context, text, &extents); - - double startX = x + (width / 2.0) - (extents.width / 2.0); - - Save(); - - Translate(startX, y + size); - - SetSourceRGB(ink); - cairo_show_text(context, text); - - NewPath(); - - Restore(); - } - - /* - * Cairo cairo_t methods - * http://cairographics.org/manual/cairo-cairo-t.html - */ - void Save(); - void Restore(); - void PushGroup(); - //cairo_push_group_with_content - void PopGroup(); - void PopGroupToSource(); - //cairo_get_group_target - void SetSourceRGB(double r, double g, double b); - void SetSourceRGB(Color const &color); - void SetSourceRGBA(double r, double g, double b, double a); - void SetSource(CairoPattern &pattern); - //cairo_set_source_surface - //cairo_get_source - void SetAntialias(cairo_antialias_t antialias); - cairo_antialias_t GetAntialias(); - void SetDash(double const * dashes, int numDashes, double offset); - //cairo_get_dash_count - //cairo_get_dash - void SetFillRule(cairo_fill_rule_t fillRule); - cairo_fill_rule_t GetFillRule(); - void SetLineCap(cairo_line_cap_t lineCap); - cairo_line_cap_t GetLineCap(); - void SetLineJoin(cairo_line_join_t lineJoin); - cairo_line_join_t GetLineJoin(); - void SetLineWidth(double width); - double GetLineWidth(); - void SetMiterLimit(double limit); - double GetMiterLimit(); - void SetOperator(cairo_operator_t op); - cairo_operator_t GetOperator(); - void SetTolerance(double tolerance); - double GetTolerance(); - void Clip(bool preserve = false); - //cairo_clip_extents - //cairo_reset_clip - //cairo_rectangle_list_destroy - //cairo_copy_clip_rectangle_list - void Fill(bool preserve = false); - //cairo_fill_extents - //cairo_in_fill - //cairo_mask - //cairo_mask_surface - void Paint(double alpha = 1.0); - void Stroke(bool preserve = false); - //cairo_stroke_extents - //cairo_in_stroke - //cairo_copy_page - //cairo_show_page - //cairo_get_reference_count probably not needed - //cairo_set_user_data probably not needed - //cairo_get_user_data probably not needed - - /* - * Cairo transformation methods - * http://cairographics.org/manual/cairo-Transformations.html - */ - void Translate(double tx, double ty); - void Scale(double sx, double sy); - void Rotate(double angle); - //cairo_transform - //cairo_set_matrix - //cairo_get_matrix - void IdentityMatrix(); - //cairo_user_to_device - //cairo_user_to_device_distance - //cairo_device_to_user - //cairo_device_to_user_distance - - /* - * Cairo path methods - * http://cairographics.org/manual/cairo-Paths.html - */ - //cairo_copy_path - //cairo_copy_path_flat - //cairo_path_destroy - //cairo_append_path - //cairo_has_current_point - Pointf GetCurrentPoint(); - void NewPath(); - //cairo_new_sub_path - void ClosePath(); - void Arc(double xc, double yc, double radius, double angle1, double angle2); - //cairo_arc_negative - void CurveTo(double x1, double y1, double x2, double y2, double x3, double y3); - void LineTo(double x, double y); - void MoveTo(double x, double y); - void Rectangle(double x, double y, double width, double height); - //cairo_glyph_path - //cairo_text_path - void RelCurveTo(double x1, double y1, double x2, double y2, double x3, double y3); - void RelLineTo(double x, double y); - void RelMoveTo(double x, double y); - //cairo_path_extents -}; - -END_UPP_NAMESPACE - -#endif diff --git a/uppdev/plugin/cairo/CairoCtrl.h b/uppdev/plugin/cairo/CairoCtrl.h deleted file mode 100644 index 3045878c9..000000000 --- a/uppdev/plugin/cairo/CairoCtrl.h +++ /dev/null @@ -1,264 +0,0 @@ -#ifndef _plugin_cairo_CairoCtrl_h_ -#define _plugin_cairo_CairoCtrl_h_ - -#include -#include "Cairo.h" -#include "CairoDraw.h" - -NAMESPACE_UPP - -#ifdef PLATFORM_WIN32 - -#include "lib/cairo-win32.h" - -class CairoCtrl : public DHCtrl -{ -private: - Drawing const *_drawing; - Color const *_backgroundColor; - HDC _hDC; - Cairo _cairo; - bool _doubleBuffering; - - void DoPaint() - { - if (!_cairo.HasContext()) - return; - - CairoDraw draw(_cairo); - - if (_drawing == NULL) - { - if (_backgroundColor != NULL) - _cairo.Clear(*_backgroundColor); - - CairoPaint(_cairo); - UppPaint(draw); - } - else - { - _cairo.Clear(_backgroundColor == NULL ? White() : *_backgroundColor); - - Size drawingSize = _drawing->GetSize(); - Size size = GetSize(); - Size drawSize = size; - int dx = 0, dy = 0; - - if(drawingSize.cy * size.cx < size.cy * drawingSize.cx) - { - drawSize.cy = drawingSize.cy * size.cx / drawingSize.cx; - dy = (size.cy - drawSize.cy) / 2; - } - else - { - drawSize.cx = drawingSize.cx * size.cy / drawingSize.cy; - dx = (size.cx - drawSize.cx) / 2; - } - - draw.Clipoff(dx, dy, drawSize.cx, drawSize.cy); - draw.DrawDrawing(drawSize, *_drawing); - draw.End(); - } - - if (_doubleBuffering) - BitBlt(_hDC, Point(0, 0), cairo_win32_surface_get_dc(_cairo.GetSurface()), GetSize()); - } - -protected: - // Called on paint events - virtual void CairoPaint(Cairo &cairo) { WhenCairoPaint(cairo); } - virtual void UppPaint(Draw &draw) { WhenPaint(draw); } - -public: - Callback1 WhenCairoPaint; - Callback1 WhenPaint; - - CairoCtrl() - : _drawing(NULL), - _hDC(NULL), - _doubleBuffering(true), - _backgroundColor(NULL) - {} - - ~CairoCtrl() - { - if (_hDC != NULL) - ReleaseDC(GetHWND(), _hDC); - - if (_backgroundColor != NULL) - delete _backgroundColor; - } - - void Set(Drawing const * const drawing) - { - _drawing = drawing; - Refresh(); - } - - void Background(Color const &color) - { - if (_backgroundColor != NULL) - delete _backgroundColor; - - _backgroundColor = new Color(color); - } - - void SetDoubleBuffering(bool buffer = true) - { - _doubleBuffering = buffer; - State(LAYOUTPOS); - } - - virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam) - { - if(message == WM_PAINT) - { - PAINTSTRUCT ps; - BeginPaint(GetHWND(), &ps); - DoPaint(); - EndPaint(GetHWND(), &ps); - return 0; - } - else if(message == WM_ERASEBKGND) - return 1; - - return DHCtrl::WindowProc(message, wParam, lParam); - } - - virtual void State(int reason) - { - DHCtrl::State(reason); - - if (reason == OPEN || reason == LAYOUTPOS) - { - HWND hwnd = GetHWND(); - if (hwnd != NULL) - _hDC = ::GetDC(hwnd); - - if (_hDC != NULL) - { - if (_doubleBuffering) - _cairo.SetSurface(cairo_win32_surface_create_with_ddb(_hDC, CAIRO_FORMAT_RGB24, GetSize().cx, GetSize().cy), GetSize().cx, GetSize().cy); - else - _cairo.SetSurface(cairo_win32_surface_create(_hDC), GetSize().cx, GetSize().cy); - } - } - else if (reason == CLOSE && _hDC != NULL) - { - ReleaseDC(GetHWND(), _hDC); - _hDC = NULL; - } - } -}; - -#else - -class CairoCtrl : public Ctrl -{ -private: - Drawing const *_drawing; - Color const *_backgroundColor; - Cairo _cairo; - ImageBuffer _buffer; - - void DoPaint() - { - if (!_cairo.HasContext()) - return; - - CairoDraw draw(_cairo); - - if (_drawing == NULL) - { - if (_backgroundColor != NULL) - _cairo.Clear(*_backgroundColor); - - CairoPaint(_cairo); - UppPaint(draw); - } - else - { - _cairo.Clear(_backgroundColor == NULL ? White() : *_backgroundColor); - - Size drawingSize = _drawing->GetSize(); - Size size = GetSize(); - Size drawSize = size; - int dx = 0, dy = 0; - - if(drawingSize.cy * size.cx < size.cy * drawingSize.cx) - { - drawSize.cy = drawingSize.cy * size.cx / drawingSize.cx; - dy = (size.cy - drawSize.cy) / 2; - } - else - { - drawSize.cx = drawingSize.cx * size.cy / drawingSize.cy; - dx = (size.cx - drawSize.cx) / 2; - } - - draw.Clipoff(dx, dy, drawSize.cx, drawSize.cy); - draw.DrawDrawing(drawSize, *_drawing); - draw.End(); - } - } - - virtual void Paint(Draw& draw) - { - if (GetSize() != _buffer.GetSize()) - { - _buffer.Create(GetSize()); - _cairo.SetSurface(_buffer); - } - - if (_buffer.IsEmpty()) - return; - - DoPaint(); - - Image i = _buffer; - draw.DrawImage(0, 0, i); - _buffer = i; - } - -protected: - // Called on paint events - virtual void CairoPaint(Cairo &cairo) { WhenCairoPaint(cairo); } - virtual void UppPaint(Draw &draw) { WhenPaint(draw); } - -public: - Callback1 WhenCairoPaint; - Callback1 WhenPaint; - - CairoCtrl() - : _drawing(NULL), - _backgroundColor(NULL) - {} - - ~CairoCtrl() - { - if (_backgroundColor != NULL) - delete _backgroundColor; - } - - void Set(Drawing const * const drawing) - { - _drawing = drawing; - Refresh(); - } - - void Background(Color const &color) - { - if (_backgroundColor != NULL) - delete _backgroundColor; - - _backgroundColor = new Color(color); - } - - void SetDoubleBuffering(bool buffer = true) {} -}; - -#endif - -END_UPP_NAMESPACE - -#endif diff --git a/uppdev/plugin/cairo/CairoDraw.cpp b/uppdev/plugin/cairo/CairoDraw.cpp deleted file mode 100644 index 3fc5cae45..000000000 --- a/uppdev/plugin/cairo/CairoDraw.cpp +++ /dev/null @@ -1,259 +0,0 @@ -#include "CairoDraw.h" - -NAMESPACE_UPP - -void CairoDraw::BeginOp() -{ - _cairo.Save(); - - _offsetStack.Add(actual_offset); - _clipStack.Add(_actualClip); -} - -void CairoDraw::EndOp() -{ - _cairo.Restore(); - - actual_offset = _offsetStack.Pop(); - _actualClip = _clipStack.Pop(); -} - -void CairoDraw::OffsetOp(Point p) -{ - Begin(); - - _cairo.Translate(p.x, p.y); - - actual_offset += p; - _actualClip -= p; -} - -bool CairoDraw::ClipOp(const Rect& r) -{ - Begin(); - - _cairo.Rectangle(r.left, r.top, r.Width(), r.Height()); - _cairo.Clip(); - - _actualClip &= r; - return !_actualClip.IsEmpty(); -} - -bool CairoDraw::ClipoffOp(const Rect& r) -{ - Begin(); - - _cairo.Translate(r.left, r.top); - - _cairo.Rectangle(0, 0, r.Width(), r.Height()); - _cairo.Clip(); - - actual_offset += r.TopLeft(); - _actualClip &= r; - _actualClip -= r.TopLeft(); - return !_actualClip.IsEmpty(); -} - -bool CairoDraw::ExcludeClipOp(const Rect& r) -{ - _cairo.MoveTo(0, 0); - _cairo.LineTo(_cairo.GetWidth(), 0); - _cairo.LineTo(_cairo.GetWidth(), _cairo.GetHeight()); - _cairo.LineTo(0, _cairo.GetHeight()); - - _cairo.LineTo(0, r.bottom); - _cairo.LineTo(r.right, r.bottom); - _cairo.LineTo(r.right, r.top); - _cairo.LineTo(r.left, r.top); - _cairo.LineTo(r.left, r.bottom); - - _cairo.LineTo(0, r.bottom); - _cairo.ClosePath(); - - _cairo.Clip(); - - return !_actualClip.IsEmpty(); -} - -bool CairoDraw::IntersectClipOp(const Rect& r) -{ - _cairo.Rectangle(r.left, r.top, r.Width(), r.Height()); - _cairo.Clip(); - - _actualClip &= r; - return !_actualClip.IsEmpty(); -} - -Rect CairoDraw::GetClipOp() const -{ - return _actualClip; -} - -bool CairoDraw::IsPaintingOp(const Rect& r) const -{ - return true; -} - - -void CairoDraw::DrawRectOp(int x, int y, int cx, int cy, Color color) -{ - _cairo.Rectangle(x, y, cx, cy); - _cairo.SetSourceRGB(color); - _cairo.Fill(); -} - -void CairoDraw::DrawImageOp(int x, int y, int cx, int cy, const Image& img, const Rect& src, Color color) -{ - _cairo.Save(); - - cairo_t *context = _cairo.GetContext(); - ASSERT(context != NULL); - - cairo_surface_t *imgSurface = cairo_image_surface_create_for_data((unsigned char *)&(img[0]->b), - CAIRO_FORMAT_ARGB32, - img.GetWidth(), - img.GetHeight(), - img.GetWidth() * 4); - - _cairo.Translate(x, y); - _cairo.Scale((double)cx / img.GetWidth(), (double)cy / img.GetHeight()); - cairo_set_source_surface(context, imgSurface, 0, 0); - cairo_rectangle(context, 0, 0, cx, cy); //todo: src rect - _cairo.Fill(); - cairo_surface_destroy(imgSurface); - - _cairo.Restore(); -} - -void CairoDraw::DrawLineOp(int x1, int y1, int x2, int y2, int width, Color color) -{ - if (width == 0) width = 1; - - _cairo.SetLineCap(CAIRO_LINE_CAP_ROUND); - _cairo.SetSourceRGB(color); - _cairo.SetLineWidth(width); - _cairo.MoveTo(x1 + 0.5, y1 + 0.5); - _cairo.LineTo(x2 + 0.5, y2 + 0.5); - _cairo.Stroke(); -} - -void CairoDraw::DrawPolyPolylineOp(const Point *vertices, int vertex_count, - const int *counts, int count_count, - int width, Color color, Color doxor) -{ - if (width == 0) width = 1; - - for (int i = 0; i < count_count; i++) - { - ASSERT(counts[i] >= 1); - _cairo.MoveTo(vertices->x + 0.5, vertices->y + 0.5); - vertices++; - - for (int j = 1; j < counts[i]; j++, vertices++) - _cairo.LineTo(vertices->x + 0.5, vertices->y + 0.5); - } - - _cairo.SetLineCap(CAIRO_LINE_CAP_ROUND); - _cairo.SetLineJoin(CAIRO_LINE_JOIN_ROUND); - _cairo.SetLineWidth(width); - _cairo.SetSourceRGB(color); - _cairo.Stroke(); -} - -void CairoDraw::DrawPolyPolyPolygonOp(const Point *vertices, int vertex_count, - const int *subpolygon_counts, int scc, - const int *disjunct_polygon_counts, int dpcc, - Color color, int width, Color outline, - uint64 pattern, Color doxor) -{ - if (width == 0) width = 1; - - for (int i = 0; i < scc; i++) - { - ASSERT(subpolygon_counts[i] >= 1); - _cairo.MoveTo(vertices->x, vertices->y); - vertices++; - - for (int j = 1; j < subpolygon_counts[i]; j++, vertices++) - _cairo.LineTo(vertices->x, vertices->y); - - _cairo.ClosePath(); - } - - _cairo.SetSourceRGB(color); - _cairo.Fill(true); - _cairo.SetLineCap(CAIRO_LINE_CAP_ROUND); - _cairo.SetLineJoin(CAIRO_LINE_JOIN_ROUND); - _cairo.SetLineWidth(width); - _cairo.SetSourceRGB(outline); - _cairo.Stroke(); -} - -void CairoDraw::DrawEllipseOp(const Rect& r, Color color, int pen, Color pencolor) -{ - if (pen == 0) pen = 1; - - _cairo.Save(); - _cairo.Translate(r.left + (r.Width() / 2.0), r.top + (r.Height() / 2.0)); - _cairo.Scale(r.Width() / 2.0, r.Height() / 2.0); - _cairo.Arc(0.0, 0.0, 1.0, 0.0, 2 * M_PI); - _cairo.Restore(); - - _cairo.SetSourceRGB(color); - - _cairo.Fill(pen != (int)Null); - - if (pen != (int)Null) - { - _cairo.SetLineWidth(pen); - _cairo.SetSourceRGB(pencolor); - _cairo.Stroke(); - } -} - -void CairoDraw::DrawArcOp(const Rect& rc, Point start, Point end, int width, Color color) -{ - if (width == 0) width = 1; - - //TODO -} - -void CairoDraw::DrawTextOp(int x, int y, int angle, const wchar *text, Font font, - Color ink, int n, const int *dx) -{ - cairo_t *context = _cairo.GetContext(); - ASSERT(context != NULL); - - /*HFONT hFont = CreateFont(font.GetHeight() ? -abs(font.GetHeight()) : -12, - font.GetWidth(), angle, angle, font.IsBold() ? FW_BOLD : FW_NORMAL, - font.IsItalic(), font.IsUnderline(), font.IsStrikeout(), - Font::GetFaceInfo(font.GetFace()) & Font::SYMBOLTYPE ? SYMBOL_CHARSET : DEFAULT_CHARSET, - font.IsTrueTypeOnly() ? OUT_TT_ONLY_PRECIS : OUT_DEFAULT_PRECIS, - CLIP_DEFAULT_PRECIS, - font.IsNonAntiAliased() ? NONANTIALIASED_QUALITY - : DEFAULT_QUALITY, - DEFAULT_PITCH|FF_DONTCARE, - Font::GetFaceName(font.GetFace())/*sFontFace().GetKey(font.GetFace())* /); - - cairo_font_face_t *fontFace = cairo_win32_font_face_create_for_hfont(hFont); - cairo_set_font_face(context, fontFace);*/ - cairo_set_font_size(context, font.GetHeight()); - - _cairo.Save(); - - _cairo.Translate(x, y + (font.GetHeight() ? abs(font.GetHeight()) : 12)); - _cairo.Rotate(angle * (-3.14159 / 1800.0)); - - _cairo.SetSourceRGB(ink); - WString tempWString = text; - cairo_show_text(context, tempWString.ToString()); - - _cairo.NewPath(); - - _cairo.Restore(); - - /*cairo_font_face_destroy(fontFace);*/ -} - -END_UPP_NAMESPACE - diff --git a/uppdev/plugin/cairo/CairoDraw.h b/uppdev/plugin/cairo/CairoDraw.h deleted file mode 100644 index 3ce14d89e..000000000 --- a/uppdev/plugin/cairo/CairoDraw.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef _plugin_cairo_CairoDraw_h_ -#define _plugin_cairo_CairoDraw_h_ - -#include -#include "Cairo.h" - -NAMESPACE_UPP - -class CairoDraw : public Draw -{ -private: - Vector _offsetStack; - Vector _clipStack; - Rect _actualClip; - Cairo &_cairo; - -public: - CairoDraw(Cairo &cairo) - : _cairo(cairo) - {} - - virtual void BeginOp(); - virtual void EndOp(); - virtual void OffsetOp(Point p); - virtual bool ClipOp(const Rect& r); - virtual bool ClipoffOp(const Rect& r); - virtual bool ExcludeClipOp(const Rect& r); - virtual bool IntersectClipOp(const Rect& r); - virtual Rect GetClipOp() const; - virtual bool IsPaintingOp(const Rect& r) const; - - virtual void DrawRectOp(int x, int y, int cx, int cy, Color color); - virtual void DrawImageOp(int x, int y, int cx, int cy, const Image& img, const Rect& src, Color color); - virtual void DrawLineOp(int x1, int y1, int x2, int y2, int width, Color color); - virtual void DrawPolyPolylineOp(const Point *vertices, int vertex_count, - const int *counts, int count_count, - int width, Color color, Color doxor); - virtual void DrawPolyPolyPolygonOp(const Point *vertices, int vertex_count, - const int *subpolygon_counts, int scc, - const int *disjunct_polygon_counts, int dpcc, - Color color, int width, Color outline, - uint64 pattern, Color doxor); - virtual void DrawEllipseOp(const Rect& r, Color color, int pen, Color pencolor); - virtual void DrawArcOp(const Rect& rc, Point start, Point end, int width, Color color); - virtual void DrawTextOp(int x, int y, int angle, const wchar *text, Font font, - Color ink, int n, const int *dx); -}; - -END_UPP_NAMESPACE - -#endif diff --git a/uppdev/plugin/cairo/CairoPattern.h b/uppdev/plugin/cairo/CairoPattern.h deleted file mode 100644 index c39461c4c..000000000 --- a/uppdev/plugin/cairo/CairoPattern.h +++ /dev/null @@ -1,185 +0,0 @@ -#ifndef _plugin_cairo_CairoPattern_h_ -#define _plugin_cairo_CairoPattern_h_ - -#include - -#include "lib/cairo.h" - -NAMESPACE_UPP - -#if 1 -#define CAIRO_METHOD_ENTER() ASSERT(_pattern != NULL) -#define CAIRO_METHOD_LEAVE() { \ - cairo_status_t status = cairo_pattern_status(_pattern); \ - ASSERT_(status == CAIRO_STATUS_SUCCESS, cairo_status_to_string(status)); \ - } -#else -#define CAIRO_METHOD_ENTER() -#define CAIRO_METHOD_LEAVE() -#endif - -class CairoPattern : public NoCopy /*abstract*/ -{ -protected: - cairo_pattern_t *_pattern; - - CairoPattern() - : _pattern(NULL) - {} - - virtual ~CairoPattern() - { - if (_pattern != NULL) - cairo_pattern_destroy(_pattern); - } - -public: - cairo_pattern_t *GetPattern() - { - return _pattern; - } - - void SetExtend(cairo_extend_t extend) - { - CAIRO_METHOD_ENTER(); - cairo_pattern_set_extend(_pattern, extend); - CAIRO_METHOD_LEAVE(); - } - - //cairo_pattern_get_extend () - - void SetFilter(cairo_filter_t filter) - { - CAIRO_METHOD_ENTER(); - cairo_pattern_set_filter(_pattern, filter); - CAIRO_METHOD_LEAVE(); - } - - //cairo_pattern_get_filter () - //cairo_pattern_set_matrix () - //cairo_pattern_get_matrix () - //cairo_pattern_get_type () -}; - -class CairoGradient : public CairoPattern /*abstract*/ -{ -protected: - CairoGradient() {} - -public: - void AddColorStopRGB(double offset, double r, double g, double b) - { - CAIRO_METHOD_ENTER(); - cairo_pattern_add_color_stop_rgb(_pattern, offset, r, g, b); - CAIRO_METHOD_LEAVE(); - } - - void AddColorStopRGB(double offset, Color const &color) - { - AddColorStopRGB(offset, color.GetR() / 255.0, color.GetG() / 255.0, color.GetB() / 255.0); - } - - void AddColorStopRGBA(double offset, double r, double g, double b, double a) - { - CAIRO_METHOD_ENTER(); - cairo_pattern_add_color_stop_rgba(_pattern, offset, r, g, b, a); - CAIRO_METHOD_LEAVE(); - } - - //cairo_pattern_get_color_stop_count () - //cairo_pattern_get_color_stop_rgba () -}; - -class CairoSolidPattern : public CairoPattern -{ -public: - CairoSolidPattern(double r, double g, double b) { SetRGB(r, g, b); } - CairoSolidPattern(Color const &color) { SetRGB(color); } - CairoSolidPattern(double r, double g, double b, double a) { SetRGBA(r, g, b, a); } - - void SetRGB(double r, double g, double b) - { - if (_pattern != NULL) - cairo_pattern_destroy(_pattern); - - _pattern = cairo_pattern_create_rgb(r, g, b); - CAIRO_METHOD_LEAVE(); - } - - void SetRGB(Color const &color) - { - SetRGB(color.GetR() / 255.0, color.GetG() / 255.0, color.GetB() / 255.0); - } - - void SetRGBA(double r, double g, double b, double a) - { - if (_pattern != NULL) - cairo_pattern_destroy(_pattern); - - _pattern = cairo_pattern_create_rgba(r, g, b, a); - CAIRO_METHOD_LEAVE(); - } - - //cairo_pattern_get_rgba () -}; - -class CairoLinearGradient : public CairoGradient -{ -public: - CairoLinearGradient(double x0, double y0, double x1, double y1) { Set(x0, y0, x1, y1); } - - void Set(double x0, double y0, double x1, double y1) - { - if (_pattern != NULL) - cairo_pattern_destroy(_pattern); - - _pattern = cairo_pattern_create_linear(x0, y0, x1, y1); - CAIRO_METHOD_LEAVE(); - } - - //cairo_pattern_get_linear_points () -}; - -class CairoRadialGradient : public CairoGradient -{ -public: - CairoRadialGradient(double cx0, double cy0, double radius0, double cx1, double cy1, double radius1) - { - Set(cx0, cy0, radius0, cx1, cy1, radius1); - } - - void Set(double cx0, double cy0, double radius0, double cx1, double cy1, double radius1) - { - if (_pattern != NULL) - cairo_pattern_destroy(_pattern); - - _pattern = cairo_pattern_create_radial(cx0, cy0, radius0, cx1, cy1, radius1); - CAIRO_METHOD_LEAVE(); - } - - //cairo_pattern_get_radial_circles () -}; - -class CairoSurfacePattern : public CairoPattern -{ -public: - CairoSurfacePattern(cairo_surface_t *surface) { Set(surface); } - - void Set(cairo_surface_t *surface) - { - if (_pattern != NULL) - cairo_pattern_destroy(_pattern); - - _pattern = cairo_pattern_create_for_surface(surface); - CAIRO_METHOD_LEAVE(); - } - - //cairo_pattern_get_surface () -}; - -END_UPP_NAMESPACE - -#undef CAIRO_METHOD_ENTER -#undef CAIRO_METHOD_LEAVE - -#endif diff --git a/uppdev/plugin/cairo/CairoUpp.cpp b/uppdev/plugin/cairo/CairoUpp.cpp deleted file mode 100644 index 3be9aad94..000000000 --- a/uppdev/plugin/cairo/CairoUpp.cpp +++ /dev/null @@ -1,390 +0,0 @@ -#include "Cairo.h" - -#include "CairoPattern.h" - -NAMESPACE_UPP - -void Cairo::SetSurface(cairo_surface_t *surface, int width, int height) -{ - ASSERT(surface != NULL); - - DestroySurface(); - - _surface = surface; - _context = cairo_create(_surface); - _width = width; - _height = height; -} - -void Cairo::SetSurface(ImageBuffer &img) -{ - ASSERT(img.IsEmpty() == false); - - cairo_surface_t *surface = cairo_image_surface_create_for_data((unsigned char *)&(img[0]->b), - CAIRO_FORMAT_ARGB32, - img.GetSize().cx, - img.GetSize().cy, - img.GetSize().cx * 4); - - SetSurface(surface, img.GetSize().cx, img.GetSize().cy); -} - -void Cairo::CreateSvgSurface(String const &filename, double widthInPoints, double heightInPoints) -{ - SetSurface(cairo_svg_surface_create(filename, widthInPoints, heightInPoints), static_cast(widthInPoints), static_cast(heightInPoints)); -} - -void Cairo::CreatePdfSurface(String const &filename, double widthInPoints, double heightInPoints) -{ - SetSurface(cairo_pdf_surface_create(filename, widthInPoints, heightInPoints), static_cast(widthInPoints), static_cast(heightInPoints)); -} - -#if 1 -#define CAIRO_METHOD_ENTER() ASSERT(_context != NULL) -#define CAIRO_METHOD_LEAVE() { \ - cairo_status_t status = cairo_status(_context); \ - ASSERT_(status == CAIRO_STATUS_SUCCESS, cairo_status_to_string(status)); \ - } -#else -#define CAIRO_METHOD_ENTER() -#define CAIRO_METHOD_LEAVE() -#endif - -void Cairo::Save() -{ - CAIRO_METHOD_ENTER(); - cairo_save(_context); - CAIRO_METHOD_LEAVE(); -} - -void Cairo::Restore() -{ - CAIRO_METHOD_ENTER(); - cairo_restore(_context); - CAIRO_METHOD_LEAVE(); -} - -void Cairo::PushGroup() -{ - CAIRO_METHOD_ENTER(); - cairo_push_group(_context); - CAIRO_METHOD_LEAVE(); -} - -void Cairo::PopGroup() -{ - CAIRO_METHOD_ENTER(); - cairo_pop_group(_context); - CAIRO_METHOD_LEAVE(); -} - -void Cairo::PopGroupToSource() -{ - CAIRO_METHOD_ENTER(); - cairo_pop_group_to_source(_context); - CAIRO_METHOD_LEAVE(); -} - -void Cairo::SetSourceRGB(double r, double g, double b) -{ - CAIRO_METHOD_ENTER(); - cairo_set_source_rgb(_context, r, g, b); - CAIRO_METHOD_LEAVE(); -} - -void Cairo::SetSourceRGB(Color const &color) -{ - CAIRO_METHOD_ENTER(); - cairo_set_source_rgb(_context, color.GetR() / 255.0, color.GetG() / 255.0, color.GetB() / 255.0); - CAIRO_METHOD_LEAVE(); -} - -void Cairo::SetSourceRGBA(double r, double g, double b, double a) -{ - CAIRO_METHOD_ENTER(); - cairo_set_source_rgba(_context, r, g, b, a); - CAIRO_METHOD_LEAVE(); -} - -void Cairo::SetSource(CairoPattern &pattern) -{ - CAIRO_METHOD_ENTER(); - cairo_set_source(_context, pattern.GetPattern()); - CAIRO_METHOD_LEAVE(); -} - -void Cairo::SetAntialias(cairo_antialias_t antialias) -{ - CAIRO_METHOD_ENTER(); - cairo_set_antialias(_context, antialias); - CAIRO_METHOD_LEAVE(); -} - -cairo_antialias_t Cairo::GetAntialias() -{ - CAIRO_METHOD_ENTER(); - cairo_antialias_t result = cairo_get_antialias(_context); - CAIRO_METHOD_LEAVE(); - return result; -} - -void Cairo::SetDash(double const * dashes, int numDashes, double offset) -{ - CAIRO_METHOD_ENTER(); - cairo_set_dash(_context, dashes, numDashes, offset); - CAIRO_METHOD_LEAVE(); -} - -void Cairo::SetFillRule(cairo_fill_rule_t fillRule) -{ - CAIRO_METHOD_ENTER(); - cairo_set_fill_rule(_context, fillRule); - CAIRO_METHOD_LEAVE(); -} - -cairo_fill_rule_t Cairo::GetFillRule() -{ - CAIRO_METHOD_ENTER(); - cairo_fill_rule_t result = cairo_get_fill_rule(_context); - CAIRO_METHOD_LEAVE(); - return result; -} - -void Cairo::SetLineCap(cairo_line_cap_t lineCap) -{ - CAIRO_METHOD_ENTER(); - cairo_set_line_cap(_context, lineCap); - CAIRO_METHOD_LEAVE(); -} - -cairo_line_cap_t Cairo::GetLineCap() -{ - CAIRO_METHOD_ENTER(); - cairo_line_cap_t result = cairo_get_line_cap(_context); - CAIRO_METHOD_LEAVE(); - return result; -} - -void Cairo::SetLineJoin(cairo_line_join_t lineJoin) -{ - CAIRO_METHOD_ENTER(); - cairo_set_line_join(_context, lineJoin); - CAIRO_METHOD_LEAVE(); -} - -cairo_line_join_t Cairo::GetLineJoin() -{ - CAIRO_METHOD_ENTER(); - cairo_line_join_t result = cairo_get_line_join(_context); - CAIRO_METHOD_LEAVE(); - return result; -} - -void Cairo::SetLineWidth(double width) -{ - CAIRO_METHOD_ENTER(); - cairo_set_line_width(_context, width); - CAIRO_METHOD_LEAVE(); -} - -double Cairo::GetLineWidth() -{ - CAIRO_METHOD_ENTER(); - double result = cairo_get_line_width(_context); - CAIRO_METHOD_LEAVE(); - return result; -} - -void Cairo::SetMiterLimit(double limit) -{ - CAIRO_METHOD_ENTER(); - cairo_set_miter_limit(_context, limit); - CAIRO_METHOD_LEAVE(); -} - -double Cairo::GetMiterLimit() -{ - CAIRO_METHOD_ENTER(); - double result = cairo_get_miter_limit(_context); - CAIRO_METHOD_LEAVE(); - return result; -} - -void Cairo::SetOperator(cairo_operator_t op) -{ - CAIRO_METHOD_ENTER(); - cairo_set_operator(_context, op); - CAIRO_METHOD_LEAVE(); -} - -cairo_operator_t Cairo::GetOperator() -{ - CAIRO_METHOD_ENTER(); - cairo_operator_t result = cairo_get_operator(_context); - CAIRO_METHOD_LEAVE(); - return result; -} - -void Cairo::SetTolerance(double tolerance) -{ - CAIRO_METHOD_ENTER(); - cairo_set_tolerance(_context, tolerance); - CAIRO_METHOD_LEAVE(); -} - -double Cairo::GetTolerance() -{ - CAIRO_METHOD_ENTER(); - double result = cairo_get_tolerance(_context); - CAIRO_METHOD_LEAVE(); - return result; -} - -void Cairo::Clip(bool preserve) -{ - CAIRO_METHOD_ENTER(); - if (!preserve) - cairo_clip(_context); - else - cairo_clip_preserve(_context); - CAIRO_METHOD_LEAVE(); -} - -void Cairo::Fill(bool preserve) -{ - CAIRO_METHOD_ENTER(); - if (!preserve) - cairo_fill(_context); - else - cairo_fill_preserve(_context); - CAIRO_METHOD_LEAVE(); -} - -void Cairo::Paint(double alpha) -{ - CAIRO_METHOD_ENTER(); - if (alpha >= 1.0) - cairo_paint(_context); - else - cairo_paint_with_alpha(_context, alpha); - CAIRO_METHOD_LEAVE(); -} - -void Cairo::Stroke(bool preserve) -{ - CAIRO_METHOD_ENTER(); - if (!preserve) - cairo_stroke(_context); - else - cairo_stroke_preserve(_context); - CAIRO_METHOD_LEAVE(); -} - -void Cairo::Translate(double tx, double ty) -{ - CAIRO_METHOD_ENTER(); - cairo_translate(_context, tx, ty); - CAIRO_METHOD_LEAVE(); -} - -void Cairo::Scale(double sx, double sy) -{ - CAIRO_METHOD_ENTER(); - cairo_scale(_context, sx, sy); - CAIRO_METHOD_LEAVE(); -} - -void Cairo::Rotate(double angle) -{ - CAIRO_METHOD_ENTER(); - cairo_rotate(_context, angle); - CAIRO_METHOD_LEAVE(); -} - -void Cairo::IdentityMatrix() -{ - CAIRO_METHOD_ENTER(); - cairo_identity_matrix(_context); - CAIRO_METHOD_LEAVE(); -} - -Pointf Cairo::GetCurrentPoint() -{ - Pointf p; - CAIRO_METHOD_ENTER(); - cairo_get_current_point(_context, &p.x, &p.y); - CAIRO_METHOD_LEAVE(); - return p; -} - -void Cairo::NewPath() -{ - CAIRO_METHOD_ENTER(); - cairo_new_path(_context); - CAIRO_METHOD_LEAVE(); -} - -void Cairo::ClosePath() -{ - CAIRO_METHOD_ENTER(); - cairo_close_path(_context); - CAIRO_METHOD_LEAVE(); -} - -void Cairo::Arc(double xc, double yc, double radius, double angle1, double angle2) -{ - CAIRO_METHOD_ENTER(); - cairo_arc(_context, xc, yc, radius, angle1, angle2); - CAIRO_METHOD_LEAVE(); -} - -void Cairo::CurveTo(double x1, double y1, double x2, double y2, double x3, double y3) -{ - CAIRO_METHOD_ENTER(); - cairo_curve_to(_context, x1, y1, x2, y2, x3, y3); - CAIRO_METHOD_LEAVE(); -} - -void Cairo::LineTo(double x, double y) -{ - CAIRO_METHOD_ENTER(); - cairo_line_to(_context, x, y); - CAIRO_METHOD_LEAVE(); -} - -void Cairo::MoveTo(double x, double y) -{ - CAIRO_METHOD_ENTER(); - cairo_move_to(_context, x, y); - CAIRO_METHOD_LEAVE(); -} - -void Cairo::Rectangle(double x, double y, double width, double height) -{ - CAIRO_METHOD_ENTER(); - cairo_rectangle(_context, x, y, width, height); - CAIRO_METHOD_LEAVE(); -} - -void Cairo::RelCurveTo(double x1, double y1, double x2, double y2, double x3, double y3) -{ - CAIRO_METHOD_ENTER(); - cairo_rel_curve_to(_context, x1, y1, x2, y2, x3, y3); - CAIRO_METHOD_LEAVE(); -} - -void Cairo::RelLineTo(double x, double y) -{ - CAIRO_METHOD_ENTER(); - cairo_rel_line_to(_context, x, y); - CAIRO_METHOD_LEAVE(); -} - -void Cairo::RelMoveTo(double x, double y) -{ - CAIRO_METHOD_ENTER(); - cairo_rel_move_to(_context, x, y); - CAIRO_METHOD_LEAVE(); -} - -END_UPP_NAMESPACE diff --git a/uppdev/plugin/cairo/cairo-version.h b/uppdev/plugin/cairo/cairo-version.h deleted file mode 100644 index c3674c464..000000000 --- a/uppdev/plugin/cairo/cairo-version.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef CAIRO_VERSION_H -#define CAIRO_VERSION_H - -#define CAIRO_VERSION_MAJOR 1 -#define CAIRO_VERSION_MINOR 8 -#define CAIRO_VERSION_MICRO 0 - -#endif diff --git a/uppdev/plugin/cairo/cairo.upp b/uppdev/plugin/cairo/cairo.upp deleted file mode 100644 index f16d65744..000000000 --- a/uppdev/plugin/cairo/cairo.upp +++ /dev/null @@ -1,27 +0,0 @@ -uses - Core, - plugin\png, - plugin\pixman; - -library(WIN32) "user32 gdi32 msimg32"; - -library(!WIN32) cairo; - -options(WIN32) "-I\"./lib\" -I\"../pixman/lib\""; - -options(WIN32) "-I\"C:/upp/uppsrc/plugin/z/lib\" -I\"C:/upp/uppsrc/plugin/png/lib\""; - -options(WIN32) -D_CRT_SECURE_NO_WARNINGS; - -file - Cairo.h, - CairoUpp.cpp, - CairoPattern.h, - CairoDraw.h, - CairoDraw.cpp, - CairoCtrl.h, - cairolib.c, - cairolibwin32.c, - Cairo readonly separator, - lib/cairo-features.h; - diff --git a/uppdev/plugin/cairo/cairolib.c b/uppdev/plugin/cairo/cairolib.c deleted file mode 100644 index 68e5964d6..000000000 --- a/uppdev/plugin/cairo/cairolib.c +++ /dev/null @@ -1,92 +0,0 @@ -#ifdef flagWIN32 - -#undef CAIRO_VERSION_H -#undef CAIRO_VERSION_MAJOR -#undef CAIRO_VERSION_MINOR -#undef CAIRO_VERSION_MICRO -#include "lib/cairo-version.c" - -#include "lib/cairo-analysis-surface.c" -#include "lib/cairo-arc.c" -#include "lib/cairo-array.c" -#include "lib/cairo-atomic.c" -#include "lib/cairo-base85-stream.c" -#include "lib/cairo-bentley-ottmann.c" -#include "lib/cairo-cache.c" - -#undef _BSD_SOURCE -#include "lib/cairo-cff-subset.c" - -#include "lib/cairo-clip.c" -#include "lib/cairo-color.c" -//#include "lib/cairo-debug.c" -#include "lib/cairo-deflate-stream.c" -#include "lib/cairo-fixed.c" - -#undef _BSD_SOURCE -#include "lib/cairo-font-face.c" - -#include "lib/cairo-font-face-twin.c" -#include "lib/cairo-font-face-twin-data.c" -#include "lib/cairo-font-options.c" -#include "lib/cairo-freelist.c" -#include "lib/cairo-gstate.c" -#include "lib/cairo-hash.c" -#include "lib/cairo-hull.c" -#include "lib/cairo-image-surface.c" -#include "lib/cairo-lzw.c" -#include "lib/cairo-matrix.c" -#include "lib/cairo-meta-surface.c" -#include "lib/cairo-misc.c" -#include "lib/cairo-mutex.c" - -#undef _BSD_SOURCE -#include "lib/cairo-output-stream.c" - -#include "lib/cairo-paginated-surface.c" -#include "lib/cairo-path-bounds.c" -#include "lib/cairo-path-fill.c" -#include "lib/cairo-path-fixed.c" -#include "lib/cairo-path-stroke.c" -#include "lib/cairo-path.c" -#include "lib/cairo-pattern.c" -#include "lib/cairo-pdf-operators.c" - -#undef _BSD_SOURCE -#include "lib/cairo-pdf-surface.c" - -#include "lib/cairo-pen.c" -#include "lib/cairo-polygon.c" -#include "lib/cairo-png.c" -#include "lib/cairo-rectangle.c" -#include "lib/cairo-region.c" -#include "lib/cairo-scaled-font-subsets.c" -#include "lib/cairo-scaled-font.c" -#include "lib/cairo-skiplist.c" -#include "lib/cairo-slope.c" -#include "lib/cairo-spline.c" -#include "lib/cairo-stroke-style.c" -#include "lib/cairo-surface-fallback.c" -#include "lib/cairo-surface.c" -#include "lib/cairo-svg-surface.c" -#include "lib/cairo-traps.c" -#include "lib/cairo-truetype-subset.c" -#include "lib/cairo-type1-fallback.c" -#include "lib/cairo-type3-glyph-surface.c" -#include "lib/cairo-unicode.c" -#include "lib/cairo-user-font.c" -#include "lib/cairo-wideint.c" -#include "lib/cairo.c" - -// files that would be needed if you want to compile for linux. -// currently we just use the cairo library from the system -/* -#include "lib/cairo-ft-font.c" -#include "lib/cairo-xlib-screen.c" -#include "lib/cairo-xlib-surface.c" -#include "lib/cairo-xlib-visual.c" -#include "lib/cairo-type1-subset.c" -#include "lib/cairo-xlib-display.c" -*/ - -#endif diff --git a/uppdev/plugin/cairo/cairolibwin32.c b/uppdev/plugin/cairo/cairolibwin32.c deleted file mode 100644 index c33048981..000000000 --- a/uppdev/plugin/cairo/cairolibwin32.c +++ /dev/null @@ -1,8 +0,0 @@ -#ifdef flagWIN32 - -//#include "lib/cairo-win32.c" -#include "lib/cairo-win32-font.c" -#include "lib/cairo-win32-printing-surface.c" -#include "lib/cairo-win32-surface.c" - -#endif diff --git a/uppdev/plugin/cairo/init b/uppdev/plugin/cairo/init deleted file mode 100644 index 9ee06d85c..000000000 --- a/uppdev/plugin/cairo/init +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _plugin_cairo_icpp_init_stub -#define _plugin_cairo_icpp_init_stub -#include "Core/init" -#include "plugin\png/init" -#include "plugin\pixman/init" -#endif diff --git a/uppdev/plugin/cairo/lib/cairo-analysis-surface-private.h b/uppdev/plugin/cairo/lib/cairo-analysis-surface-private.h deleted file mode 100644 index 28bfd3bf4..000000000 --- a/uppdev/plugin/cairo/lib/cairo-analysis-surface-private.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright © 2005 Keith Packard - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Keith Packard - * - * Contributor(s): - * Keith Packard - */ - -#ifndef CAIRO_ANALYSIS_SURFACE_H -#define CAIRO_ANALYSIS_SURFACE_H - -#include "cairoint.h" - -cairo_private cairo_surface_t * -_cairo_analysis_surface_create (cairo_surface_t *target, - int width, - int height); - -cairo_private void -_cairo_analysis_surface_set_ctm (cairo_surface_t *surface, - cairo_matrix_t *ctm); - -cairo_private void -_cairo_analysis_surface_get_ctm (cairo_surface_t *surface, - cairo_matrix_t *ctm); - -cairo_private cairo_region_t * -_cairo_analysis_surface_get_supported (cairo_surface_t *surface); - -cairo_private cairo_region_t * -_cairo_analysis_surface_get_unsupported (cairo_surface_t *surface); - -cairo_private cairo_bool_t -_cairo_analysis_surface_has_supported (cairo_surface_t *surface); - -cairo_private cairo_bool_t -_cairo_analysis_surface_has_unsupported (cairo_surface_t *surface); - -cairo_private void -_cairo_analysis_surface_get_bounding_box (cairo_surface_t *surface, - cairo_box_t *bbox); - -cairo_private cairo_int_status_t -_cairo_analysis_surface_merge_status (cairo_int_status_t status_a, - cairo_int_status_t status_b); - -cairo_private cairo_surface_t * -_cairo_null_surface_create (cairo_content_t content); - -#endif /* CAIRO_ANALYSIS_SURFACE_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-analysis-surface.c b/uppdev/plugin/cairo/lib/cairo-analysis-surface.c deleted file mode 100644 index 057be529d..000000000 --- a/uppdev/plugin/cairo/lib/cairo-analysis-surface.c +++ /dev/null @@ -1,988 +0,0 @@ -/* - * Copyright © 2006 Keith Packard - * Copyright © 2007 Adrian Johnson - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Keith Packard - * - * Contributor(s): - * Keith Packard - * Adrian Johnson - */ - -#include "cairoint.h" - -#include "cairo-analysis-surface-private.h" -#include "cairo-paginated-private.h" -#include "cairo-region-private.h" -#include "cairo-meta-surface-private.h" - -typedef struct { - cairo_surface_t base; - int width; - int height; - - cairo_surface_t *target; - - cairo_bool_t first_op; - cairo_bool_t has_supported; - cairo_bool_t has_unsupported; - - cairo_region_t supported_region; - cairo_region_t fallback_region; - cairo_rectangle_int_t current_clip; - cairo_box_t page_bbox; - - cairo_bool_t has_ctm; - cairo_matrix_t ctm; - -} cairo_analysis_surface_t; - -cairo_int_status_t -_cairo_analysis_surface_merge_status (cairo_int_status_t status_a, - cairo_int_status_t status_b) -{ - /* fatal errors should be checked and propagated at source */ - assert (! _cairo_status_is_error (status_a)); - assert (! _cairo_status_is_error (status_b)); - - /* return the most important status */ - if (status_a == CAIRO_INT_STATUS_UNSUPPORTED || - status_b == CAIRO_INT_STATUS_UNSUPPORTED) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (status_a == CAIRO_INT_STATUS_IMAGE_FALLBACK || - status_b == CAIRO_INT_STATUS_IMAGE_FALLBACK) - return CAIRO_INT_STATUS_IMAGE_FALLBACK; - - if (status_a == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN || - status_b == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN) - return CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN; - - if (status_a == CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY || - status_b == CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY) - return CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY; - - /* at this point we have checked all the valid internal codes, so... */ - assert (status_a == CAIRO_STATUS_SUCCESS && - status_b == CAIRO_STATUS_SUCCESS); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_analyze_meta_surface_pattern (cairo_analysis_surface_t *surface, - cairo_pattern_t *pattern) -{ - cairo_surface_t *analysis = &surface->base; - cairo_surface_pattern_t *surface_pattern; - cairo_status_t status; - cairo_bool_t old_has_ctm; - cairo_matrix_t old_ctm, p2d; - cairo_rectangle_int_t old_clip; - cairo_rectangle_int_t meta_extents; - int old_width; - int old_height; - - assert (pattern->type == CAIRO_PATTERN_TYPE_SURFACE); - surface_pattern = (cairo_surface_pattern_t *) pattern; - assert (_cairo_surface_is_meta (surface_pattern->surface)); - - old_width = surface->width; - old_height = surface->height; - old_clip = surface->current_clip; - status = _cairo_surface_get_extents (surface_pattern->surface, &meta_extents); - if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - - surface->width = meta_extents.width; - surface->height = meta_extents.height; - surface->current_clip.x = 0; - surface->current_clip.y = 0; - surface->current_clip.width = surface->width; - surface->current_clip.height = surface->height; - old_ctm = surface->ctm; - old_has_ctm = surface->has_ctm; - p2d = pattern->matrix; - status = cairo_matrix_invert (&p2d); - /* _cairo_pattern_set_matrix guarantees invertibility */ - assert (status == CAIRO_STATUS_SUCCESS); - - cairo_matrix_multiply (&surface->ctm, &p2d, &surface->ctm); - surface->has_ctm = !_cairo_matrix_is_identity (&surface->ctm); - - status = _cairo_meta_surface_replay_and_create_regions (surface_pattern->surface, - analysis); - if (status == CAIRO_STATUS_SUCCESS) - status = analysis->status; - - surface->ctm = old_ctm; - surface->has_ctm = old_has_ctm; - surface->current_clip = old_clip; - surface->width = old_width; - surface->height = old_height; - - return status; -} - -static cairo_int_status_t -_add_operation (cairo_analysis_surface_t *surface, - cairo_rectangle_int_t *rect, - cairo_int_status_t backend_status) -{ - cairo_int_status_t status; - cairo_box_t bbox; - - if (rect->width == 0 || rect->height == 0) { - /* Even though the operation is not visible we must be careful - * to not allow unsupported operations to be replayed to the - * backend during CAIRO_PAGINATED_MODE_RENDER */ - if (backend_status == CAIRO_STATUS_SUCCESS || - backend_status == CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY) - { - return CAIRO_STATUS_SUCCESS; - } - else - { - return CAIRO_INT_STATUS_IMAGE_FALLBACK; - } - } - - _cairo_box_from_rectangle (&bbox, rect); - - if (surface->has_ctm) { - - _cairo_matrix_transform_bounding_box_fixed (&surface->ctm, &bbox, NULL); - - if (bbox.p1.x == bbox.p2.x || bbox.p1.y == bbox.p2.y) { - /* Even though the operation is not visible we must be - * careful to not allow unsupported operations to be - * replayed to the backend during - * CAIRO_PAGINATED_MODE_RENDER */ - if (backend_status == CAIRO_STATUS_SUCCESS || - backend_status == CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY) - { - return CAIRO_STATUS_SUCCESS; - } - else - { - return CAIRO_INT_STATUS_IMAGE_FALLBACK; - } - } - - _cairo_box_round_to_rectangle (&bbox, rect); - } - - if (surface->first_op) { - surface->first_op = FALSE; - surface->page_bbox = bbox; - } else { - if (bbox.p1.x < surface->page_bbox.p1.x) - surface->page_bbox.p1.x = bbox.p1.x; - if (bbox.p1.y < surface->page_bbox.p1.y) - surface->page_bbox.p1.y = bbox.p1.y; - if (bbox.p2.x > surface->page_bbox.p2.x) - surface->page_bbox.p2.x = bbox.p2.x; - if (bbox.p2.y > surface->page_bbox.p2.y) - surface->page_bbox.p2.y = bbox.p2.y; - } - - /* If the operation is completely enclosed within the fallback - * region there is no benefit in emitting a native operation as - * the fallback image will be painted on top. - */ - if (_cairo_region_contains_rectangle (&surface->fallback_region, rect) == PIXMAN_REGION_IN) - return CAIRO_INT_STATUS_IMAGE_FALLBACK; - - if (backend_status == CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY) { - /* A status of CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY indicates - * that the backend only supports this operation if the - * transparency removed. If the extents of this operation does - * not intersect any other native operation, the operation is - * natively supported and the backend will blend the - * transparency into the white background. - */ - if (_cairo_region_contains_rectangle (&surface->supported_region, rect) == PIXMAN_REGION_OUT) - backend_status = CAIRO_STATUS_SUCCESS; - } - - if (backend_status == CAIRO_STATUS_SUCCESS) { - /* Add the operation to the supported region. Operations in - * this region will be emitted as native operations. - */ - surface->has_supported = TRUE; - status = _cairo_region_union_rect (&surface->supported_region, - &surface->supported_region, - rect); - return status; - } - - /* Add the operation to the unsupported region. This region will - * be painted as an image after all native operations have been - * emitted. - */ - surface->has_unsupported = TRUE; - status = _cairo_region_union_rect (&surface->fallback_region, - &surface->fallback_region, - rect); - - /* The status CAIRO_INT_STATUS_IMAGE_FALLBACK is used to indicate - * unsupported operations to the meta surface as using - * CAIRO_INT_STATUS_UNSUPPORTED would cause cairo-surface to - * invoke the cairo-surface-fallback path then return - * CAIRO_STATUS_SUCCESS. - */ - if (status == CAIRO_STATUS_SUCCESS) - return CAIRO_INT_STATUS_IMAGE_FALLBACK; - else - return status; -} - -static cairo_status_t -_cairo_analysis_surface_finish (void *abstract_surface) -{ - cairo_analysis_surface_t *surface = (cairo_analysis_surface_t *) abstract_surface; - - _cairo_region_fini (&surface->supported_region); - _cairo_region_fini (&surface->fallback_region); - - cairo_surface_destroy (surface->target); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_analysis_surface_intersect_clip_path (void *abstract_surface, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_analysis_surface_t *surface = abstract_surface; - double x1, y1, x2, y2; - cairo_rectangle_int_t extent; - cairo_bool_t is_empty; - - if (path == NULL) { - surface->current_clip.x = 0; - surface->current_clip.y = 0; - surface->current_clip.width = surface->width; - surface->current_clip.height = surface->height; - } else { - cairo_status_t status; - - status = _cairo_path_fixed_bounds (path, &x1, &y1, &x2, &y2, tolerance); - if (status) - return status; - - extent.x = floor (x1); - extent.y = floor (y1); - extent.width = ceil (x2) - extent.x; - extent.height = ceil (y2) - extent.y; - - is_empty = _cairo_rectangle_intersect (&surface->current_clip, &extent); - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_analysis_surface_get_extents (void *abstract_surface, - cairo_rectangle_int_t *rectangle) -{ - cairo_analysis_surface_t *surface = abstract_surface; - - return _cairo_surface_get_extents (surface->target, rectangle); -} - -static cairo_int_status_t -_cairo_analysis_surface_paint (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source) -{ - cairo_analysis_surface_t *surface = abstract_surface; - cairo_status_t status, backend_status; - cairo_rectangle_int_t extents; - cairo_bool_t is_empty; - - if (!surface->target->backend->paint) - backend_status = CAIRO_INT_STATUS_UNSUPPORTED; - else - backend_status = (*surface->target->backend->paint) (surface->target, op, - source); - - if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN) - backend_status = _analyze_meta_surface_pattern (surface, source); - - status = _cairo_surface_get_extents (&surface->base, &extents); - if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - - if (_cairo_operator_bounded_by_source (op)) { - cairo_rectangle_int_t source_extents; - - status = _cairo_pattern_get_extents (source, &source_extents); - if (status) - return status; - - is_empty = _cairo_rectangle_intersect (&extents, &source_extents); - } - - is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip); - - status = _add_operation (surface, &extents, backend_status); - - return status; -} - -static cairo_int_status_t -_cairo_analysis_surface_mask (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_pattern_t *mask) -{ - cairo_analysis_surface_t *surface = abstract_surface; - cairo_int_status_t status, backend_status; - cairo_rectangle_int_t extents; - cairo_bool_t is_empty; - - if (!surface->target->backend->mask) - backend_status = CAIRO_INT_STATUS_UNSUPPORTED; - else - backend_status = (*surface->target->backend->mask) (surface->target, op, - source, mask); - - if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN) { - cairo_int_status_t backend_source_status = CAIRO_STATUS_SUCCESS; - cairo_int_status_t backend_mask_status = CAIRO_STATUS_SUCCESS; - - if (source->type == CAIRO_PATTERN_TYPE_SURFACE) { - cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) source; - if (_cairo_surface_is_meta (surface_pattern->surface)) { - backend_source_status = - _analyze_meta_surface_pattern (surface, source); - if (_cairo_status_is_error (backend_source_status)) - return backend_source_status; - } - } - - if (mask->type == CAIRO_PATTERN_TYPE_SURFACE) { - cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) mask; - if (_cairo_surface_is_meta (surface_pattern->surface)) { - backend_mask_status = - _analyze_meta_surface_pattern (surface, mask); - if (_cairo_status_is_error (backend_mask_status)) - return backend_mask_status; - } - } - - backend_status = - _cairo_analysis_surface_merge_status (backend_source_status, - backend_mask_status); - } - - status = _cairo_surface_get_extents (&surface->base, &extents); - if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - - if (_cairo_operator_bounded_by_source (op)) { - cairo_rectangle_int_t source_extents; - status = _cairo_pattern_get_extents (source, &source_extents); - if (status) - return status; - - is_empty = _cairo_rectangle_intersect (&extents, &source_extents); - } - - if (_cairo_operator_bounded_by_mask (op)) { - cairo_rectangle_int_t mask_extents; - - status = _cairo_pattern_get_extents (mask, &mask_extents); - if (status) - return status; - - is_empty = _cairo_rectangle_intersect (&extents, &mask_extents); - } - - is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip); - - status = _add_operation (surface, &extents, backend_status); - - return status; -} - -static cairo_int_status_t -_cairo_analysis_surface_stroke (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - 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_analysis_surface_t *surface = abstract_surface; - cairo_status_t status, backend_status; - cairo_traps_t traps; - cairo_rectangle_int_t extents; - cairo_bool_t is_empty; - - if (!surface->target->backend->stroke) - backend_status = CAIRO_INT_STATUS_UNSUPPORTED; - else - backend_status = (*surface->target->backend->stroke) (surface->target, op, - source, path, style, - ctm, ctm_inverse, - tolerance, antialias); - - if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN) - backend_status = _analyze_meta_surface_pattern (surface, source); - - status = _cairo_surface_get_extents (&surface->base, &extents); - if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - - if (_cairo_operator_bounded_by_source (op)) { - cairo_rectangle_int_t source_extents; - - status = _cairo_pattern_get_extents (source, &source_extents); - if (status) - return status; - - is_empty = _cairo_rectangle_intersect (&extents, &source_extents); - } - - is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip); - - if (_cairo_operator_bounded_by_mask (op)) { - cairo_box_t box; - - _cairo_box_from_rectangle (&box, &extents); - - _cairo_traps_init (&traps); - _cairo_traps_limit (&traps, &box); - status = _cairo_path_fixed_stroke_to_traps (path, - style, - ctm, ctm_inverse, - tolerance, - &traps); - if (status) { - _cairo_traps_fini (&traps); - return status; - } - - _cairo_traps_extents (&traps, &box); - _cairo_traps_fini (&traps); - - _cairo_box_round_to_rectangle (&box, &extents); - } - - status = _add_operation (surface, &extents, backend_status); - - return status; -} - -static cairo_int_status_t -_cairo_analysis_surface_fill (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_analysis_surface_t *surface = abstract_surface; - cairo_status_t status, backend_status; - cairo_traps_t traps; - cairo_rectangle_int_t extents; - cairo_bool_t is_empty; - - if (!surface->target->backend->fill) - backend_status = CAIRO_INT_STATUS_UNSUPPORTED; - else - backend_status = (*surface->target->backend->fill) (surface->target, op, - source, path, fill_rule, - tolerance, antialias); - - if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN) - backend_status = _analyze_meta_surface_pattern (surface, source); - - status = _cairo_surface_get_extents (&surface->base, &extents); - if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - - if (_cairo_operator_bounded_by_source (op)) { - cairo_rectangle_int_t source_extents; - - status = _cairo_pattern_get_extents (source, &source_extents); - if (status) - return status; - - is_empty = _cairo_rectangle_intersect (&extents, &source_extents); - } - - is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip); - - if (_cairo_operator_bounded_by_mask (op)) { - cairo_box_t box; - - _cairo_box_from_rectangle (&box, &extents); - - _cairo_traps_init (&traps); - _cairo_traps_limit (&traps, &box); - status = _cairo_path_fixed_fill_to_traps (path, - fill_rule, - tolerance, - &traps); - if (status) { - _cairo_traps_fini (&traps); - return status; - } - - _cairo_traps_extents (&traps, &box); - _cairo_traps_fini (&traps); - - _cairo_box_round_to_rectangle (&box, &extents); - } - - status = _add_operation (surface, &extents, backend_status); - - return status; -} - -static cairo_int_status_t -_cairo_analysis_surface_show_glyphs (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font, - int *remaining_glyphs) -{ - cairo_analysis_surface_t *surface = abstract_surface; - cairo_status_t status, backend_status; - cairo_rectangle_int_t extents, glyph_extents; - cairo_bool_t is_empty; - - /* Adapted from _cairo_surface_show_glyphs */ - if (surface->target->backend->show_glyphs) - backend_status = (*surface->target->backend->show_glyphs) (surface->target, op, - source, - glyphs, num_glyphs, - scaled_font, - remaining_glyphs); - else if (surface->target->backend->show_text_glyphs) - backend_status = surface->target->backend->show_text_glyphs (surface->target, op, - source, - NULL, 0, - glyphs, num_glyphs, - NULL, 0, - FALSE, - scaled_font); - else - backend_status = CAIRO_INT_STATUS_UNSUPPORTED; - - if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN) - backend_status = _analyze_meta_surface_pattern (surface, source); - - status = _cairo_surface_get_extents (&surface->base, &extents); - if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - - if (_cairo_operator_bounded_by_source (op)) { - cairo_rectangle_int_t source_extents; - - status = _cairo_pattern_get_extents (source, &source_extents); - if (status) - return status; - - is_empty = _cairo_rectangle_intersect (&extents, &source_extents); - } - - is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip); - - if (_cairo_operator_bounded_by_mask (op)) { - status = _cairo_scaled_font_glyph_device_extents (scaled_font, - glyphs, - num_glyphs, - &glyph_extents); - if (status) - return status; - - is_empty = _cairo_rectangle_intersect (&extents, &glyph_extents); - } - - status = _add_operation (surface, &extents, backend_status); - - return status; -} - -static cairo_bool_t -_cairo_analysis_surface_has_show_text_glyphs (void *abstract_surface) -{ - cairo_analysis_surface_t *surface = abstract_surface; - - return cairo_surface_has_show_text_glyphs (surface->target); -} - -static cairo_int_status_t -_cairo_analysis_surface_show_text_glyphs (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - const char *utf8, - int utf8_len, - cairo_glyph_t *glyphs, - int num_glyphs, - const cairo_text_cluster_t *clusters, - int num_clusters, - cairo_text_cluster_flags_t cluster_flags, - cairo_scaled_font_t *scaled_font) -{ - cairo_analysis_surface_t *surface = abstract_surface; - cairo_status_t status, backend_status; - cairo_rectangle_int_t extents, glyph_extents; - cairo_bool_t is_empty; - - /* Adapted from _cairo_surface_show_glyphs */ - backend_status = CAIRO_INT_STATUS_UNSUPPORTED; - if (surface->target->backend->show_text_glyphs) - backend_status = surface->target->backend->show_text_glyphs (surface->target, op, - source, - utf8, utf8_len, - glyphs, num_glyphs, - clusters, num_clusters, cluster_flags, - scaled_font); - if (backend_status == CAIRO_INT_STATUS_UNSUPPORTED && surface->target->backend->show_glyphs) { - int remaining_glyphs = num_glyphs; - backend_status = surface->target->backend->show_glyphs (surface->target, op, - source, - glyphs, num_glyphs, - scaled_font, - &remaining_glyphs); - glyphs += num_glyphs - remaining_glyphs; - num_glyphs = remaining_glyphs; - if (remaining_glyphs == 0) - backend_status = CAIRO_STATUS_SUCCESS; - } - - if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN) - backend_status = _analyze_meta_surface_pattern (surface, source); - - status = _cairo_surface_get_extents (&surface->base, &extents); - if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - - if (_cairo_operator_bounded_by_source (op)) { - cairo_rectangle_int_t source_extents; - - status = _cairo_pattern_get_extents (source, &source_extents); - if (status) - return status; - - is_empty = _cairo_rectangle_intersect (&extents, &source_extents); - } - - is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip); - - if (_cairo_operator_bounded_by_mask (op)) { - status = _cairo_scaled_font_glyph_device_extents (scaled_font, - glyphs, - num_glyphs, - &glyph_extents); - if (status) - return status; - - is_empty = _cairo_rectangle_intersect (&extents, &glyph_extents); - } - - status = _add_operation (surface, &extents, backend_status); - - return status; -} - -static const cairo_surface_backend_t cairo_analysis_surface_backend = { - CAIRO_INTERNAL_SURFACE_TYPE_ANALYSIS, - NULL, /* create_similar */ - _cairo_analysis_surface_finish, - NULL, /* acquire_source_image */ - NULL, /* release_source_image */ - NULL, /* acquire_dest_image */ - NULL, /* release_dest_image */ - NULL, /* clone_similar */ - NULL, /* composite */ - NULL, /* fill_rectangles */ - NULL, /* composite_trapezoids */ - NULL, /* copy_page */ - NULL, /* show_page */ - NULL, /* set_clip_region */ - _cairo_analysis_surface_intersect_clip_path, - _cairo_analysis_surface_get_extents, - NULL, /* old_show_glyphs */ - NULL, /* get_font_options */ - NULL, /* flush */ - NULL, /* mark_dirty_rectangle */ - NULL, /* scaled_font_fini */ - NULL, /* scaled_glyph_fini */ - _cairo_analysis_surface_paint, - _cairo_analysis_surface_mask, - _cairo_analysis_surface_stroke, - _cairo_analysis_surface_fill, - _cairo_analysis_surface_show_glyphs, - NULL, /* snapshot */ - NULL, /* is_similar */ - NULL, /* reset */ - NULL, /* fill_stroke */ - NULL, /* create_solid_pattern_surface */ - _cairo_analysis_surface_has_show_text_glyphs, - _cairo_analysis_surface_show_text_glyphs -}; - -cairo_surface_t * -_cairo_analysis_surface_create (cairo_surface_t *target, - int width, - int height) -{ - cairo_analysis_surface_t *surface; - cairo_status_t status; - - status = target->status; - if (status) - return _cairo_surface_create_in_error (status); - - surface = malloc (sizeof (cairo_analysis_surface_t)); - if (surface == NULL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - /* I believe the content type here is truly arbitrary. I'm quite - * sure nothing will ever use this value. */ - _cairo_surface_init (&surface->base, &cairo_analysis_surface_backend, - CAIRO_CONTENT_COLOR_ALPHA); - - surface->width = width; - surface->height = height; - cairo_matrix_init_identity (&surface->ctm); - surface->has_ctm = FALSE; - - surface->target = cairo_surface_reference (target); - surface->first_op = TRUE; - surface->has_supported = FALSE; - surface->has_unsupported = FALSE; - - surface->page_bbox.p1.x = 0; - surface->page_bbox.p1.y = 0; - surface->page_bbox.p2.x = 0; - surface->page_bbox.p2.y = 0; - - _cairo_region_init (&surface->supported_region); - _cairo_region_init (&surface->fallback_region); - - if (width == -1 && height == -1) { - surface->current_clip.x = CAIRO_RECT_INT_MIN; - surface->current_clip.y = CAIRO_RECT_INT_MIN; - surface->current_clip.width = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN; - surface->current_clip.height = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN; - } else { - surface->current_clip.x = 0; - surface->current_clip.y = 0; - surface->current_clip.width = width; - surface->current_clip.height = height; - } - - return &surface->base; -} - -void -_cairo_analysis_surface_set_ctm (cairo_surface_t *abstract_surface, - cairo_matrix_t *ctm) -{ - cairo_analysis_surface_t *surface; - - if (abstract_surface->status) - return; - - surface = (cairo_analysis_surface_t *) abstract_surface; - - surface->ctm = *ctm; - surface->has_ctm = !_cairo_matrix_is_identity (&surface->ctm); -} - -void -_cairo_analysis_surface_get_ctm (cairo_surface_t *abstract_surface, - cairo_matrix_t *ctm) -{ - cairo_analysis_surface_t *surface = (cairo_analysis_surface_t *) abstract_surface; - - *ctm = surface->ctm; -} - - -cairo_region_t * -_cairo_analysis_surface_get_supported (cairo_surface_t *abstract_surface) -{ - cairo_analysis_surface_t *surface = (cairo_analysis_surface_t *) abstract_surface; - - return &surface->supported_region; -} - -cairo_region_t * -_cairo_analysis_surface_get_unsupported (cairo_surface_t *abstract_surface) -{ - cairo_analysis_surface_t *surface = (cairo_analysis_surface_t *) abstract_surface; - - return &surface->fallback_region; -} - -cairo_bool_t -_cairo_analysis_surface_has_supported (cairo_surface_t *abstract_surface) -{ - cairo_analysis_surface_t *surface = (cairo_analysis_surface_t *) abstract_surface; - - return surface->has_supported; -} - -cairo_bool_t -_cairo_analysis_surface_has_unsupported (cairo_surface_t *abstract_surface) -{ - cairo_analysis_surface_t *surface = (cairo_analysis_surface_t *) abstract_surface; - - return surface->has_unsupported; -} - -void -_cairo_analysis_surface_get_bounding_box (cairo_surface_t *abstract_surface, - cairo_box_t *bbox) -{ - cairo_analysis_surface_t *surface = (cairo_analysis_surface_t *) abstract_surface; - - *bbox = surface->page_bbox; -} - -/* null surface type: a surface that does nothing (has no side effects, yay!) */ - -static cairo_int_status_t -_return_success (void) -{ - return CAIRO_STATUS_SUCCESS; -} - -/* These typedefs are just to silence the compiler... */ -typedef cairo_int_status_t -(*_set_clip_region_func) (void *surface, - cairo_region_t *region); -typedef cairo_int_status_t -(*_paint_func) (void *surface, - cairo_operator_t op, - cairo_pattern_t *source); - -typedef cairo_int_status_t -(*_mask_func) (void *surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_pattern_t *mask); - -typedef cairo_int_status_t -(*_stroke_func) (void *surface, - cairo_operator_t op, - cairo_pattern_t *source, - 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); - -typedef cairo_int_status_t -(*_fill_func) (void *surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias); - -typedef cairo_int_status_t -(*_show_glyphs_func) (void *surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font, - int *remaining_glyphs); - -static const cairo_surface_backend_t cairo_null_surface_backend = { - CAIRO_INTERNAL_SURFACE_TYPE_NULL, - - NULL, /* create_similar */ - NULL, /* finish */ - NULL, /* acquire_source_image */ - NULL, /* release_source_image */ - NULL, /* acquire_dest_image */ - NULL, /* release_dest_image */ - NULL, /* clone_similar */ - NULL, /* composite */ - NULL, /* fill_rectangles */ - NULL, /* composite_trapezoids */ - NULL, /* copy_page */ - NULL, /* show_page */ - (_set_clip_region_func) _return_success, /* set_clip_region */ - NULL, /* intersect_clip_path */ - NULL, /* get_extents */ - NULL, /* old_show_glyphs */ - NULL, /* get_font_options */ - NULL, /* flush */ - NULL, /* mark_dirty_rectangle */ - NULL, /* scaled_font_fini */ - NULL, /* scaled_glyph_fini */ - (_paint_func) _return_success, /* paint */ - (_mask_func) _return_success, /* mask */ - (_stroke_func) _return_success, /* stroke */ - (_fill_func) _return_success, /* fill */ - (_show_glyphs_func) _return_success, /* show_glyphs */ - NULL, /* snapshot */ - NULL, /* is_similar */ - NULL, /* reset */ - NULL, /* fill_stroke */ - NULL, /* create_solid_pattern_surface */ - NULL, /* has_show_text_glyphs */ - NULL /* show_text_glyphs */ -}; - -cairo_surface_t * -_cairo_null_surface_create (cairo_content_t content) -{ - cairo_surface_t *surface; - - surface = malloc (sizeof (cairo_surface_t)); - if (surface == NULL) { - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - } - - _cairo_surface_init (surface, &cairo_null_surface_backend, content); - - return surface; -} diff --git a/uppdev/plugin/cairo/lib/cairo-arc-private.h b/uppdev/plugin/cairo/lib/cairo-arc-private.h deleted file mode 100644 index 633fbfa5a..000000000 --- a/uppdev/plugin/cairo/lib/cairo-arc-private.h +++ /dev/null @@ -1,57 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Carl D. Worth - */ - -#ifndef CAIRO_ARC_PRIVATE_H -#define CAIRO_ARC_PRIVATE_H - -#include "cairoint.h" - -cairo_private void -_cairo_arc_path (cairo_t *cr, - double xc, - double yc, - double radius, - double angle1, - double angle2); - -cairo_private void -_cairo_arc_path_negative (cairo_t *cr, - double xc, - double yc, - double radius, - double angle1, - double angle2); - -#endif /* CAIRO_ARC_PRIVATE_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-arc.c b/uppdev/plugin/cairo/lib/cairo-arc.c deleted file mode 100644 index 2b368099e..000000000 --- a/uppdev/plugin/cairo/lib/cairo-arc.c +++ /dev/null @@ -1,292 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - */ - -#include "cairoint.h" - -#include "cairo-arc-private.h" - -/* Spline deviation from the circle in radius would be given by: - - error = sqrt (x**2 + y**2) - 1 - - A simpler error function to work with is: - - e = x**2 + y**2 - 1 - - From "Good approximation of circles by curvature-continuous Bezier - curves", Tor Dokken and Morten Daehlen, Computer Aided Geometric - Design 8 (1990) 22-41, we learn: - - abs (max(e)) = 4/27 * sin**6(angle/4) / cos**2(angle/4) - - and - abs (error) =~ 1/2 * e - - Of course, this error value applies only for the particular spline - approximation that is used in _cairo_gstate_arc_segment. -*/ -static double -_arc_error_normalized (double angle) -{ - return 2.0/27.0 * pow (sin (angle / 4), 6) / pow (cos (angle / 4), 2); -} - -static double -_arc_max_angle_for_tolerance_normalized (double tolerance) -{ - double angle, error; - int i; - - /* Use table lookup to reduce search time in most cases. */ - struct { - double angle; - double error; - } table[] = { - { M_PI / 1.0, 0.0185185185185185036127 }, - { M_PI / 2.0, 0.000272567143730179811158 }, - { M_PI / 3.0, 2.38647043651461047433e-05 }, - { M_PI / 4.0, 4.2455377443222443279e-06 }, - { M_PI / 5.0, 1.11281001494389081528e-06 }, - { M_PI / 6.0, 3.72662000942734705475e-07 }, - { M_PI / 7.0, 1.47783685574284411325e-07 }, - { M_PI / 8.0, 6.63240432022601149057e-08 }, - { M_PI / 9.0, 3.2715520137536980553e-08 }, - { M_PI / 10.0, 1.73863223499021216974e-08 }, - { M_PI / 11.0, 9.81410988043554039085e-09 }, - }; - int table_size = ARRAY_LENGTH (table); - - for (i = 0; i < table_size; i++) - if (table[i].error < tolerance) - return table[i].angle; - - ++i; - do { - angle = M_PI / i++; - error = _arc_error_normalized (angle); - } while (error > tolerance); - - return angle; -} - -static int -_arc_segments_needed (double angle, - double radius, - cairo_matrix_t *ctm, - double tolerance) -{ - double major_axis, max_angle; - - /* the error is amplified by at most the length of the - * major axis of the circle; see cairo-pen.c for a more detailed analysis - * of this. */ - major_axis = _cairo_matrix_transformed_circle_major_axis (ctm, radius); - max_angle = _arc_max_angle_for_tolerance_normalized (tolerance / major_axis); - - return (int) ceil (angle / max_angle); -} - -/* We want to draw a single spline approximating a circular arc radius - R from angle A to angle B. Since we want a symmetric spline that - matches the endpoints of the arc in position and slope, we know - that the spline control points must be: - - (R * cos(A), R * sin(A)) - (R * cos(A) - h * sin(A), R * sin(A) + h * cos (A)) - (R * cos(B) + h * sin(B), R * sin(B) - h * cos (B)) - (R * cos(B), R * sin(B)) - - for some value of h. - - "Approximation of circular arcs by cubic poynomials", Michael - Goldapp, Computer Aided Geometric Design 8 (1991) 227-238, provides - various values of h along with error analysis for each. - - From that paper, a very practical value of h is: - - h = 4/3 * tan(angle/4) - - This value does not give the spline with minimal error, but it does - provide a very good approximation, (6th-order convergence), and the - error expression is quite simple, (see the comment for - _arc_error_normalized). -*/ -static void -_cairo_arc_segment (cairo_t *cr, - double xc, - double yc, - double radius, - double angle_A, - double angle_B) -{ - double r_sin_A, r_cos_A; - double r_sin_B, r_cos_B; - double h; - - r_sin_A = radius * sin (angle_A); - r_cos_A = radius * cos (angle_A); - r_sin_B = radius * sin (angle_B); - r_cos_B = radius * cos (angle_B); - - h = 4.0/3.0 * tan ((angle_B - angle_A) / 4.0); - - cairo_curve_to (cr, - xc + r_cos_A - h * r_sin_A, - yc + r_sin_A + h * r_cos_A, - xc + r_cos_B + h * r_sin_B, - yc + r_sin_B - h * r_cos_B, - xc + r_cos_B, - yc + r_sin_B); -} - -static void -_cairo_arc_in_direction (cairo_t *cr, - double xc, - double yc, - double radius, - double angle_min, - double angle_max, - cairo_direction_t dir) -{ - if (cairo_status (cr)) - return; - - while (angle_max - angle_min > 4 * M_PI) - angle_max -= 2 * M_PI; - - /* Recurse if drawing arc larger than pi */ - if (angle_max - angle_min > M_PI) { - double angle_mid = angle_min + (angle_max - angle_min) / 2.0; - if (dir == CAIRO_DIRECTION_FORWARD) { - _cairo_arc_in_direction (cr, xc, yc, radius, - angle_min, angle_mid, - dir); - - _cairo_arc_in_direction (cr, xc, yc, radius, - angle_mid, angle_max, - dir); - } else { - _cairo_arc_in_direction (cr, xc, yc, radius, - angle_mid, angle_max, - dir); - - _cairo_arc_in_direction (cr, xc, yc, radius, - angle_min, angle_mid, - dir); - } - } else if (angle_max != angle_min) { - cairo_matrix_t ctm; - int i, segments; - double angle, angle_step; - - cairo_get_matrix (cr, &ctm); - segments = _arc_segments_needed (angle_max - angle_min, - radius, &ctm, - cairo_get_tolerance (cr)); - angle_step = (angle_max - angle_min) / (double) segments; - - if (dir == CAIRO_DIRECTION_FORWARD) { - angle = angle_min; - } else { - angle = angle_max; - angle_step = - angle_step; - } - - for (i = 0; i < segments; i++, angle += angle_step) { - _cairo_arc_segment (cr, xc, yc, - radius, - angle, - angle + angle_step); - } - } -} - -/** - * _cairo_arc_path - * @cr: a cairo context - * @xc: X position of the center of the arc - * @yc: Y position of the center of the arc - * @radius: the radius of the arc - * @angle1: the start angle, in radians - * @angle2: the end angle, in radians - * - * Compute a path for the given arc and append it onto the current - * path within @cr. The arc will be accurate within the current - * tolerance and given the current transformation. - **/ -void -_cairo_arc_path (cairo_t *cr, - double xc, - double yc, - double radius, - double angle1, - double angle2) -{ - _cairo_arc_in_direction (cr, xc, yc, - radius, - angle1, angle2, - CAIRO_DIRECTION_FORWARD); -} - -/** - * _cairo_arc_path_negative: - * @xc: X position of the center of the arc - * @yc: Y position of the center of the arc - * @radius: the radius of the arc - * @angle1: the start angle, in radians - * @angle2: the end angle, in radians - * @ctm: the current transformation matrix - * @tolerance: the current tolerance value - * @path: the path onto which the arc will be appended - * - * Compute a path for the given arc (defined in the negative - * direction) and append it onto the current path within @cr. The arc - * will be accurate within the current tolerance and given the current - * transformation. - **/ -void -_cairo_arc_path_negative (cairo_t *cr, - double xc, - double yc, - double radius, - double angle1, - double angle2) -{ - _cairo_arc_in_direction (cr, xc, yc, - radius, - angle2, angle1, - CAIRO_DIRECTION_REVERSE); -} diff --git a/uppdev/plugin/cairo/lib/cairo-array.c b/uppdev/plugin/cairo/lib/cairo-array.c deleted file mode 100644 index b2790c8a1..000000000 --- a/uppdev/plugin/cairo/lib/cairo-array.c +++ /dev/null @@ -1,492 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2004 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Kristian Høgsberg - * Carl Worth - */ - -#include "cairoint.h" - -/** - * _cairo_array_init: - * - * Initialize a new #cairo_array_t object to store objects each of size - * @element_size. - * - * The #cairo_array_t object provides grow-by-doubling storage. It - * never interprets the data passed to it, nor does it provide any - * sort of callback mechanism for freeing resources held onto by - * stored objects. - * - * When finished using the array, _cairo_array_fini() should be - * called to free resources allocated during use of the array. - **/ -void -_cairo_array_init (cairo_array_t *array, int element_size) -{ - array->size = 0; - array->num_elements = 0; - array->element_size = element_size; - array->elements = NULL; - - array->is_snapshot = FALSE; -} - -/** - * _cairo_array_init_snapshot: - * @array: A #cairo_array_t to be initialized as a snapshot - * @other: The #cairo_array_t from which to create the snapshot - * - * Initialize @array as an immutable copy of @other. It is an error to - * call an array-modifying function (other than _cairo_array_fini) on - * @array after calling this function. - **/ -void -_cairo_array_init_snapshot (cairo_array_t *array, - const cairo_array_t *other) -{ - array->size = other->size; - array->num_elements = other->num_elements; - array->element_size = other->element_size; - array->elements = other->elements; - - array->is_snapshot = TRUE; -} - -/** - * _cairo_array_fini: - * @array: A #cairo_array_t - * - * Free all resources associated with @array. After this call, @array - * should not be used again without a subsequent call to - * _cairo_array_init() again first. - **/ -void -_cairo_array_fini (cairo_array_t *array) -{ - if (array->is_snapshot) - return; - - if (array->elements) { - free (* array->elements); - free (array->elements); - } -} - -/** - * _cairo_array_grow_by: - * @array: a #cairo_array_t - * - * Increase the size of @array (if needed) so that there are at least - * @additional free spaces in the array. The actual size of the array - * is always increased by doubling as many times as necessary. - **/ -cairo_status_t -_cairo_array_grow_by (cairo_array_t *array, unsigned int additional) -{ - char *new_elements; - unsigned int old_size = array->size; - unsigned int required_size = array->num_elements + additional; - unsigned int new_size; - - assert (! array->is_snapshot); - - /* check for integer overflow */ - if (required_size > INT_MAX || required_size < array->num_elements) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - if (required_size <= old_size) - return CAIRO_STATUS_SUCCESS; - - if (old_size == 0) - new_size = 1; - else - new_size = old_size * 2; - - while (new_size < required_size) - new_size = new_size * 2; - - if (array->elements == NULL) { - array->elements = malloc (sizeof (char *)); - if (array->elements == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - *array->elements = NULL; - } - - array->size = new_size; - new_elements = _cairo_realloc_ab (*array->elements, - array->size, array->element_size); - - if (new_elements == NULL) { - array->size = old_size; - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - *array->elements = new_elements; - - return CAIRO_STATUS_SUCCESS; -} - -/** - * _cairo_array_truncate: - * @array: a #cairo_array_t - * - * Truncate size of the array to @num_elements if less than the - * current size. No memory is actually freed. The stored objects - * beyond @num_elements are simply "forgotten". - **/ -void -_cairo_array_truncate (cairo_array_t *array, unsigned int num_elements) -{ - assert (! array->is_snapshot); - - if (num_elements < array->num_elements) - array->num_elements = num_elements; -} - -/** - * _cairo_array_index: - * @array: a #cairo_array_t - * Returns: A pointer to the object stored at @index. - * - * If the resulting value is assigned to a pointer to an object of the same - * element_size as initially passed to _cairo_array_init() then that - * pointer may be used for further direct indexing with []. For - * example: - * - * - * cairo_array_t array; - * double *values; - * - * _cairo_array_init (&array, sizeof(double)); - * ... calls to _cairo_array_append() here ... - * - * values = _cairo_array_index (&array, 0); - * for (i = 0; i < _cairo_array_num_elements (&array); i++) - * ... use values[i] here ... - * - **/ -void * -_cairo_array_index (cairo_array_t *array, unsigned int index) -{ - /* We allow an index of 0 for the no-elements case. - * This makes for cleaner calling code which will often look like: - * - * elements = _cairo_array_index (array, num_elements); - * for (i=0; i < num_elements; i++) { - * ... use elements[i] here ... - * } - * - * which in the num_elements==0 case gets the NULL pointer here, - * but never dereferences it. - */ - if (index == 0 && array->num_elements == 0) - return NULL; - - assert (index < array->num_elements); - - return (void *) &(*array->elements)[index * array->element_size]; -} - -/** - * _cairo_array_copy_element: - * @array: a #cairo_array_t - * - * Copy a single element out of the array from index @index into the - * location pointed to by @dst. - **/ -void -_cairo_array_copy_element (cairo_array_t *array, int index, void *dst) -{ - memcpy (dst, _cairo_array_index (array, index), array->element_size); -} - -/** - * _cairo_array_append: - * @array: a #cairo_array_t - * - * Append a single item onto the array by growing the array by at - * least one element, then copying element_size bytes from @element - * into the array. The address of the resulting object within the - * array can be determined with: - * - * _cairo_array_index (array, _cairo_array_num_elements (array) - 1); - * - * Return value: %CAIRO_STATUS_SUCCESS if successful or - * %CAIRO_STATUS_NO_MEMORY if insufficient memory is available for the - * operation. - **/ -cairo_status_t -_cairo_array_append (cairo_array_t *array, - const void *element) -{ - assert (! array->is_snapshot); - - return _cairo_array_append_multiple (array, element, 1); -} - -/** - * _cairo_array_append: - * @array: a #cairo_array_t - * - * Append one or more items onto the array by growing the array by - * @num_elements, then copying @num_elements * element_size bytes from - * @elements into the array. - * - * Return value: %CAIRO_STATUS_SUCCESS if successful or - * %CAIRO_STATUS_NO_MEMORY if insufficient memory is available for the - * operation. - **/ -cairo_status_t -_cairo_array_append_multiple (cairo_array_t *array, - const void *elements, - int num_elements) -{ - cairo_status_t status; - void *dest; - - assert (! array->is_snapshot); - - status = _cairo_array_allocate (array, num_elements, &dest); - if (status) - return status; - - memcpy (dest, elements, num_elements * array->element_size); - - return CAIRO_STATUS_SUCCESS; -} - -/** - * _cairo_array_allocate: - * @array: a #cairo_array_t - * - * Allocate space at the end of the array for @num_elements additional - * elements, providing the address of the new memory chunk in - * @elements. This memory will be unitialized, but will be accounted - * for in the return value of _cairo_array_num_elements(). - * - * Return value: %CAIRO_STATUS_SUCCESS if successful or - * %CAIRO_STATUS_NO_MEMORY if insufficient memory is available for the - * operation. - **/ -cairo_status_t -_cairo_array_allocate (cairo_array_t *array, - unsigned int num_elements, - void **elements) -{ - cairo_status_t status; - - assert (! array->is_snapshot); - - status = _cairo_array_grow_by (array, num_elements); - if (status) - return status; - - assert (array->num_elements + num_elements <= array->size); - - *elements = &(*array->elements)[array->num_elements * array->element_size]; - - array->num_elements += num_elements; - - return CAIRO_STATUS_SUCCESS; -} - -/** - * _cairo_array_num_elements: - * @array: a #cairo_array_t - * Returns: The number of elements stored in @array. - * - * This space was left intentionally blank, but gtk-doc filled it. - **/ -int -_cairo_array_num_elements (cairo_array_t *array) -{ - return array->num_elements; -} - -/** - * _cairo_array_size: - * @array: a #cairo_array_t - * Returns: The number of elements for which there is currently space - * allocated in @array. - * - * This space was left intentionally blank, but gtk-doc filled it. - **/ -int -_cairo_array_size (cairo_array_t *array) -{ - return array->size; -} - -/* #cairo_user_data_array_t */ - -typedef struct { - const cairo_user_data_key_t *key; - void *user_data; - cairo_destroy_func_t destroy; -} cairo_user_data_slot_t; - -/** - * _cairo_user_data_array_init: - * @array: a #cairo_user_data_array_t - * - * Initializes a #cairo_user_data_array_t structure for future - * use. After initialization, the array has no keys. Call - * _cairo_user_data_array_fini() to free any allocated memory - * when done using the array. - **/ -void -_cairo_user_data_array_init (cairo_user_data_array_t *array) -{ - _cairo_array_init (array, sizeof (cairo_user_data_slot_t)); -} - -/** - * _cairo_user_data_array_fini: - * @array: a #cairo_user_data_array_t - * - * Destroys all current keys in the user data array and deallocates - * any memory allocated for the array itself. - **/ -void -_cairo_user_data_array_fini (cairo_user_data_array_t *array) -{ - int i, num_slots; - cairo_user_data_slot_t *slots; - - num_slots = array->num_elements; - slots = _cairo_array_index (array, 0); - for (i = 0; i < num_slots; i++) { - if (slots[i].user_data != NULL && slots[i].destroy != NULL) - slots[i].destroy (slots[i].user_data); - } - - _cairo_array_fini (array); -} - -/** - * _cairo_user_data_array_get_data: - * @array: a #cairo_user_data_array_t - * @key: the address of the #cairo_user_data_key_t the user data was - * attached to - * - * Returns user data previously attached using the specified - * key. If no user data has been attached with the given key this - * function returns %NULL. - * - * Return value: the user data previously attached or %NULL. - **/ -void * -_cairo_user_data_array_get_data (cairo_user_data_array_t *array, - const cairo_user_data_key_t *key) -{ - int i, num_slots; - cairo_user_data_slot_t *slots; - - /* We allow this to support degenerate objects such as cairo_surface_nil. */ - if (array == NULL) - return NULL; - - num_slots = array->num_elements; - slots = _cairo_array_index (array, 0); - for (i = 0; i < num_slots; i++) { - if (slots[i].key == key) - return slots[i].user_data; - } - - return NULL; -} - -/** - * _cairo_user_data_array_set_data: - * @array: a #cairo_user_data_array_t - * @key: the address of a #cairo_user_data_key_t to attach the user data to - * @user_data: the user data to attach - * @destroy: a #cairo_destroy_func_t which will be called when the - * user data array is destroyed or when new user data is attached using the - * same key. - * - * Attaches user data to a user data array. To remove user data, - * call this function with the key that was used to set it and %NULL - * for @data. - * - * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a - * slot could not be allocated for the user data. - **/ -cairo_status_t -_cairo_user_data_array_set_data (cairo_user_data_array_t *array, - const cairo_user_data_key_t *key, - void *user_data, - cairo_destroy_func_t destroy) -{ - cairo_status_t status; - int i, num_slots; - cairo_user_data_slot_t *slots, *slot, new_slot; - - if (user_data) { - new_slot.key = key; - new_slot.user_data = user_data; - new_slot.destroy = destroy; - } else { - new_slot.key = NULL; - new_slot.user_data = NULL; - new_slot.destroy = NULL; - } - - slot = NULL; - num_slots = array->num_elements; - slots = _cairo_array_index (array, 0); - for (i = 0; i < num_slots; i++) { - if (slots[i].key == key) { - slot = &slots[i]; - if (slot->destroy && slot->user_data) - slot->destroy (slot->user_data); - break; - } - if (user_data && slots[i].user_data == NULL) { - slot = &slots[i]; /* Have to keep searching for an exact match */ - } - } - - if (slot) { - *slot = new_slot; - return CAIRO_STATUS_SUCCESS; - } - - status = _cairo_array_append (array, &new_slot); - if (status) - return status; - - return CAIRO_STATUS_SUCCESS; -} diff --git a/uppdev/plugin/cairo/lib/cairo-atomic-private.h b/uppdev/plugin/cairo/lib/cairo-atomic-private.h deleted file mode 100644 index 2914a0221..000000000 --- a/uppdev/plugin/cairo/lib/cairo-atomic-private.h +++ /dev/null @@ -1,104 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2007 Chris Wilson - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Chris Wilson - */ - -#ifndef CAIRO_ATOMIC_PRIVATE_H -#define CAIRO_ATOMIC_PRIVATE_H - -# include "cairo-compiler-private.h" - -#if HAVE_CONFIG_H -#include "config.h" -#endif - -CAIRO_BEGIN_DECLS - -#if HAVE_INTEL_ATOMIC_PRIMITIVES - -#define HAS_ATOMIC_OPS 1 - -typedef int cairo_atomic_int_t; - -# define _cairo_atomic_int_inc(x) ((void) __sync_fetch_and_add(x, 1)) -# define _cairo_atomic_int_dec_and_test(x) (__sync_fetch_and_add(x, -1) == 1) -# define _cairo_atomic_int_cmpxchg(x, oldv, newv) __sync_val_compare_and_swap (x, oldv, newv) - -#endif - - -#ifndef HAS_ATOMIC_OPS - -typedef int cairo_atomic_int_t; - -cairo_private void -_cairo_atomic_int_inc (int *x); - -cairo_private cairo_bool_t -_cairo_atomic_int_dec_and_test (int *x); - -cairo_private int -_cairo_atomic_int_cmpxchg (int *x, int oldv, int newv); - -#endif - - -#ifdef ATOMIC_OP_NEEDS_MEMORY_BARRIER - -# include "cairo-compiler-private.h" - -cairo_private int -_cairo_atomic_int_get (int *x); - -cairo_private void -_cairo_atomic_int_set (int *x, int value); - -#else - -# define _cairo_atomic_int_get(x) (*x) -# define _cairo_atomic_int_set(x, value) ((*x) = value) - -#endif - - -#define _cairo_status_set_error(status, err) do { \ - /* hide compiler warnings about cairo_status_t != int (gcc treats its as \ - * an unsigned integer instead, and about ignoring the return value. */ \ - int ret__ = _cairo_atomic_int_cmpxchg ((int *) status, CAIRO_STATUS_SUCCESS, err); \ - (void) ret__; \ -} while (0) - -CAIRO_END_DECLS - -#endif diff --git a/uppdev/plugin/cairo/lib/cairo-atomic.c b/uppdev/plugin/cairo/lib/cairo-atomic.c deleted file mode 100644 index c569000cb..000000000 --- a/uppdev/plugin/cairo/lib/cairo-atomic.c +++ /dev/null @@ -1,96 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2007 Chris Wilson - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * Contributor(s): - * Chris Wilson - */ - -#include "cairoint.h" - -#include "cairo-atomic-private.h" -#include "cairo-mutex-private.h" - -#ifndef HAS_ATOMIC_OPS -void -_cairo_atomic_int_inc (int *x) -{ - CAIRO_MUTEX_LOCK (_cairo_atomic_mutex); - *x += 1; - CAIRO_MUTEX_UNLOCK (_cairo_atomic_mutex); -} - -cairo_bool_t -_cairo_atomic_int_dec_and_test (int *x) -{ - cairo_bool_t ret; - - CAIRO_MUTEX_LOCK (_cairo_atomic_mutex); - ret = --*x == 0; - CAIRO_MUTEX_UNLOCK (_cairo_atomic_mutex); - - return ret; -} - -int -_cairo_atomic_int_cmpxchg (int *x, int oldv, int newv) -{ - int ret; - - CAIRO_MUTEX_LOCK (_cairo_atomic_mutex); - ret = *x; - if (ret == oldv) - *x = newv; - CAIRO_MUTEX_UNLOCK (_cairo_atomic_mutex); - - return ret; -} - -#endif - -#ifdef ATOMIC_OP_NEEDS_MEMORY_BARRIER -int -_cairo_atomic_int_get (int *x) -{ - int ret; - - CAIRO_MUTEX_LOCK (_cairo_atomic_mutex); - ret = *x; - CAIRO_MUTEX_UNLOCK (_cairo_atomic_mutex); - - return ret; -} - -void -_cairo_atomic_int_set (int *x, int value) -{ - CAIRO_MUTEX_LOCK (_cairo_atomic_mutex); - *x = value; - CAIRO_MUTEX_UNLOCK (_cairo_atomic_mutex); -} -#endif diff --git a/uppdev/plugin/cairo/lib/cairo-base85-stream.c b/uppdev/plugin/cairo/lib/cairo-base85-stream.c deleted file mode 100644 index 889740392..000000000 --- a/uppdev/plugin/cairo/lib/cairo-base85-stream.c +++ /dev/null @@ -1,132 +0,0 @@ -/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */ -/* cairo - a vector graphics library with display and print output - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Author(s): - * Kristian Høgsberg - */ - -#include "cairoint.h" -#include "cairo-output-stream-private.h" - -typedef struct _cairo_base85_stream { - cairo_output_stream_t base; - cairo_output_stream_t *output; - unsigned char four_tuple[4]; - int pending; -} cairo_base85_stream_t; - -static void -_expand_four_tuple_to_five (unsigned char four_tuple[4], - unsigned char five_tuple[5], - cairo_bool_t *all_zero) -{ - uint32_t value; - int digit, i; - - value = four_tuple[0] << 24 | four_tuple[1] << 16 | four_tuple[2] << 8 | four_tuple[3]; - if (all_zero) - *all_zero = TRUE; - for (i = 0; i < 5; i++) { - digit = value % 85; - if (digit != 0 && all_zero) - *all_zero = FALSE; - five_tuple[4-i] = digit + 33; - value = value / 85; - } -} - -static cairo_status_t -_cairo_base85_stream_write (cairo_output_stream_t *base, - const unsigned char *data, - unsigned int length) -{ - cairo_base85_stream_t *stream = (cairo_base85_stream_t *) base; - const unsigned char *ptr = data; - unsigned char five_tuple[5]; - cairo_bool_t is_zero; - - while (length) { - stream->four_tuple[stream->pending++] = *ptr++; - length--; - if (stream->pending == 4) { - _expand_four_tuple_to_five (stream->four_tuple, five_tuple, &is_zero); - if (is_zero) - _cairo_output_stream_write (stream->output, "z", 1); - else - _cairo_output_stream_write (stream->output, five_tuple, 5); - stream->pending = 0; - } - } - - return _cairo_output_stream_get_status (stream->output); -} - -static cairo_status_t -_cairo_base85_stream_close (cairo_output_stream_t *base) -{ - cairo_base85_stream_t *stream = (cairo_base85_stream_t *) base; - unsigned char five_tuple[5]; - - if (stream->pending) { - memset (stream->four_tuple + stream->pending, 0, 4 - stream->pending); - _expand_four_tuple_to_five (stream->four_tuple, five_tuple, NULL); - _cairo_output_stream_write (stream->output, five_tuple, stream->pending + 1); - } - - /* Mark end of base85 data */ - _cairo_output_stream_printf (stream->output, "~>"); - - return _cairo_output_stream_get_status (stream->output); -} - -cairo_output_stream_t * -_cairo_base85_stream_create (cairo_output_stream_t *output) -{ - cairo_base85_stream_t *stream; - - if (output->status) - return _cairo_output_stream_create_in_error (output->status); - - stream = malloc (sizeof (cairo_base85_stream_t)); - if (stream == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_output_stream_t *) &_cairo_output_stream_nil; - } - - _cairo_output_stream_init (&stream->base, - _cairo_base85_stream_write, - _cairo_base85_stream_close); - stream->output = output; - stream->pending = 0; - - return &stream->base; -} diff --git a/uppdev/plugin/cairo/lib/cairo-bentley-ottmann.c b/uppdev/plugin/cairo/lib/cairo-bentley-ottmann.c deleted file mode 100644 index c657dd9cd..000000000 --- a/uppdev/plugin/cairo/lib/cairo-bentley-ottmann.c +++ /dev/null @@ -1,1935 +0,0 @@ -/* - * Copyright © 2004 Carl Worth - * Copyright © 2006 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Carl Worth - * - * Contributor(s): - * Carl D. Worth - */ - -/* Provide definitions for standalone compilation */ -#include "cairoint.h" - -#include "cairo-skiplist-private.h" -#include "cairo-freelist-private.h" - -#define DEBUG_VALIDATE 0 -#define DEBUG_PRINT_STATE 0 - -typedef cairo_point_t cairo_bo_point32_t; - -typedef struct _cairo_bo_point128 { - cairo_int128_t x; - cairo_int128_t y; -} cairo_bo_point128_t; - -typedef struct _cairo_bo_intersect_ordinate { - int32_t ordinate; - enum { EXACT, INEXACT } exactness; -} cairo_bo_intersect_ordinate_t; - -typedef struct _cairo_bo_intersect_point { - cairo_bo_intersect_ordinate_t x; - cairo_bo_intersect_ordinate_t y; -} cairo_bo_intersect_point_t; - -typedef struct _cairo_bo_edge cairo_bo_edge_t; -typedef struct _sweep_line_elt sweep_line_elt_t; -typedef struct _cairo_bo_trap cairo_bo_trap_t; -typedef struct _cairo_bo_traps cairo_bo_traps_t; - -/* A deferred trapezoid of an edge. */ -struct _cairo_bo_trap { - cairo_bo_edge_t *right; - int32_t top; -}; - -struct _cairo_bo_traps { - cairo_traps_t *traps; - cairo_freelist_t freelist; - - /* These form the closed bounding box of the original input - * points. */ - cairo_fixed_t xmin; - cairo_fixed_t ymin; - cairo_fixed_t xmax; - cairo_fixed_t ymax; -}; - -struct _cairo_bo_edge { - cairo_bo_point32_t top; - cairo_bo_point32_t middle; - cairo_bo_point32_t bottom; - cairo_bool_t reversed; - cairo_bo_edge_t *prev; - cairo_bo_edge_t *next; - cairo_bo_trap_t *deferred_trap; - sweep_line_elt_t *sweep_line_elt; -}; - -struct _sweep_line_elt { - cairo_bo_edge_t *edge; - skip_elt_t elt; -}; - -#define SKIP_ELT_TO_EDGE_ELT(elt) SKIP_LIST_ELT_TO_DATA (sweep_line_elt_t, (elt)) -#define SKIP_ELT_TO_EDGE(elt) (SKIP_ELT_TO_EDGE_ELT (elt)->edge) - -typedef enum { - CAIRO_BO_STATUS_INTERSECTION, - CAIRO_BO_STATUS_PARALLEL, - CAIRO_BO_STATUS_NO_INTERSECTION -} cairo_bo_status_t; - -typedef enum { - CAIRO_BO_EVENT_TYPE_START, - CAIRO_BO_EVENT_TYPE_STOP, - CAIRO_BO_EVENT_TYPE_INTERSECTION -} cairo_bo_event_type_t; - -typedef struct _cairo_bo_event { - cairo_bo_event_type_t type; - cairo_bo_edge_t *e1; - cairo_bo_edge_t *e2; - cairo_bo_point32_t point; - skip_elt_t elt; -} cairo_bo_event_t; - -#define SKIP_ELT_TO_EVENT(elt) SKIP_LIST_ELT_TO_DATA (cairo_bo_event_t, (elt)) - -typedef struct _cairo_bo_event_queue { - cairo_skip_list_t intersection_queue; - - cairo_bo_event_t *startstop_events; - cairo_bo_event_t **sorted_startstop_event_ptrs; - unsigned next_startstop_event_index; - unsigned num_startstop_events; -} cairo_bo_event_queue_t; - -/* This structure extends #cairo_skip_list_t, which must come first. */ -typedef struct _cairo_bo_sweep_line { - cairo_skip_list_t active_edges; - cairo_bo_edge_t *head; - cairo_bo_edge_t *tail; - int32_t current_y; -} cairo_bo_sweep_line_t; - - -static inline int -_cairo_bo_point32_compare (cairo_bo_point32_t const *a, - cairo_bo_point32_t const *b) -{ - int cmp = a->y - b->y; - if (cmp) return cmp; - return a->x - b->x; -} - -/* Compare the slope of a to the slope of b, returning 1, 0, -1 if the - * slope a is respectively greater than, equal to, or less than the - * slope of b. - * - * For each edge, consider the direction vector formed from: - * - * top -> bottom - * - * which is: - * - * (dx, dy) = (bottom.x - top.x, bottom.y - top.y) - * - * We then define the slope of each edge as dx/dy, (which is the - * inverse of the slope typically used in math instruction). We never - * compute a slope directly as the value approaches infinity, but we - * can derive a slope comparison without division as follows, (where - * the ? represents our compare operator). - * - * 1. slope(a) ? slope(b) - * 2. adx/ady ? bdx/bdy - * 3. (adx * bdy) ? (bdx * ady) - * - * Note that from step 2 to step 3 there is no change needed in the - * sign of the result since both ady and bdy are guaranteed to be - * greater than or equal to 0. - * - * When using this slope comparison to sort edges, some care is needed - * when interpreting the results. Since the slope compare operates on - * distance vectors from top to bottom it gives a correct left to - * right sort for edges that have a common top point, (such as two - * edges with start events at the same location). On the other hand, - * the sense of the result will be exactly reversed for two edges that - * have a common stop point. - */ -static int -_slope_compare (cairo_bo_edge_t *a, - cairo_bo_edge_t *b) -{ - /* 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 adx = a->bottom.x - a->top.x; - int32_t bdx = b->bottom.x - b->top.x; - - /* Since the dy's are all positive by construction we can fast - * path the case where the two edges point in different directions - * with respect to x. */ - if ((adx ^ bdx) < 0) { - return adx < 0 ? -1 : +1; - } else { - int32_t ady = a->bottom.y - a->top.y; - int32_t bdy = b->bottom.y - b->top.y; - cairo_int64_t adx_bdy = _cairo_int32x32_64_mul (adx, bdy); - cairo_int64_t bdx_ady = _cairo_int32x32_64_mul (bdx, ady); - - return _cairo_int64_cmp (adx_bdy, bdx_ady); - } -} - -/* - * 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. - * - * (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 adx, ady; - int32_t bdx, bdy; - cairo_int128_t L, R; - - adx = a->bottom.x - a->top.x; - ady = a->bottom.y - a->top.y; - - bdx = b->bottom.x - b->top.x; - bdy = b->bottom.y - b->top.y; - - L = _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (ady, bdy), - a->top.x - b->top.x); - - R = _cairo_int128_sub (_cairo_int64x32_128_mul (_cairo_int32x32_64_mul (bdx, - ady), - y - b->top.y), - _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (adx, - bdy), - y - a->top.y)); - - /* return _cairo_int128_cmp (L, R); */ - if (_cairo_int128_lt (L, R)) - return -1; - if (_cairo_int128_gt (L, R)) - return 1; - return 0; -} - -/* - * We need to compare the x-coordinate of a line for a particular y wrt to a - * given x, 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 -?- X - * where -?- is our inequality operator. - * - * By construction, we know that A_dy (and (Y - A_y)) are - * all positive, so we can rearrange it thus without causing a sign change: - * (Y - A_y) * A_dx -?- (X - A_x) * A_dy - * - * Given the assumption that all the deltas fit within 32 bits, we can compute - * this comparison directly using 64 bit arithmetic. - * - * See the similar discussion for _slope_compare() and - * edges_compare_x_for_y_general(). - */ -static int -edge_compare_for_y_against_x (const cairo_bo_edge_t *a, - int32_t y, - int32_t x) -{ - int32_t adx, ady; - int32_t dx, dy; - cairo_int64_t L, R; - - adx = a->bottom.x - a->top.x; - ady = a->bottom.y - a->top.y; - - dy = y - a->top.y; - dx = x - a->top.x; - - L = _cairo_int32x32_64_mul (dy, adx); - R = _cairo_int32x32_64_mul (dx, ady); - - 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->top.y) - ax = a->top.x; - else if (y == a->bottom.y) - ax = a->bottom.x; - else - have_ax_bx &= ~HAVE_AX; - - if (y == b->top.y) - bx = b->top.x; - else if (y == b->bottom.y) - bx = b->bottom.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 int -_cairo_bo_sweep_line_compare_edges (cairo_bo_sweep_line_t *sweep_line, - cairo_bo_edge_t *a, - cairo_bo_edge_t *b) -{ - int cmp; - - if (a == b) - return 0; - - /* 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->middle.x < a->bottom.x) { - amin = a->middle.x; - amax = a->bottom.x; - } else { - amin = a->bottom.x; - amax = a->middle.x; - } - if (b->middle.x < b->bottom.x) { - bmin = b->middle.x; - bmax = b->bottom.x; - } else { - bmin = b->bottom.x; - bmax = b->middle.x; - } - if (amax < bmin) return -1; - if (amin > bmax) 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) - return cmp; - - /* We've got two collinear edges now. */ - - /* Since we're dealing with start events, prefer comparing top - * edges before bottom edges. */ - cmp = _cairo_bo_point32_compare (&a->top, &b->top); - if (cmp) - return cmp; - - cmp = _cairo_bo_point32_compare (&a->bottom, &b->bottom); - if (cmp) - return cmp; - - /* Finally, we've got two identical edges. Let's finally - * discriminate by a simple pointer comparison, (which works only - * because we "know" the edges are all in a single array and don't - * move. */ - if (a > b) - return 1; - else - return -1; -} - -static int -_sweep_line_elt_compare (void *list, - void *a, - void *b) -{ - cairo_bo_sweep_line_t *sweep_line = list; - sweep_line_elt_t *edge_elt_a = a; - sweep_line_elt_t *edge_elt_b = b; - - return _cairo_bo_sweep_line_compare_edges (sweep_line, - edge_elt_a->edge, - edge_elt_b->edge); -} - -static inline int -cairo_bo_event_compare (cairo_bo_event_t const *a, - cairo_bo_event_t const *b) -{ - int cmp; - - /* The major motion of the sweep line is vertical (top-to-bottom), - * and the minor motion is horizontal (left-to-right), dues to the - * infinitesimal tilt rule. - * - * Our point comparison function respects these rules. - */ - cmp = _cairo_bo_point32_compare (&a->point, &b->point); - if (cmp) - return cmp; - - /* The events share a common point, so further discrimination is - * determined by the event type. Due to the infinitesimal - * shortening rule, stop events come first, then intersection - * events, then start events. - */ - if (a->type != b->type) { - if (a->type == CAIRO_BO_EVENT_TYPE_STOP) - return -1; - if (a->type == CAIRO_BO_EVENT_TYPE_START) - return 1; - - if (b->type == CAIRO_BO_EVENT_TYPE_STOP) - return 1; - if (b->type == CAIRO_BO_EVENT_TYPE_START) - return -1; - } - - /* At this stage we are looking at two events of the same type at - * the same point. The final sort key is a slope comparison. We - * need a different sense for start and stop events based on the - * shortening rule. - * - * Note: Fortunately, we get to ignore errors in the relative - * ordering of intersection events. This means we don't even have - * to look at e2 here, nor worry about which sense of the slope - * comparison test is used for intersection events. - */ - cmp = _slope_compare (a->e1, b->e1); - if (cmp) { - if (a->type == CAIRO_BO_EVENT_TYPE_START) - return cmp; - else - return - cmp; - } - - /* Next look at the opposite point. This leaves ambiguities only - * for identical edges. */ - if (a->type == CAIRO_BO_EVENT_TYPE_START) { - cmp = _cairo_bo_point32_compare (&b->e1->bottom, - &a->e1->bottom); - if (cmp) - return cmp; - } - else if (a->type == CAIRO_BO_EVENT_TYPE_STOP) { - cmp = _cairo_bo_point32_compare (&a->e1->top, - &b->e1->top); - if (cmp) - return cmp; - } - else { /* CAIRO_BO_EVENT_TYPE_INTERSECT */ - /* For two intersection events at the identical point, we - * don't care what order they sort in, but we do care that we - * have a stable sort. In particular intersections between - * different pairs of edges must never return 0. */ - cmp = _cairo_bo_point32_compare (&a->e2->top, &b->e2->top); - if (cmp) - return cmp; - cmp = _cairo_bo_point32_compare (&a->e2->bottom, &b->e2->bottom); - if (cmp) - return cmp; - cmp = _cairo_bo_point32_compare (&a->e1->top, &b->e1->top); - if (cmp) - return cmp; - cmp = _cairo_bo_point32_compare (&a->e1->bottom, &b->e1->bottom); - if (cmp) - return cmp; - } - - /* Discrimination based on the edge pointers. */ - if (a->e1 < b->e1) - return -1; - if (a->e1 > b->e1) - return +1; - if (a->e2 < b->e2) - return -1; - if (a->e2 > b->e2) - return +1; - return 0; -} - -static int -cairo_bo_event_compare_abstract (void *list, - void *a, - void *b) -{ - cairo_bo_event_t *event_a = a; - cairo_bo_event_t *event_b = b; - - return cairo_bo_event_compare (event_a, event_b); -} - -static int -cairo_bo_event_compare_pointers (void const *voida, - void const *voidb) -{ - cairo_bo_event_t const * const *a = voida; - cairo_bo_event_t const * const *b = voidb; - if (*a != *b) { - int cmp = cairo_bo_event_compare (*a, *b); - if (cmp) - return cmp; - if (*a < *b) - return -1; - if (*a > *b) - return +1; - } - return 0; -} - -static inline cairo_int64_t -det32_64 (int32_t a, - int32_t b, - int32_t c, - int32_t d) -{ - cairo_int64_t ad; - cairo_int64_t bc; - - /* det = a * d - b * c */ - ad = _cairo_int32x32_64_mul (a, d); - bc = _cairo_int32x32_64_mul (b, c); - - return _cairo_int64_sub (ad, bc); -} - -static inline cairo_int128_t -det64x32_128 (cairo_int64_t a, - int32_t b, - cairo_int64_t c, - int32_t d) -{ - cairo_int128_t ad; - cairo_int128_t bc; - - /* det = a * d - b * c */ - ad = _cairo_int64x32_128_mul (a, d); - bc = _cairo_int64x32_128_mul (c, b); - - return _cairo_int128_sub (ad, bc); -} - -/* Compute the intersection of two lines as defined by two edges. The - * result is provided as a coordinate pair of 128-bit integers. - * - * Returns %CAIRO_BO_STATUS_INTERSECTION if there is an intersection or - * %CAIRO_BO_STATUS_PARALLEL if the two lines are exactly parallel. - */ -static cairo_bo_status_t -intersect_lines (cairo_bo_edge_t *a, - cairo_bo_edge_t *b, - cairo_bo_intersect_point_t *intersection) -{ - cairo_int64_t a_det, b_det; - - /* 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. - * What we're doing to mitigate this is to perform clamping in - * cairo_bo_tessellate_polygon(). - */ - int32_t dx1 = a->top.x - a->bottom.x; - int32_t dy1 = a->top.y - a->bottom.y; - - int32_t dx2 = b->top.x - b->bottom.x; - int32_t dy2 = b->top.y - b->bottom.y; - - cairo_int64_t den_det = det32_64 (dx1, dy1, dx2, dy2); - cairo_quorem64_t qr; - - if (_cairo_int64_is_zero (den_det)) - return CAIRO_BO_STATUS_PARALLEL; - - a_det = det32_64 (a->top.x, a->top.y, - a->bottom.x, a->bottom.y); - b_det = det32_64 (b->top.x, b->top.y, - b->bottom.x, b->bottom.y); - - /* x = det (a_det, dx1, b_det, dx2) / den_det */ - qr = _cairo_int_96by64_32x64_divrem (det64x32_128 (a_det, dx1, - b_det, dx2), - den_det); - if (_cairo_int64_eq (qr.rem, den_det)) - return CAIRO_BO_STATUS_NO_INTERSECTION; - intersection->x.ordinate = _cairo_int64_to_int32 (qr.quo); - intersection->x.exactness = _cairo_int64_is_zero (qr.rem) ? EXACT : INEXACT; - - /* y = det (a_det, dy1, b_det, dy2) / den_det */ - qr = _cairo_int_96by64_32x64_divrem (det64x32_128 (a_det, dy1, - b_det, dy2), - den_det); - if (_cairo_int64_eq (qr.rem, den_det)) - return CAIRO_BO_STATUS_NO_INTERSECTION; - intersection->y.ordinate = _cairo_int64_to_int32 (qr.quo); - intersection->y.exactness = _cairo_int64_is_zero (qr.rem) ? EXACT : INEXACT; - - return CAIRO_BO_STATUS_INTERSECTION; -} - -static int -_cairo_bo_intersect_ordinate_32_compare (cairo_bo_intersect_ordinate_t a, - int32_t b) -{ - /* First compare the quotient */ - if (a.ordinate > b) - return +1; - if (a.ordinate < b) - return -1; - /* With quotient identical, if remainder is 0 then compare equal */ - /* Otherwise, the non-zero remainder makes a > b */ - return INEXACT == a.exactness; -} - -/* Does the given edge contain the given point. The point must already - * be known to be contained within the line determined by the edge, - * (most likely the point results from an intersection of this edge - * with another). - * - * If we had exact arithmetic, then this function would simply be a - * matter of examining whether the y value of the point lies within - * the range of y values of the edge. But since intersection points - * are not exact due to being rounded to the nearest integer within - * the available precision, we must also examine the x value of the - * point. - * - * The definition of "contains" here is that the given intersection - * point will be seen by the sweep line after the start event for the - * given edge and before the stop event for the edge. See the comments - * in the implementation for more details. - */ -static cairo_bool_t -_cairo_bo_edge_contains_intersect_point (cairo_bo_edge_t *edge, - cairo_bo_intersect_point_t *point) -{ - int cmp_top, cmp_bottom; - - /* XXX: When running the actual algorithm, we don't actually need to - * compare against edge->top at all here, since any intersection above - * top is eliminated early via a slope comparison. We're leaving these - * here for now only for the sake of the quadratic-time intersection - * finder which needs them. - */ - - cmp_top = _cairo_bo_intersect_ordinate_32_compare (point->y, edge->top.y); - cmp_bottom = _cairo_bo_intersect_ordinate_32_compare (point->y, edge->bottom.y); - - if (cmp_top < 0 || cmp_bottom > 0) - { - return FALSE; - } - - if (cmp_top > 0 && cmp_bottom < 0) - { - return TRUE; - } - - /* At this stage, the point lies on the same y value as either - * edge->top or edge->bottom, so we have to examine the x value in - * order to properly determine containment. */ - - /* If the y value of the point is the same as the y value of the - * top of the edge, then the x value of the point must be greater - * to be considered as inside the edge. Similarly, if the y value - * of the point is the same as the y value of the bottom of the - * edge, then the x value of the point must be less to be - * considered as inside. */ - - if (cmp_top == 0) - return (_cairo_bo_intersect_ordinate_32_compare (point->x, edge->top.x) > 0); - else /* cmp_bottom == 0 */ - return (_cairo_bo_intersect_ordinate_32_compare (point->x, edge->bottom.x) < 0); -} - -/* Compute the intersection of two edges. The result is provided as a - * coordinate pair of 128-bit integers. - * - * Returns %CAIRO_BO_STATUS_INTERSECTION if there is an intersection - * that is within both edges, %CAIRO_BO_STATUS_NO_INTERSECTION if the - * intersection of the lines defined by the edges occurs outside of - * one or both edges, and %CAIRO_BO_STATUS_PARALLEL if the two edges - * are exactly parallel. - * - * Note that when determining if a candidate intersection is "inside" - * an edge, we consider both the infinitesimal shortening and the - * infinitesimal tilt rules described by John Hobby. Specifically, if - * the intersection is exactly the same as an edge point, it is - * effectively outside (no intersection is returned). Also, if the - * intersection point has the same - */ -static cairo_bo_status_t -_cairo_bo_edge_intersect (cairo_bo_edge_t *a, - cairo_bo_edge_t *b, - cairo_bo_point32_t *intersection) -{ - cairo_bo_status_t status; - cairo_bo_intersect_point_t quorem; - - status = intersect_lines (a, b, &quorem); - if (status) - return status; - - if (! _cairo_bo_edge_contains_intersect_point (a, &quorem)) - return CAIRO_BO_STATUS_NO_INTERSECTION; - - if (! _cairo_bo_edge_contains_intersect_point (b, &quorem)) - return CAIRO_BO_STATUS_NO_INTERSECTION; - - /* Now that we've correctly compared the intersection point and - * determined that it lies within the edge, then we know that we - * no longer need any more bits of storage for the intersection - * than we do for our edge coordinates. We also no longer need the - * remainder from the division. */ - intersection->x = quorem.x.ordinate; - intersection->y = quorem.y.ordinate; - - return CAIRO_BO_STATUS_INTERSECTION; -} - -static void -_cairo_bo_event_init (cairo_bo_event_t *event, - cairo_bo_event_type_t type, - cairo_bo_edge_t *e1, - cairo_bo_edge_t *e2, - cairo_bo_point32_t point) -{ - event->type = type; - event->e1 = e1; - event->e2 = e2; - event->point = point; -} - -static cairo_status_t -_cairo_bo_event_queue_insert (cairo_bo_event_queue_t *queue, - cairo_bo_event_t *event) -{ - cairo_status_t status = CAIRO_STATUS_SUCCESS; - /* Don't insert if there's already an equivalent intersection event in the queue. */ - if (_cairo_skip_list_insert (&queue->intersection_queue, event, - event->type == CAIRO_BO_EVENT_TYPE_INTERSECTION) == NULL) - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - return status; -} - -static void -_cairo_bo_event_queue_delete (cairo_bo_event_queue_t *queue, - cairo_bo_event_t *event) -{ - if (CAIRO_BO_EVENT_TYPE_INTERSECTION == event->type) - _cairo_skip_list_delete_given ( &queue->intersection_queue, &event->elt ); -} - -static cairo_bo_event_t * -_cairo_bo_event_dequeue (cairo_bo_event_queue_t *event_queue) -{ - skip_elt_t *elt = event_queue->intersection_queue.chains[0]; - cairo_bo_event_t *intersection = elt ? SKIP_ELT_TO_EVENT (elt) : NULL; - cairo_bo_event_t *startstop; - - if (event_queue->next_startstop_event_index == event_queue->num_startstop_events) - return intersection; - startstop = event_queue->sorted_startstop_event_ptrs[ - event_queue->next_startstop_event_index]; - - if (!intersection || cairo_bo_event_compare (startstop, intersection) <= 0) - { - event_queue->next_startstop_event_index++; - return startstop; - } - return intersection; -} - -static cairo_status_t -_cairo_bo_event_queue_init (cairo_bo_event_queue_t *event_queue, - cairo_bo_edge_t *edges, - int num_edges) -{ - int i; - cairo_bo_event_t *events, **sorted_event_ptrs; - unsigned num_events = 2*num_edges; - - memset (event_queue, 0, sizeof(*event_queue)); - - _cairo_skip_list_init (&event_queue->intersection_queue, - cairo_bo_event_compare_abstract, - sizeof (cairo_bo_event_t)); - if (0 == num_edges) - return CAIRO_STATUS_SUCCESS; - - /* The skip_elt_t field of a cairo_bo_event_t isn't used for start - * or stop events, so this allocation is safe. XXX: make the - * event type a union so it doesn't always contain the skip - * elt? */ - events = _cairo_malloc_ab (num_events, sizeof (cairo_bo_event_t) + sizeof(cairo_bo_event_t*)); - if (events == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - sorted_event_ptrs = (cairo_bo_event_t **) (events + num_events); - event_queue->startstop_events = events; - event_queue->sorted_startstop_event_ptrs = sorted_event_ptrs; - event_queue->num_startstop_events = num_events; - event_queue->next_startstop_event_index = 0; - - for (i = 0; i < num_edges; i++) { - sorted_event_ptrs[2*i] = &events[2*i]; - sorted_event_ptrs[2*i+1] = &events[2*i+1]; - - /* Initialize "middle" to top */ - edges[i].middle = edges[i].top; - - _cairo_bo_event_init (&events[2*i], - CAIRO_BO_EVENT_TYPE_START, - &edges[i], NULL, - edges[i].top); - - _cairo_bo_event_init (&events[2*i+1], - CAIRO_BO_EVENT_TYPE_STOP, - &edges[i], NULL, - edges[i].bottom); - } - - qsort (sorted_event_ptrs, num_events, - sizeof(cairo_bo_event_t *), - cairo_bo_event_compare_pointers); - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_bo_event_queue_fini (cairo_bo_event_queue_t *event_queue) -{ - _cairo_skip_list_fini (&event_queue->intersection_queue); - if (event_queue->startstop_events) - free (event_queue->startstop_events); -} - -static cairo_status_t -_cairo_bo_event_queue_insert_if_intersect_below_current_y (cairo_bo_event_queue_t *event_queue, - cairo_bo_edge_t *left, - cairo_bo_edge_t *right) -{ - cairo_bo_status_t status; - cairo_bo_point32_t intersection; - cairo_bo_event_t event; - - if (left == NULL || right == NULL) - return CAIRO_STATUS_SUCCESS; - - /* The names "left" and "right" here are correct descriptions of - * the order of the two edges within the active edge list. So if a - * slope comparison also puts left less than right, then we know - * that the intersection of these two segments has oalready - * occurred before the current sweep line position. */ - if (_slope_compare (left, right) < 0) - return CAIRO_STATUS_SUCCESS; - - status = _cairo_bo_edge_intersect (left, right, &intersection); - if (status == CAIRO_BO_STATUS_PARALLEL || - status == CAIRO_BO_STATUS_NO_INTERSECTION) - { - return CAIRO_STATUS_SUCCESS; - } - - _cairo_bo_event_init (&event, - CAIRO_BO_EVENT_TYPE_INTERSECTION, - left, right, - intersection); - - return _cairo_bo_event_queue_insert (event_queue, &event); -} - -static void -_cairo_bo_sweep_line_init (cairo_bo_sweep_line_t *sweep_line) -{ - _cairo_skip_list_init (&sweep_line->active_edges, - _sweep_line_elt_compare, - sizeof (sweep_line_elt_t)); - sweep_line->head = NULL; - sweep_line->tail = NULL; - sweep_line->current_y = 0; -} - -static void -_cairo_bo_sweep_line_fini (cairo_bo_sweep_line_t *sweep_line) -{ - _cairo_skip_list_fini (&sweep_line->active_edges); -} - -static cairo_status_t -_cairo_bo_sweep_line_insert (cairo_bo_sweep_line_t *sweep_line, - cairo_bo_edge_t *edge) -{ - skip_elt_t *next_elt; - sweep_line_elt_t *sweep_line_elt; - cairo_bo_edge_t **prev_of_next, **next_of_prev; - - sweep_line_elt = _cairo_skip_list_insert (&sweep_line->active_edges, &edge, - 1 /* unique inserts*/); - if (sweep_line_elt == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - next_elt = sweep_line_elt->elt.next[0]; - if (next_elt) - prev_of_next = & (SKIP_ELT_TO_EDGE (next_elt)->prev); - else - prev_of_next = &sweep_line->tail; - - if (*prev_of_next) - next_of_prev = &(*prev_of_next)->next; - else - next_of_prev = &sweep_line->head; - - edge->prev = *prev_of_next; - edge->next = *next_of_prev; - *prev_of_next = edge; - *next_of_prev = edge; - - edge->sweep_line_elt = sweep_line_elt; - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_bo_sweep_line_delete (cairo_bo_sweep_line_t *sweep_line, - cairo_bo_edge_t *edge) -{ - cairo_bo_edge_t **left_next, **right_prev; - - _cairo_skip_list_delete_given (&sweep_line->active_edges, &edge->sweep_line_elt->elt); - - left_next = &sweep_line->head; - if (edge->prev) - left_next = &edge->prev->next; - - right_prev = &sweep_line->tail; - if (edge->next) - right_prev = &edge->next->prev; - - *left_next = edge->next; - *right_prev = edge->prev; -} - -static void -_cairo_bo_sweep_line_swap (cairo_bo_sweep_line_t *sweep_line, - cairo_bo_edge_t *left, - cairo_bo_edge_t *right) -{ - sweep_line_elt_t *left_elt, *right_elt; - cairo_bo_edge_t **before_left, **after_right; - - /* Within the skip list we can do the swap simply by swapping the - * pointers to the edge elements and leaving all of the skip list - * elements and pointers unchanged. */ - left_elt = left->sweep_line_elt; - right_elt = SKIP_ELT_TO_EDGE_ELT (left_elt->elt.next[0]); - - left_elt->edge = right; - right->sweep_line_elt = left_elt; - - right_elt->edge = left; - left->sweep_line_elt = right_elt; - - /* Within the doubly-linked list of edges, there's a bit more - * bookkeeping involved with the swap. */ - before_left = &sweep_line->head; - if (left->prev) - before_left = &left->prev->next; - *before_left = right; - - after_right = &sweep_line->tail; - if (right->next) - after_right = &right->next->prev; - *after_right = left; - - left->next = right->next; - right->next = left; - - right->prev = left->prev; - left->prev = right; -} - -#if DEBUG_PRINT_STATE -static void -_cairo_bo_edge_print (cairo_bo_edge_t *edge) -{ - printf ("(0x%x, 0x%x)-(0x%x, 0x%x)", - edge->top.x, edge->top.y, - edge->bottom.x, edge->bottom.y); -} - -static void -_cairo_bo_event_print (cairo_bo_event_t *event) -{ - switch (event->type) { - case CAIRO_BO_EVENT_TYPE_START: - printf ("Start: "); - break; - case CAIRO_BO_EVENT_TYPE_STOP: - printf ("Stop: "); - break; - case CAIRO_BO_EVENT_TYPE_INTERSECTION: - printf ("Intersection: "); - break; - } - printf ("(%d, %d)\t", event->point.x, event->point.y); - _cairo_bo_edge_print (event->e1); - if (event->type == CAIRO_BO_EVENT_TYPE_INTERSECTION) { - printf (" X "); - _cairo_bo_edge_print (event->e2); - } - printf ("\n"); -} - -static void -_cairo_bo_event_queue_print (cairo_bo_event_queue_t *event_queue) -{ - skip_elt_t *elt; - /* XXX: fixme to print the start/stop array too. */ - cairo_skip_list_t *queue = &event_queue->intersection_queue; - cairo_bo_event_t *event; - - printf ("Event queue:\n"); - - for (elt = queue->chains[0]; - elt; - elt = elt->next[0]) - { - event = SKIP_ELT_TO_EVENT (elt); - _cairo_bo_event_print (event); - } -} - -static void -_cairo_bo_sweep_line_print (cairo_bo_sweep_line_t *sweep_line) -{ - cairo_bool_t first = TRUE; - skip_elt_t *elt; - cairo_bo_edge_t *edge; - - printf ("Sweep line (reversed): "); - - for (edge = sweep_line->tail; - edge; - edge = edge->prev) - { - if (!first) - printf (", "); - _cairo_bo_edge_print (edge); - first = FALSE; - } - printf ("\n"); - - - printf ("Sweep line from edge list: "); - first = TRUE; - for (edge = sweep_line->head; - edge; - edge = edge->next) - { - if (!first) - printf (", "); - _cairo_bo_edge_print (edge); - first = FALSE; - } - printf ("\n"); - - printf ("Sweep line from skip list: "); - first = TRUE; - for (elt = sweep_line->active_edges.chains[0]; - elt; - elt = elt->next[0]) - { - if (!first) - printf (", "); - _cairo_bo_edge_print (SKIP_ELT_TO_EDGE (elt)); - first = FALSE; - } - printf ("\n"); -} - -static void -print_state (const char *msg, - cairo_bo_event_queue_t *event_queue, - cairo_bo_sweep_line_t *sweep_line) -{ - printf ("%s\n", msg); - _cairo_bo_event_queue_print (event_queue); - _cairo_bo_sweep_line_print (sweep_line); - printf ("\n"); -} -#endif - -/* Adds the trapezoid, if any, of the left edge to the #cairo_traps_t - * of bo_traps. */ -static cairo_status_t -_cairo_bo_edge_end_trap (cairo_bo_edge_t *left, - int32_t bot, - cairo_bo_traps_t *bo_traps) -{ - cairo_fixed_t fixed_top, fixed_bot; - cairo_bo_trap_t *trap = left->deferred_trap; - cairo_bo_edge_t *right; - - if (!trap) - return CAIRO_STATUS_SUCCESS; - - /* If the right edge of the trapezoid stopped earlier than the - * left edge, then cut the trapezoid bottom early. */ - right = trap->right; - if (right->bottom.y < bot) - bot = right->bottom.y; - - fixed_top = trap->top; - fixed_bot = bot; - - /* Only emit trapezoids with positive height. */ - if (fixed_top < fixed_bot) { - cairo_line_t left_line; - cairo_line_t right_line; - cairo_fixed_t xmin = bo_traps->xmin; - cairo_fixed_t ymin = bo_traps->ymin; - fixed_top += ymin; - fixed_bot += ymin; - - left_line.p1.x = left->top.x + xmin; - left_line.p1.y = left->top.y + ymin; - right_line.p1.x = right->top.x + xmin; - right_line.p1.y = right->top.y + ymin; - - left_line.p2.x = left->bottom.x + xmin; - left_line.p2.y = left->bottom.y + ymin; - right_line.p2.x = right->bottom.x + xmin; - right_line.p2.y = right->bottom.y + ymin; - - /* Avoid emitting the trapezoid if it is obviously degenerate. - * TODO: need a real collinearity test here for the cases - * where the trapezoid is degenerate, yet the top and bottom - * coordinates aren't equal. */ - if (left_line.p1.x != right_line.p1.x || - left_line.p1.y != right_line.p1.y || - left_line.p2.x != right_line.p2.x || - left_line.p2.y != right_line.p2.y) - { - _cairo_traps_add_trap (bo_traps->traps, - fixed_top, fixed_bot, - &left_line, &right_line); - -#if DEBUG_PRINT_STATE - printf ("Deferred trap: left=(%08x, %08x)-(%08x,%08x) " - "right=(%08x,%08x)-(%08x,%08x) top=%08x, bot=%08x\n", - left->top.x, left->top.y, left->bottom.x, left->bottom.y, - right->top.x, right->top.y, right->bottom.x, right->bottom.y, - trap->top, bot); -#endif - } - } - - _cairo_freelist_free (&bo_traps->freelist, trap); - left->deferred_trap = NULL; - - return _cairo_traps_status (bo_traps->traps); -} - -/* Start a new trapezoid at the given top y coordinate, whose edges - * are `edge' and `edge->next'. If `edge' already has a trapezoid, - * then either add it to the traps in `bo_traps', if the trapezoid's - * right edge differs from `edge->next', or do nothing if the new - * trapezoid would be a continuation of the existing one. */ -static cairo_status_t -_cairo_bo_edge_start_or_continue_trap (cairo_bo_edge_t *edge, - int32_t top, - cairo_bo_traps_t *bo_traps) -{ - cairo_status_t status; - cairo_bo_trap_t *trap = edge->deferred_trap; - - if (trap) { - if (trap->right == edge->next) return CAIRO_STATUS_SUCCESS; - status = _cairo_bo_edge_end_trap (edge, top, bo_traps); - if (status) - return status; - } - - if (edge->next) { - trap = edge->deferred_trap = _cairo_freelist_alloc (&bo_traps->freelist); - if (!edge->deferred_trap) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - trap->right = edge->next; - trap->top = top; - } - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_bo_traps_init (cairo_bo_traps_t *bo_traps, - cairo_traps_t *traps, - cairo_fixed_t xmin, - cairo_fixed_t ymin, - cairo_fixed_t xmax, - cairo_fixed_t ymax) -{ - bo_traps->traps = traps; - _cairo_freelist_init (&bo_traps->freelist, sizeof(cairo_bo_trap_t)); - bo_traps->xmin = xmin; - bo_traps->ymin = ymin; - bo_traps->xmax = xmax; - bo_traps->ymax = ymax; -} - -static void -_cairo_bo_traps_fini (cairo_bo_traps_t *bo_traps) -{ - _cairo_freelist_fini (&bo_traps->freelist); -} - -#if DEBUG_VALIDATE -static void -_cairo_bo_sweep_line_validate (cairo_bo_sweep_line_t *sweep_line) -{ - cairo_bo_edge_t *edge; - skip_elt_t *elt; - - /* March through both the skip list's singly-linked list and the - * sweep line's own list through pointers in the edges themselves - * and make sure they agree at every point. */ - - for (edge = sweep_line->head, elt = sweep_line->active_edges.chains[0]; - edge && elt; - edge = edge->next, elt = elt->next[0]) - { - if (SKIP_ELT_TO_EDGE (elt) != edge) { - fprintf (stderr, "*** Error: Sweep line fails to validate: Inconsistent data in the two lists.\n"); - abort (); - } - } - - if (edge || elt) { - fprintf (stderr, "*** Error: Sweep line fails to validate: One list ran out before the other.\n"); - abort (); - } -} -#endif - - -static cairo_status_t -_active_edges_to_traps (cairo_bo_edge_t *head, - int32_t top, - cairo_fill_rule_t fill_rule, - cairo_bo_traps_t *bo_traps) -{ - cairo_status_t status; - int in_out = 0; - cairo_bo_edge_t *edge; - - for (edge = head; edge; edge = edge->next) { - if (fill_rule == CAIRO_FILL_RULE_WINDING) { - if (edge->reversed) - in_out++; - else - in_out--; - if (in_out == 0) { - status = _cairo_bo_edge_end_trap (edge, top, bo_traps); - if (status) - return status; - continue; - } - } else { - in_out++; - if ((in_out & 1) == 0) { - status = _cairo_bo_edge_end_trap (edge, top, bo_traps); - if (status) - return status; - continue; - } - } - - status = _cairo_bo_edge_start_or_continue_trap (edge, top, bo_traps); - if (status) - return status; - } - - return CAIRO_STATUS_SUCCESS; -} - -/* Execute a single pass of the Bentley-Ottmann algorithm on edges, - * generating trapezoids according to the fill_rule and appending them - * to traps. */ -static cairo_status_t -_cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_edge_t *edges, - int num_edges, - cairo_fill_rule_t fill_rule, - cairo_traps_t *traps, - cairo_fixed_t xmin, - cairo_fixed_t ymin, - cairo_fixed_t xmax, - cairo_fixed_t ymax, - int *num_intersections) -{ - cairo_status_t status; - int intersection_count = 0; - cairo_bo_event_queue_t event_queue; - cairo_bo_sweep_line_t sweep_line; - cairo_bo_traps_t bo_traps; - cairo_bo_event_t *event, event_saved; - cairo_bo_edge_t *edge; - cairo_bo_edge_t *left, *right; - cairo_bo_edge_t *edge1, *edge2; - - status = _cairo_bo_event_queue_init (&event_queue, edges, num_edges); - if (status) - return status; - - _cairo_bo_sweep_line_init (&sweep_line); - _cairo_bo_traps_init (&bo_traps, traps, xmin, ymin, xmax, ymax); - -#if DEBUG_PRINT_STATE - print_state ("After initializing", &event_queue, &sweep_line); -#endif - - while (1) - { - event = _cairo_bo_event_dequeue (&event_queue); - if (!event) - break; - - if (event->point.y != sweep_line.current_y) { - status = _active_edges_to_traps (sweep_line.head, - sweep_line.current_y, - fill_rule, &bo_traps); - if (status) - goto unwind; - - sweep_line.current_y = event->point.y; - } - - event_saved = *event; - _cairo_bo_event_queue_delete (&event_queue, event); - event = &event_saved; - - switch (event->type) { - case CAIRO_BO_EVENT_TYPE_START: - edge = event->e1; - - status = _cairo_bo_sweep_line_insert (&sweep_line, edge); - if (status) - goto unwind; - /* Cache the insert position for use in pass 2. - event->e2 = Sortlist::prev (sweep_line, edge); - */ - - left = edge->prev; - right = edge->next; - - status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, left, edge); - if (status) - goto unwind; - - status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, edge, right); - if (status) - goto unwind; - -#if DEBUG_PRINT_STATE - print_state ("After processing start", &event_queue, &sweep_line); -#endif - break; - - case CAIRO_BO_EVENT_TYPE_STOP: - edge = event->e1; - - left = edge->prev; - right = edge->next; - - _cairo_bo_sweep_line_delete (&sweep_line, edge); - - status = _cairo_bo_edge_end_trap (edge, edge->bottom.y, &bo_traps); - if (status) - goto unwind; - - status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, left, right); - if (status) - goto unwind; - -#if DEBUG_PRINT_STATE - print_state ("After processing stop", &event_queue, &sweep_line); -#endif - break; - - case CAIRO_BO_EVENT_TYPE_INTERSECTION: - edge1 = event->e1; - edge2 = event->e2; - - /* skip this intersection if its edges are not adjacent */ - if (edge2 != edge1->next) - break; - - intersection_count++; - - edge1->middle = event->point; - edge2->middle = event->point; - - left = edge1->prev; - right = edge2->next; - - _cairo_bo_sweep_line_swap (&sweep_line, edge1, edge2); - - /* after the swap e2 is left of e1 */ - - status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, - left, edge2); - if (status) - goto unwind; - - status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, - edge1, right); - if (status) - goto unwind; - -#if DEBUG_PRINT_STATE - print_state ("After processing intersection", &event_queue, &sweep_line); -#endif - break; - } -#if DEBUG_VALIDATE - _cairo_bo_sweep_line_validate (&sweep_line); -#endif - } - - *num_intersections = intersection_count; - unwind: - for (edge = sweep_line.head; edge; edge = edge->next) { - cairo_status_t status2 = _cairo_bo_edge_end_trap (edge, - sweep_line.current_y, - &bo_traps); - if (!status) - status = status2; - } - _cairo_bo_traps_fini (&bo_traps); - _cairo_bo_sweep_line_fini (&sweep_line); - _cairo_bo_event_queue_fini (&event_queue); - return status; -} - -static void -update_minmax(cairo_fixed_t *inout_min, - cairo_fixed_t *inout_max, - cairo_fixed_t v) -{ - if (v < *inout_min) - *inout_min = v; - if (v > *inout_max) - *inout_max = v; -} - -cairo_status_t -_cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps, - const cairo_polygon_t *polygon, - cairo_fill_rule_t fill_rule) -{ - int intersections; - cairo_status_t status; - cairo_bo_edge_t stack_edges[CAIRO_STACK_ARRAY_LENGTH (cairo_bo_edge_t)]; - cairo_bo_edge_t *edges; - cairo_fixed_t xmin = 0x7FFFFFFF; - cairo_fixed_t ymin = 0x7FFFFFFF; - cairo_fixed_t xmax = -0x80000000; - cairo_fixed_t ymax = -0x80000000; - cairo_box_t limit; - cairo_bool_t has_limits; - int num_bo_edges; - int i; - - if (0 == polygon->num_edges) - return CAIRO_STATUS_SUCCESS; - - has_limits = _cairo_traps_get_limit (traps, &limit); - - if (polygon->num_edges < ARRAY_LENGTH (stack_edges)) { - edges = stack_edges; - } else { - edges = _cairo_malloc_ab (polygon->num_edges, sizeof (cairo_bo_edge_t)); - if (edges == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - /* Figure out the bounding box of the input coordinates and - * validate that we're not given invalid polygon edges. */ - for (i = 0; i < polygon->num_edges; i++) { - update_minmax (&xmin, &xmax, polygon->edges[i].edge.p1.x); - update_minmax (&ymin, &ymax, polygon->edges[i].edge.p1.y); - update_minmax (&xmin, &xmax, polygon->edges[i].edge.p2.x); - update_minmax (&ymin, &ymax, polygon->edges[i].edge.p2.y); - assert (polygon->edges[i].edge.p1.y <= polygon->edges[i].edge.p2.y && - "BUG: tessellator given upside down or horizontal edges"); - } - - /* The tessellation functions currently assume that no line - * segment extends more than 2^31-1 in either dimension. We - * guarantee this by offsetting the internal coordinates to the - * range [0,2^31-1], and clamping to 2^31-1 if a coordinate - * exceeds the range (and yes, this generates an incorrect - * result). First we have to clamp the bounding box itself. */ - /* XXX: Rather than changing the input values, a better approach - * would be to detect out-of-bounds input and return a - * CAIRO_STATUS_OVERFLOW value to the user. */ - if (xmax - xmin < 0) - xmax = xmin + 0x7FFFFFFF; - if (ymax - ymin < 0) - ymax = ymin + 0x7FFFFFFF; - - for (i = 0, num_bo_edges = 0; i < polygon->num_edges; i++) { - cairo_bo_edge_t *edge = &edges[num_bo_edges]; - cairo_point_t top = polygon->edges[i].edge.p1; - cairo_point_t bot = polygon->edges[i].edge.p2; - - /* Discard the edge if it lies outside the limits of traps. */ - if (has_limits) { - /* Strictly above or below the limits? */ - if (bot.y <= limit.p1.y || top.y >= limit.p2.y) - continue; - } - - /* Offset coordinates into the non-negative range. */ - top.x -= xmin; - top.y -= ymin; - bot.x -= xmin; - bot.y -= ymin; - - /* If the coordinates are still negative, then their extent is - * overflowing 2^31-1. We're going to kludge it and clamp the - * coordinates into the clamped bounding box. */ - if (top.x < 0) top.x = xmax - xmin; - if (top.y < 0) top.y = ymax - ymin; - if (bot.x < 0) bot.x = xmax - xmin; - if (bot.y < 0) bot.y = ymax - ymin; - - if (top.y == bot.y) { - /* Clamping might have produced horizontal edges. Ignore - * those. */ - continue; - } - assert (top.y < bot.y && - "BUG: clamping the input range flipped the " - "orientation of an edge"); - - edge->top.x = top.x; - edge->top.y = top.y; - edge->bottom.x = bot.x; - edge->bottom.y = bot.y; - /* XXX: The 'clockWise' name that cairo_polygon_t uses is - * totally bogus. It's really a (negated!) description of - * whether the edge is reversed. */ - edge->reversed = (! polygon->edges[i].clockWise); - edge->deferred_trap = NULL; - edge->prev = NULL; - edge->next = NULL; - edge->sweep_line_elt = NULL; - - num_bo_edges++; - } - - /* XXX: This would be the convenient place to throw in multiple - * passes of the Bentley-Ottmann algorithm. It would merely - * require storing the results of each pass into a temporary - * cairo_traps_t. */ - status = _cairo_bentley_ottmann_tessellate_bo_edges (edges, num_bo_edges, - fill_rule, traps, - xmin, ymin, xmax, ymax, - &intersections); - - if (edges != stack_edges) - free (edges); - - return status; -} - -#if 0 -static cairo_bool_t -edges_have_an_intersection_quadratic (cairo_bo_edge_t *edges, - int num_edges) - -{ - int i, j; - cairo_bo_edge_t *a, *b; - cairo_bo_point32_t intersection; - cairo_bo_status_t status; - - /* We must not be given any upside-down edges. */ - for (i = 0; i < num_edges; i++) { - assert (_cairo_bo_point32_compare (&edges[i].top, &edges[i].bottom) < 0); - edges[i].top.x <<= CAIRO_BO_GUARD_BITS; - edges[i].top.y <<= CAIRO_BO_GUARD_BITS; - edges[i].bottom.x <<= CAIRO_BO_GUARD_BITS; - edges[i].bottom.y <<= CAIRO_BO_GUARD_BITS; - } - - for (i = 0; i < num_edges; i++) { - for (j = 0; j < num_edges; j++) { - if (i == j) - continue; - - a = &edges[i]; - b = &edges[j]; - - status = _cairo_bo_edge_intersect (a, b, &intersection); - if (status == CAIRO_BO_STATUS_PARALLEL || - status == CAIRO_BO_STATUS_NO_INTERSECTION) - { - continue; - } - - printf ("Found intersection (%d,%d) between (%d,%d)-(%d,%d) and (%d,%d)-(%d,%d)\n", - intersection.x, - intersection.y, - a->top.x, a->top.y, - a->bottom.x, a->bottom.y, - b->top.x, b->top.y, - b->bottom.x, b->bottom.y); - - return TRUE; - } - } - return FALSE; -} - -#define TEST_MAX_EDGES 10 - -typedef struct test { - const char *name; - const char *description; - int num_edges; - cairo_bo_edge_t edges[TEST_MAX_EDGES]; -} test_t; - -static test_t -tests[] = { - { - "3 near misses", - "3 edges all intersecting very close to each other", - 3, - { - { { 4, 2}, {0, 0}, { 9, 9}, NULL, NULL }, - { { 7, 2}, {0, 0}, { 2, 3}, NULL, NULL }, - { { 5, 2}, {0, 0}, { 1, 7}, NULL, NULL } - } - }, - { - "inconsistent data", - "Derived from random testing---was leading to skip list and edge list disagreeing.", - 2, - { - { { 2, 3}, {0, 0}, { 8, 9}, NULL, NULL }, - { { 2, 3}, {0, 0}, { 6, 7}, NULL, NULL } - } - }, - { - "failed sort", - "A test derived from random testing that leads to an inconsistent sort --- looks like we just can't attempt to validate the sweep line with edge_compare?", - 3, - { - { { 6, 2}, {0, 0}, { 6, 5}, NULL, NULL }, - { { 3, 5}, {0, 0}, { 5, 6}, NULL, NULL }, - { { 9, 2}, {0, 0}, { 5, 6}, NULL, NULL }, - } - }, - { - "minimal-intersection", - "Intersection of a two from among the smallest possible edges.", - 2, - { - { { 0, 0}, {0, 0}, { 1, 1}, NULL, NULL }, - { { 1, 0}, {0, 0}, { 0, 1}, NULL, NULL } - } - }, - { - "simple", - "A simple intersection of two edges at an integer (2,2).", - 2, - { - { { 1, 1}, {0, 0}, { 3, 3}, NULL, NULL }, - { { 2, 1}, {0, 0}, { 2, 3}, NULL, NULL } - } - }, - { - "bend-to-horizontal", - "With intersection truncation one edge bends to horizontal", - 2, - { - { { 9, 1}, {0, 0}, {3, 7}, NULL, NULL }, - { { 3, 5}, {0, 0}, {9, 9}, NULL, NULL } - } - } -}; - -/* - { - "endpoint", - "An intersection that occurs at the endpoint of a segment.", - { - { { 4, 6}, { 5, 6}, NULL, { { NULL }} }, - { { 4, 5}, { 5, 7}, NULL, { { NULL }} }, - { { 0, 0}, { 0, 0}, NULL, { { NULL }} }, - } - } - { - name = "overlapping", - desc = "Parallel segments that share an endpoint, with different slopes.", - edges = { - { top = { x = 2, y = 0}, bottom = { x = 1, y = 1}}, - { top = { x = 2, y = 0}, bottom = { x = 0, y = 2}}, - { top = { x = 0, y = 3}, bottom = { x = 1, y = 3}}, - { top = { x = 0, y = 3}, bottom = { x = 2, y = 3}}, - { top = { x = 0, y = 4}, bottom = { x = 0, y = 6}}, - { top = { x = 0, y = 5}, bottom = { x = 0, y = 6}} - } - }, - { - name = "hobby_stage_3", - desc = "A particularly tricky part of the 3rd stage of the 'hobby' test below.", - edges = { - { top = { x = -1, y = -2}, bottom = { x = 4, y = 2}}, - { top = { x = 5, y = 3}, bottom = { x = 9, y = 5}}, - { top = { x = 5, y = 3}, bottom = { x = 6, y = 3}}, - } - }, - { - name = "hobby", - desc = "Example from John Hobby's paper. Requires 3 passes of the iterative algorithm.", - edges = { - { top = { x = 0, y = 0}, bottom = { x = 9, y = 5}}, - { top = { x = 0, y = 0}, bottom = { x = 13, y = 6}}, - { top = { x = -1, y = -2}, bottom = { x = 9, y = 5}} - } - }, - { - name = "slope", - desc = "Edges with same start/stop points but different slopes", - edges = { - { top = { x = 4, y = 1}, bottom = { x = 6, y = 3}}, - { top = { x = 4, y = 1}, bottom = { x = 2, y = 3}}, - { top = { x = 2, y = 4}, bottom = { x = 4, y = 6}}, - { top = { x = 6, y = 4}, bottom = { x = 4, y = 6}} - } - }, - { - name = "horizontal", - desc = "Test of a horizontal edge", - edges = { - { top = { x = 1, y = 1}, bottom = { x = 6, y = 6}}, - { top = { x = 2, y = 3}, bottom = { x = 5, y = 3}} - } - }, - { - name = "vertical", - desc = "Test of a vertical edge", - edges = { - { top = { x = 5, y = 1}, bottom = { x = 5, y = 7}}, - { top = { x = 2, y = 4}, bottom = { x = 8, y = 5}} - } - }, - { - name = "congruent", - desc = "Two overlapping edges with the same slope", - edges = { - { top = { x = 5, y = 1}, bottom = { x = 5, y = 7}}, - { top = { x = 5, y = 2}, bottom = { x = 5, y = 6}}, - { top = { x = 2, y = 4}, bottom = { x = 8, y = 5}} - } - }, - { - name = "multi", - desc = "Several segments with a common intersection point", - edges = { - { top = { x = 1, y = 2}, bottom = { x = 5, y = 4} }, - { top = { x = 1, y = 1}, bottom = { x = 5, y = 5} }, - { top = { x = 2, y = 1}, bottom = { x = 4, y = 5} }, - { top = { x = 4, y = 1}, bottom = { x = 2, y = 5} }, - { top = { x = 5, y = 1}, bottom = { x = 1, y = 5} }, - { top = { x = 5, y = 2}, bottom = { x = 1, y = 4} } - } - } -}; -*/ - -static int -run_test (const char *test_name, - cairo_bo_edge_t *test_edges, - int num_edges) -{ - int i, intersections, passes; - cairo_bo_edge_t *edges; - cairo_array_t intersected_edges; - - printf ("Testing: %s\n", test_name); - - _cairo_array_init (&intersected_edges, sizeof (cairo_bo_edge_t)); - - intersections = _cairo_bentley_ottmann_intersect_edges (test_edges, num_edges, &intersected_edges); - if (intersections) - printf ("Pass 1 found %d intersections:\n", intersections); - - - /* XXX: Multi-pass Bentley-Ottmmann. Preferable would be to add a - * pass of Hobby's tolerance-square algorithm instead. */ - passes = 1; - while (intersections) { - int num_edges = _cairo_array_num_elements (&intersected_edges); - passes++; - edges = _cairo_malloc_ab (num_edges, sizeof (cairo_bo_edge_t)); - assert (edges != NULL); - memcpy (edges, _cairo_array_index (&intersected_edges, 0), num_edges * sizeof (cairo_bo_edge_t)); - _cairo_array_fini (&intersected_edges); - _cairo_array_init (&intersected_edges, sizeof (cairo_bo_edge_t)); - intersections = _cairo_bentley_ottmann_intersect_edges (edges, num_edges, &intersected_edges); - free (edges); - - if (intersections){ - printf ("Pass %d found %d remaining intersections:\n", passes, intersections); - } else { - if (passes > 3) - for (i = 0; i < passes; i++) - printf ("*"); - printf ("No remainining intersections found after pass %d\n", passes); - } - } - - if (edges_have_an_intersection_quadratic (_cairo_array_index (&intersected_edges, 0), - _cairo_array_num_elements (&intersected_edges))) - printf ("*** FAIL ***\n"); - else - printf ("PASS\n"); - - _cairo_array_fini (&intersected_edges); - - return 0; -} - -#define MAX_RANDOM 300 - -int -main (void) -{ - char random_name[] = "random-XX"; - cairo_bo_edge_t random_edges[MAX_RANDOM], *edge; - unsigned int i, num_random; - test_t *test; - - for (i = 0; i < ARRAY_LENGTH (tests); i++) { - test = &tests[i]; - run_test (test->name, test->edges, test->num_edges); - } - - for (num_random = 0; num_random < MAX_RANDOM; num_random++) { - srand (0); - for (i = 0; i < num_random; i++) { - do { - edge = &random_edges[i]; - edge->top.x = (int32_t) (10.0 * (rand() / (RAND_MAX + 1.0))); - edge->top.y = (int32_t) (10.0 * (rand() / (RAND_MAX + 1.0))); - edge->bottom.x = (int32_t) (10.0 * (rand() / (RAND_MAX + 1.0))); - edge->bottom.y = (int32_t) (10.0 * (rand() / (RAND_MAX + 1.0))); - if (edge->top.y > edge->bottom.y) { - int32_t tmp = edge->top.y; - edge->top.y = edge->bottom.y; - edge->bottom.y = tmp; - } - } while (edge->top.y == edge->bottom.y); - } - - sprintf (random_name, "random-%02d", num_random); - - run_test (random_name, random_edges, num_random); - } - - return 0; -} -#endif - diff --git a/uppdev/plugin/cairo/lib/cairo-beos.h b/uppdev/plugin/cairo/lib/cairo-beos.h deleted file mode 100644 index f53be5a7e..000000000 --- a/uppdev/plugin/cairo/lib/cairo-beos.h +++ /dev/null @@ -1,60 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2005 Christian Biesinger - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Christian Biesinger - * - * - * Contributor(s): - */ - -#ifndef CAIRO_BEOS_H -#define CAIRO_BEOS_H - -#include "cairo.h" - -#if CAIRO_HAS_BEOS_SURFACE - -#include - -CAIRO_BEGIN_DECLS - -cairo_public cairo_surface_t * -cairo_beos_surface_create (BView* view); - -cairo_public cairo_surface_t * -cairo_beos_surface_create_for_bitmap (BView* view, - BBitmap* bmp); - -CAIRO_END_DECLS - -#else /* CAIRO_HAS_BEOS_SURFACE */ -# error Cairo was not compiled with support for the beos backend -#endif /* CAIRO_HAS_BEOS_SURFACE */ - -#endif /* CAIRO_BEOS_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-cache-private.h b/uppdev/plugin/cairo/lib/cairo-cache-private.h deleted file mode 100644 index 4ae63ade7..000000000 --- a/uppdev/plugin/cairo/lib/cairo-cache-private.h +++ /dev/null @@ -1,126 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2004 Red Hat, Inc. - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Keith Packard - * Graydon Hoare - * Carl Worth - */ - -#ifndef CAIRO_CACHE_PRIVATE_H -#define CAIRO_CACHE_PRIVATE_H - -#include "cairo-compiler-private.h" -#include "cairo-types-private.h" - -/** - * cairo_cache_entry_t: - * - * 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 - * have a #cairo_cache_entry_t as their first field. For example: - * - * typedef _my_entry { - * cairo_cache_entry_t base; - * ... Remainder of key and value fields here .. - * } my_entry_t; - * - * which then allows a pointer to my_entry_t to be passed to any of - * the #cairo_cache_t functions as follows without requiring a cast: - * - * _cairo_cache_insert (cache, &my_entry->base, size); - * - * IMPORTANT: The caller is responsible for initializing - * my_entry->base.hash with a hash code derived from the key. The - * essential property of the hash code is that keys_equal must never - * return %TRUE for two keys that have different hashes. The best hash - * code will reduce the frequency of two keys with the same code for - * which keys_equal returns %FALSE. - * - * The user must also initialize my_entry->base.size to indicate - * the size of the current entry. What units to use for size is - * entirely up to the caller, (though the same units must be used for - * the max_size parameter passed to _cairo_cache_create()). If all - * entries are close to the same size, the simplest thing to do is to - * just use units of "entries", (eg. set size==1 in all entries and - * set max_size to the number of entries which you want to be saved - * in the cache). - * - * Which parts of the entry make up the "key" and which part make up - * the value are entirely up to the caller, (as determined by the - * computation going into base.hash as well as the keys_equal - * function). A few of the #cairo_cache_t functions accept an entry which - * will be used exclusively as a "key", (indicated by a parameter name - * of key). In these cases, the value-related fields of the entry need - * not be initialized if so desired. - **/ -typedef struct _cairo_cache_entry { - unsigned long hash; - unsigned long size; -} cairo_cache_entry_t; - -typedef cairo_bool_t -(*cairo_cache_keys_equal_func_t) (const void *key_a, const void *key_b); - -typedef void -(*cairo_cache_callback_func_t) (void *entry, - void *closure); - -cairo_private cairo_cache_t * -_cairo_cache_create (cairo_cache_keys_equal_func_t keys_equal, - cairo_destroy_func_t entry_destroy, - unsigned long max_size); - -cairo_private void -_cairo_cache_destroy (cairo_cache_t *cache); - -cairo_private void -_cairo_cache_freeze (cairo_cache_t *cache); - -cairo_private void -_cairo_cache_thaw (cairo_cache_t *cache); - -cairo_private cairo_bool_t -_cairo_cache_lookup (cairo_cache_t *cache, - cairo_cache_entry_t *key, - cairo_cache_entry_t **entry_return); - -cairo_private cairo_status_t -_cairo_cache_insert (cairo_cache_t *cache, - cairo_cache_entry_t *entry); - -cairo_private void -_cairo_cache_foreach (cairo_cache_t *cache, - cairo_cache_callback_func_t cache_callback, - void *closure); - -#endif diff --git a/uppdev/plugin/cairo/lib/cairo-cache.c b/uppdev/plugin/cairo/lib/cairo-cache.c deleted file mode 100644 index 1c458dff3..000000000 --- a/uppdev/plugin/cairo/lib/cairo-cache.c +++ /dev/null @@ -1,363 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2004 Red Hat, Inc. - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Keith Packard - * Graydon Hoare - * Carl Worth - */ - -#include "cairoint.h" - -static void -_cairo_cache_remove (cairo_cache_t *cache, - cairo_cache_entry_t *entry); - -static void -_cairo_cache_shrink_to_accommodate (cairo_cache_t *cache, - unsigned long additional); - -static cairo_status_t -_cairo_cache_init (cairo_cache_t *cache, - cairo_cache_keys_equal_func_t keys_equal, - cairo_destroy_func_t entry_destroy, - unsigned long max_size) -{ - cache->hash_table = _cairo_hash_table_create (keys_equal); - if (cache->hash_table == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - cache->entry_destroy = entry_destroy; - - cache->max_size = max_size; - cache->size = 0; - - cache->freeze_count = 0; - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_cache_fini (cairo_cache_t *cache) -{ - cairo_cache_entry_t *entry; - - /* We have to manually remove all entries from the cache ourselves - * rather than relying on _cairo_hash_table_destroy() to do that - * since otherwise the cache->entry_destroy callback would not get - * called on each entry. */ - - while (1) { - entry = _cairo_hash_table_random_entry (cache->hash_table, NULL); - if (entry == NULL) - break; - _cairo_cache_remove (cache, entry); - } - - _cairo_hash_table_destroy (cache->hash_table); - cache->size = 0; -} - -/** - * _cairo_cache_create: - * @keys_equal: a function to return %TRUE if two keys are equal - * @entry_destroy: destroy notifier for cache entries - * @max_size: the maximum size for this cache - * Returns: the newly created #cairo_cache_t - * - * Creates a new cache using the keys_equal() function to determine - * the equality of entries. - * - * Data is provided to the cache in the form of user-derived version - * of #cairo_cache_entry_t. A cache entry must be able to hold hash - * code, a size, and the key/value pair being stored in the - * cache. Sometimes only the key will be necessary, (as in - * _cairo_cache_lookup()), and in these cases the value portion of the - * entry need not be initialized. - * - * The units for max_size can be chosen by the caller, but should be - * consistent with the units of the size field of cache entries. When - * adding an entry with _cairo_cache_insert() if the total size of - * entries in the cache would exceed max_size then entries will be - * removed at random until the new entry would fit or the cache is - * empty. Then the new entry is inserted. - * - * There are cases in which the automatic removal of entries is - * undesired. If the cache entries have reference counts, then it is a - * simple matter to use the reference counts to ensure that entries - * continue to live even after being ejected from the cache. However, - * in some cases the memory overhead of adding a reference count to - * the entry would be objectionable. In such cases, the - * _cairo_cache_freeze() and _cairo_cache_thaw() calls can be - * used to establish a window during which no automatic removal of - * entries will occur. - **/ -cairo_cache_t * -_cairo_cache_create (cairo_cache_keys_equal_func_t keys_equal, - cairo_destroy_func_t entry_destroy, - unsigned long max_size) -{ - cairo_status_t status; - cairo_cache_t *cache; - - cache = malloc (sizeof (cairo_cache_t)); - if (cache == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - return NULL; - } - - status = _cairo_cache_init (cache, keys_equal, entry_destroy, max_size); - if (status) { - free (cache); - return NULL; - } - - return cache; -} - -/** - * _cairo_cache_destroy: - * @cache: a cache to destroy - * - * Immediately destroys the given cache, freeing all resources - * associated with it. As part of this process, the entry_destroy() - * function, (as passed to _cairo_cache_create()), will be called for - * each entry in the cache. - **/ -void -_cairo_cache_destroy (cairo_cache_t *cache) -{ - _cairo_cache_fini (cache); - - free (cache); -} - -/** - * _cairo_cache_freeze: - * @cache: a cache with some precious entries in it (or about to be - * added) - * - * Disable the automatic ejection of entries from the cache. For as - * long as the cache is "frozen", calls to _cairo_cache_insert() will - * add new entries to the cache regardless of how large the cache - * grows. See _cairo_cache_thaw(). - * - * Note: Multiple calls to _cairo_cache_freeze() will stack, in that - * the cache will remain "frozen" until a corresponding number of - * calls are made to _cairo_cache_thaw(). - **/ -void -_cairo_cache_freeze (cairo_cache_t *cache) -{ - assert (cache->freeze_count >= 0); - - cache->freeze_count++; -} - -/** - * _cairo_cache_thaw: - * @cache: a cache, just after the entries in it have become less - * precious - * - * Cancels the effects of _cairo_cache_freeze(). - * - * When a number of calls to _cairo_cache_thaw() is made corresponding - * to the number of calls to _cairo_cache_freeze() the cache will no - * longer be "frozen". If the cache had grown larger than max_size - * while frozen, entries will immediately be ejected (by random) from - * the cache until the cache is smaller than max_size. Also, the - * automatic ejection of entries on _cairo_cache_insert() will resume. - **/ -void -_cairo_cache_thaw (cairo_cache_t *cache) -{ - assert (cache->freeze_count > 0); - - cache->freeze_count--; - - if (cache->freeze_count == 0) - _cairo_cache_shrink_to_accommodate (cache, 0); -} - -/** - * _cairo_cache_lookup: - * @cache: a cache - * @key: the key of interest - * @entry_return: pointer for return value - * - * Performs a lookup in @cache looking for an entry which has a key - * that matches @key, (as determined by the keys_equal() function - * passed to _cairo_cache_create()). - * - * Return value: %TRUE if there is an entry in the cache that matches - * @key, (which will now be in *entry_return). %FALSE otherwise, (in - * which case *entry_return will be %NULL). - **/ -cairo_bool_t -_cairo_cache_lookup (cairo_cache_t *cache, - cairo_cache_entry_t *key, - cairo_cache_entry_t **entry_return) -{ - return _cairo_hash_table_lookup (cache->hash_table, - (cairo_hash_entry_t *) key, - (cairo_hash_entry_t **) entry_return); -} - -/** - * _cairo_cache_remove_random: - * @cache: a cache - * - * Remove a random entry from the cache. - * - * Return value: %TRUE if an entry was successfully removed. - * %FALSE if there are no entries that can be removed. - **/ -static cairo_bool_t -_cairo_cache_remove_random (cairo_cache_t *cache) -{ - cairo_cache_entry_t *entry; - - entry = _cairo_hash_table_random_entry (cache->hash_table, NULL); - if (entry == NULL) - return FALSE; - - _cairo_cache_remove (cache, entry); - - return TRUE; -} - -/** - * _cairo_cache_shrink_to_accommodate: - * @cache: a cache - * @additional: additional size requested in bytes - * - * If cache is not frozen, eject entries randomly until the size of - * the cache is at least @additional bytes less than - * cache->max_size. That is, make enough room to accommodate a new - * entry of size @additional. - **/ -static void -_cairo_cache_shrink_to_accommodate (cairo_cache_t *cache, - unsigned long additional) -{ - if (cache->freeze_count) - return; - - while (cache->size + additional > cache->max_size) { - if (! _cairo_cache_remove_random (cache)) - return; - } -} - -/** - * _cairo_cache_insert: - * @cache: a cache - * @entry: an entry to be inserted - * - * Insert @entry into the cache. If an entry exists in the cache with - * a matching key, then the old entry will be removed first, (and the - * entry_destroy() callback will be called on it). - * - * Return value: %CAIRO_STATUS_SUCCESS if successful or - * %CAIRO_STATUS_NO_MEMORY if insufficient memory is available. - **/ -cairo_status_t -_cairo_cache_insert (cairo_cache_t *cache, - cairo_cache_entry_t *entry) -{ - cairo_status_t status; - - _cairo_cache_shrink_to_accommodate (cache, entry->size); - - status = _cairo_hash_table_insert (cache->hash_table, - (cairo_hash_entry_t *) entry); - if (status) - return status; - - cache->size += entry->size; - - return CAIRO_STATUS_SUCCESS; -} - -/** - * _cairo_cache_remove: - * @cache: a cache - * @entry: an entry that exists in the cache - * - * Remove an existing entry from the cache. - * - * (Note: If any caller wanted access to a non-static version of this - * function, an improved version would require only a key rather than - * an entry. Fixing that would require fixing _cairo_hash_table_remove - * to return (a copy of?) the entry being removed.) - **/ -static void -_cairo_cache_remove (cairo_cache_t *cache, - cairo_cache_entry_t *entry) -{ - cache->size -= entry->size; - - _cairo_hash_table_remove (cache->hash_table, - (cairo_hash_entry_t *) entry); - - if (cache->entry_destroy) - cache->entry_destroy (entry); -} - -/** - * _cairo_cache_foreach: - * @cache: a cache - * @cache_callback: function to be called for each entry - * @closure: additional argument to be passed to @cache_callback - * - * Call @cache_callback for each entry in the cache, in a - * non-specified order. - **/ -void -_cairo_cache_foreach (cairo_cache_t *cache, - cairo_cache_callback_func_t cache_callback, - void *closure) -{ - _cairo_hash_table_foreach (cache->hash_table, - cache_callback, - closure); -} - -unsigned long -_cairo_hash_string (const char *c) -{ - /* This is the djb2 hash. */ - unsigned long hash = 5381; - while (c && *c) - hash = ((hash << 5) + hash) + *c++; - return hash; -} diff --git a/uppdev/plugin/cairo/lib/cairo-cff-subset.c b/uppdev/plugin/cairo/lib/cairo-cff-subset.c deleted file mode 100644 index 008cc68a3..000000000 --- a/uppdev/plugin/cairo/lib/cairo-cff-subset.c +++ /dev/null @@ -1,2289 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2006 Adrian Johnson - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Adrian Johnson. - * - * Contributor(s): - * Adrian Johnson - * Eugeniy Meshcheryakov - */ - -/* - * Useful links: - * http://www.adobe.com/devnet/font/pdfs/5176.CFF.pdf - */ - -#define _BSD_SOURCE /* for snprintf(), strdup() */ -#include "cairoint.h" - -#if CAIRO_HAS_FONT_SUBSET - -#include "cairo-scaled-font-subsets-private.h" -#include "cairo-truetype-subset-private.h" -#include - -/* CFF Dict Operators. If the high byte is 0 the command is encoded - * with a single byte. */ -#define BASEFONTNAME_OP 0x0c16 -#define CIDCOUNT_OP 0x0c22 -#define CHARSET_OP 0x000f -#define CHARSTRINGS_OP 0x0011 -#define COPYRIGHT_OP 0x0c00 -#define ENCODING_OP 0x0010 -#define FAMILYNAME_OP 0x0003 -#define FDARRAY_OP 0x0c24 -#define FDSELECT_OP 0x0c25 -#define FONTBBOX_OP 0x0005 -#define FONTNAME_OP 0x0c26 -#define FULLNAME_OP 0x0002 -#define LOCAL_SUB_OP 0x0013 -#define NOTICE_OP 0x0001 -#define POSTSCRIPT_OP 0x0c15 -#define PRIVATE_OP 0x0012 -#define ROS_OP 0x0c1e -#define UNIQUEID_OP 0x000d -#define VERSION_OP 0x0000 -#define WEIGHT_OP 0x0004 -#define XUID_OP 0x000e - -#define NUM_STD_STRINGS 391 - -typedef struct _cff_header { - uint8_t major; - uint8_t minor; - uint8_t header_size; - uint8_t offset_size; -} cff_header_t; - -typedef struct _cff_index_element { - cairo_bool_t is_copy; - unsigned char *data; - int length; -} cff_index_element_t; - -typedef struct _cff_dict_operator { - cairo_hash_entry_t base; - - unsigned short operator; - unsigned char *operand; - int operand_length; - int operand_offset; -} cff_dict_operator_t; - -typedef struct _cairo_cff_font { - - cairo_scaled_font_subset_t *scaled_font_subset; - const cairo_scaled_font_backend_t *backend; - - /* Font Data */ - unsigned char *data; - unsigned long data_length; - unsigned char *current_ptr; - unsigned char *data_end; - cff_header_t *header; - char *font_name; - cairo_hash_table_t *top_dict; - cairo_hash_table_t *private_dict; - cairo_array_t strings_index; - cairo_array_t charstrings_index; - cairo_array_t global_sub_index; - cairo_array_t local_sub_index; - int num_glyphs; - cairo_bool_t is_cid; - - /* CID Font Data */ - int *fdselect; - unsigned int num_fontdicts; - cairo_hash_table_t **fd_dict; - cairo_hash_table_t **fd_private_dict; - cairo_array_t *fd_local_sub_index; - - /* Subsetted Font Data */ - char *subset_font_name; - cairo_array_t charstrings_subset_index; - cairo_array_t strings_subset_index; - int *fdselect_subset; - unsigned int num_subset_fontdicts; - int *fd_subset_map; - int *private_dict_offset; - cairo_array_t output; - - /* Subset Metrics */ - int *widths; - int x_min, y_min, x_max, y_max; - int ascent, descent; - -} cairo_cff_font_t; - -/* Encoded integer using maximum sized encoding. This is required for - * operands that are later modified after encoding. */ -static unsigned char * -encode_integer_max (unsigned char *p, int i) -{ - *p++ = 29; - *p++ = i >> 24; - *p++ = (i >> 16) & 0xff; - *p++ = (i >> 8) & 0xff; - *p++ = i & 0xff; - return p; -} - -static unsigned char * -encode_integer (unsigned char *p, int i) -{ - if (i >= -107 && i <= 107) { - *p++ = i + 139; - } else if (i >= 108 && i <= 1131) { - i -= 108; - *p++ = (i >> 8)+ 247; - *p++ = i & 0xff; - } else if (i >= -1131 && i <= -108) { - i = -i - 108; - *p++ = (i >> 8)+ 251; - *p++ = i & 0xff; - } else if (i >= -32768 && i <= 32767) { - *p++ = 28; - *p++ = (i >> 8) & 0xff; - *p++ = i & 0xff; - } else { - p = encode_integer_max (p, i); - } - return p; -} - -static unsigned char * -decode_integer (unsigned char *p, int *integer) -{ - if (*p == 28) { - *integer = (int)(p[1]<<8 | p[2]); - p += 3; - } else if (*p == 29) { - *integer = (int)((p[1] << 24) | (p[2] << 16) | (p[3] << 8) | p[4]); - p += 5; - } else if (*p >= 32 && *p <= 246) { - *integer = *p++ - 139; - } else if (*p <= 250) { - *integer = (p[0] - 247) * 256 + p[1] + 108; - p += 2; - } else if (*p <= 254) { - *integer = -(p[0] - 251) * 256 - p[1] - 108; - p += 2; - } else { - *integer = 0; - p += 1; - } - return p; -} - -static unsigned char * -decode_operator (unsigned char *p, unsigned short *operator) -{ - unsigned short op = 0; - - op = *p++; - if (op == 12) { - op <<= 8; - op |= *p++; - } - *operator = op; - return p; -} - -/* return 0 if not an operand */ -static int -operand_length (unsigned char *p) -{ - unsigned char *begin = p; - - if (*p == 28) - return 3; - - if (*p == 29) - return 5; - - if (*p >= 32 && *p <= 246) - return 1; - - if (*p >= 247 && *p <= 254) - return 2; - - if (*p == 30) { - while ((*p & 0x0f) != 0x0f) - p++; - return p - begin + 1; - } - - return 0; -} - -static unsigned char * -encode_index_offset (unsigned char *p, int offset_size, unsigned long offset) -{ - while (--offset_size >= 0) { - p[offset_size] = (unsigned char) (offset & 0xff); - offset >>= 8; - } - return p + offset_size; -} - -static unsigned long -decode_index_offset(unsigned char *p, int off_size) -{ - unsigned long offset = 0; - - while (off_size-- > 0) - offset = offset*256 + *p++; - return offset; -} - -static void -cff_index_init (cairo_array_t *index) -{ - _cairo_array_init (index, sizeof (cff_index_element_t)); -} - -static cairo_int_status_t -cff_index_read (cairo_array_t *index, unsigned char **ptr, unsigned char *end_ptr) -{ - cff_index_element_t element; - unsigned char *data, *p; - cairo_status_t status; - int offset_size, count, start, i; - int end = 0; - - p = *ptr; - if (p + 2 > end_ptr) - return CAIRO_INT_STATUS_UNSUPPORTED; - count = be16_to_cpu( *((uint16_t *)p) ); - p += 2; - if (count > 0) { - offset_size = *p++; - if (p + (count + 1)*offset_size > end_ptr) - return CAIRO_INT_STATUS_UNSUPPORTED; - data = p + offset_size*(count + 1) - 1; - start = decode_index_offset (p, offset_size); - p += offset_size; - for (i = 0; i < count; i++) { - end = decode_index_offset (p, offset_size); - p += offset_size; - if (p > end_ptr) - return CAIRO_INT_STATUS_UNSUPPORTED; - element.length = end - start; - element.is_copy = FALSE; - element.data = data + start; - status = _cairo_array_append (index, &element); - if (status) - return status; - start = end; - } - p = data + end; - } - *ptr = p; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -cff_index_write (cairo_array_t *index, cairo_array_t *output) -{ - int offset_size; - int offset; - int num_elem; - int i; - cff_index_element_t *element; - uint16_t count; - unsigned char buf[5]; - cairo_status_t status; - - num_elem = _cairo_array_num_elements (index); - count = cpu_to_be16 ((uint16_t) num_elem); - status = _cairo_array_append_multiple (output, &count, 2); - if (status) - return status; - - if (num_elem == 0) - return CAIRO_STATUS_SUCCESS; - - /* Find maximum offset to determine offset size */ - offset = 1; - for (i = 0; i < num_elem; i++) { - element = _cairo_array_index (index, i); - offset += element->length; - } - if (offset < 0x100) - offset_size = 1; - else if (offset < 0x10000) - offset_size = 2; - else if (offset < 0x1000000) - offset_size = 3; - else - offset_size = 4; - - buf[0] = (unsigned char) offset_size; - status = _cairo_array_append (output, buf); - if (status) - return status; - - offset = 1; - encode_index_offset (buf, offset_size, offset); - status = _cairo_array_append_multiple (output, buf, offset_size); - if (status) - return status; - - for (i = 0; i < num_elem; i++) { - element = _cairo_array_index (index, i); - offset += element->length; - encode_index_offset (buf, offset_size, offset); - status = _cairo_array_append_multiple (output, buf, offset_size); - if (status) - return status; - } - - for (i = 0; i < num_elem; i++) { - element = _cairo_array_index (index, i); - status = _cairo_array_append_multiple (output, - element->data, - element->length); - if (status) - return status; - } - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -cff_index_append (cairo_array_t *index, unsigned char *object , int length) -{ - cff_index_element_t element; - - element.length = length; - element.is_copy = FALSE; - element.data = object; - - return _cairo_array_append (index, &element); -} - -static cairo_status_t -cff_index_append_copy (cairo_array_t *index, - const unsigned char *object, - unsigned int length) -{ - cff_index_element_t element; - cairo_status_t status; - - element.length = length; - element.is_copy = TRUE; - element.data = malloc (element.length); - if (element.data == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - memcpy (element.data, object, element.length); - - status = _cairo_array_append (index, &element); - if (status) { - free (element.data); - return status; - } - - return CAIRO_STATUS_SUCCESS; -} - -static void -cff_index_fini (cairo_array_t *index) -{ - cff_index_element_t *element; - int i; - - for (i = 0; i < _cairo_array_num_elements (index); i++) { - element = _cairo_array_index (index, i); - if (element->is_copy) - free (element->data); - } - _cairo_array_fini (index); -} - -static cairo_bool_t -_cairo_cff_dict_equal (const void *key_a, const void *key_b) -{ - const cff_dict_operator_t *op_a = key_a; - const cff_dict_operator_t *op_b = key_b; - - return op_a->operator == op_b->operator; -} - -static cairo_status_t -cff_dict_init (cairo_hash_table_t **dict) -{ - *dict = _cairo_hash_table_create (_cairo_cff_dict_equal); - if (*dict == NULL) - return CAIRO_STATUS_NO_MEMORY; - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_dict_init_key (cff_dict_operator_t *key, int operator) -{ - key->base.hash = (unsigned long) operator; - key->operator = operator; -} - -static cairo_status_t -cff_dict_create_operator (int operator, - unsigned char *operand, - int operand_length, - cff_dict_operator_t **out) -{ - cff_dict_operator_t *op; - - op = malloc (sizeof (cff_dict_operator_t)); - if (op == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - _cairo_dict_init_key (op, operator); - op->operand = malloc (operand_length); - if (op->operand == NULL) { - free (op); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - memcpy (op->operand, operand, operand_length); - op->operand_length = operand_length; - op->operand_offset = -1; - - *out = op; - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -cff_dict_read (cairo_hash_table_t *dict, unsigned char *p, int dict_size) -{ - unsigned char *end; - cairo_array_t operands; - cff_dict_operator_t *op; - unsigned short operator; - cairo_status_t status = CAIRO_STATUS_SUCCESS; - int size; - - end = p + dict_size; - _cairo_array_init (&operands, 1); - while (p < end) { - size = operand_length (p); - if (size != 0) { - status = _cairo_array_append_multiple (&operands, p, size); - if (status) - goto fail; - - p += size; - } else { - p = decode_operator (p, &operator); - status = cff_dict_create_operator (operator, - _cairo_array_index (&operands, 0), - _cairo_array_num_elements (&operands), - &op); - if (status) - goto fail; - - status = _cairo_hash_table_insert (dict, &op->base); - if (status) - goto fail; - - _cairo_array_truncate (&operands, 0); - } - } - -fail: - _cairo_array_fini (&operands); - - return status; -} - -static void -cff_dict_remove (cairo_hash_table_t *dict, unsigned short operator) -{ - cff_dict_operator_t key, *op; - - _cairo_dict_init_key (&key, operator); - if (_cairo_hash_table_lookup (dict, &key.base, - (cairo_hash_entry_t **) &op)) - { - free (op->operand); - _cairo_hash_table_remove (dict, (cairo_hash_entry_t *) op); - free (op); - } -} - -static unsigned char * -cff_dict_get_operands (cairo_hash_table_t *dict, - unsigned short operator, - int *size) -{ - cff_dict_operator_t key, *op; - - _cairo_dict_init_key (&key, operator); - if (_cairo_hash_table_lookup (dict, &key.base, - (cairo_hash_entry_t **) &op)) - { - *size = op->operand_length; - return op->operand; - } - - return NULL; -} - -static cairo_status_t -cff_dict_set_operands (cairo_hash_table_t *dict, - unsigned short operator, - unsigned char *operand, - int size) -{ - cff_dict_operator_t key, *op; - cairo_status_t status; - - _cairo_dict_init_key (&key, operator); - if (_cairo_hash_table_lookup (dict, &key.base, - (cairo_hash_entry_t **) &op)) - { - free (op->operand); - op->operand = malloc (size); - if (op->operand == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - memcpy (op->operand, operand, size); - op->operand_length = size; - } - else - { - status = cff_dict_create_operator (operator, operand, size, &op); - if (status) - return status; - - status = _cairo_hash_table_insert (dict, &op->base); - if (status) - return status; - } - - return CAIRO_STATUS_SUCCESS; -} - -static int -cff_dict_get_location (cairo_hash_table_t *dict, - unsigned short operator, - int *size) -{ - cff_dict_operator_t key, *op; - - _cairo_dict_init_key (&key, operator); - if (_cairo_hash_table_lookup (dict, &key.base, - (cairo_hash_entry_t **) &op)) - { - *size = op->operand_length; - return op->operand_offset; - } - - return -1; -} - -typedef struct _dict_write_info { - cairo_array_t *output; - cairo_status_t status; -} dict_write_info_t; - -static void -cairo_dict_write_operator (cff_dict_operator_t *op, dict_write_info_t *write_info) -{ - unsigned char data; - - op->operand_offset = _cairo_array_num_elements (write_info->output); - write_info->status = _cairo_array_append_multiple (write_info->output, op->operand, op->operand_length); - if (write_info->status) - return; - - if (op->operator & 0xff00) { - data = op->operator >> 8; - write_info->status = _cairo_array_append (write_info->output, &data); - if (write_info->status) - return; - } - data = op->operator & 0xff; - write_info->status = _cairo_array_append (write_info->output, &data); -} - -static void -_cairo_dict_collect (void *entry, void *closure) -{ - dict_write_info_t *write_info = closure; - cff_dict_operator_t *op = entry; - - if (write_info->status) - return; - - /* The ROS operator is handled separately in cff_dict_write() */ - if (op->operator != ROS_OP) - cairo_dict_write_operator (op, write_info); -} - -static cairo_status_t -cff_dict_write (cairo_hash_table_t *dict, cairo_array_t *output) -{ - dict_write_info_t write_info; - cff_dict_operator_t key, *op; - - write_info.output = output; - write_info.status = CAIRO_STATUS_SUCCESS; - - /* The CFF specification requires that the Top Dict of CID fonts - * begin with the ROS operator. */ - _cairo_dict_init_key (&key, ROS_OP); - if (_cairo_hash_table_lookup (dict, &key.base, - (cairo_hash_entry_t **) &op)) - cairo_dict_write_operator (op, &write_info); - - _cairo_hash_table_foreach (dict, _cairo_dict_collect, &write_info); - - return write_info.status; -} - -static void -cff_dict_fini (cairo_hash_table_t *dict) -{ - cff_dict_operator_t *entry; - - while (1) { - entry = _cairo_hash_table_random_entry (dict, NULL); - if (entry == NULL) - break; - free (entry->operand); - _cairo_hash_table_remove (dict, (cairo_hash_entry_t *) entry); - free (entry); - } - _cairo_hash_table_destroy (dict); -} - -static cairo_int_status_t -cairo_cff_font_read_header (cairo_cff_font_t *font) -{ - if (font->data_length < sizeof (cff_header_t)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - font->header = (cff_header_t *) font->data; - font->current_ptr = font->data + font->header->header_size; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -cairo_cff_font_read_name (cairo_cff_font_t *font) -{ - cairo_array_t index; - cairo_int_status_t status; - - /* The original font name is not used in the subset. Read the name - * index to skip over it. */ - cff_index_init (&index); - status = cff_index_read (&index, &font->current_ptr, font->data_end); - cff_index_fini (&index); - - return status; -} - -static cairo_int_status_t -cairo_cff_font_read_private_dict (cairo_cff_font_t *font, - cairo_hash_table_t *private_dict, - cairo_array_t *local_sub_index, - unsigned char *ptr, - int size) -{ - cairo_int_status_t status; - unsigned char buf[10]; - unsigned char *end_buf; - int offset; - int i; - unsigned char *operand; - unsigned char *p; - - status = cff_dict_read (private_dict, ptr, size); - if (status) - return status; - - operand = cff_dict_get_operands (private_dict, LOCAL_SUB_OP, &i); - if (operand) { - decode_integer (operand, &offset); - p = ptr + offset; - status = cff_index_read (local_sub_index, &p, font->data_end); - if (status) - return status; - - /* Use maximum sized encoding to reserve space for later modification. */ - end_buf = encode_integer_max (buf, 0); - status = cff_dict_set_operands (private_dict, LOCAL_SUB_OP, buf, end_buf - buf); - if (status) - return status; - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -cairo_cff_font_read_fdselect (cairo_cff_font_t *font, unsigned char *p) -{ - int type, num_ranges, first, last, fd, i, j; - - font->fdselect = calloc (font->num_glyphs, sizeof (int)); - if (font->fdselect == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - type = *p++; - if (type == 0) - { - for (i = 0; i < font->num_glyphs; i++) - font->fdselect[i] = *p++; - } else if (type == 3) { - num_ranges = be16_to_cpu( *((uint16_t *)p) ); - p += 2; - for (i = 0; i < num_ranges; i++) - { - first = be16_to_cpu( *((uint16_t *)p) ); - p += 2; - fd = *p++; - last = be16_to_cpu( *((uint16_t *)p) ); - for (j = first; j < last; j++) - font->fdselect[j] = fd; - } - } else { - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -cairo_cff_font_read_cid_fontdict (cairo_cff_font_t *font, unsigned char *ptr) -{ - cairo_array_t index; - cff_index_element_t *element; - unsigned int i; - int size; - unsigned char *operand; - int offset; - cairo_int_status_t status; - unsigned char buf[100]; - unsigned char *end_buf; - - cff_index_init (&index); - status = cff_index_read (&index, &ptr, font->data_end); - if (status) - goto fail; - - font->num_fontdicts = _cairo_array_num_elements (&index); - - font->fd_dict = calloc (sizeof (cairo_hash_table_t *), font->num_fontdicts); - if (font->fd_dict == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto fail; - } - - font->fd_private_dict = calloc (sizeof (cairo_hash_table_t *), font->num_fontdicts); - if (font->fd_private_dict == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto fail; - } - - font->fd_local_sub_index = calloc (sizeof (cairo_array_t), font->num_fontdicts); - if (font->fd_local_sub_index == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto fail; - } - - for (i = 0; i < font->num_fontdicts; i++) { - status = cff_dict_init (&font->fd_dict[i]); - if (status) - goto fail; - - element = _cairo_array_index (&index, i); - status = cff_dict_read (font->fd_dict[i], element->data, element->length); - if (status) - goto fail; - - operand = cff_dict_get_operands (font->fd_dict[i], PRIVATE_OP, &size); - if (operand == NULL) { - status = CAIRO_INT_STATUS_UNSUPPORTED; - goto fail; - } - operand = decode_integer (operand, &size); - decode_integer (operand, &offset); - status = cff_dict_init (&font->fd_private_dict[i]); - if (status) - goto fail; - - cff_index_init (&font->fd_local_sub_index[i]); - status = cairo_cff_font_read_private_dict (font, - font->fd_private_dict[i], - &font->fd_local_sub_index[i], - font->data + offset, - size); - if (status) - goto fail; - - /* Set integer operand to max value to use max size encoding to reserve - * space for any value later */ - end_buf = encode_integer_max (buf, 0); - end_buf = encode_integer_max (end_buf, 0); - status = cff_dict_set_operands (font->fd_dict[i], PRIVATE_OP, buf, end_buf - buf); - if (status) - goto fail; - } - - return CAIRO_STATUS_SUCCESS; - -fail: - cff_index_fini (&index); - - return status; -} - -static cairo_int_status_t -cairo_cff_font_read_top_dict (cairo_cff_font_t *font) -{ - cairo_array_t index; - cff_index_element_t *element; - unsigned char buf[20]; - unsigned char *end_buf; - unsigned char *operand; - cairo_int_status_t status; - unsigned char *p; - int size; - int offset; - - cff_index_init (&index); - status = cff_index_read (&index, &font->current_ptr, font->data_end); - if (status) - goto fail; - - element = _cairo_array_index (&index, 0); - status = cff_dict_read (font->top_dict, element->data, element->length); - if (status) - goto fail; - - if (cff_dict_get_operands (font->top_dict, ROS_OP, &size) != NULL) - font->is_cid = TRUE; - else - font->is_cid = FALSE; - - operand = cff_dict_get_operands (font->top_dict, CHARSTRINGS_OP, &size); - decode_integer (operand, &offset); - p = font->data + offset; - status = cff_index_read (&font->charstrings_index, &p, font->data_end); - if (status) - goto fail; - font->num_glyphs = _cairo_array_num_elements (&font->charstrings_index); - - if (font->is_cid) { - operand = cff_dict_get_operands (font->top_dict, FDSELECT_OP, &size); - decode_integer (operand, &offset); - status = cairo_cff_font_read_fdselect (font, font->data + offset); - if (status) - goto fail; - - operand = cff_dict_get_operands (font->top_dict, FDARRAY_OP, &size); - decode_integer (operand, &offset); - status = cairo_cff_font_read_cid_fontdict (font, font->data + offset); - if (status) - goto fail; - } else { - operand = cff_dict_get_operands (font->top_dict, PRIVATE_OP, &size); - operand = decode_integer (operand, &size); - decode_integer (operand, &offset); - status = cairo_cff_font_read_private_dict (font, - font->private_dict, - &font->local_sub_index, - font->data + offset, - size); - if (status) - goto fail; - } - - /* Use maximum sized encoding to reserve space for later modification. */ - end_buf = encode_integer_max (buf, 0); - status = cff_dict_set_operands (font->top_dict, - CHARSTRINGS_OP, buf, end_buf - buf); - if (status) - goto fail; - - status = cff_dict_set_operands (font->top_dict, - FDSELECT_OP, buf, end_buf - buf); - if (status) - goto fail; - - status = cff_dict_set_operands (font->top_dict, - FDARRAY_OP, buf, end_buf - buf); - if (status) - goto fail; - - status = cff_dict_set_operands (font->top_dict, - CHARSET_OP, buf, end_buf - buf); - if (status) - goto fail; - - cff_dict_remove (font->top_dict, ENCODING_OP); - cff_dict_remove (font->top_dict, PRIVATE_OP); - - /* Remove the unique identifier operators as the subsetted font is - * not the same is the original font. */ - cff_dict_remove (font->top_dict, UNIQUEID_OP); - cff_dict_remove (font->top_dict, XUID_OP); - -fail: - cff_index_fini (&index); - - return status; -} - -static cairo_int_status_t -cairo_cff_font_read_strings (cairo_cff_font_t *font) -{ - return cff_index_read (&font->strings_index, &font->current_ptr, font->data_end); -} - -static cairo_int_status_t -cairo_cff_font_read_global_subroutines (cairo_cff_font_t *font) -{ - return cff_index_read (&font->global_sub_index, &font->current_ptr, font->data_end); -} - -typedef cairo_int_status_t -(*font_read_t) (cairo_cff_font_t *font); - -static const font_read_t font_read_funcs[] = { - cairo_cff_font_read_header, - cairo_cff_font_read_name, - cairo_cff_font_read_top_dict, - cairo_cff_font_read_strings, - cairo_cff_font_read_global_subroutines, -}; - -static cairo_int_status_t -cairo_cff_font_read_font (cairo_cff_font_t *font) -{ - cairo_int_status_t status; - unsigned int i; - - for (i = 0; i < ARRAY_LENGTH (font_read_funcs); i++) { - status = font_read_funcs[i] (font); - if (status) - return status; - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -cairo_cff_font_set_ros_strings (cairo_cff_font_t *font) -{ - cairo_status_t status; - unsigned char buf[30]; - unsigned char *p; - int sid1, sid2; - const char *registry = "Adobe"; - const char *ordering = "Identity"; - - sid1 = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index); - status = cff_index_append_copy (&font->strings_subset_index, - (unsigned char *)registry, - strlen(registry)); - if (status) - return status; - - sid2 = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index); - status = cff_index_append_copy (&font->strings_subset_index, - (unsigned char *)ordering, - strlen(ordering)); - if (status) - return status; - - p = encode_integer (buf, sid1); - p = encode_integer (p, sid2); - p = encode_integer (p, 0); - status = cff_dict_set_operands (font->top_dict, ROS_OP, buf, p - buf); - if (status) - return status; - - p = encode_integer (buf, font->scaled_font_subset->num_glyphs); - status = cff_dict_set_operands (font->top_dict, CIDCOUNT_OP, buf, p - buf); - if (status) - return status; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -cairo_cff_font_subset_dict_string(cairo_cff_font_t *font, - cairo_hash_table_t *dict, - int operator) -{ - int size; - unsigned char *p; - int sid; - unsigned char buf[100]; - cff_index_element_t *element; - cairo_status_t status; - - p = cff_dict_get_operands (dict, operator, &size); - if (!p) - return CAIRO_STATUS_SUCCESS; - - decode_integer (p, &sid); - if (sid < NUM_STD_STRINGS) - return CAIRO_STATUS_SUCCESS; - - element = _cairo_array_index (&font->strings_index, sid - NUM_STD_STRINGS); - sid = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index); - status = cff_index_append (&font->strings_subset_index, element->data, element->length); - if (status) - return status; - - p = encode_integer (buf, sid); - status = cff_dict_set_operands (dict, operator, buf, p - buf); - if (status) - return status; - - return CAIRO_STATUS_SUCCESS; -} - -static const int dict_strings[] = { - VERSION_OP, - NOTICE_OP, - COPYRIGHT_OP, - FULLNAME_OP, - FAMILYNAME_OP, - WEIGHT_OP, - POSTSCRIPT_OP, - BASEFONTNAME_OP, - FONTNAME_OP, -}; - -static cairo_status_t -cairo_cff_font_subset_dict_strings (cairo_cff_font_t *font, - cairo_hash_table_t *dict) -{ - cairo_status_t status; - unsigned int i; - - for (i = 0; i < ARRAY_LENGTH (dict_strings); i++) { - status = cairo_cff_font_subset_dict_string (font, dict, dict_strings[i]); - if (status) - return status; - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -cairo_cff_font_subset_charstrings (cairo_cff_font_t *font) -{ - cff_index_element_t *element; - unsigned int i; - cairo_status_t status; - - for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) { - element = _cairo_array_index (&font->charstrings_index, - font->scaled_font_subset->glyphs[i]); - status = cff_index_append (&font->charstrings_subset_index, - element->data, - element->length); - if (status) - return status; - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -cairo_cff_font_subset_fontdict (cairo_cff_font_t *font) -{ - unsigned int i; - int fd; - int *reverse_map; - - font->fdselect_subset = calloc (font->scaled_font_subset->num_glyphs, - sizeof (int)); - if (font->fdselect_subset == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - font->fd_subset_map = calloc (font->num_fontdicts, sizeof (int)); - if (font->fd_subset_map == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - font->private_dict_offset = calloc (font->num_fontdicts, sizeof (int)); - if (font->private_dict_offset == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - reverse_map = calloc (font->num_fontdicts, sizeof (int)); - if (reverse_map == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - for (i = 0; i < font->num_fontdicts; i++) - reverse_map[i] = -1; - - font->num_subset_fontdicts = 0; - for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) { - fd = font->fdselect[font->scaled_font_subset->glyphs[i]]; - if (reverse_map[fd] < 0) { - font->fd_subset_map[font->num_subset_fontdicts] = fd; - reverse_map[fd] = font->num_subset_fontdicts++; - } - font->fdselect_subset[i] = reverse_map[fd]; - } - - free (reverse_map); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -cairo_cff_font_create_cid_fontdict (cairo_cff_font_t *font) -{ - unsigned char buf[100]; - unsigned char *end_buf; - cairo_status_t status; - - font->num_fontdicts = 1; - font->fd_dict = malloc (sizeof (cairo_hash_table_t *)); - if (font->fd_dict == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - if (cff_dict_init (&font->fd_dict[0])) { - free (font->fd_dict); - font->fd_dict = NULL; - font->num_fontdicts = 0; - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - font->fd_subset_map = malloc (sizeof (int)); - if (font->fd_subset_map == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - font->private_dict_offset = malloc (sizeof (int)); - if (font->private_dict_offset == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - font->fd_subset_map[0] = 0; - font->num_subset_fontdicts = 1; - - /* Set integer operand to max value to use max size encoding to reserve - * space for any value later */ - end_buf = encode_integer_max (buf, 0); - end_buf = encode_integer_max (end_buf, 0); - status = cff_dict_set_operands (font->fd_dict[0], PRIVATE_OP, buf, end_buf - buf); - if (status) - return status; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -cairo_cff_font_subset_strings (cairo_cff_font_t *font) -{ - cairo_status_t status; - unsigned int i; - - status = cairo_cff_font_subset_dict_strings (font, font->top_dict); - if (status) - return status; - - if (font->is_cid) { - for (i = 0; i < font->num_subset_fontdicts; i++) { - status = cairo_cff_font_subset_dict_strings (font, font->fd_dict[font->fd_subset_map[i]]); - if (status) - return status; - - status = cairo_cff_font_subset_dict_strings (font, font->fd_private_dict[font->fd_subset_map[i]]); - if (status) - return status; - } - } else { - status = cairo_cff_font_subset_dict_strings (font, font->private_dict); - } - - return status; -} - -static cairo_status_t -cairo_cff_font_subset_font (cairo_cff_font_t *font) -{ - cairo_status_t status; - - status = cairo_cff_font_set_ros_strings (font); - if (status) - return status; - - status = cairo_cff_font_subset_charstrings (font); - if (status) - return status; - - if (font->is_cid) - status = cairo_cff_font_subset_fontdict (font); - else - status = cairo_cff_font_create_cid_fontdict (font); - if (status) - return status; - - status = cairo_cff_font_subset_strings (font); - if (status) - return status; - - return status; -} - -/* Set the operand of the specified operator in the (already written) - * top dict to point to the current position in the output - * array. Operands updated with this function must have previously - * been encoded with the 5-byte (max) integer encoding. */ -static void -cairo_cff_font_set_topdict_operator_to_cur_pos (cairo_cff_font_t *font, - int operator) -{ - int cur_pos; - int offset; - int size; - unsigned char buf[10]; - unsigned char *buf_end; - unsigned char *op_ptr; - - cur_pos = _cairo_array_num_elements (&font->output); - buf_end = encode_integer_max (buf, cur_pos); - offset = cff_dict_get_location (font->top_dict, operator, &size); - assert (offset > 0); - op_ptr = _cairo_array_index (&font->output, offset); - memcpy (op_ptr, buf, buf_end - buf); -} - -static cairo_status_t -cairo_cff_font_write_header (cairo_cff_font_t *font) -{ - return _cairo_array_append_multiple (&font->output, - font->header, - font->header->header_size); -} - -static cairo_status_t -cairo_cff_font_write_name (cairo_cff_font_t *font) -{ - cairo_status_t status = CAIRO_STATUS_SUCCESS; - cairo_array_t index; - - cff_index_init (&index); - - status = cff_index_append_copy (&index, - (unsigned char *) font->subset_font_name, - strlen(font->subset_font_name)); - if (status) - goto FAIL; - - status = cff_index_write (&index, &font->output); - if (status) - goto FAIL; - -FAIL: - cff_index_fini (&index); - - return status; -} - -static cairo_status_t -cairo_cff_font_write_top_dict (cairo_cff_font_t *font) -{ - uint16_t count; - unsigned char buf[10]; - unsigned char *p; - int offset_index; - int dict_start, dict_size; - int offset_size = 4; - cairo_status_t status; - - /* Write an index containing the top dict */ - - count = cpu_to_be16 (1); - status = _cairo_array_append_multiple (&font->output, &count, 2); - if (status) - return status; - buf[0] = offset_size; - status = _cairo_array_append (&font->output, buf); - if (status) - return status; - encode_index_offset (buf, offset_size, 1); - status = _cairo_array_append_multiple (&font->output, buf, offset_size); - if (status) - return status; - - /* Reserve space for last element of offset array and update after - * dict is written */ - offset_index = _cairo_array_num_elements (&font->output); - status = _cairo_array_append_multiple (&font->output, buf, offset_size); - if (status) - return status; - - dict_start = _cairo_array_num_elements (&font->output); - status = cff_dict_write (font->top_dict, &font->output); - if (status) - return status; - dict_size = _cairo_array_num_elements (&font->output) - dict_start; - - encode_index_offset (buf, offset_size, dict_size + 1); - p = _cairo_array_index (&font->output, offset_index); - memcpy (p, buf, offset_size); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -cairo_cff_font_write_strings (cairo_cff_font_t *font) -{ - return cff_index_write (&font->strings_subset_index, &font->output); -} - -static cairo_status_t -cairo_cff_font_write_global_subrs (cairo_cff_font_t *font) -{ - return cff_index_write (&font->global_sub_index, &font->output); -} - -static cairo_status_t -cairo_cff_font_write_fdselect (cairo_cff_font_t *font) -{ - unsigned char data; - unsigned int i; - cairo_int_status_t status; - - cairo_cff_font_set_topdict_operator_to_cur_pos (font, FDSELECT_OP); - - if (font->is_cid) { - data = 0; - status = _cairo_array_append (&font->output, &data); - if (status) - return status; - - for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) { - data = font->fdselect_subset[i]; - status = _cairo_array_append (&font->output, &data); - if (status) - return status; - } - } else { - unsigned char byte; - uint16_t word; - - status = _cairo_array_grow_by (&font->output, 9); - if (status) - return status; - - byte = 3; - status = _cairo_array_append (&font->output, &byte); - assert (status == CAIRO_STATUS_SUCCESS); - - word = cpu_to_be16 (1); - status = _cairo_array_append_multiple (&font->output, &word, 2); - assert (status == CAIRO_STATUS_SUCCESS); - - word = cpu_to_be16 (0); - status = _cairo_array_append_multiple (&font->output, &word, 2); - assert (status == CAIRO_STATUS_SUCCESS); - - byte = 0; - status = _cairo_array_append (&font->output, &byte); - assert (status == CAIRO_STATUS_SUCCESS); - - word = cpu_to_be16 (font->scaled_font_subset->num_glyphs); - status = _cairo_array_append_multiple (&font->output, &word, 2); - assert (status == CAIRO_STATUS_SUCCESS); - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -cairo_cff_font_write_charset (cairo_cff_font_t *font) -{ - unsigned char byte; - uint16_t word; - cairo_status_t status; - - cairo_cff_font_set_topdict_operator_to_cur_pos (font, CHARSET_OP); - status = _cairo_array_grow_by (&font->output, 5); - if (status) - return status; - - byte = 2; - status = _cairo_array_append (&font->output, &byte); - assert (status == CAIRO_STATUS_SUCCESS); - - word = cpu_to_be16 (1); - status = _cairo_array_append_multiple (&font->output, &word, 2); - assert (status == CAIRO_STATUS_SUCCESS); - - word = cpu_to_be16 (font->scaled_font_subset->num_glyphs - 2); - status = _cairo_array_append_multiple (&font->output, &word, 2); - assert (status == CAIRO_STATUS_SUCCESS); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -cairo_cff_font_write_charstrings (cairo_cff_font_t *font) -{ - cairo_cff_font_set_topdict_operator_to_cur_pos (font, CHARSTRINGS_OP); - - return cff_index_write (&font->charstrings_subset_index, &font->output); -} - -static cairo_status_t -cairo_cff_font_write_cid_fontdict (cairo_cff_font_t *font) -{ - unsigned int i; - cairo_int_status_t status; - uint32_t *offset_array; - int offset_base; - uint16_t count; - uint8_t offset_size = 4; - - cairo_cff_font_set_topdict_operator_to_cur_pos (font, FDARRAY_OP); - count = cpu_to_be16 (font->num_subset_fontdicts); - status = _cairo_array_append_multiple (&font->output, &count, sizeof (uint16_t)); - if (status) - return status; - status = _cairo_array_append (&font->output, &offset_size); - if (status) - return status; - status = _cairo_array_allocate (&font->output, - (font->num_subset_fontdicts + 1)*offset_size, - (void **) &offset_array); - if (status) - return status; - offset_base = _cairo_array_num_elements (&font->output) - 1; - *offset_array++ = cpu_to_be32(1); - for (i = 0; i < font->num_subset_fontdicts; i++) { - status = cff_dict_write (font->fd_dict[font->fd_subset_map[i]], - &font->output); - if (status) - return status; - *offset_array++ = cpu_to_be32(_cairo_array_num_elements (&font->output) - offset_base); - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -cairo_cff_font_write_private_dict (cairo_cff_font_t *font, - int dict_num, - cairo_hash_table_t *parent_dict, - cairo_hash_table_t *private_dict) -{ - int offset; - int size; - unsigned char buf[10]; - unsigned char *buf_end; - unsigned char *p; - cairo_status_t status; - - /* Write private dict and update offset and size in top dict */ - font->private_dict_offset[dict_num] = _cairo_array_num_elements (&font->output); - status = cff_dict_write (private_dict, &font->output); - if (status) - return status; - - size = _cairo_array_num_elements (&font->output) - font->private_dict_offset[dict_num]; - /* private entry has two operands - size and offset */ - buf_end = encode_integer_max (buf, size); - buf_end = encode_integer_max (buf_end, font->private_dict_offset[dict_num]); - offset = cff_dict_get_location (parent_dict, PRIVATE_OP, &size); - assert (offset > 0); - p = _cairo_array_index (&font->output, offset); - memcpy (p, buf, buf_end - buf); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -cairo_cff_font_write_local_sub (cairo_cff_font_t *font, - int dict_num, - cairo_hash_table_t *private_dict, - cairo_array_t *local_sub_index) -{ - int offset; - int size; - unsigned char buf[10]; - unsigned char *buf_end; - unsigned char *p; - cairo_status_t status; - - if (_cairo_array_num_elements (local_sub_index) > 0) { - /* Write local subroutines and update offset in private - * dict. Local subroutines offset is relative to start of - * private dict */ - offset = _cairo_array_num_elements (&font->output) - font->private_dict_offset[dict_num]; - buf_end = encode_integer_max (buf, offset); - offset = cff_dict_get_location (private_dict, LOCAL_SUB_OP, &size); - assert (offset > 0); - p = _cairo_array_index (&font->output, offset); - memcpy (p, buf, buf_end - buf); - status = cff_index_write (local_sub_index, &font->output); - if (status) - return status; - } - - return CAIRO_STATUS_SUCCESS; -} - - -static cairo_status_t -cairo_cff_font_write_cid_private_dict_and_local_sub (cairo_cff_font_t *font) -{ - unsigned int i; - cairo_int_status_t status; - - if (font->is_cid) { - for (i = 0; i < font->num_subset_fontdicts; i++) { - status = cairo_cff_font_write_private_dict ( - font, - i, - font->fd_dict[font->fd_subset_map[i]], - font->fd_private_dict[font->fd_subset_map[i]]); - if (status) - return status; - } - - for (i = 0; i < font->num_subset_fontdicts; i++) { - status = cairo_cff_font_write_local_sub ( - font, - i, - font->fd_private_dict[font->fd_subset_map[i]], - &font->fd_local_sub_index[font->fd_subset_map[i]]); - if (status) - return status; - } - } else { - status = cairo_cff_font_write_private_dict (font, - 0, - font->fd_dict[0], - font->private_dict); - if (status) - return status; - - status = cairo_cff_font_write_local_sub (font, - 0, - font->private_dict, - &font->local_sub_index); - if (status) - return status; - } - - return CAIRO_STATUS_SUCCESS; -} - -typedef cairo_status_t -(*font_write_t) (cairo_cff_font_t *font); - -static const font_write_t font_write_funcs[] = { - cairo_cff_font_write_header, - cairo_cff_font_write_name, - cairo_cff_font_write_top_dict, - cairo_cff_font_write_strings, - cairo_cff_font_write_global_subrs, - cairo_cff_font_write_charset, - cairo_cff_font_write_fdselect, - cairo_cff_font_write_charstrings, - cairo_cff_font_write_cid_fontdict, - cairo_cff_font_write_cid_private_dict_and_local_sub, -}; - -static cairo_status_t -cairo_cff_font_write_subset (cairo_cff_font_t *font) -{ - cairo_int_status_t status; - unsigned int i; - - for (i = 0; i < ARRAY_LENGTH (font_write_funcs); i++) { - status = font_write_funcs[i] (font); - if (status) - return status; - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -cairo_cff_font_generate (cairo_cff_font_t *font, - const char **data, - unsigned long *length) -{ - cairo_int_status_t status; - - status = cairo_cff_font_read_font (font); - if (status) - return status; - - status = cairo_cff_font_subset_font (font); - if (status) - return status; - - status = cairo_cff_font_write_subset (font); - if (status) - return status; - - *data = _cairo_array_index (&font->output, 0); - *length = _cairo_array_num_elements (&font->output); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -cairo_cff_font_create_set_widths (cairo_cff_font_t *font) -{ - unsigned long size; - unsigned long long_entry_size; - unsigned long short_entry_size; - unsigned int i; - tt_hhea_t hhea; - int num_hmetrics; - unsigned char buf[10]; - int glyph_index; - cairo_int_status_t status; - - size = sizeof (tt_hhea_t); - status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, - TT_TAG_hhea, 0, - (unsigned char*) &hhea, &size); - if (status) - return status; - num_hmetrics = be16_to_cpu (hhea.num_hmetrics); - - for (i = 1; i < font->scaled_font_subset->num_glyphs; i++) { - glyph_index = font->scaled_font_subset->glyphs[i]; - long_entry_size = 2 * sizeof (int16_t); - short_entry_size = sizeof (int16_t); - if (glyph_index < num_hmetrics) { - status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, - TT_TAG_hmtx, - glyph_index * long_entry_size, - buf, &short_entry_size); - if (status) - return status; - } - else - { - 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); - if (status) - return status; - } - font->widths[i] = be16_to_cpu (*((int16_t*)buf)); - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_cff_font_create (cairo_scaled_font_subset_t *scaled_font_subset, - cairo_cff_font_t **font_return, - const char *subset_name) -{ - const cairo_scaled_font_backend_t *backend; - cairo_status_t status; - cairo_cff_font_t *font; - tt_head_t head; - tt_hhea_t hhea; - tt_name_t *name; - tt_name_record_t *record; - unsigned long size, data_length; - int i, j; - - backend = scaled_font_subset->scaled_font->backend; - if (!backend->load_truetype_table) - return CAIRO_INT_STATUS_UNSUPPORTED; - - data_length = 0; - status = backend->load_truetype_table( scaled_font_subset->scaled_font, - TT_TAG_CFF, 0, NULL, &data_length); - if (status) - return status; - - size = sizeof (tt_head_t); - status = backend->load_truetype_table (scaled_font_subset->scaled_font, - TT_TAG_head, 0, - (unsigned char *) &head, &size); - if (status) - return status; - - size = sizeof (tt_hhea_t); - status = backend->load_truetype_table (scaled_font_subset->scaled_font, - TT_TAG_hhea, 0, - (unsigned char *) &hhea, &size); - if (status) - return status; - - size = 0; - status = backend->load_truetype_table (scaled_font_subset->scaled_font, - TT_TAG_hmtx, 0, NULL, &size); - if (status) - return status; - - size = 0; - status = backend->load_truetype_table (scaled_font_subset->scaled_font, - TT_TAG_name, 0, NULL, &size); - if (status) - return status; - - name = malloc (size); - if (name == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - status = backend->load_truetype_table (scaled_font_subset->scaled_font, - TT_TAG_name, 0, - (unsigned char *) name, &size); - if (status) - goto fail1; - - font = malloc (sizeof (cairo_cff_font_t)); - if (font == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto fail1; - } - - font->backend = backend; - font->scaled_font_subset = scaled_font_subset; - - _cairo_array_init (&font->output, sizeof (char)); - status = _cairo_array_grow_by (&font->output, 4096); - if (status) - goto fail2; - - font->subset_font_name = strdup (subset_name); - if (font->subset_font_name == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto fail2; - } - font->x_min = (int16_t) be16_to_cpu (head.x_min); - font->y_min = (int16_t) be16_to_cpu (head.y_min); - font->x_max = (int16_t) be16_to_cpu (head.x_max); - font->y_max = (int16_t) be16_to_cpu (head.y_max); - font->ascent = (int16_t) be16_to_cpu (hhea.ascender); - font->descent = (int16_t) be16_to_cpu (hhea.descender); - - /* Extract the font name from the name table. At present this - * just looks for the Mac platform/Roman encoded font name. It - * should be extended to use any suitable font name in the - * name table. If the mac/roman font name is not found a - * CairoFont-x-y name is created. - */ - font->font_name = NULL; - for (i = 0; i < be16_to_cpu(name->num_records); i++) { - record = &(name->records[i]); - if ((be16_to_cpu (record->platform) == 1) && - (be16_to_cpu (record->encoding) == 0) && - (be16_to_cpu (record->name) == 4)) { - font->font_name = malloc (be16_to_cpu(record->length) + 1); - if (font->font_name) { - strncpy(font->font_name, - ((char*)name) + be16_to_cpu (name->strings_offset) + be16_to_cpu (record->offset), - be16_to_cpu (record->length)); - font->font_name[be16_to_cpu (record->length)] = 0; - } - break; - } - } - - if (font->font_name == NULL) { - font->font_name = malloc (30); - if (font->font_name == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto fail3; - } - snprintf(font->font_name, 30, "CairoFont-%u-%u", - scaled_font_subset->font_id, - scaled_font_subset->subset_id); - } - - for (i = 0, j = 0; font->font_name[j]; j++) { - if (font->font_name[j] == ' ') - continue; - font->font_name[i++] = font->font_name[j]; - } - font->font_name[i] = '\0'; - - font->widths = calloc (font->scaled_font_subset->num_glyphs, sizeof (int)); - if (font->widths == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto fail4; - } - - status = cairo_cff_font_create_set_widths (font); - if (status) - goto fail5; - - font->data_length = data_length; - font->data = malloc (data_length); - if (font->data == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto fail5; - } - status = font->backend->load_truetype_table ( font->scaled_font_subset->scaled_font, - TT_TAG_CFF, 0, font->data, - &font->data_length); - if (status) - goto fail6; - - font->data_end = font->data + font->data_length; - - status = cff_dict_init (&font->top_dict); - if (status) - goto fail6; - - status = cff_dict_init (&font->private_dict); - if (status) - goto fail7; - - cff_index_init (&font->strings_index); - cff_index_init (&font->charstrings_index); - cff_index_init (&font->global_sub_index); - cff_index_init (&font->local_sub_index); - cff_index_init (&font->charstrings_subset_index); - cff_index_init (&font->strings_subset_index); - font->fdselect = NULL; - font->fd_dict = NULL; - font->fd_private_dict = NULL; - font->fd_local_sub_index = NULL; - font->fdselect_subset = NULL; - font->fd_subset_map = NULL; - font->private_dict_offset = NULL; - - free (name); - *font_return = font; - - return CAIRO_STATUS_SUCCESS; - -fail7: - _cairo_hash_table_destroy (font->top_dict); -fail6: - free (font->data); -fail5: - free (font->widths); -fail4: - free (font->font_name); -fail3: - free (font->subset_font_name); -fail2: - _cairo_array_fini (&font->output); - free (font); -fail1: - free (name); - return status; -} - -static void -cairo_cff_font_destroy (cairo_cff_font_t *font) -{ - unsigned int i; - - free (font->widths); - free (font->font_name); - free (font->subset_font_name); - _cairo_array_fini (&font->output); - cff_dict_fini (font->top_dict); - cff_dict_fini (font->private_dict); - cff_index_fini (&font->strings_index); - cff_index_fini (&font->charstrings_index); - cff_index_fini (&font->global_sub_index); - cff_index_fini (&font->local_sub_index); - cff_index_fini (&font->charstrings_subset_index); - cff_index_fini (&font->strings_subset_index); - - /* If we bailed out early as a result of an error some of the - * following cairo_cff_font_t members may still be NULL */ - if (font->fd_dict) { - for (i = 0; i < font->num_fontdicts; i++) { - if (font->fd_dict[i]) - cff_dict_fini (font->fd_dict[i]); - } - free (font->fd_dict); - } - if (font->fd_subset_map) - free (font->fd_subset_map); - if (font->private_dict_offset) - free (font->private_dict_offset); - - if (font->is_cid) { - if (font->fdselect) - free (font->fdselect); - if (font->fdselect_subset) - free (font->fdselect_subset); - if (font->fd_private_dict) { - for (i = 0; i < font->num_fontdicts; i++) { - if (font->fd_private_dict[i]) - cff_dict_fini (font->fd_private_dict[i]); - } - free (font->fd_private_dict); - } - if (font->fd_local_sub_index) { - for (i = 0; i < font->num_fontdicts; i++) - cff_index_fini (&font->fd_local_sub_index[i]); - free (font->fd_local_sub_index); - } - } - - if (font->data) - free (font->data); - - free (font); -} - -cairo_status_t -_cairo_cff_subset_init (cairo_cff_subset_t *cff_subset, - const char *subset_name, - cairo_scaled_font_subset_t *font_subset) -{ - cairo_cff_font_t *font = NULL; /* squelch bogus compiler warning */ - cairo_status_t status; - const char *data = NULL; /* squelch bogus compiler warning */ - unsigned long length = 0; /* squelch bogus compiler warning */ - unsigned int i; - - status = _cairo_cff_font_create (font_subset, &font, subset_name); - if (status) - return status; - - status = cairo_cff_font_generate (font, &data, &length); - if (status) - goto fail1; - - cff_subset->base_font = strdup (font->font_name); - if (cff_subset->base_font == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto fail1; - } - - cff_subset->widths = calloc (sizeof (int), font->scaled_font_subset->num_glyphs); - if (cff_subset->widths == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto fail2; - } - for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) - cff_subset->widths[i] = font->widths[i]; - - cff_subset->x_min = font->x_min; - cff_subset->y_min = font->y_min; - cff_subset->x_max = font->x_max; - cff_subset->y_max = font->y_max; - cff_subset->ascent = font->ascent; - cff_subset->descent = font->descent; - - cff_subset->data = malloc (length); - if (cff_subset->data == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto fail3; - } - - memcpy (cff_subset->data, data, length); - cff_subset->data_length = length; - - cairo_cff_font_destroy (font); - - return CAIRO_STATUS_SUCCESS; - - fail3: - free (cff_subset->widths); - fail2: - free (cff_subset->base_font); - fail1: - cairo_cff_font_destroy (font); - - return status; -} - -void -_cairo_cff_subset_fini (cairo_cff_subset_t *subset) -{ - free (subset->base_font); - free (subset->widths); - free (subset->data); -} - -static cairo_int_status_t -_cairo_cff_font_fallback_create (cairo_scaled_font_subset_t *scaled_font_subset, - cairo_cff_font_t **font_return, - const char *subset_name) -{ - cairo_status_t status; - cairo_cff_font_t *font; - - font = malloc (sizeof (cairo_cff_font_t)); - if (font == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - font->backend = NULL; - font->scaled_font_subset = scaled_font_subset; - - _cairo_array_init (&font->output, sizeof (char)); - status = _cairo_array_grow_by (&font->output, 4096); - if (status) - goto fail1; - - font->subset_font_name = strdup (subset_name); - if (font->subset_font_name == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto fail1; - } - - font->font_name = strdup (subset_name); - if (font->subset_font_name == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto fail2; - } - - font->x_min = 0; - font->y_min = 0; - font->x_max = 0; - font->y_max = 0; - font->ascent = 0; - font->descent = 0; - - font->widths = calloc (font->scaled_font_subset->num_glyphs, sizeof (int)); - if (font->widths == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto fail3; - } - - font->data_length = 0; - font->data = NULL; - font->data_end = NULL; - - status = cff_dict_init (&font->top_dict); - if (status) - goto fail4; - - status = cff_dict_init (&font->private_dict); - if (status) - goto fail5; - - cff_index_init (&font->strings_index); - cff_index_init (&font->charstrings_index); - cff_index_init (&font->global_sub_index); - cff_index_init (&font->local_sub_index); - cff_index_init (&font->charstrings_subset_index); - cff_index_init (&font->strings_subset_index); - font->fdselect = NULL; - font->fd_dict = NULL; - font->fd_private_dict = NULL; - font->fd_local_sub_index = NULL; - font->fdselect_subset = NULL; - font->fd_subset_map = NULL; - font->private_dict_offset = NULL; - - *font_return = font; - - return CAIRO_STATUS_SUCCESS; - -fail5: - _cairo_hash_table_destroy (font->top_dict); -fail4: - free (font->widths); -fail3: - free (font->font_name); -fail2: - free (font->subset_font_name); -fail1: - _cairo_array_fini (&font->output); - free (font); - return status; -} - -static cairo_int_status_t -cairo_cff_font_fallback_generate (cairo_cff_font_t *font, - cairo_type2_charstrings_t *type2_subset, - const char **data, - unsigned long *length) -{ - cairo_int_status_t status; - cff_header_t header; - cairo_array_t *charstring; - unsigned char buf[40]; - unsigned char *end_buf; - unsigned int i; - - /* Create header */ - header.major = 1; - header.minor = 0; - header.header_size = 4; - header.offset_size = 4; - font->header = &header; - - /* Create Top Dict */ - font->is_cid = FALSE; - end_buf = encode_integer (buf, type2_subset->x_min); - end_buf = encode_integer (end_buf, type2_subset->y_min); - end_buf = encode_integer (end_buf, type2_subset->x_max); - end_buf = encode_integer (end_buf, type2_subset->y_max); - status = cff_dict_set_operands (font->top_dict, - FONTBBOX_OP, buf, end_buf - buf); - if (status) - return status; - - end_buf = encode_integer_max (buf, 0); - status = cff_dict_set_operands (font->top_dict, - CHARSTRINGS_OP, buf, end_buf - buf); - if (status) - return status; - - status = cff_dict_set_operands (font->top_dict, - FDSELECT_OP, buf, end_buf - buf); - if (status) - return status; - - status = cff_dict_set_operands (font->top_dict, - FDARRAY_OP, buf, end_buf - buf); - if (status) - return status; - - status = cff_dict_set_operands (font->top_dict, - CHARSET_OP, buf, end_buf - buf); - if (status) - return status; - - status = cairo_cff_font_set_ros_strings (font); - if (status) - return status; - - /* Create CID FD dictionary */ - status = cairo_cff_font_create_cid_fontdict (font); - if (status) - return status; - - /* Create charstrings */ - for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) { - charstring = _cairo_array_index(&type2_subset->charstrings, i); - - status = cff_index_append (&font->charstrings_subset_index, - _cairo_array_index (charstring, 0), - _cairo_array_num_elements (charstring)); - - if (status) - return status; - } - - status = cairo_cff_font_write_subset (font); - if (status) - return status; - - *data = _cairo_array_index (&font->output, 0); - *length = _cairo_array_num_elements (&font->output); - - return CAIRO_STATUS_SUCCESS; -} - -cairo_status_t -_cairo_cff_fallback_init (cairo_cff_subset_t *cff_subset, - const char *subset_name, - cairo_scaled_font_subset_t *font_subset) -{ - cairo_cff_font_t *font = NULL; /* squelch bogus compiler warning */ - cairo_status_t status; - const char *data = NULL; /* squelch bogus compiler warning */ - unsigned long length = 0; /* squelch bogus compiler warning */ - unsigned int i; - cairo_type2_charstrings_t type2_subset; - - status = _cairo_cff_font_fallback_create (font_subset, &font, subset_name); - if (status) - return status; - - status = _cairo_type2_charstrings_init (&type2_subset, font_subset); - if (status) - goto fail1; - - status = cairo_cff_font_fallback_generate (font, &type2_subset, &data, &length); - if (status) - goto fail2; - - cff_subset->base_font = strdup (font->font_name); - if (cff_subset->base_font == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto fail2; - } - - cff_subset->widths = calloc (sizeof (int), font->scaled_font_subset->num_glyphs); - if (cff_subset->widths == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto fail3; - } - for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) - cff_subset->widths[i] = type2_subset.widths[i]; - - cff_subset->x_min = type2_subset.x_min; - cff_subset->y_min = type2_subset.y_min; - cff_subset->x_max = type2_subset.x_max; - cff_subset->y_max = type2_subset.y_max; - cff_subset->ascent = type2_subset.y_max; - cff_subset->descent = type2_subset.y_min; - - cff_subset->data = malloc (length); - if (cff_subset->data == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto fail4; - } - - memcpy (cff_subset->data, data, length); - cff_subset->data_length = length; - cff_subset->data_length = length; - - _cairo_type2_charstrings_fini (&type2_subset); - cairo_cff_font_destroy (font); - - return CAIRO_STATUS_SUCCESS; - - fail4: - free (cff_subset->widths); - fail3: - free (cff_subset->base_font); - fail2: - _cairo_type2_charstrings_fini (&type2_subset); - fail1: - cairo_cff_font_destroy (font); - - return status; -} - -void -_cairo_cff_fallback_fini (cairo_cff_subset_t *subset) -{ - free (subset->base_font); - free (subset->widths); - free (subset->data); -} - -#endif /* CAIRO_HAS_FONT_SUBSET */ diff --git a/uppdev/plugin/cairo/lib/cairo-clip-private.h b/uppdev/plugin/cairo/lib/cairo-clip-private.h deleted file mode 100644 index 36c0fbdcf..000000000 --- a/uppdev/plugin/cairo/lib/cairo-clip-private.h +++ /dev/null @@ -1,136 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Kristian Høgsberg - */ - -#ifndef CAIRO_CLIP_PRIVATE_H -#define CAIRO_CLIP_PRIVATE_H - -#include "cairo-types-private.h" -#include "cairo-compiler-private.h" -#include "cairo-path-fixed-private.h" -#include "cairo-reference-count-private.h" -#include "cairo-region-private.h" - -extern const cairo_private cairo_rectangle_list_t _cairo_rectangles_nil; - -struct _cairo_clip_path { - cairo_reference_count_t ref_count; - cairo_path_fixed_t path; - cairo_fill_rule_t fill_rule; - double tolerance; - cairo_antialias_t antialias; - cairo_clip_path_t *prev; -}; - -struct _cairo_clip { - cairo_clip_mode_t mode; - - cairo_bool_t all_clipped; - - /* - * Mask-based clipping for cases where the backend - * clipping isn't sufficiently able. - * - * The rectangle here represents the - * portion of the destination surface that this - * clip surface maps to, it does not - * represent the extents of the clip region or - * clip paths - */ - cairo_surface_t *surface; - cairo_rectangle_int_t surface_rect; - /* - * Surface clip serial number to store - * in the surface when this clip is set - */ - unsigned int serial; - /* - * A clip region that can be placed in the surface - */ - cairo_region_t region; - cairo_bool_t has_region; - /* - * If the surface supports path clipping, we store the list of - * clipping paths that has been set here as a linked list. - */ - cairo_clip_path_t *path; -}; - -cairo_private void -_cairo_clip_init (cairo_clip_t *clip, cairo_surface_t *target); - -cairo_private cairo_status_t -_cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other); - -cairo_private cairo_status_t -_cairo_clip_init_deep_copy (cairo_clip_t *clip, - cairo_clip_t *other, - cairo_surface_t *target); - -cairo_private void -_cairo_clip_reset (cairo_clip_t *clip); - -cairo_private cairo_status_t -_cairo_clip_clip (cairo_clip_t *clip, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias, - cairo_surface_t *target); - -cairo_private cairo_status_t -_cairo_clip_intersect_to_rectangle (cairo_clip_t *clip, - cairo_rectangle_int_t *rectangle); - -cairo_private cairo_status_t -_cairo_clip_intersect_to_region (cairo_clip_t *clip, - cairo_region_t *region); - -cairo_private cairo_status_t -_cairo_clip_combine_to_surface (cairo_clip_t *clip, - cairo_operator_t op, - cairo_surface_t *dst, - int dst_x, - int dst_y, - const cairo_rectangle_int_t *extents); - -cairo_private void -_cairo_clip_translate (cairo_clip_t *clip, - cairo_fixed_t tx, - cairo_fixed_t ty); - -cairo_private cairo_rectangle_list_t* -_cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate); - -#endif /* CAIRO_CLIP_PRIVATE_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-clip.c b/uppdev/plugin/cairo/lib/cairo-clip.c deleted file mode 100644 index 8a0d4db15..000000000 --- a/uppdev/plugin/cairo/lib/cairo-clip.c +++ /dev/null @@ -1,858 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - * Kristian Høgsberg - */ - -#include "cairoint.h" -#include "cairo-clip-private.h" - -static cairo_clip_path_t * -_cairo_clip_path_reference (cairo_clip_path_t *clip_path); - -static void -_cairo_clip_path_destroy (cairo_clip_path_t *clip_path); - -void -_cairo_clip_init (cairo_clip_t *clip, cairo_surface_t *target) -{ - if (target) - clip->mode = _cairo_surface_get_clip_mode (target); - else - clip->mode = CAIRO_CLIP_MODE_MASK; - - clip->all_clipped = FALSE; - - clip->surface = NULL; - clip->surface_rect.x = 0; - clip->surface_rect.y = 0; - clip->surface_rect.width = 0; - clip->surface_rect.height = 0; - - clip->serial = 0; - - _cairo_region_init (&clip->region); - clip->has_region = FALSE; - - clip->path = NULL; -} - -cairo_status_t -_cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other) -{ - clip->mode = other->mode; - - clip->all_clipped = other->all_clipped; - - clip->surface = cairo_surface_reference (other->surface); - clip->surface_rect = other->surface_rect; - - clip->serial = other->serial; - - _cairo_region_init (&clip->region); - - if (other->has_region) { - cairo_status_t status; - - status = _cairo_region_copy (&clip->region, &other->region); - if (status) { - _cairo_region_fini (&clip->region); - cairo_surface_destroy (clip->surface); - return status; - } - clip->has_region = TRUE; - } else { - clip->has_region = FALSE; - } - - clip->path = _cairo_clip_path_reference (other->path); - - return CAIRO_STATUS_SUCCESS; -} - -void -_cairo_clip_reset (cairo_clip_t *clip) -{ - clip->all_clipped = FALSE; - - /* destroy any existing clip-region artifacts */ - cairo_surface_destroy (clip->surface); - clip->surface = NULL; - - clip->serial = 0; - - if (clip->has_region) { - /* _cairo_region_fini just releases the resources used but - * doesn't bother with leaving the region in a valid state. - * So _cairo_region_init has to be called afterwards. */ - _cairo_region_fini (&clip->region); - _cairo_region_init (&clip->region); - - clip->has_region = FALSE; - } - - _cairo_clip_path_destroy (clip->path); - clip->path = NULL; -} - -static void -_cairo_clip_set_all_clipped (cairo_clip_t *clip, cairo_surface_t *target) -{ - _cairo_clip_reset (clip); - - clip->all_clipped = TRUE; - clip->serial = _cairo_surface_allocate_clip_serial (target); -} - - -static cairo_status_t -_cairo_clip_path_intersect_to_rectangle (cairo_clip_path_t *clip_path, - cairo_rectangle_int_t *rectangle) -{ - while (clip_path) { - cairo_status_t status; - cairo_traps_t traps; - cairo_box_t extents; - cairo_rectangle_int_t extents_rect; - - _cairo_box_from_rectangle (&extents, rectangle); - - _cairo_traps_init (&traps); - _cairo_traps_limit (&traps, &extents); - - status = _cairo_path_fixed_fill_to_traps (&clip_path->path, - clip_path->fill_rule, - clip_path->tolerance, - &traps); - if (status) { - _cairo_traps_fini (&traps); - return status; - } - - _cairo_traps_extents (&traps, &extents); - _cairo_traps_fini (&traps); - - _cairo_box_round_to_rectangle (&extents, &extents_rect); - if (! _cairo_rectangle_intersect (rectangle, &extents_rect)) - return CAIRO_STATUS_SUCCESS; - - clip_path = clip_path->prev; - } - - return CAIRO_STATUS_SUCCESS; -} - -cairo_status_t -_cairo_clip_intersect_to_rectangle (cairo_clip_t *clip, - cairo_rectangle_int_t *rectangle) -{ - cairo_status_t status; - cairo_bool_t is_empty; - - if (!clip) - return CAIRO_STATUS_SUCCESS; - - if (clip->all_clipped) { - *rectangle = clip->surface_rect; - return CAIRO_STATUS_SUCCESS; - } - - if (clip->path) { - status = _cairo_clip_path_intersect_to_rectangle (clip->path, - rectangle); - if (status) - return status; - } - - if (clip->has_region) { - cairo_region_t intersection; - - _cairo_region_init_rect (&intersection, rectangle); - - status = _cairo_region_intersect (&intersection, &clip->region, - &intersection); - - if (!status) - _cairo_region_get_extents (&intersection, rectangle); - - _cairo_region_fini (&intersection); - - if (status) - return status; - } - - if (clip->surface) - is_empty = _cairo_rectangle_intersect (rectangle, &clip->surface_rect); - - return CAIRO_STATUS_SUCCESS; -} - -cairo_status_t -_cairo_clip_intersect_to_region (cairo_clip_t *clip, - cairo_region_t *region) -{ - cairo_status_t status; - - if (!clip) - return CAIRO_STATUS_SUCCESS; - - if (clip->all_clipped) { - cairo_region_t clip_rect; - - _cairo_region_init_rect (&clip_rect, &clip->surface_rect); - - status = _cairo_region_intersect (region, &clip_rect, region); - - _cairo_region_fini (&clip_rect); - - return status; - } - - if (clip->path) { - /* Intersect clip path into region. */ - } - - if (clip->has_region) { - status = _cairo_region_intersect (region, &clip->region, region); - if (status) - return status; - } - - if (clip->surface) { - cairo_region_t clip_rect; - - _cairo_region_init_rect (&clip_rect, &clip->surface_rect); - - status = _cairo_region_intersect (region, &clip_rect, region); - - _cairo_region_fini (&clip_rect); - - if (status) - return status; - } - - return CAIRO_STATUS_SUCCESS; -} - -/* Combines the region of clip->surface given by extents in - * device backend coordinates into the given temporary surface, - * which has its origin at dst_x, dst_y in backend coordinates - */ -cairo_status_t -_cairo_clip_combine_to_surface (cairo_clip_t *clip, - cairo_operator_t op, - cairo_surface_t *dst, - int dst_x, - int dst_y, - const cairo_rectangle_int_t *extents) -{ - cairo_surface_pattern_t pattern; - cairo_status_t status; - - if (clip->all_clipped) - return CAIRO_STATUS_SUCCESS; - - _cairo_pattern_init_for_surface (&pattern, clip->surface); - - status = _cairo_surface_composite (op, - &pattern.base, - NULL, - dst, - extents->x - clip->surface_rect.x, - extents->y - clip->surface_rect.y, - 0, 0, - extents->x - dst_x, - extents->y - dst_y, - extents->width, extents->height); - - _cairo_pattern_fini (&pattern.base); - - return status; -} - -static cairo_status_t -_cairo_clip_intersect_path (cairo_clip_t *clip, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_clip_path_t *clip_path; - cairo_status_t status; - - if (clip->mode != CAIRO_CLIP_MODE_PATH) - return CAIRO_INT_STATUS_UNSUPPORTED; - - clip_path = malloc (sizeof (cairo_clip_path_t)); - if (clip_path == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - status = _cairo_path_fixed_init_copy (&clip_path->path, path); - if (status) { - free (clip_path); - return status; - } - - CAIRO_REFERENCE_COUNT_INIT (&clip_path->ref_count, 1); - clip_path->fill_rule = fill_rule; - clip_path->tolerance = tolerance; - clip_path->antialias = antialias; - clip_path->prev = clip->path; - clip->path = clip_path; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_clip_path_t * -_cairo_clip_path_reference (cairo_clip_path_t *clip_path) -{ - if (clip_path == NULL) - return NULL; - - assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&clip_path->ref_count)); - - _cairo_reference_count_inc (&clip_path->ref_count); - - return clip_path; -} - -static void -_cairo_clip_path_destroy (cairo_clip_path_t *clip_path) -{ - if (clip_path == NULL) - return; - - assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&clip_path->ref_count)); - - if (! _cairo_reference_count_dec_and_test (&clip_path->ref_count)) - return; - - _cairo_path_fixed_fini (&clip_path->path); - _cairo_clip_path_destroy (clip_path->prev); - free (clip_path); -} - - -static cairo_int_status_t -_cairo_clip_intersect_region (cairo_clip_t *clip, - cairo_traps_t *traps, - cairo_surface_t *target) -{ - cairo_region_t region; - cairo_int_status_t status; - - if (clip->all_clipped) - return CAIRO_STATUS_SUCCESS; - - if (clip->mode != CAIRO_CLIP_MODE_REGION) - return CAIRO_INT_STATUS_UNSUPPORTED; - - status = _cairo_traps_extract_region (traps, ®ion); - - if (status) - return status; - - if (!clip->has_region) { - status = _cairo_region_copy (&clip->region, ®ion); - if (status == CAIRO_STATUS_SUCCESS) - clip->has_region = TRUE; - } else { - cairo_region_t intersection; - - _cairo_region_init (&intersection); - - status = _cairo_region_intersect (&intersection, - &clip->region, - ®ion); - - if (status == CAIRO_STATUS_SUCCESS) - status = _cairo_region_copy (&clip->region, &intersection); - - _cairo_region_fini (&intersection); - } - - clip->serial = _cairo_surface_allocate_clip_serial (target); - _cairo_region_fini (®ion); - - if (! _cairo_region_not_empty (&clip->region)) - _cairo_clip_set_all_clipped (clip, target); - - return status; -} - -static cairo_status_t -_cairo_clip_intersect_mask (cairo_clip_t *clip, - cairo_traps_t *traps, - cairo_antialias_t antialias, - cairo_surface_t *target) -{ - cairo_pattern_union_t pattern; - cairo_box_t extents; - cairo_rectangle_int_t surface_rect, target_rect; - cairo_surface_t *surface = NULL; - cairo_status_t status; - - if (clip->all_clipped) - return CAIRO_STATUS_SUCCESS; - - /* Represent the clip as a mask surface. We create a new surface - * the size of the intersection of the old mask surface and the - * extents of the new clip path. */ - - _cairo_traps_extents (traps, &extents); - _cairo_box_round_to_rectangle (&extents, &surface_rect); - - if (clip->surface != NULL) { - if (! _cairo_rectangle_intersect (&surface_rect, &clip->surface_rect)) - goto DONE; - } - - /* Intersect with the target surface rectangle so we don't use - * more memory and time than we need to. */ - status = _cairo_surface_get_extents (target, &target_rect); - if (status == CAIRO_STATUS_SUCCESS) { - if (! _cairo_rectangle_intersect (&surface_rect, &target_rect)) - goto DONE; - } - - if (surface_rect.width == 0 || surface_rect.height == 0) - goto DONE; - - _cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE, - CAIRO_CONTENT_COLOR); - /* The clipping operation should ideally be something like the following to - * avoid having to do as many passes over the data - - if (clip->surface != NULL) { - _cairo_pattern_init_for_surface (&pattern.surface, clip->surface); - } else { - _cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE, - CAIRO_CONTENT_COLOR); - } - status = _cairo_surface_composite_trapezoids (CAIRO_OPERATOR_IN, - &pattern.base, - surface, - antialias, - 0, 0, - 0, 0, - surface_rect.width, - surface_rect.height, - traps->traps, - traps->num_traps); - - However this operation is not accelerated by pixman - - I believe the best possible operation would probably an unbounded SRC - operator. Using SRC we could potentially avoid having to initialize - the surface which would be ideal from an efficiency point of view. - However, _cairo_surface_composite_trapezoids (CAIRO_OPERATOR_SOURCE) is - bounded by the mask. - - */ - - surface = _cairo_surface_create_similar_solid (target, - CAIRO_CONTENT_ALPHA, - surface_rect.width, - surface_rect.height, - CAIRO_COLOR_TRANSPARENT); - if (surface->status) { - _cairo_pattern_fini (&pattern.base); - return surface->status; - } - - /* Render the new clipping path into the new mask surface. */ - - _cairo_traps_translate (traps, -surface_rect.x, -surface_rect.y); - - status = _cairo_surface_composite_trapezoids (CAIRO_OPERATOR_ADD, - &pattern.base, - surface, - antialias, - 0, 0, - 0, 0, - surface_rect.width, - surface_rect.height, - traps->traps, - traps->num_traps); - - _cairo_pattern_fini (&pattern.base); - - if (status) { - cairo_surface_destroy (surface); - return status; - } - - /* If there was a clip surface already, combine it with the new - * mask surface using the IN operator, so we get the intersection - * of the old and new clipping paths. */ - - if (clip->surface != NULL) { - _cairo_pattern_init_for_surface (&pattern.surface, clip->surface); - - status = _cairo_surface_composite (CAIRO_OPERATOR_IN, - &pattern.base, - NULL, - surface, - surface_rect.x - clip->surface_rect.x, - surface_rect.y - clip->surface_rect.y, - 0, 0, - 0, 0, - surface_rect.width, - surface_rect.height); - - _cairo_pattern_fini (&pattern.base); - - if (status) { - cairo_surface_destroy (surface); - return status; - } - } - - DONE: - cairo_surface_destroy (clip->surface); - clip->surface = surface; - clip->surface_rect = surface_rect; - clip->serial = _cairo_surface_allocate_clip_serial (target); - - if (surface_rect.width == 0 || surface_rect.height == 0) - _cairo_clip_set_all_clipped (clip, target); - - return status; -} - -cairo_status_t -_cairo_clip_clip (cairo_clip_t *clip, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias, - cairo_surface_t *target) -{ - cairo_status_t status; - cairo_rectangle_int_t rectangle; - cairo_traps_t traps; - - if (clip->all_clipped) - return CAIRO_STATUS_SUCCESS; - - /* catch the empty clip path */ - if (! path->has_current_point) { - _cairo_clip_set_all_clipped (clip, target); - return CAIRO_STATUS_SUCCESS; - } - - status = _cairo_clip_intersect_path (clip, - path, fill_rule, tolerance, - antialias); - if (status == CAIRO_STATUS_SUCCESS) - clip->serial = _cairo_surface_allocate_clip_serial (target); - - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - - _cairo_traps_init (&traps); - - /* Limit the traps to the target surface - * - so we don't add more traps than needed. */ - status = _cairo_surface_get_extents (target, &rectangle); - if (status == CAIRO_STATUS_SUCCESS) { - cairo_box_t box; - - _cairo_box_from_rectangle (&box, &rectangle); - _cairo_traps_limit (&traps, &box); - } - - status = _cairo_path_fixed_fill_to_traps (path, - fill_rule, - tolerance, - &traps); - if (status) - goto bail; - - status = _cairo_clip_intersect_region (clip, &traps, target); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - goto bail; - - status = _cairo_clip_intersect_mask (clip, &traps, antialias, target); - - bail: - _cairo_traps_fini (&traps); - - return status; -} - -void -_cairo_clip_translate (cairo_clip_t *clip, - cairo_fixed_t tx, - cairo_fixed_t ty) -{ - if (clip->all_clipped) - return; - - if (clip->has_region) { - _cairo_region_translate (&clip->region, - _cairo_fixed_integer_part (tx), - _cairo_fixed_integer_part (ty)); - } - - if (clip->surface) { - clip->surface_rect.x += _cairo_fixed_integer_part (tx); - clip->surface_rect.y += _cairo_fixed_integer_part (ty); - } - - if (clip->path) { - cairo_clip_path_t *clip_path = clip->path; - cairo_matrix_t matrix; - - cairo_matrix_init_translate (&matrix, - _cairo_fixed_to_double (tx), - _cairo_fixed_to_double (ty)); - - while (clip_path) { - _cairo_path_fixed_transform (&clip_path->path, &matrix); - clip_path = clip_path->prev; - } - } -} - -static cairo_status_t -_cairo_clip_path_reapply_clip_path (cairo_clip_t *clip, - cairo_clip_path_t *clip_path) -{ - cairo_status_t status; - - if (clip_path->prev) { - status = _cairo_clip_path_reapply_clip_path (clip, clip_path->prev); - if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - } - - return _cairo_clip_intersect_path (clip, - &clip_path->path, - clip_path->fill_rule, - clip_path->tolerance, - clip_path->antialias); -} - -cairo_status_t -_cairo_clip_init_deep_copy (cairo_clip_t *clip, - cairo_clip_t *other, - cairo_surface_t *target) -{ - cairo_status_t status; - - _cairo_clip_init (clip, target); - - if (other->mode != clip->mode) { - /* We should reapply the original clip path in this case, and let - * whatever the right handling is happen */ - } else { - if (other->has_region) { - status = _cairo_region_copy (&clip->region, &other->region); - if (status) - goto BAIL; - - clip->has_region = TRUE; - } - - if (other->surface) { - int dx, dy; - status = _cairo_surface_clone_similar (target, other->surface, - 0, - 0, - other->surface_rect.width, - other->surface_rect.height, - &dx, &dy, - &clip->surface); - if (status) - goto BAIL; - - clip->surface_rect = other->surface_rect; - - /* src offset was 0, so we expect an exact replica of the surface */ - assert (dx == 0); - assert (dy == 0); - } - - if (other->path) { - status = _cairo_clip_path_reapply_clip_path (clip, other->path); - if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) - goto BAIL; - } - } - - return CAIRO_STATUS_SUCCESS; - -BAIL: - if (clip->has_region) - _cairo_region_fini (&clip->region); - if (clip->surface) - cairo_surface_destroy (clip->surface); - - return status; -} - -const cairo_rectangle_list_t _cairo_rectangles_nil = - { CAIRO_STATUS_NO_MEMORY, NULL, 0 }; -static const cairo_rectangle_list_t _cairo_rectangles_not_representable = - { CAIRO_STATUS_CLIP_NOT_REPRESENTABLE, NULL, 0 }; - -static cairo_bool_t -_cairo_clip_int_rect_to_user (cairo_gstate_t *gstate, - cairo_rectangle_int_t *clip_rect, - cairo_rectangle_t *user_rect) -{ - cairo_bool_t is_tight; - - double x1 = clip_rect->x; - double y1 = clip_rect->y; - double x2 = clip_rect->x + (int) clip_rect->width; - double y2 = clip_rect->y + (int) clip_rect->height; - - _cairo_gstate_backend_to_user_rectangle (gstate, - &x1, &y1, &x2, &y2, - &is_tight); - - user_rect->x = x1; - user_rect->y = y1; - user_rect->width = x2 - x1; - user_rect->height = y2 - y1; - - return is_tight; -} - -cairo_rectangle_list_t * -_cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate) -{ - cairo_rectangle_list_t *list; - cairo_rectangle_t *rectangles = NULL; - int n_boxes = 0; - - if (clip->all_clipped) - goto DONE; - - if (clip->path || clip->surface) { - _cairo_error_throw (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE); - return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable; - } - - if (clip->has_region) { - cairo_box_int_t *boxes; - int i; - - if (_cairo_region_get_boxes (&clip->region, &n_boxes, &boxes)) - return (cairo_rectangle_list_t*) &_cairo_rectangles_nil; - - if (n_boxes) { - rectangles = _cairo_malloc_ab (n_boxes, sizeof (cairo_rectangle_t)); - if (rectangles == NULL) { - _cairo_region_boxes_fini (&clip->region, boxes); - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_rectangle_list_t*) &_cairo_rectangles_nil; - } - - for (i = 0; i < n_boxes; ++i) { - cairo_rectangle_int_t clip_rect; - - clip_rect.x = boxes[i].p1.x; - clip_rect.y = boxes[i].p1.y; - clip_rect.width = boxes[i].p2.x - boxes[i].p1.x; - clip_rect.height = boxes[i].p2.y - boxes[i].p1.y; - - if (!_cairo_clip_int_rect_to_user(gstate, &clip_rect, &rectangles[i])) { - _cairo_error_throw (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE); - _cairo_region_boxes_fini (&clip->region, boxes); - free (rectangles); - return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable; - } - } - } - - _cairo_region_boxes_fini (&clip->region, boxes); - } else { - cairo_rectangle_int_t extents; - - n_boxes = 1; - - rectangles = malloc(sizeof (cairo_rectangle_t)); - if (rectangles == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_rectangle_list_t*) &_cairo_rectangles_nil; - } - - if (_cairo_surface_get_extents (_cairo_gstate_get_target (gstate), &extents) || - !_cairo_clip_int_rect_to_user(gstate, &extents, rectangles)) - { - _cairo_error_throw (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE); - free (rectangles); - return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable; - } - } - - DONE: - list = malloc (sizeof (cairo_rectangle_list_t)); - if (list == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - free (rectangles); - return (cairo_rectangle_list_t*) &_cairo_rectangles_nil; - } - - list->status = CAIRO_STATUS_SUCCESS; - list->rectangles = rectangles; - list->num_rectangles = n_boxes; - return list; -} - -/** - * cairo_rectangle_list_destroy: - * @rectangle_list: a rectangle list, as obtained from cairo_copy_clip_rectangles() - * - * Unconditionally frees @rectangle_list and all associated - * references. After this call, the @rectangle_list pointer must not - * be dereferenced. - * - * Since: 1.4 - **/ -void -cairo_rectangle_list_destroy (cairo_rectangle_list_t *rectangle_list) -{ - if (rectangle_list == NULL || rectangle_list == &_cairo_rectangles_nil || - rectangle_list == &_cairo_rectangles_not_representable) - return; - - free (rectangle_list->rectangles); - free (rectangle_list); -} diff --git a/uppdev/plugin/cairo/lib/cairo-color.c b/uppdev/plugin/cairo/lib/cairo-color.c deleted file mode 100644 index 7640bf436..000000000 --- a/uppdev/plugin/cairo/lib/cairo-color.c +++ /dev/null @@ -1,175 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - */ - -#include "cairoint.h" - -static cairo_color_t const cairo_color_white = { - 1.0, 1.0, 1.0, 1.0, - 0xffff, 0xffff, 0xffff, 0xffff -}; - -static cairo_color_t const cairo_color_black = { - 0.0, 0.0, 0.0, 1.0, - 0x0, 0x0, 0x0, 0xffff -}; - -static cairo_color_t const cairo_color_transparent = { - 0.0, 0.0, 0.0, 0.0, - 0x0, 0x0, 0x0, 0x0 -}; - -static cairo_color_t const cairo_color_magenta = { - 1.0, 0.0, 1.0, 1.0, - 0xffff, 0x0, 0xffff, 0xffff -}; - -const cairo_color_t * -_cairo_stock_color (cairo_stock_t stock) -{ - switch (stock) { - case CAIRO_STOCK_WHITE: - return &cairo_color_white; - case CAIRO_STOCK_BLACK: - return &cairo_color_black; - case CAIRO_STOCK_TRANSPARENT: - return &cairo_color_transparent; - } - - ASSERT_NOT_REACHED; - - /* If the user can get here somehow, give a color that indicates a - * problem. */ - return &cairo_color_magenta; -} - -void -_cairo_color_init (cairo_color_t *color) -{ - *color = cairo_color_white; -} - -void -_cairo_color_init_rgb (cairo_color_t *color, - double red, double green, double blue) -{ - _cairo_color_init_rgba (color, red, green, blue, 1.0); -} - -/* 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. - */ -uint16_t -_cairo_color_double_to_short (double d) -{ - uint32_t i; - i = (uint32_t) (d * 65536); - i -= (i >> 16); - return i; -} - -static void -_cairo_color_compute_shorts (cairo_color_t *color) -{ - color->red_short = _cairo_color_double_to_short (color->red * color->alpha); - color->green_short = _cairo_color_double_to_short (color->green * color->alpha); - color->blue_short = _cairo_color_double_to_short (color->blue * color->alpha); - color->alpha_short = _cairo_color_double_to_short (color->alpha); -} - -void -_cairo_color_init_rgba (cairo_color_t *color, - double red, double green, double blue, - double alpha) -{ - color->red = red; - color->green = green; - color->blue = blue; - color->alpha = alpha; - - _cairo_color_compute_shorts (color); -} - -void -_cairo_color_multiply_alpha (cairo_color_t *color, - double alpha) -{ - color->alpha *= alpha; - - _cairo_color_compute_shorts (color); -} - -void -_cairo_color_get_rgba (cairo_color_t *color, - double *red, - double *green, - double *blue, - double *alpha) -{ - *red = color->red; - *green = color->green; - *blue = color->blue; - *alpha = color->alpha; -} - -void -_cairo_color_get_rgba_premultiplied (cairo_color_t *color, - double *red, - double *green, - double *blue, - double *alpha) -{ - *red = color->red * color->alpha; - *green = color->green * color->alpha; - *blue = color->blue * color->alpha; - *alpha = color->alpha; -} - -cairo_bool_t -_cairo_color_equal (const cairo_color_t *color_a, - const cairo_color_t *color_b) -{ - if (color_a == color_b) - return TRUE; - - return color_a->red_short == color_b->red_short && - color_a->green_short == color_b->green_short && - color_a->blue_short == color_b->blue_short && - color_a->alpha_short == color_b->alpha_short; -} diff --git a/uppdev/plugin/cairo/lib/cairo-compiler-private.h b/uppdev/plugin/cairo/lib/cairo-compiler-private.h deleted file mode 100644 index b93fd8298..000000000 --- a/uppdev/plugin/cairo/lib/cairo-compiler-private.h +++ /dev/null @@ -1,162 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - */ - -#ifndef CAIRO_COMPILER_PRIVATE_H -#define CAIRO_COMPILER_PRIVATE_H - -#include "cairo.h" - -#if HAVE_CONFIG_H -#include "config.h" -#endif - -#if __GNUC__ >= 3 && defined(__ELF__) && !defined(__sun) -# define slim_hidden_proto(name) slim_hidden_proto1(name, slim_hidden_int_name(name)) cairo_private -# define slim_hidden_proto_no_warn(name) slim_hidden_proto1(name, slim_hidden_int_name(name)) cairo_private_no_warn -# define slim_hidden_def(name) slim_hidden_def1(name, slim_hidden_int_name(name)) -# define slim_hidden_int_name(name) INT_##name -# define slim_hidden_proto1(name, internal) \ - extern __typeof (name) name \ - __asm__ (slim_hidden_asmname (internal)) -# define slim_hidden_def1(name, internal) \ - extern __typeof (name) EXT_##name __asm__(slim_hidden_asmname(name)) \ - __attribute__((__alias__(slim_hidden_asmname(internal)))) -# define slim_hidden_ulp slim_hidden_ulp1(__USER_LABEL_PREFIX__) -# define slim_hidden_ulp1(x) slim_hidden_ulp2(x) -# define slim_hidden_ulp2(x) #x -# define slim_hidden_asmname(name) slim_hidden_asmname1(name) -# define slim_hidden_asmname1(name) slim_hidden_ulp #name -#else -# define slim_hidden_proto(name) int _cairo_dummy_prototype(void) -# define slim_hidden_proto_no_warn(name) int _cairo_dummy_prototype(void) -# define slim_hidden_def(name) int _cairo_dummy_prototype(void) -#endif - -#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4) -#define CAIRO_PRINTF_FORMAT(fmt_index, va_index) \ - __attribute__((__format__(__printf__, fmt_index, va_index))) -#else -#define CAIRO_PRINTF_FORMAT(fmt_index, va_index) -#endif - -/* slim_internal.h */ -#define CAIRO_HAS_HIDDEN_SYMBOLS 1 -#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) && defined(__ELF__) && !defined(__sun) -#define cairo_private_no_warn __attribute__((__visibility__("hidden"))) -#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550) -#define cairo_private_no_warn __hidden -#else /* not gcc >= 3.3 and not Sun Studio >= 8 */ -#define cairo_private_no_warn -#undef CAIRO_HAS_HIDDEN_SYMBOLS -#endif - -#ifndef WARN_UNUSED_RESULT -#define WARN_UNUSED_RESULT -#endif -/* Add attribute(warn_unused_result) if supported */ -#define cairo_warn WARN_UNUSED_RESULT -#define cairo_private cairo_private_no_warn cairo_warn - -/* This macro allow us to deprecate a function by providing an alias - for the old function name to the new function name. With this - macro, binary compatibility is preserved. The macro only works on - some platforms --- tough. - - Meanwhile, new definitions in the public header file break the - source code so that it will no longer link against the old - symbols. Instead it will give a descriptive error message - indicating that the old function has been deprecated by the new - function. -*/ -#if __GNUC__ >= 2 && defined(__ELF__) -# define CAIRO_FUNCTION_ALIAS(old, new) \ - extern __typeof (new) old \ - __asm__ ("" #old) \ - __attribute__((__alias__("" #new))) -#else -# define CAIRO_FUNCTION_ALIAS(old, new) -#endif - -/* - * Cairo uses the following function attributes in order to improve the - * generated code (effectively by manual inter-procedural analysis). - * - * 'cairo_pure': The function is only allowed to read from its arguments - * and global memory (i.e. following a pointer argument or - * accessing a shared variable). The return value should - * only depend on its arguments, and for an identical set of - * arguments should return the same value. - * - * 'cairo_const': The function is only allowed to read from its arguments. - * It is not allowed to access global memory. The return - * value should only depend its arguments, and for an - * identical set of arguments should return the same value. - * This is currently the most strict function attribute. - * - * Both these function attributes allow gcc to perform CSE and - * constant-folding, with 'cairo_const 'also guaranteeing that pointer contents - * do not change across the function call. - */ -#if __GNUC__ >= 3 -#define cairo_pure __attribute__((pure)) -#define cairo_const __attribute__((const)) -#else -#define cairo_pure -#define cairo_const -#endif - -#ifndef __GNUC__ -#undef __attribute__ -#define __attribute__(x) -#endif - -#if (defined(__WIN32__) && !defined(__WINE__)) || defined(_MSC_VER) -#define snprintf _snprintf -#define popen _popen -#endif - -#ifdef _MSC_VER -#undef inline -#define inline __inline -#endif - -#ifdef __STRICT_ANSI__ -#undef inline -#define inline __inline__ -#endif - -#endif diff --git a/uppdev/plugin/cairo/lib/cairo-debug.c b/uppdev/plugin/cairo/lib/cairo-debug.c deleted file mode 100644 index 61156f0d9..000000000 --- a/uppdev/plugin/cairo/lib/cairo-debug.c +++ /dev/null @@ -1,75 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Carl D. Worth - */ - -#include "cairoint.h" - -/** - * cairo_debug_reset_static_data: - * - * Resets all static data within cairo to its original state, - * (ie. identical to the state at the time of program invocation). For - * example, all caches within cairo will be flushed empty. - * - * This function is intended to be useful when using memory-checking - * tools such as valgrind. When valgrind's memcheck analyzes a - * cairo-using program without a call to cairo_debug_reset_static_data(), - * it will report all data reachable via cairo's static objects as - * "still reachable". Calling cairo_debug_reset_static_data() just prior - * to program termination will make it easier to get squeaky clean - * reports from valgrind. - * - * WARNING: It is only safe to call this function when there are no - * active cairo objects remaining, (ie. the appropriate destroy - * functions have been called as necessary). If there are active cairo - * objects, this call is likely to cause a crash, (eg. an assertion - * failure due to a hash table being destroyed when non-empty). - **/ -void -cairo_debug_reset_static_data (void) -{ - CAIRO_MUTEX_INITIALIZE (); - - _cairo_font_face_reset_static_data (); - -#if CAIRO_HAS_FT_FONT - _cairo_ft_font_reset_static_data (); -#endif - - _cairo_scaled_font_reset_static_data (); - - _cairo_pattern_reset_static_data (); - - CAIRO_MUTEX_FINALIZE (); -} diff --git a/uppdev/plugin/cairo/lib/cairo-deflate-stream.c b/uppdev/plugin/cairo/lib/cairo-deflate-stream.c deleted file mode 100644 index bf2784a20..000000000 --- a/uppdev/plugin/cairo/lib/cairo-deflate-stream.c +++ /dev/null @@ -1,149 +0,0 @@ -/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2006 Adrian Johnson - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Adrian Johnson. - * - * Author(s): - * Adrian Johnson - */ - -#include "cairoint.h" -#include "cairo-output-stream-private.h" -#include - -#define BUFFER_SIZE 16384 - -typedef struct _cairo_deflate_stream { - cairo_output_stream_t base; - cairo_output_stream_t *output; - z_stream zlib_stream; - unsigned char input_buf[BUFFER_SIZE]; - unsigned char output_buf[BUFFER_SIZE]; -} cairo_deflate_stream_t; - -static void -cairo_deflate_stream_deflate (cairo_deflate_stream_t *stream, cairo_bool_t flush) -{ - int ret; - cairo_bool_t finished; - - do { - ret = deflate (&stream->zlib_stream, flush ? Z_FINISH : Z_NO_FLUSH); - if (flush || stream->zlib_stream.avail_out == 0) - { - _cairo_output_stream_write (stream->output, - stream->output_buf, - BUFFER_SIZE - stream->zlib_stream.avail_out); - stream->zlib_stream.next_out = stream->output_buf; - stream->zlib_stream.avail_out = BUFFER_SIZE; - } - - finished = TRUE; - if (stream->zlib_stream.avail_in != 0) - finished = FALSE; - if (flush && ret != Z_STREAM_END) - finished = FALSE; - - } while (!finished); - - stream->zlib_stream.next_in = stream->input_buf; -} - -static cairo_status_t -_cairo_deflate_stream_write (cairo_output_stream_t *base, - const unsigned char *data, - unsigned int length) -{ - cairo_deflate_stream_t *stream = (cairo_deflate_stream_t *) base; - unsigned int count; - const unsigned char *p = data; - - while (length) { - count = length; - if (count > BUFFER_SIZE - stream->zlib_stream.avail_in) - count = BUFFER_SIZE - stream->zlib_stream.avail_in; - memcpy (stream->input_buf + stream->zlib_stream.avail_in, p, count); - p += count; - stream->zlib_stream.avail_in += count; - length -= count; - - if (stream->zlib_stream.avail_in == BUFFER_SIZE) - cairo_deflate_stream_deflate (stream, FALSE); - } - - return _cairo_output_stream_get_status (stream->output); -} - -static cairo_status_t -_cairo_deflate_stream_close (cairo_output_stream_t *base) -{ - cairo_deflate_stream_t *stream = (cairo_deflate_stream_t *) base; - - cairo_deflate_stream_deflate (stream, TRUE); - deflateEnd (&stream->zlib_stream); - - return _cairo_output_stream_get_status (stream->output); -} - -cairo_output_stream_t * -_cairo_deflate_stream_create (cairo_output_stream_t *output) -{ - cairo_deflate_stream_t *stream; - - if (output->status) - return _cairo_output_stream_create_in_error (output->status); - - stream = malloc (sizeof (cairo_deflate_stream_t)); - if (stream == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_output_stream_t *) &_cairo_output_stream_nil; - } - - _cairo_output_stream_init (&stream->base, - _cairo_deflate_stream_write, - _cairo_deflate_stream_close); - stream->output = output; - - stream->zlib_stream.zalloc = Z_NULL; - stream->zlib_stream.zfree = Z_NULL; - stream->zlib_stream.opaque = Z_NULL; - - if (deflateInit (&stream->zlib_stream, Z_DEFAULT_COMPRESSION) != Z_OK) { - free (stream); - return (cairo_output_stream_t *) &_cairo_output_stream_nil; - } - - stream->zlib_stream.next_in = stream->input_buf; - stream->zlib_stream.avail_in = 0; - stream->zlib_stream.next_out = stream->output_buf; - stream->zlib_stream.avail_out = BUFFER_SIZE; - - return &stream->base; -} diff --git a/uppdev/plugin/cairo/lib/cairo-deprecated.h b/uppdev/plugin/cairo/lib/cairo-deprecated.h deleted file mode 100644 index b59ea643a..000000000 --- a/uppdev/plugin/cairo/lib/cairo-deprecated.h +++ /dev/null @@ -1,138 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2006 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Carl D. Worth - */ - -#ifndef CAIRO_DEPRECATED_H -#define CAIRO_DEPRECATED_H - -/* The %CAIRO_FORMAT_RGB16_565 value was added in cairo 1.2.0 as part - * of fixing cairo's xlib backend to work with X servers advertising a - * 16-bit, 565 visual. But as it turned out, adding this format to - * #cairo_format_t was not necessary, and was a mistake, (cairo's xlib - * backend can work fine with 16-bit visuals in the same way it works - * with BGR visuals without any BGR formats in - * #cairo_format_t). - * - * Additionally, the support for the RGB16_565 format was never - * completely implemented. So while this format value is currently - * deprecated, it may eventually acquire complete support in the future. - */ -#define CAIRO_FORMAT_RGB16_565 4 - -#define CAIRO_FONT_TYPE_ATSUI CAIRO_FONT_TYPE_QUARTZ - -/* Obsolete functions. These definitions exist to coerce the compiler - * into providing a little bit of guidance with its error - * messages. The idea is to help users port their old code without - * having to dig through lots of documentation. - * - * The first set of REPLACED_BY functions is for functions whose names - * have just been changed. So fixing these up is mechanical, (and - * automated by means of the cairo/util/cairo-api-update script. - * - * The second set of DEPRECATED_BY functions is for functions where - * the replacement is used in a different way, (ie. different - * arguments, multiple functions instead of one, etc). Fixing these up - * will require a bit more work on the user's part, (and hopefully we - * can get cairo-api-update to find these and print some guiding - * information). - */ -#define cairo_current_font_extents cairo_current_font_extents_REPLACED_BY_cairo_font_extents -#define cairo_get_font_extents cairo_get_font_extents_REPLACED_BY_cairo_font_extents -#define cairo_current_operator cairo_current_operator_REPLACED_BY_cairo_get_operator -#define cairo_current_tolerance cairo_current_tolerance_REPLACED_BY_cairo_get_tolerance -#define cairo_current_point cairo_current_point_REPLACED_BY_cairo_get_current_point -#define cairo_current_fill_rule cairo_current_fill_rule_REPLACED_BY_cairo_get_fill_rule -#define cairo_current_line_width cairo_current_line_width_REPLACED_BY_cairo_get_line_width -#define cairo_current_line_cap cairo_current_line_cap_REPLACED_BY_cairo_get_line_cap -#define cairo_current_line_join cairo_current_line_join_REPLACED_BY_cairo_get_line_join -#define cairo_current_miter_limit cairo_current_miter_limit_REPLACED_BY_cairo_get_miter_limit -#define cairo_current_matrix cairo_current_matrix_REPLACED_BY_cairo_get_matrix -#define cairo_current_target_surface cairo_current_target_surface_REPLACED_BY_cairo_get_target -#define cairo_get_status cairo_get_status_REPLACED_BY_cairo_status -#define cairo_concat_matrix cairo_concat_matrix_REPLACED_BY_cairo_transform -#define cairo_scale_font cairo_scale_font_REPLACED_BY_cairo_set_font_size -#define cairo_select_font cairo_select_font_REPLACED_BY_cairo_select_font_face -#define cairo_transform_font cairo_transform_font_REPLACED_BY_cairo_set_font_matrix -#define cairo_transform_point cairo_transform_point_REPLACED_BY_cairo_user_to_device -#define cairo_transform_distance cairo_transform_distance_REPLACED_BY_cairo_user_to_device_distance -#define cairo_inverse_transform_point cairo_inverse_transform_point_REPLACED_BY_cairo_device_to_user -#define cairo_inverse_transform_distance cairo_inverse_transform_distance_REPLACED_BY_cairo_device_to_user_distance -#define cairo_init_clip cairo_init_clip_REPLACED_BY_cairo_reset_clip -#define cairo_surface_create_for_image cairo_surface_create_for_image_REPLACED_BY_cairo_image_surface_create_for_data -#define cairo_default_matrix cairo_default_matrix_REPLACED_BY_cairo_identity_matrix -#define cairo_matrix_set_affine cairo_matrix_set_affine_REPLACED_BY_cairo_matrix_init -#define cairo_matrix_set_identity cairo_matrix_set_identity_REPLACED_BY_cairo_matrix_init_identity -#define cairo_pattern_add_color_stop cairo_pattern_add_color_stop_REPLACED_BY_cairo_pattern_add_color_stop_rgba -#define cairo_set_rgb_color cairo_set_rgb_color_REPLACED_BY_cairo_set_source_rgb -#define cairo_set_pattern cairo_set_pattern_REPLACED_BY_cairo_set_source -#define cairo_xlib_surface_create_for_pixmap_with_visual cairo_xlib_surface_create_for_pixmap_with_visual_REPLACED_BY_cairo_xlib_surface_create -#define cairo_xlib_surface_create_for_window_with_visual cairo_xlib_surface_create_for_window_with_visual_REPLACED_BY_cairo_xlib_surface_create -#define cairo_xcb_surface_create_for_pixmap_with_visual cairo_xcb_surface_create_for_pixmap_with_visual_REPLACED_BY_cairo_xcb_surface_create -#define cairo_xcb_surface_create_for_window_with_visual cairo_xcb_surface_create_for_window_with_visual_REPLACED_BY_cairo_xcb_surface_create -#define cairo_ps_surface_set_dpi cairo_ps_surface_set_dpi_REPLACED_BY_cairo_surface_set_fallback_resolution -#define cairo_pdf_surface_set_dpi cairo_pdf_surface_set_dpi_REPLACED_BY_cairo_surface_set_fallback_resolution -#define cairo_svg_surface_set_dpi cairo_svg_surface_set_dpi_REPLACED_BY_cairo_surface_set_fallback_resolution -#define cairo_atsui_font_face_create_for_atsu_font_id cairo_atsui_font_face_create_for_atsu_font_id_REPLACED_BY_cairo_quartz_font_face_create_for_atsu_font_id - -#define cairo_current_path cairo_current_path_DEPRECATED_BY_cairo_copy_path -#define cairo_current_path_flat cairo_current_path_flat_DEPRECATED_BY_cairo_copy_path_flat -#define cairo_get_path cairo_get_path_DEPRECATED_BY_cairo_copy_path -#define cairo_get_path_flat cairo_get_path_flat_DEPRECATED_BY_cairo_get_path_flat -#define cairo_set_alpha cairo_set_alpha_DEPRECATED_BY_cairo_set_source_rgba_OR_cairo_paint_with_alpha -#define cairo_show_surface cairo_show_surface_DEPRECATED_BY_cairo_set_source_surface_AND_cairo_paint -#define cairo_copy cairo_copy_DEPRECATED_BY_cairo_create_AND_MANY_INDIVIDUAL_FUNCTIONS -#define cairo_surface_set_repeat cairo_surface_set_repeat_DEPRECATED_BY_cairo_pattern_set_extend -#define cairo_surface_set_matrix cairo_surface_set_matrix_DEPRECATED_BY_cairo_pattern_set_matrix -#define cairo_surface_get_matrix cairo_surface_get_matrix_DEPRECATED_BY_cairo_pattern_get_matrix -#define cairo_surface_set_filter cairo_surface_set_filter_DEPRECATED_BY_cairo_pattern_set_filter -#define cairo_surface_get_filter cairo_surface_get_filter_DEPRECATED_BY_cairo_pattern_get_filter -#define cairo_matrix_create cairo_matrix_create_DEPRECATED_BY_cairo_matrix_t -#define cairo_matrix_destroy cairo_matrix_destroy_DEPRECATED_BY_cairo_matrix_t -#define cairo_matrix_copy cairo_matrix_copy_DEPRECATED_BY_cairo_matrix_t -#define cairo_matrix_get_affine cairo_matrix_get_affine_DEPRECATED_BY_cairo_matrix_t -#define cairo_set_target_surface cairo_set_target_surface_DEPRECATED_BY_cairo_create -#define cairo_set_target_glitz cairo_set_target_glitz_DEPRECATED_BY_cairo_glitz_surface_create -#define cairo_set_target_image cairo_set_target_image_DEPRECATED_BY_cairo_image_surface_create_for_data -#define cairo_set_target_pdf cairo_set_target_pdf_DEPRECATED_BY_cairo_pdf_surface_create -#define cairo_set_target_png cairo_set_target_png_DEPRECATED_BY_cairo_surface_write_to_png -#define cairo_set_target_ps cairo_set_target_ps_DEPRECATED_BY_cairo_ps_surface_create -#define cairo_set_target_quartz cairo_set_target_quartz_DEPRECATED_BY_cairo_quartz_surface_create -#define cairo_set_target_win32 cairo_set_target_win32_DEPRECATED_BY_cairo_win32_surface_create -#define cairo_set_target_xcb cairo_set_target_xcb_DEPRECATED_BY_cairo_xcb_surface_create -#define cairo_set_target_drawable cairo_set_target_drawable_DEPRECATED_BY_cairo_xlib_surface_create -#define cairo_get_status_string cairo_get_status_string_DEPRECATED_BY_cairo_status_AND_cairo_status_to_string -#define cairo_status_string cairo_status_string_DEPRECATED_BY_cairo_status_AND_cairo_status_to_string - -#endif /* CAIRO_DEPRECATED_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-directfb-surface.c b/uppdev/plugin/cairo/lib/cairo-directfb-surface.c deleted file mode 100644 index aa67b023b..000000000 --- a/uppdev/plugin/cairo/lib/cairo-directfb-surface.c +++ /dev/null @@ -1,1932 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2003 University of Southern California - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Michael Emmel - * Claudio Ciccani - */ - -#include "cairoint.h" -#include "cairo-directfb.h" - -#include -#include -#include -#include -#include - -#include "cairo-clip-private.h" - -/* - * Rectangle works fine. - * Bugs 361377, 359553, 359243 in Gnome BTS are caused - * by GDK/DirectFB, not by Cairo/DirectFB. - */ -#define DFB_RECTANGLES 1 - -/* - * Composite works fine. - */ -#define DFB_COMPOSITE 1 - -/* - * CompositeTrapezoids works (without antialiasing). - */ -#define DFB_COMPOSITE_TRAPEZOIDS 1 - -/* - * ShowGlyphs works fine. - */ -#define DFB_SHOW_GLYPHS 1 - - -D_DEBUG_DOMAIN (CairoDFB_Acquire, "CairoDFB/Acquire", "Cairo DirectFB Acquire"); -D_DEBUG_DOMAIN (CairoDFB_Clip, "CairoDFB/Clip", "Cairo DirectFB Clipping"); -D_DEBUG_DOMAIN (CairoDFB_Font, "CairoDFB/Font", "Cairo DirectFB Font Rendering"); -D_DEBUG_DOMAIN (CairoDFB_Render, "CairoDFB/Render", "Cairo DirectFB Rendering"); -D_DEBUG_DOMAIN (CairoDFB_Surface, "CairoDFB/Surface", "Cairo DirectFB Surface"); - -/*****************************************************************************/ - -typedef struct _cairo_directfb_surface { - cairo_surface_t base; - cairo_format_t format; - cairo_content_t content; - - IDirectFB *dfb; - IDirectFBSurface *dfbsurface; - IDirectFBSurface *tmpsurface; - - cairo_bool_t has_clip; - DFBRegion *clips; - int n_clips; - - int width; - int height; - - unsigned local : 1; - unsigned blit_premultiplied : 1; -} cairo_directfb_surface_t; - - -typedef struct _cairo_directfb_font_cache { - IDirectFB *dfb; - IDirectFBSurface *dfbsurface; - - int width; - int height; - - /* coordinates within the surface - * of the last loaded glyph */ - int x; - int y; -} cairo_directfb_font_cache_t; - -static cairo_surface_backend_t _cairo_directfb_surface_backend; - -/*****************************************************************************/ - -static int _directfb_argb_font = 0; - -/*****************************************************************************/ - -#define RUN_CLIPPED(surface, clip, func) {\ - if ((surface)->has_clip) {\ - int k;\ - for (k = 0; k < (surface)->n_clips; k++) {\ - if (clip) {\ - DFBRegion reg = (surface)->clips[k];\ - DFBRegion *cli = (clip);\ - if (reg.x2 < cli->x1 || reg.y2 < cli->y1 ||\ - reg.x1 > cli->x2 || reg.y1 > cli->y2)\ - continue;\ - if (reg.x1 < cli->x1)\ - reg.x1 = cli->x1;\ - if (reg.y1 < cli->y1)\ - reg.y1 = cli->y1;\ - if (reg.x2 > cli->x2)\ - reg.x2 = cli->x2;\ - if (reg.y2 > cli->y2)\ - reg.y2 = cli->y2;\ - (surface)->dfbsurface->SetClip ((surface)->dfbsurface, ®);\ - } else {\ - (surface)->dfbsurface->SetClip ((surface)->dfbsurface,\ - &(surface)->clips[k]);\ - }\ - func;\ - }\ - } else {\ - (surface)->dfbsurface->SetClip ((surface)->dfbsurface, clip);\ - func;\ - }\ -} - -#define TRANSFORM_POINT2X(m, x, y, ret_x, ret_y) {\ - double _x = (x);\ - double _y = (y);\ - (ret_x) = (_x * (m).xx + (m).x0);\ - (ret_y) = (_y * (m).yy + (m).y0);\ -} - -#define TRANSFORM_POINT3X(m, x, y, ret_x, ret_y) {\ - double _x = (x);\ - double _y = (y);\ - (ret_x) = (_x * (m).xx + _y * (m).xy + (m).x0);\ - (ret_y) = (_x * (m).yx + _y * (m).yy + (m).y0);\ -} - -/* XXX: A1 has a different bits ordering in cairo. - * Probably we should drop it. - */ - -static cairo_content_t -_directfb_format_to_content (DFBSurfacePixelFormat format) -{ - if (DFB_PIXELFORMAT_HAS_ALPHA (format)) { - if (DFB_COLOR_BITS_PER_PIXEL (format)) - return CAIRO_CONTENT_COLOR_ALPHA; - - return CAIRO_CONTENT_ALPHA; - } - - return CAIRO_CONTENT_COLOR; -} - -static inline DFBSurfacePixelFormat -_cairo_to_directfb_format (cairo_format_t format) -{ - switch (format) { - case CAIRO_FORMAT_RGB24: - return DSPF_RGB32; - case CAIRO_FORMAT_ARGB32: - return DSPF_ARGB; - case CAIRO_FORMAT_A8: - return DSPF_A8; - case CAIRO_FORMAT_A1: - return DSPF_A1; - default: - break; - } - - return -1; -} - -static inline cairo_format_t -_directfb_to_cairo_format (DFBSurfacePixelFormat format) -{ - switch (format) { - case DSPF_RGB32: - return CAIRO_FORMAT_RGB24; - case DSPF_ARGB: - return CAIRO_FORMAT_ARGB32; - case DSPF_A8: - return CAIRO_FORMAT_A8; - case DSPF_A1: - return CAIRO_FORMAT_A1; - default: - break; - } - - return -1; -} - -static cairo_bool_t -_directfb_get_operator (cairo_operator_t operator, - DFBSurfaceBlendFunction *ret_srcblend, - DFBSurfaceBlendFunction *ret_dstblend) -{ - DFBSurfaceBlendFunction srcblend = DSBF_ONE; - DFBSurfaceBlendFunction dstblend = DSBF_ZERO; - - switch (operator) { - case CAIRO_OPERATOR_CLEAR: - srcblend = DSBF_ZERO; - dstblend = DSBF_ZERO; - break; - case CAIRO_OPERATOR_SOURCE: - srcblend = DSBF_ONE; - dstblend = DSBF_ZERO; - break; - case CAIRO_OPERATOR_OVER: - srcblend = DSBF_ONE; - dstblend = DSBF_INVSRCALPHA; - break; - case CAIRO_OPERATOR_IN: - srcblend = DSBF_DESTALPHA; - dstblend = DSBF_ZERO; - break; - case CAIRO_OPERATOR_OUT: - srcblend = DSBF_INVDESTALPHA; - dstblend = DSBF_ZERO; - break; - case CAIRO_OPERATOR_ATOP: - srcblend = DSBF_DESTALPHA; - dstblend = DSBF_INVSRCALPHA; - break; - case CAIRO_OPERATOR_DEST: - srcblend = DSBF_ZERO; - dstblend = DSBF_ONE; - break; - case CAIRO_OPERATOR_DEST_OVER: - srcblend = DSBF_INVDESTALPHA; - dstblend = DSBF_ONE; - break; - case CAIRO_OPERATOR_DEST_IN: - srcblend = DSBF_ZERO; - dstblend = DSBF_SRCALPHA; - break; - case CAIRO_OPERATOR_DEST_OUT: - srcblend = DSBF_ZERO; - dstblend = DSBF_INVSRCALPHA; - break; - case CAIRO_OPERATOR_DEST_ATOP: - srcblend = DSBF_INVDESTALPHA; - dstblend = DSBF_SRCALPHA; - break; - case CAIRO_OPERATOR_XOR: - srcblend = DSBF_INVDESTALPHA; - dstblend = DSBF_INVSRCALPHA; - break; - case CAIRO_OPERATOR_ADD: - srcblend = DSBF_ONE; - dstblend = DSBF_ONE; - break; - case CAIRO_OPERATOR_SATURATE: - /* XXX This does not work. */ -#if 0 - srcblend = DSBF_SRCALPHASAT; - dstblend = DSBF_ONE; - break; -#endif - default: - return FALSE; - } - - *ret_srcblend = srcblend; - *ret_dstblend = dstblend; - - return TRUE; -} - -static cairo_status_t -_directfb_buffer_surface_create (IDirectFB *dfb, - DFBSurfacePixelFormat format, - int width, - int height, - IDirectFBSurface **out) -{ - IDirectFBSurface *buffer; - DFBSurfaceDescription dsc; - DFBResult ret; - - dsc.flags = DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT; - dsc.caps = DSCAPS_PREMULTIPLIED; - dsc.width = width; - dsc.height = height; - dsc.pixelformat = format; - - ret = dfb->CreateSurface (dfb, &dsc, &buffer); - if (ret) { - DirectFBError ("IDirectFB::CreateSurface()", ret); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - *out = buffer; - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_directfb_acquire_surface (cairo_directfb_surface_t *surface, - cairo_rectangle_int_t *intrest_rec, - cairo_image_surface_t **image_out, - cairo_rectangle_int_t *image_rect_out, - void **image_extra, - DFBSurfaceLockFlags lock_flags) -{ - IDirectFBSurface *buffer = NULL; - DFBRectangle source_rect; - cairo_surface_t *image; - cairo_format_t cairo_format; - cairo_status_t status; - void *data; - int pitch; - - if (surface->format == (cairo_format_t) -1 || - (lock_flags & DSLF_WRITE && surface->has_clip)) - { - DFBSurfaceCapabilities caps; - - if (intrest_rec) { - source_rect.x = intrest_rec->x; - source_rect.y = intrest_rec->y; - source_rect.w = intrest_rec->width; - source_rect.h = intrest_rec->height; - } else { - source_rect.x = 0; - source_rect.y = 0; - surface->dfbsurface->GetSize (surface->dfbsurface, - &source_rect.w, &source_rect.h); - } - - if (surface->tmpsurface) { - int w, h; - surface->tmpsurface->GetSize (surface->tmpsurface, &w, &h); - if (w < source_rect.w || h < source_rect.h) { - surface->tmpsurface->Release (surface->tmpsurface); - surface->tmpsurface = NULL; - } - } - - cairo_format = _cairo_format_from_content (surface->content); - if (!surface->tmpsurface) { - D_DEBUG_AT (CairoDFB_Acquire, "Allocating buffer for surface %p.\n", surface); - - status = - _directfb_buffer_surface_create (surface->dfb, - _cairo_to_directfb_format (cairo_format), - source_rect.w, source_rect.h, - &surface->tmpsurface); - if (status) - goto ERROR; - } - buffer = surface->tmpsurface; - -/* surface->dfbsurface->GetCapabilities (surface->dfbsurface, &caps); - if (caps & DSCAPS_FLIPPING) { - DFBRegion region = { .x1 = source_rect.x, .y1 = source_rect.y, - .x2 = source_rect.x + source_rect.w - 1, - .y2 = source_rect.y + source_rect.h - 1 }; - surface->dfbsurface->Flip (surface->dfbsurface, ®ion, DSFLIP_BLIT); - } */ - buffer->Blit (buffer, surface->dfbsurface, &source_rect, 0, 0); - } else { - /*might be a subsurface get the offset*/ - surface->dfbsurface->GetVisibleRectangle (surface->dfbsurface, &source_rect); - cairo_format = surface->format; - buffer = surface->dfbsurface; - } - - if (buffer->Lock (buffer, lock_flags, &data, &pitch)) { - D_DEBUG_AT (CairoDFB_Acquire, "Couldn't lock surface!\n"); - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto ERROR; - } - - image = cairo_image_surface_create_for_data (data, cairo_format, - source_rect.w, source_rect.h, - pitch); - status = image->status; - if (status) - goto ERROR; - - if (image_rect_out) { - image_rect_out->x = source_rect.x; - image_rect_out->y = source_rect.y; - image_rect_out->width = source_rect.w; - image_rect_out->height = source_rect.h; - } else { - /* lock for read */ - /* might be a subsurface */ - if (buffer == surface->dfbsurface) { - cairo_surface_set_device_offset (image, - source_rect.x, source_rect.y); - } - } - - *image_extra = buffer; - *image_out = (cairo_image_surface_t *) image; - return CAIRO_STATUS_SUCCESS; - -ERROR: - if (buffer) { - buffer->Unlock (buffer); - if (buffer != surface->dfbsurface) - buffer->Release (buffer); - } - return status; -} - -static cairo_surface_t * -_cairo_directfb_surface_create_similar (void *abstract_src, - cairo_content_t content, - int width, - int height) -{ - cairo_directfb_surface_t *source = abstract_src; - cairo_directfb_surface_t *surface; - cairo_format_t format; - cairo_status_t status; - - D_DEBUG_AT (CairoDFB_Surface, - "%s( src=%p, content=0x%x, width=%d, height=%d).\n", - __FUNCTION__, source, content, width, height); - - width = (width <= 0) ? 1 : width; - height = (height<= 0) ? 1 : height; - - format = _cairo_format_from_content (content); - surface = calloc (1, sizeof (cairo_directfb_surface_t)); - if (surface == NULL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - surface->dfb = source->dfb; - - if (width < 8 || height < 8) { - IDirectFBSurface *tmp; - DFBRectangle rect = { .x=0, .y=0, .w=width, .h=height }; - - /* Some cards (e.g. Matrox) don't support surfaces smaller than 8x8 */ - status = _directfb_buffer_surface_create (surface->dfb, - _cairo_to_directfb_format (format), - MAX (width, 8), MAX (height, 8), - &tmp); - if (status) { - free (surface); - return _cairo_surface_create_in_error (status); - } - - tmp->GetSubSurface (tmp, &rect, &surface->dfbsurface); - tmp->Release (tmp); - } else { - status = - _directfb_buffer_surface_create (surface->dfb, - _cairo_to_directfb_format (format), - width, height, - &surface->dfbsurface); - if (status) { - free (surface); - return _cairo_surface_create_in_error (status); - } - } - - _cairo_surface_init (&surface->base, - &_cairo_directfb_surface_backend, - content); - surface->format = format; - surface->content = content; - surface->width = width; - surface->height = height; - surface->local = TRUE; - surface->blit_premultiplied = TRUE; - - return &surface->base; -} - -static cairo_status_t -_cairo_directfb_surface_finish (void *data) -{ - cairo_directfb_surface_t *surface = (cairo_directfb_surface_t *)data; - - D_DEBUG_AT (CairoDFB_Surface, "%s( surface=%p ).\n", __FUNCTION__, surface); - - if (surface->clips) { - free (surface->clips); - surface->clips = NULL; - surface->n_clips = 0; - } - - if (surface->tmpsurface) { - surface->tmpsurface->Release (surface->tmpsurface); - surface->tmpsurface = NULL; - } - - if (surface->dfbsurface) { - surface->dfbsurface->Release (surface->dfbsurface); - surface->dfbsurface = NULL; - } - - if (surface->dfb) - surface->dfb = NULL; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_directfb_surface_acquire_source_image (void *abstract_surface, - cairo_image_surface_t **image_out, - void **image_extra) -{ - cairo_directfb_surface_t *surface = abstract_surface; - - D_DEBUG_AT (CairoDFB_Acquire, - "%s( surface=%p ).\n", __FUNCTION__, surface); - - return _directfb_acquire_surface (surface, NULL, image_out, - NULL, image_extra, DSLF_READ); -} - -static void -_cairo_directfb_surface_release_source_image (void *abstract_surface, - cairo_image_surface_t *image, - void *image_extra) -{ - IDirectFBSurface *buffer = image_extra; - - D_DEBUG_AT (CairoDFB_Acquire, - "%s( surface=%p ).\n", __FUNCTION__, surface); - - buffer->Unlock (buffer); - - cairo_surface_destroy (&image->base); -} - -static cairo_status_t -_cairo_directfb_surface_acquire_dest_image (void *abstract_surface, - cairo_rectangle_int_t *interest_rect, - cairo_image_surface_t **image_out, - cairo_rectangle_int_t *image_rect_out, - void **image_extra) -{ - cairo_directfb_surface_t *surface = abstract_surface; - - D_DEBUG_AT (CairoDFB_Acquire, - "%s( surface=%p (%dx%d), interest_rect={ %u %u %u %u } ).\n", - __FUNCTION__, surface, surface->width, surface->height, - interest_rect ? interest_rect->x : 0, - interest_rect ? interest_rect->y : 0, - interest_rect ? interest_rect->width : (unsigned) surface->width, - interest_rect ? interest_rect->height : (unsigned) surface->height); - - return _directfb_acquire_surface (surface, interest_rect, image_out, - image_rect_out, image_extra, - DSLF_READ | DSLF_WRITE); -} - -static void -_cairo_directfb_surface_release_dest_image (void *abstract_surface, - cairo_rectangle_int_t *interest_rect, - cairo_image_surface_t *image, - cairo_rectangle_int_t *image_rect, - void *image_extra) -{ - cairo_directfb_surface_t *surface = abstract_surface; - IDirectFBSurface *buffer = image_extra; - - D_DEBUG_AT (CairoDFB_Acquire, - "%s( surface=%p ).\n", __FUNCTION__, surface); - - buffer->Unlock (buffer); - - if (surface->dfbsurface != buffer) { - DFBRegion region = { - .x1 = interest_rect->x, - .y1 = interest_rect->y, - .x2 = interest_rect->x + interest_rect->width - 1, - .y2 = interest_rect->y + interest_rect->height - 1 - }; - surface->dfbsurface->SetBlittingFlags (surface->dfbsurface, DSBLIT_NOFX); - RUN_CLIPPED (surface, ®ion, - surface->dfbsurface->Blit (surface->dfbsurface, - buffer, NULL, - image_rect->x, image_rect->y)); - } - - cairo_surface_destroy (&image->base); -} - -static cairo_status_t -_cairo_directfb_surface_clone_similar (void *abstract_surface, - cairo_surface_t *src, - int src_x, - int src_y, - int width, - int height, - int *clone_offset_x, - int *clone_offset_y, - cairo_surface_t **clone_out) -{ - cairo_directfb_surface_t *surface = abstract_surface; - cairo_directfb_surface_t *clone; - - D_DEBUG_AT (CairoDFB_Surface, - "%s( surface=%p, src=%p ).\n", __FUNCTION__, surface, src); - - if (src->backend == surface->base.backend) { - *clone_offset_x = 0; - *clone_offset_y = 0; - *clone_out = cairo_surface_reference (src); - - return CAIRO_STATUS_SUCCESS; - } else if (_cairo_surface_is_image (src)) { - cairo_image_surface_t *image_src = (cairo_image_surface_t *) src; - unsigned char *dst, *src = image_src->data; - int pitch; - int i, j; - DFBResult ret; - - clone = (cairo_directfb_surface_t *) - _cairo_directfb_surface_create_similar (surface, - _cairo_content_from_format (image_src->format), - width, height); - if (clone == NULL) - return CAIRO_INT_STATUS_UNSUPPORTED; - if (clone->base.status) - return clone->base.status; - - ret = clone->dfbsurface->Lock (clone->dfbsurface, - DSLF_WRITE, (void *)&dst, &pitch); - if (ret) { - DirectFBError ("IDirectFBSurface::Lock()", ret); - cairo_surface_destroy (&clone->base); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - src += image_src->stride * src_y; - if (image_src->format == CAIRO_FORMAT_A1) { - /* A1 -> A8 */ - dst -= src_x; - for (i = 0; i < height; i++) { - for (j = src_x; j < src_x + width; j++) - dst[j] = (src[j>>3] & (1 << (j&7))) ? 0xff : 0x00; - dst += pitch; - src += image_src->stride; - } - } else { - int len; - - if (image_src->format == CAIRO_FORMAT_A8) { - src += src_x; - len = width; - } else { - src += src_x * 4; - len = width * 4; - } - - for (i = 0; i < height; i++) { - direct_memcpy (dst, src, len); - dst += pitch; - src += image_src->stride; - } - } - - clone->dfbsurface->Unlock (clone->dfbsurface); - - *clone_offset_x = src_x; - *clone_offset_y = src_y; - *clone_out = &clone->base; - return CAIRO_STATUS_SUCCESS; - } - - return CAIRO_INT_STATUS_UNSUPPORTED; -} - -#if DFB_COMPOSITE || DFB_COMPOSITE_TRAPEZOIDS -static cairo_int_status_t -_directfb_prepare_composite (cairo_directfb_surface_t *dst, - cairo_pattern_t *src_pattern, - cairo_pattern_t *mask_pattern, - cairo_operator_t op, - int *src_x, int *src_y, - int *mask_x, int *mask_y, - unsigned int width, - unsigned int height, - cairo_directfb_surface_t **ret_src, - cairo_surface_attributes_t *ret_src_attr) -{ - cairo_directfb_surface_t *src; - cairo_surface_attributes_t src_attr; - cairo_status_t status; - DFBSurfaceBlittingFlags flags; - DFBSurfaceBlendFunction sblend; - DFBSurfaceBlendFunction dblend; - const cairo_color_t *color; - - /* XXX Unbounded operators are not handled correctly */ - if (! _cairo_operator_bounded_by_source (op)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (! _directfb_get_operator (op, &sblend, &dblend)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (mask_pattern) { - cairo_solid_pattern_t *pattern; - - return CAIRO_INT_STATUS_UNSUPPORTED; - if (mask_pattern->type != CAIRO_PATTERN_TYPE_SOLID) { - cairo_pattern_t *tmp; - int tmp_x, tmp_y; - - if (src_pattern->type != CAIRO_PATTERN_TYPE_SOLID || - sblend == DSBF_INVDESTALPHA) /* Doesn't work correctly */ - return CAIRO_INT_STATUS_UNSUPPORTED; - - D_DEBUG_AT (CairoDFB_Render, "Replacing src pattern by mask pattern.\n"); - - tmp = src_pattern; - tmp_x = *src_x; tmp_y = *src_y; - - src_pattern = mask_pattern; - *src_x = *mask_x; *src_y = *mask_y; - - mask_pattern = tmp; - *mask_x = tmp_x; *mask_y = tmp_y; - - if (sblend == DSBF_ONE) { - sblend = DSBF_SRCALPHA; - /*dblend = DSBF_INVSRCALPHA;*/ - } - } - - color = &((cairo_solid_pattern_t *) mask_pattern)->color; - } else { - color = _cairo_stock_color (CAIRO_STOCK_WHITE); - } - - /* XXX DirectFB currently does not support filtering, so force NEAREST - * in order to hit optimisations inside core. - */ - src_pattern->filter = CAIRO_FILTER_NEAREST; - - status = _cairo_pattern_acquire_surface (src_pattern, &dst->base, - *src_x, *src_y, width, height, - (cairo_surface_t **) &src, - &src_attr); - if (status) - return status; - - if (src->base.backend != &_cairo_directfb_surface_backend || - src->dfb != dst->dfb) - { - _cairo_pattern_release_surface (src_pattern, &src->base, &src_attr); - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - if (src->content == CAIRO_CONTENT_COLOR) { - if (sblend == DSBF_SRCALPHA) - sblend = DSBF_ONE; - else if (sblend == DSBF_INVSRCALPHA) - sblend = DSBF_ZERO; - - if (dblend == DSBF_SRCALPHA) - dblend = DSBF_ONE; - else if (dblend == DSBF_INVSRCALPHA) - dblend = DSBF_ZERO; - } - - if (dst->content == CAIRO_CONTENT_COLOR) { - if (sblend == DSBF_DESTALPHA) - sblend = DSBF_ONE; - else if (sblend == DSBF_INVDESTALPHA) - sblend = DSBF_ZERO; - - if (dblend == DSBF_DESTALPHA) - dblend = DSBF_ONE; - else if (dblend == DSBF_INVDESTALPHA) - dblend = DSBF_ZERO; - } - - flags = (sblend == DSBF_ONE && dblend == DSBF_ZERO) - ? DSBLIT_NOFX : DSBLIT_BLEND_ALPHACHANNEL; - if (! CAIRO_COLOR_IS_OPAQUE (color)) - flags |= DSBLIT_BLEND_COLORALPHA; - if (! _cairo_color_equal (color, _cairo_stock_color (CAIRO_STOCK_WHITE))) - flags |= DSBLIT_COLORIZE; - - dst->dfbsurface->SetBlittingFlags (dst->dfbsurface, flags); - - if (flags & (DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_BLEND_COLORALPHA)) { - dst->dfbsurface->SetSrcBlendFunction (dst->dfbsurface, sblend); - dst->dfbsurface->SetDstBlendFunction (dst->dfbsurface, dblend); - } - - if (flags & (DSBLIT_BLEND_COLORALPHA | DSBLIT_COLORIZE)) { - if (dst->blit_premultiplied) { - dst->dfbsurface->SetColor (dst->dfbsurface, - color->red_short >> 8, - color->green_short >> 8, - color->blue_short >> 8, - color->alpha_short >> 8); - } else { - dst->dfbsurface->SetColor (dst->dfbsurface, - color->red * 0xff, - color->green * 0xff, - color->blue * 0xff, - color->alpha * 0xff); - } - } - - *ret_src = src; - *ret_src_attr = src_attr; - - return CAIRO_STATUS_SUCCESS; -} - -static void -_directfb_finish_composite (cairo_directfb_surface_t *dst, - cairo_pattern_t *src_pattern, - cairo_surface_t *src, - cairo_surface_attributes_t *src_attr) -{ - _cairo_pattern_release_surface (src_pattern, src, src_attr); -} -#endif /* DFB_COMPOSITE || DFB_COMPOSITE_TRAPEZOIDS */ - -#if DFB_COMPOSITE -static DFBAccelerationMask -_directfb_categorize_operation (cairo_surface_attributes_t *src_attr) -{ - cairo_matrix_t *m = &src_attr->matrix; - - if (m->xy != 0 || m->yx != 0 || m->xx < 0 || m->yy < 0) { - if (src_attr->extend != CAIRO_EXTEND_NONE) - return DFXL_NONE; - - return DFXL_TEXTRIANGLES; - } - - if (m->xx != 1 || m->yy != 1) { - if (src_attr->extend != CAIRO_EXTEND_NONE) - return DFXL_NONE; - - return DFXL_STRETCHBLIT; - } - - switch (src_attr->extend) { - case CAIRO_EXTEND_NONE: - case CAIRO_EXTEND_REPEAT: - if (_cairo_matrix_is_integer_translation (&src_attr->matrix, - NULL, NULL)) - { - return DFXL_BLIT; - } - else - { - return DFXL_STRETCHBLIT; - } - - default: - case CAIRO_EXTEND_REFLECT: - case CAIRO_EXTEND_PAD: - return DFXL_NONE; - } -} - -static cairo_int_status_t -_cairo_directfb_surface_composite (cairo_operator_t op, - cairo_pattern_t *src_pattern, - cairo_pattern_t *mask_pattern, - void *abstract_dst, - 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_directfb_surface_t *dst = abstract_dst; - cairo_directfb_surface_t *src; - cairo_surface_attributes_t src_attr; - cairo_bool_t is_integer_translation; - DFBAccelerationMask accel, mask; - cairo_int_status_t status; - int tx, ty; - - D_DEBUG_AT (CairoDFB_Render, - "%s( op=%d, src_pattern=%p, mask_pattern=%p, dst=%p," - " src_x=%d, src_y=%d, mask_x=%d, mask_y=%d, dst_x=%d," - " dst_y=%d, width=%u, height=%u ).\n", - __FUNCTION__, op, src_pattern, mask_pattern, dst, - src_x, src_y, mask_x, mask_y, dst_x, dst_y, width, height); - - status = _directfb_prepare_composite (dst, src_pattern, mask_pattern, op, - &src_x, &src_y, &mask_x, &mask_y, - width, height, &src, &src_attr); - if (status) - return status; - - accel = _directfb_categorize_operation (&src_attr); - if (accel == DFXL_NONE) { - _directfb_finish_composite (dst, src_pattern, &src->base, &src_attr); - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - dst->dfbsurface->GetAccelerationMask (dst->dfbsurface, - src->dfbsurface, - &mask); - if ((mask & accel) == 0) { - D_DEBUG_AT (CairoDFB_Render, "No acceleration (%08x)!\n", accel); - if (accel != DFXL_BLIT) { - _directfb_finish_composite (dst, src_pattern, &src->base, &src_attr); - return CAIRO_INT_STATUS_UNSUPPORTED; - } - } - - src_x += src_attr.x_offset; - src_y += src_attr.y_offset; - - switch (accel) { - case DFXL_BLIT: - { - DFBRectangle sr; - - is_integer_translation = - _cairo_matrix_is_integer_translation (&src_attr.matrix, - &tx, &ty); - assert (is_integer_translation); - - sr.x = src_x + tx; - sr.y = src_y + ty; - sr.w = width; - sr.h = height; - - if (src_attr.extend == CAIRO_EXTEND_NONE) { - D_DEBUG_AT (CairoDFB_Render, "Running Blit().\n"); - - RUN_CLIPPED (dst, NULL, - dst->dfbsurface->Blit (dst->dfbsurface, - src->dfbsurface, - &sr, - dst_x, dst_y)); - } else if (src_attr.extend == CAIRO_EXTEND_REPEAT) { - DFBRegion clip; - - clip.x1 = dst_x; - clip.y1 = dst_y; - clip.x2 = dst_x + width - 1; - clip.y2 = dst_y + height - 1; - - D_DEBUG_AT (CairoDFB_Render, "Running TileBlit().\n"); - - RUN_CLIPPED (dst, &clip, - dst->dfbsurface->TileBlit (dst->dfbsurface, - src->dfbsurface, - &sr, - dst_x, dst_y)); - } - break; - } - - case DFXL_STRETCHBLIT: - { - DFBRectangle sr, dr; - double x1, y1, x2, y2; - - TRANSFORM_POINT2X (src_attr.matrix, - src_x, src_y, x1, y1); - TRANSFORM_POINT2X (src_attr.matrix, - src_x+width, src_y+height, x2, y2); - - sr.x = floor (x1); - sr.y = floor (y1); - sr.w = ceil (x2) - sr.x; - sr.h = ceil (y2) - sr.y; - - dr.x = dst_x; - dr.y = dst_y; - dr.w = width; - dr.h = height; - - D_DEBUG_AT (CairoDFB_Render, "Running StretchBlit().\n"); - - RUN_CLIPPED (dst, NULL, - dst->dfbsurface->StretchBlit (dst->dfbsurface, - src->dfbsurface, &sr, &dr)); - break; - } - - case DFXL_TEXTRIANGLES: - { - DFBRegion clip; - DFBVertex v[4]; - float x1, y1, x2, y2; - int w, h; - - status = cairo_matrix_invert (&src_attr.matrix); - /* guaranteed by cairo_pattern_set_matrix (); */ - assert (status == CAIRO_STATUS_SUCCESS); - - x1 = src_x; - y1 = src_y; - x2 = width + x1; - y2 = height + y1; - - src->dfbsurface->GetSize (src->dfbsurface, &w, &h); - - TRANSFORM_POINT3X (src_attr.matrix, - x1, y1, v[0].x, v[0].y); - v[0].z = 0; - v[0].w = 1; - v[0].s = x1 / w; - v[0].t = y1 / h; - - TRANSFORM_POINT3X (src_attr.matrix, - x2, y1, v[1].x, v[1].y); - v[1].z = 0; - v[1].w = 1; - v[1].s = x2 / w; - v[1].t = y1 / h; - - TRANSFORM_POINT3X (src_attr.matrix, - x2, y2, v[2].x, v[2].y); - v[2].z = 0; - v[2].w = 1; - v[2].s = x2 / w; - v[2].t = y2 / h; - - TRANSFORM_POINT3X (src_attr.matrix, - x1, y2, v[3].x, v[3].y); - v[3].z = 0; - v[3].w = 1; - v[3].s = x1 / w; - v[3].t = y2 / h; - - clip.x1 = dst_x; - clip.y1 = dst_y; - clip.x2 = dst_x + width - 1; - clip.y2 = dst_y + height - 1; - - D_DEBUG_AT (CairoDFB_Render, "Running TextureTriangles().\n"); - - RUN_CLIPPED (dst, &clip, - dst->dfbsurface->TextureTriangles (dst->dfbsurface, - src->dfbsurface, v, NULL, 4, DTTF_FAN)); - break; - } - - default: - D_BUG ("Unexpected operation"); - break; - } - - _directfb_finish_composite (dst, src_pattern, &src->base, &src_attr); - - return status; -} -#endif /* DFB_COMPOSITE */ - -#if DFB_RECTANGLES -static cairo_int_status_t -_cairo_directfb_surface_fill_rectangles (void *abstract_surface, - cairo_operator_t op, - const cairo_color_t *color, - cairo_rectangle_int_t *rects, - int n_rects) -{ - cairo_directfb_surface_t *dst = abstract_surface; - DFBSurfaceDrawingFlags flags; - DFBSurfaceBlendFunction sblend; - DFBSurfaceBlendFunction dblend; - DFBRectangle r[n_rects]; - int i; - - D_DEBUG_AT (CairoDFB_Render, - "%s( dst=%p, op=%d, color=%p, rects=%p, n_rects=%d ).\n", - __FUNCTION__, dst, op, color, rects, n_rects); - - if (! _cairo_operator_bounded_by_source (op)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (! _directfb_get_operator (op, &sblend, &dblend)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (CAIRO_COLOR_IS_OPAQUE (color)) { - if (sblend == DSBF_SRCALPHA) - sblend = DSBF_ONE; - else if (sblend == DSBF_INVSRCALPHA) - sblend = DSBF_ZERO; - - if (dblend == DSBF_SRCALPHA) - dblend = DSBF_ONE; - else if (dblend == DSBF_INVSRCALPHA) - dblend = DSBF_ZERO; - } - if (dst->content == CAIRO_CONTENT_COLOR) { - if (sblend == DSBF_DESTALPHA) - sblend = DSBF_ONE; - else if (sblend == DSBF_INVDESTALPHA) - sblend = DSBF_ZERO; - - if (dblend == DSBF_DESTALPHA) - dblend = DSBF_ONE; - else if (dblend == DSBF_INVDESTALPHA) - dblend = DSBF_ZERO; - } - - flags = (sblend == DSBF_ONE && dblend == DSBF_ZERO) ? DSDRAW_NOFX : DSDRAW_BLEND; - dst->dfbsurface->SetDrawingFlags (dst->dfbsurface, flags); - if (flags & DSDRAW_BLEND) { - dst->dfbsurface->SetSrcBlendFunction (dst->dfbsurface, sblend); - dst->dfbsurface->SetDstBlendFunction (dst->dfbsurface, dblend); - } - - dst->dfbsurface->SetColor (dst->dfbsurface, - color->red_short >> 8, - color->green_short >> 8, - color->blue_short >> 8, - color->alpha_short >> 8); - - for (i = 0; i < n_rects; i++) { - r[i].x = rects[i].x; - r[i].y = rects[i].y; - r[i].w = rects[i].width; - r[i].h = rects[i].height; - } - - RUN_CLIPPED (dst, NULL, - dst->dfbsurface->FillRectangles (dst->dfbsurface, r, n_rects)); - - return CAIRO_STATUS_SUCCESS; -} -#endif - -#if DFB_COMPOSITE_TRAPEZOIDS -static cairo_int_status_t -_cairo_directfb_surface_composite_trapezoids (cairo_operator_t op, - cairo_pattern_t *pattern, - void *abstract_dst, - cairo_antialias_t antialias, - int src_x, int src_y, - int dst_x, int dst_y, - unsigned int width, - unsigned int height, - cairo_trapezoid_t *traps, - int num_traps) -{ - cairo_directfb_surface_t *dst = abstract_dst; - cairo_directfb_surface_t *src; - cairo_surface_attributes_t src_attr; - cairo_status_t status; - DFBAccelerationMask accel; - - D_DEBUG_AT (CairoDFB_Render, - "%s( op=%d, pattern=%p, dst=%p, antialias=%d," - " src_x=%d, src_y=%d, dst_x=%d, dst_y=%d," - " width=%u, height=%u, traps=%p, num_traps=%d ).\n", - __FUNCTION__, op, pattern, dst, antialias, - src_x, src_y, dst_x, dst_y, width, height, traps, num_traps); - - if (antialias != CAIRO_ANTIALIAS_NONE) - return CAIRO_INT_STATUS_UNSUPPORTED; - - /* Textures are not supported yet. */ - if (pattern->type != CAIRO_PATTERN_TYPE_SOLID) - return CAIRO_INT_STATUS_UNSUPPORTED; - - status = _directfb_prepare_composite (dst, pattern, NULL, op, - &src_x, &src_y, NULL, NULL, - width, height, &src, &src_attr); - if (status) - return status; - - dst->dfbsurface->GetAccelerationMask (dst->dfbsurface, - src->dfbsurface, - &accel); - - status = CAIRO_INT_STATUS_UNSUPPORTED; - - if (accel & DFXL_TEXTRIANGLES) { - DFBVertex vertex[6*num_traps]; - DFBVertex *v = &vertex[0]; - int n = 0; - -#define ADD_TRI_V(V, X, Y) do { \ - (V)->x = (X); (V)->y = (Y); (V)->w = 1; (V)->z = (V)->s = (V)->t = 0; \ -} while (0) -#define ADD_TRI(id, x1, y1, x2, y2, x3, y3) do {\ - const int p = (id)*3;\ - ADD_TRI_V (v+p+0, x1, y1); \ - ADD_TRI_V (v+p+1, x2, y2); \ - ADD_TRI_V (v+p+2, x3, y3); \ -} while (0) - while (num_traps--) { - double lx1, ly1, lx2, ly2; - double rx1, ry1, rx2, ry2; - - lx1 = _cairo_fixed_to_double (traps->left.p1.x); - ly1 = _cairo_fixed_to_double (traps->left.p1.y); - lx2 = _cairo_fixed_to_double (traps->left.p2.x); - ly2 = _cairo_fixed_to_double (traps->left.p2.y); - rx1 = _cairo_fixed_to_double (traps->right.p1.x); - ry1 = _cairo_fixed_to_double (traps->right.p1.y); - rx2 = _cairo_fixed_to_double (traps->right.p2.x); - ry2 = _cairo_fixed_to_double (traps->right.p2.y); - - if (traps->left.p1.y < traps->top) { - double y = _cairo_fixed_to_double (traps->top); - if (lx2 != lx1) - lx1 = (y - ly1) * (lx2 - lx1) / (ly2 - ly1) + lx1; - ly1 = y; - } - if (traps->left.p2.y > traps->bottom) { - double y = _cairo_fixed_to_double (traps->bottom); - if (lx2 != lx1) - lx2 = (y - ly1) * (lx2 - lx1) / (ly2 - ly1) + lx1; - ly2 = y; - } - - if (traps->right.p1.y < traps->top) { - double y = _cairo_fixed_to_double (traps->top); - if (rx2 != rx1) - rx1 = (y - ry1) * (rx2 - rx1) / (ry2 - ry1) + rx1; - ry1 = y; - } - if (traps->right.p2.y > traps->bottom) { - double y = _cairo_fixed_to_double (traps->bottom); - if (rx2 != rx1) - rx2 = (y - ry1) * (rx2 - rx1) / (ry2 - ry1) + rx1; - ry2 = y; - } - - if (lx1 == rx1 && ly1 == ry1) { - ADD_TRI (0, lx2, ly2, lx1, ly1, rx2, ry2); - v += 3; - n += 3; - } else if (lx2 == rx2 && ly2 == ry2) { - ADD_TRI (0, lx1, ly1, lx2, ly2, rx1, ry1); - v += 3; - n += 3; - } else { - ADD_TRI (0, lx1, ly1, rx1, ry1, lx2, ly2); - ADD_TRI (1, lx2, ly2, rx1, ry1, rx2, ry2); - v += 6; - n += 6; - } - - traps++; - } -#undef ADD_TRI -#undef ADD_TRI_V - - D_DEBUG_AT (CairoDFB_Render, "Running TextureTriangles().\n"); - - RUN_CLIPPED (dst, NULL, - dst->dfbsurface->TextureTriangles (dst->dfbsurface, - src->dfbsurface, - vertex, NULL, n, - DTTF_LIST)); - - status = CAIRO_STATUS_SUCCESS; - } - - _directfb_finish_composite (dst, pattern, &src->base, &src_attr); - - return status; -} -#endif /* DFB_COMPOSITE_TRAPEZOIDS */ - -static cairo_int_status_t -_cairo_directfb_surface_set_clip_region (void *abstract_surface, - cairo_region_t *region) -{ - cairo_directfb_surface_t *surface = abstract_surface; - - D_DEBUG_AT (CairoDFB_Clip, - "%s( surface=%p, region=%p ).\n", - __FUNCTION__, surface, region); - - if (region) { - cairo_box_int_t *boxes; - int n_boxes; - cairo_status_t status; - int i; - - surface->has_clip = TRUE; - - status = _cairo_region_get_boxes (region, &n_boxes, &boxes); - if (n_boxes == 0) - return CAIRO_STATUS_SUCCESS; - if (status) - return status; - - if (surface->n_clips != n_boxes) { - if (surface->clips) - free (surface->clips); - - surface->clips = _cairo_malloc_ab (n_boxes, sizeof (DFBRegion)); - if (!surface->clips) { - surface->n_clips = 0; - _cairo_region_boxes_fini (region, boxes); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - surface->n_clips = n_boxes; - } - - for (i = 0; i < n_boxes; i++) { - surface->clips[i].x1 = boxes[i].p1.x; - surface->clips[i].y1 = boxes[i].p1.y; - surface->clips[i].x2 = boxes[i].p2.x - 1; - surface->clips[i].y2 = boxes[i].p2.y - 1; - } - - _cairo_region_boxes_fini (region, boxes); - } else { - surface->has_clip = FALSE; - if (surface->clips) { - free (surface->clips); - surface->clips = NULL; - surface->n_clips = 0; - } - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_directfb_abstract_surface_get_extents (void *abstract_surface, - cairo_rectangle_int_t *rectangle) -{ - cairo_directfb_surface_t *surface = abstract_surface; - - D_DEBUG_AT (CairoDFB_Surface, - "%s( surface=%p, rectangle=%p ).\n", - __FUNCTION__, surface, rectangle); - - if (!surface->local) { - surface->dfbsurface->GetSize (surface->dfbsurface, - &surface->width, &surface->height); - } - - rectangle->x = 0; - rectangle->y = 0; - rectangle->width = surface->width; - rectangle->height = surface->height; - - return CAIRO_STATUS_SUCCESS; -} - -#if DFB_SHOW_GLYPHS -static cairo_status_t -_directfb_allocate_font_cache (IDirectFB *dfb, - int width, int height, - cairo_directfb_font_cache_t **out) -{ - cairo_directfb_font_cache_t *cache; - cairo_status_t status; - - cache = calloc (1, sizeof (cairo_directfb_font_cache_t)); - if (cache == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - cache->dfb = dfb; - status = _directfb_buffer_surface_create (dfb, - _directfb_argb_font ? DSPF_ARGB : DSPF_A8, - width, height, - &cache->dfbsurface); - if (status) { - free (cache); - return status; - } - - cache->width = width; - cache->height = height; - *out = cache; - return CAIRO_STATUS_SUCCESS; -} - -static void -_directfb_destroy_font_cache (cairo_directfb_font_cache_t *cache) -{ - cache->dfbsurface->Release (cache->dfbsurface); - free (cache); -} - -static cairo_status_t -_directfb_acquire_font_cache (cairo_directfb_surface_t *surface, - cairo_scaled_font_t *scaled_font, - const cairo_glyph_t *glyphs, - int num_glyphs, - cairo_directfb_font_cache_t **ret_cache, - DFBRectangle *rects, - DFBPoint *points, - int *ret_num) -{ - cairo_status_t status; - cairo_scaled_glyph_t *chars[num_glyphs]; - int num_chars = 0; - cairo_directfb_font_cache_t *cache = NULL; - int n = 0; - int x = 0; - int y = 0; - int w = 8; - int h = 8; - int i; - - D_DEBUG_AT (CairoDFB_Font, "%s( %p [%d] )\n", __FUNCTION__, glyphs, num_glyphs ); - - _cairo_cache_freeze (scaled_font->glyphs); - - if (scaled_font->surface_private) { - cache = scaled_font->surface_private; - x = cache->x; - y = cache->y; - } - - for (i = 0; i < num_glyphs; i++) { - cairo_scaled_glyph_t *scaled_glyph; - cairo_image_surface_t *img; - - D_DEBUG_AT (CairoDFB_Font, " -> [%2d] = %4lu\n", i, glyphs[i].index ); - - status = _cairo_scaled_glyph_lookup (scaled_font, glyphs[i].index, - CAIRO_SCALED_GLYPH_INFO_SURFACE, - &scaled_glyph); - if (status) { - _cairo_cache_thaw (scaled_font->glyphs); - return status; - } - - img = scaled_glyph->surface; - switch (img->format) { - case CAIRO_FORMAT_A1: - case CAIRO_FORMAT_A8: - case CAIRO_FORMAT_ARGB32: - break; - default: - D_DEBUG_AT (CairoDFB_Font, - " -> Unsupported font format %d!\n", img->format); - _cairo_cache_thaw (scaled_font->glyphs); - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - points[n].x = _cairo_lround (glyphs[i].x - img->base.device_transform.x0); - points[n].y = _cairo_lround (glyphs[i].y - img->base.device_transform.y0); - - // D_DEBUG_AT (CairoDFB_Font, " (%4d,%4d) [%2d]\n", points[n].x, points[n].y, n ); - - if (points[n].x >= surface->width || - points[n].y >= surface->height || - points[n].x+img->width <= 0 || - points[n].y+img->height <= 0) - { - continue; - } - - if (scaled_glyph->surface_private == NULL) { - DFBRectangle *rect; - - if (x+img->width > 2048) { - x = 0; - y = h; - h = 0; - } - - rects[n].x = x; - rects[n].y = y; - rects[n].w = img->width; - rects[n].h = img->height; - - x += img->width; - h = MAX (h, img->height); - w = MAX (w, x); - - /* Remember glyph location */ - rect = malloc (sizeof (DFBRectangle)); - if (rect == NULL) { - _cairo_cache_thaw (scaled_font->glyphs); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - *rect = rects[n]; - - scaled_glyph->surface_private = rect; - chars[num_chars++] = scaled_glyph; - - D_DEBUG_AT (CairoDFB_Font, " -> loading at %4d,%2d <- rect %p, img %p, entry %p\n", - rects[n].x, rects[n].y, rect, scaled_glyph->surface, scaled_glyph); - } else { - rects[n] = *(DFBRectangle *) scaled_glyph->surface_private; - - D_DEBUG_AT (CairoDFB_Font, " -> exists at %4d,%2d\n", rects[n].x, rects[n].y); - } - - n++; - } - - if (n == 0) { - _cairo_cache_thaw (scaled_font->glyphs); - return CAIRO_INT_STATUS_NOTHING_TO_DO; - } - - h += y; - w = MAX (w, 8); - h = MAX (h, 8); - - /* XXX query maximum surface size */ - if (w > 2048 || h > 2048) { - _cairo_cache_thaw (scaled_font->glyphs); - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - if (cache) { - if (cache->width < w || cache->height < h) { - cairo_directfb_font_cache_t *new_cache; - - w = MAX (w, cache->width); - h = MAX (h, cache->height); - - D_DEBUG_AT (CairoDFB_Font, " -> Reallocating font cache (%dx%d).\n", w, h); - - status = _directfb_allocate_font_cache (surface->dfb, - w, h, - &new_cache); - if (status) { - _cairo_cache_thaw (scaled_font->glyphs); - return status; - } - - new_cache->dfbsurface->Blit (new_cache->dfbsurface, - cache->dfbsurface, NULL, 0, 0); - - _directfb_destroy_font_cache (cache); - scaled_font->surface_private = cache = new_cache; - } - } else { - D_DEBUG_AT (CairoDFB_Font, " -> Allocating font cache (%dx%d).\n", w, h); - - status = _directfb_allocate_font_cache (surface->dfb, w, h, &cache); - if (status) { - _cairo_cache_thaw (scaled_font->glyphs); - return status; - } - - scaled_font->surface_backend = &_cairo_directfb_surface_backend; - scaled_font->surface_private = cache; - } - - if (num_chars) { - unsigned char *data; - int pitch; - - if (cache->dfbsurface->Lock (cache->dfbsurface, - DSLF_WRITE, (void *)&data, &pitch)) - { - _cairo_cache_thaw (scaled_font->glyphs); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - D_DEBUG_AT (CairoDFB_Font, " => %d chars to load, cache %dx%d\n", num_chars, cache->width, cache->height); - - for (i = 0; i < num_chars; i++) { - cairo_image_surface_t *img = chars[i]->surface; - DFBRectangle *rect = chars[i]->surface_private; - unsigned char *dst = data; - unsigned char *src; - int j; - - D_DEBUG_AT (CairoDFB_Font, " -> loading [%2d] <- rect %p, img %p, entry %p\n", i, rect, img, chars[i]); - - src = img->data; - - D_DEBUG_AT (CairoDFB_Font, " from %p\n", src); - - dst += rect->y * pitch + (_directfb_argb_font ? (rect->x<<2) : rect->x); - - D_DEBUG_AT (CairoDFB_Font, " to %4d,%2d (%p)\n", rect->x, rect->y, dst); - - if (img->format == CAIRO_FORMAT_A1) { - for (h = rect->h; h; h--) { - if (_directfb_argb_font) { - for (j = 0; j < rect->w; j++) - ((uint32_t *) dst)[j] = (src[j>>3] & (1 << (j&7))) ? 0xffffffff : 0; - } else { - for (j = 0; j < rect->w; j++) - dst[j] = (src[j>>3] & (1 << (j&7))) ? 0xff : 0; - } - - dst += pitch; - src += img->stride; - } - } else if (img->format == CAIRO_FORMAT_A8) { - for (h = rect->h; h; h--) { - if (_directfb_argb_font) { - for (j = 0; j < rect->w; j++) - ((uint32_t *) dst)[j] = src[j] * 0x01010101; - } else { - direct_memcpy (dst, src, rect->w); - } - - dst += pitch; - src += img->stride; - } - } else { /* ARGB32 */ - for (h = rect->h; h; h--) { - if (_directfb_argb_font) { - direct_memcpy (dst, src, rect->w<<2); - } else { - for (j = 0; j < rect->w; j++) - dst[j] = ((uint32_t *) src)[j] >> 24; - } - - dst += pitch; - src += img->stride; - } - } - } - - cache->dfbsurface->Unlock (cache->dfbsurface); - } - - _cairo_cache_thaw (scaled_font->glyphs); - - cache->x = x; - cache->y = y; - - D_DEBUG_AT (CairoDFB_Font, " => cache %d,%d, %p [%d]\n", x, y, cache, n); - - *ret_cache = cache; - *ret_num = n; - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_directfb_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font) -{ - cairo_directfb_font_cache_t *cache = scaled_font->surface_private; - - D_DEBUG_AT (CairoDFB_Font, - "%s( scaled_font=%p ).\n", __FUNCTION__, scaled_font); - - if (cache != NULL) { - _directfb_destroy_font_cache (cache); - scaled_font->surface_private = NULL; - } -} - -static void -_cairo_directfb_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph, - cairo_scaled_font_t *scaled_font) -{ - D_DEBUG_AT (CairoDFB_Font, - "%s( scaled_glyph=%p, scaled_font=%p ).\n", - __FUNCTION__, scaled_glyph, scaled_font); - - if (scaled_glyph->surface_private != NULL) { - free (scaled_glyph->surface_private); - scaled_glyph->surface_private = NULL; - } -} - -static cairo_int_status_t -_cairo_directfb_surface_show_glyphs (void *abstract_dst, - cairo_operator_t op, - cairo_pattern_t *pattern, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font, - int *remaining_glyphs) -{ - cairo_directfb_surface_t *dst = abstract_dst; - cairo_directfb_font_cache_t *cache; - cairo_status_t status; - DFBSurfaceBlittingFlags flags; - DFBSurfaceBlendFunction sblend; - DFBSurfaceBlendFunction dblend; - DFBRectangle rects[num_glyphs]; - DFBPoint points[num_glyphs]; - int num; - const cairo_color_t *color; - - - D_DEBUG_AT (CairoDFB_Font, - "%s( dst=%p, op=%d, pattern=%p, glyphs=%p, num_glyphs=%d, scaled_font=%p ).\n", - __FUNCTION__, dst, op, pattern, glyphs, num_glyphs, scaled_font); - - if (pattern->type != CAIRO_PATTERN_TYPE_SOLID) - return CAIRO_INT_STATUS_UNSUPPORTED; - - /* Fallback if we need to emulate clip regions */ - if (dst->base.clip && - (dst->base.clip->mode != CAIRO_CLIP_MODE_REGION || - dst->base.clip->surface != NULL)) - { - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - /* XXX Unbounded operators are not handled correctly */ - if (! _cairo_operator_bounded_by_mask (op)) - return CAIRO_INT_STATUS_UNSUPPORTED; - if (! _cairo_operator_bounded_by_source (op)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (! _directfb_get_operator (op, &sblend, &dblend) || - sblend == DSBF_DESTALPHA || sblend == DSBF_INVDESTALPHA) - { - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - status = _directfb_acquire_font_cache (dst, scaled_font, glyphs, num_glyphs, - &cache, &rects[0], &points[0], &num); - if (status) { - if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) - status = CAIRO_STATUS_SUCCESS; - return status; - } - - color = &((cairo_solid_pattern_t *) pattern)->color; - - flags = DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_COLORIZE; - if (! CAIRO_COLOR_IS_OPAQUE (color)) - flags |= DSBLIT_BLEND_COLORALPHA; - - if (!_directfb_argb_font) { - if (sblend == DSBF_ONE) { - sblend = DSBF_SRCALPHA; - if (dblend == DSBF_ZERO) - dblend = DSBF_INVSRCALPHA; - } - } - - dst->dfbsurface->SetBlittingFlags (dst->dfbsurface, flags); - dst->dfbsurface->SetSrcBlendFunction (dst->dfbsurface, sblend); - dst->dfbsurface->SetDstBlendFunction (dst->dfbsurface, dblend); - if (dst->blit_premultiplied) { - dst->dfbsurface->SetColor (dst->dfbsurface, - color->red_short >> 8, - color->green_short >> 8, - color->blue_short >> 8, - color->alpha_short >> 8); - } else { - dst->dfbsurface->SetColor (dst->dfbsurface, - color->red * 0xff, - color->green * 0xff, - color->blue * 0xff, - color->alpha * 0xff); - } - - D_DEBUG_AT (CairoDFB_Font, "Running BatchBlit().\n"); - - RUN_CLIPPED (dst, NULL, - dst->dfbsurface->BatchBlit (dst->dfbsurface, - cache->dfbsurface, rects, points, num)); - - return CAIRO_STATUS_SUCCESS; -} -#endif /* DFB_SHOW_GLYPHS */ - - -static cairo_bool_t -_cairo_directfb_surface_is_similar (void *surface_a, void *surface_b, cairo_content_t content) -{ - cairo_directfb_surface_t *a = (cairo_directfb_surface_t *) surface_a; - cairo_directfb_surface_t *b = (cairo_directfb_surface_t *) surface_b; - - return a->dfb == b->dfb; -} - -static cairo_surface_backend_t -_cairo_directfb_surface_backend = { - CAIRO_SURFACE_TYPE_DIRECTFB, /*type*/ - _cairo_directfb_surface_create_similar,/*create_similar*/ - _cairo_directfb_surface_finish, /*finish*/ - _cairo_directfb_surface_acquire_source_image,/*acquire_source_image*/ - _cairo_directfb_surface_release_source_image,/*release_source_image*/ - _cairo_directfb_surface_acquire_dest_image,/*acquire_dest_image*/ - _cairo_directfb_surface_release_dest_image,/*release_dest_image*/ - _cairo_directfb_surface_clone_similar,/*clone_similar*/ -#if DFB_COMPOSITE - _cairo_directfb_surface_composite,/*composite*/ -#else - NULL,/*composite*/ -#endif -#if DFB_RECTANGLES - _cairo_directfb_surface_fill_rectangles,/*fill_rectangles*/ -#else - NULL,/*fill_rectangles*/ -#endif -#if DFB_COMPOSITE_TRAPEZOIDS - _cairo_directfb_surface_composite_trapezoids,/*composite_trapezoids*/ -#else - NULL,/*composite_trapezoids*/ -#endif - NULL, /* copy_page */ - NULL, /* show_page */ - _cairo_directfb_surface_set_clip_region,/* set_clip_region */ - NULL, /* intersect_clip_path */ - _cairo_directfb_abstract_surface_get_extents,/* get_extents */ - NULL, /* old_show_glyphs */ - NULL, /* get_font_options */ - NULL, /* flush */ - NULL, /* mark_dirty_rectangle */ -#if DFB_SHOW_GLYPHS - _cairo_directfb_surface_scaled_font_fini,/* scaled_font_fini */ - _cairo_directfb_surface_scaled_glyph_fini,/* scaled_glyph_fini */ -#else - NULL, - NULL, -#endif - NULL, /* paint */ - NULL, /* mask */ - NULL, /* stroke */ - NULL, /* fill */ -#if DFB_SHOW_GLYPHS - _cairo_directfb_surface_show_glyphs,/* show_glyphs */ -#else - NULL, /* show_glyphs */ -#endif - NULL, /* snapshot */ - _cairo_directfb_surface_is_similar, - NULL /* reset */ -}; - - -static void -cairo_directfb_surface_backend_init (IDirectFB *dfb) -{ - static int done = 0; - - if (done) - return; - - if (getenv ("CAIRO_DIRECTFB_NO_ACCEL")) { -#if DFB_RECTANGLES - _cairo_directfb_surface_backend.fill_rectangles = NULL; -#endif -#if DFB_COMPOSITE - _cairo_directfb_surface_backend.composite = NULL; -#endif -#if DFB_COMPOSITE_TRAPEZOIDS - _cairo_directfb_surface_backend.composite_trapezoids = NULL; -#endif -#if DFB_SHOW_GLYPHS - _cairo_directfb_surface_backend.scaled_font_fini = NULL; - _cairo_directfb_surface_backend.scaled_glyph_fini = NULL; - _cairo_directfb_surface_backend.show_glyphs = NULL; -#endif - D_DEBUG_AT (CairoDFB_Surface, "Acceleration disabled.\n"); - } else { - DFBGraphicsDeviceDescription dsc; - - dfb->GetDeviceDescription (dfb, &dsc); - -#if DFB_COMPOSITE - // if (!(dsc.acceleration_mask & DFXL_BLIT)) - // _cairo_directfb_surface_backend.composite = NULL; -#endif - -#if DFB_COMPOSITE_TRAPEZOIDS - // if (!(dsc.acceleration_mask & DFXL_TEXTRIANGLES)) - // _cairo_directfb_surface_backend.composite_trapezoids = NULL; -#endif - } - - if (getenv ("CAIRO_DIRECTFB_ARGB_FONT")) { - _directfb_argb_font = 1; - D_DEBUG_AT (CairoDFB_Surface, "Using ARGB fonts.\n"); - } - - done = 1; -} - -cairo_surface_t * -cairo_directfb_surface_create (IDirectFB *dfb, IDirectFBSurface *dfbsurface) -{ - cairo_directfb_surface_t *surface; - DFBSurfacePixelFormat format; - DFBSurfaceCapabilities caps; - - D_ASSERT (dfb != NULL); - D_ASSERT (dfbsurface != NULL); - - cairo_directfb_surface_backend_init (dfb); - - surface = calloc (1, sizeof (cairo_directfb_surface_t)); - if (surface == NULL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - dfbsurface->AddRef (dfbsurface); - dfbsurface->GetPixelFormat (dfbsurface, &format); - dfbsurface->GetSize (dfbsurface, &surface->width, &surface->height); - surface->dfb = dfb; - surface->dfbsurface = dfbsurface; - surface->format = _directfb_to_cairo_format (format); - surface->content = _directfb_format_to_content (format); - - dfbsurface->GetCapabilities (dfbsurface, &caps); - if (caps & DSCAPS_PREMULTIPLIED) - surface->blit_premultiplied = TRUE; - - _cairo_surface_init (&surface->base, - &_cairo_directfb_surface_backend, - surface->content); - - return &surface->base; -} diff --git a/uppdev/plugin/cairo/lib/cairo-directfb.h b/uppdev/plugin/cairo/lib/cairo-directfb.h deleted file mode 100644 index 0396cb13a..000000000 --- a/uppdev/plugin/cairo/lib/cairo-directfb.h +++ /dev/null @@ -1,67 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2003 University of Southern California - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - */ - -/* - * Environment variables affecting the backend: - * - * %CAIRO_DIRECTFB_NO_ACCEL (boolean) - * if found, disables acceleration at all - * - * %CAIRO_DIRECTFB_ARGB_FONT (boolean) - * if found, enables using ARGB fonts instead of A8 - */ - -#ifndef CAIRO_DIRECTFB_H -#define CAIRO_DIRECTFB_H - -#include "cairo.h" - -#if CAIRO_HAS_DIRECTFB_SURFACE - -#include - -CAIRO_BEGIN_DECLS - -cairo_public cairo_surface_t * -cairo_directfb_surface_create (IDirectFB *dfb, IDirectFBSurface *surface); - -CAIRO_END_DECLS - -#else /*CAIRO_HAS_DIRECTFB_SURFACE*/ -# error Cairo was not compiled with support for the directfb backend -#endif /*CAIRO_HAS_DIRECTFB_SURFACE*/ - -#endif /*CAIRO_DIRECTFB_H*/ diff --git a/uppdev/plugin/cairo/lib/cairo-features.h b/uppdev/plugin/cairo/lib/cairo-features.h deleted file mode 100644 index e0999de94..000000000 --- a/uppdev/plugin/cairo/lib/cairo-features.h +++ /dev/null @@ -1,28 +0,0 @@ -/* Generated by configure. Do not edit. */ -#ifndef CAIRO_FEATURES_H -#define CAIRO_FEATURES_H - -#define CAIRO_HAS_IMAGE_SURFACE 1 -#define CAIRO_HAS_PDF_SURFACE 1 -#define CAIRO_HAS_PNG_FUNCTIONS 1 -//#define CAIRO_HAS_PS_SURFACE 1 -#define CAIRO_HAS_SVG_SURFACE 1 -//#define CAIRO_HAS_USER_FONT 1 - -/*#undef CAIRO_HAS_QUARTZ_FONT */ -/*#undef CAIRO_HAS_QUARTZ_SURFACE */ - -#ifndef cairo_public - #define cairo_public -#endif - -#ifdef flagWIN32 - #define CAIRO_HAS_WIN32_SURFACE 1 - #define CAIRO_HAS_WIN32_FONT 1 -#else - #define CAIRO_HAS_XLIB_SURFACE 1 - #define CAIRO_HAS_XLIB_XRENDER_SURFACE 1 - #define CAIRO_HAS_FT_FONT 1 -#endif - -#endif diff --git a/uppdev/plugin/cairo/lib/cairo-fixed-private.h b/uppdev/plugin/cairo/lib/cairo-fixed-private.h deleted file mode 100644 index 630f0327c..000000000 --- a/uppdev/plugin/cairo/lib/cairo-fixed-private.h +++ /dev/null @@ -1,244 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* Cairo - a vector graphics library with display and print output - * - * Copyright © 2007 Mozilla Corporation - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Mozilla Corporation - * - * Contributor(s): - * Vladimir Vukicevic - */ - -#ifndef CAIRO_FIXED_PRIVATE_H -#define CAIRO_FIXED_PRIVATE_H - -#include "cairo-fixed-type-private.h" - -#include "cairo-wideint-private.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. -#endif - -#define CAIRO_FIXED_ONE ((cairo_fixed_t)(1 << CAIRO_FIXED_FRAC_BITS)) -#define CAIRO_FIXED_ONE_DOUBLE ((double)(1 << CAIRO_FIXED_FRAC_BITS)) -#define CAIRO_FIXED_EPSILON ((cairo_fixed_t)(1)) - -#define CAIRO_FIXED_FRAC_MASK (((cairo_fixed_unsigned_t)(-1)) >> (CAIRO_FIXED_BITS - CAIRO_FIXED_FRAC_BITS)) -#define CAIRO_FIXED_WHOLE_MASK (~CAIRO_FIXED_FRAC_MASK) - -static inline cairo_fixed_t -_cairo_fixed_from_int (int i) -{ - return i << CAIRO_FIXED_FRAC_BITS; -} - -/* This is the "magic number" approach to converting a double into fixed - * point as described here: - * - * http://www.stereopsis.com/sree/fpu2006.html (an overview) - * http://www.d6.com/users/checker/pdfs/gdmfp.pdf (in detail) - * - * The basic idea is to add a large enough number to the double that the - * literal floating point is moved up to the extent that it forces the - * double's value to be shifted down to the bottom of the mantissa (to make - * room for the large number being added in). Since the mantissa is, at a - * given moment in time, a fixed point integer itself, one can convert a - * float to various fixed point representations by moving around the point - * of a floating point number through arithmetic operations. This behavior - * is reliable on most modern platforms as it is mandated by the IEEE-754 - * standard for floating point arithmetic. - * - * For our purposes, a "magic number" must be carefully selected that is - * both large enough to produce the desired point-shifting effect, and also - * has no lower bits in its representation that would interfere with our - * value at the bottom of the mantissa. The magic number is calculated as - * follows: - * - * (2 ^ (MANTISSA_SIZE - FRACTIONAL_SIZE)) * 1.5 - * - * where in our case: - * - MANTISSA_SIZE for 64-bit doubles is 52 - * - FRACTIONAL_SIZE for 16.16 fixed point is 16 - * - * Although this approach provides a very large speedup of this function - * on a wide-array of systems, it does come with two caveats: - * - * 1) It uses banker's rounding as opposed to arithmetic rounding. - * 2) It doesn't function properly if the FPU is in single-precision - * mode. - */ - -/* The 16.16 number must always be available */ -#define CAIRO_MAGIC_NUMBER_FIXED_16_16 (103079215104.0) - -#if CAIRO_FIXED_BITS <= 32 -#define CAIRO_MAGIC_NUMBER_FIXED ((1LL << (52 - CAIRO_FIXED_FRAC_BITS)) * 1.5) - -/* For 32-bit fixed point numbers */ -static inline cairo_fixed_t -_cairo_fixed_from_double (double d) -{ - union { - double d; - int32_t i[2]; - } u; - - u.d = d + CAIRO_MAGIC_NUMBER_FIXED; -#ifdef FLOAT_WORDS_BIGENDIAN - return u.i[1]; -#else - return u.i[0]; -#endif -} - -#else -# error Please define a magic number for your fixed point type! -# error See cairo-fixed-private.h for details. -#endif - -static inline cairo_fixed_t -_cairo_fixed_from_26_6 (uint32_t i) -{ -#if CAIRO_FIXED_FRAC_BITS > 6 - return i << (CAIRO_FIXED_FRAC_BITS - 6); -#else - return i >> (6 - CAIRO_FIXED_FRAC_BITS); -#endif -} - -static inline double -_cairo_fixed_to_double (cairo_fixed_t f) -{ - return ((double) f) / CAIRO_FIXED_ONE_DOUBLE; -} - -static inline int -_cairo_fixed_is_integer (cairo_fixed_t f) -{ - return (f & CAIRO_FIXED_FRAC_MASK) == 0; -} - -static inline int -_cairo_fixed_integer_part (cairo_fixed_t f) -{ - return f >> CAIRO_FIXED_FRAC_BITS; -} - -static inline int -_cairo_fixed_integer_floor (cairo_fixed_t f) -{ - if (f >= 0) - return f >> CAIRO_FIXED_FRAC_BITS; - else - return -((-f - 1) >> CAIRO_FIXED_FRAC_BITS) - 1; -} - -static inline int -_cairo_fixed_integer_ceil (cairo_fixed_t f) -{ - if (f > 0) - return ((f - 1)>>CAIRO_FIXED_FRAC_BITS) + 1; - else - return - (-f >> CAIRO_FIXED_FRAC_BITS); -} - -/* A bunch of explicit 16.16 operators; we need these - * to interface with pixman and other backends that require - * 16.16 fixed point types. - */ -static inline cairo_fixed_16_16_t -_cairo_fixed_to_16_16 (cairo_fixed_t f) -{ -#if (CAIRO_FIXED_FRAC_BITS == 16) && (CAIRO_FIXED_BITS == 32) - return f; -#elif CAIRO_FIXED_FRAC_BITS > 16 - /* We're just dropping the low bits, so we won't ever got over/underflow here */ - return f >> (CAIRO_FIXED_FRAC_BITS - 16); -#else - cairo_fixed_16_16_t x; - - /* Handle overflow/underflow by clamping to the lowest/highest - * value representable as 16.16 - */ - if ((f >> CAIRO_FIXED_FRAC_BITS) < INT16_MIN) { - x = INT32_MIN; - } else if ((f >> CAIRO_FIXED_FRAC_BITS) > INT16_MAX) { - x = INT32_MAX; - } else { - x = f << (16 - CAIRO_FIXED_FRAC_BITS); - } - - return x; -#endif -} - -static inline cairo_fixed_16_16_t -_cairo_fixed_16_16_from_double (double d) -{ - union { - double d; - int32_t i[2]; - } u; - - u.d = d + CAIRO_MAGIC_NUMBER_FIXED_16_16; -#ifdef FLOAT_WORDS_BIGENDIAN - return u.i[1]; -#else - return u.i[0]; -#endif -} - -#if CAIRO_FIXED_BITS == 32 - -static inline cairo_fixed_t -_cairo_fixed_mul (cairo_fixed_t a, cairo_fixed_t b) -{ - cairo_int64_t temp = _cairo_int32x32_64_mul (a, b); - return _cairo_int64_to_int32(_cairo_int64_rsl (temp, CAIRO_FIXED_FRAC_BITS)); -} - -/* computes a * b / c */ -static inline cairo_fixed_t -_cairo_fixed_mul_div (cairo_fixed_t a, cairo_fixed_t b, cairo_fixed_t c) -{ - cairo_int64_t ab = _cairo_int32x32_64_mul (a, b); - cairo_int64_t c64 = _cairo_int32_to_int64 (c); - cairo_int64_t quo = _cairo_int64_divrem (ab, c64).quo; - - return _cairo_int64_to_int32(quo); -} - -#else -# error Please define multiplication and other operands for your fixed-point type size -#endif - -#endif /* CAIRO_FIXED_PRIVATE_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-fixed-type-private.h b/uppdev/plugin/cairo/lib/cairo-fixed-type-private.h deleted file mode 100644 index 7dd579706..000000000 --- a/uppdev/plugin/cairo/lib/cairo-fixed-type-private.h +++ /dev/null @@ -1,70 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* Cairo - a vector graphics library with display and print output - * - * Copyright © 2007 Mozilla Corporation - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Mozilla Corporation - * - * Contributor(s): - * Vladimir Vukicevic - */ - -#ifndef CAIRO_FIXED_TYPE_PRIVATE_H -#define CAIRO_FIXED_TYPE_PRIVATE_H - -#include "cairo-wideint-type-private.h" - -/* - * Fixed-point configuration - */ - -typedef int32_t cairo_fixed_16_16_t; -typedef cairo_int64_t cairo_fixed_32_32_t; -typedef cairo_int64_t cairo_fixed_48_16_t; -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 - * size of a fixed type. For now, it must be 32. - */ -#define CAIRO_FIXED_BITS 32 - -/* The number of fractional bits. Changing this involves - * making sure that you compute a double-to-fixed magic number. - * (see below). - */ -#define CAIRO_FIXED_FRAC_BITS 8 - -/* A signed type %CAIRO_FIXED_BITS in size; the main fixed point type */ -typedef int32_t cairo_fixed_t; - -/* An unsigned type of the same size as #cairo_fixed_t */ -typedef uint32_t cairo_fixed_unsigned_t; - -#endif /* CAIRO_FIXED_TYPE_PRIVATE_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-fixed.c b/uppdev/plugin/cairo/lib/cairo-fixed.c deleted file mode 100644 index 2bb0dfe17..000000000 --- a/uppdev/plugin/cairo/lib/cairo-fixed.c +++ /dev/null @@ -1,39 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2003 University of Southern California - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - */ - -#include "cairoint.h" - -#include "cairo-fixed-private.h" diff --git a/uppdev/plugin/cairo/lib/cairo-font-face-twin-data.c b/uppdev/plugin/cairo/lib/cairo-font-face-twin-data.c deleted file mode 100644 index 7a703244a..000000000 --- a/uppdev/plugin/cairo/lib/cairo-font-face-twin-data.c +++ /dev/null @@ -1,1030 +0,0 @@ -/* See cairo-font-face-twin.c for copyright info */ - -#include "cairoint.h" - -const int8_t _cairo_twin_outlines[] = { -/* 0x0 '\0' offset 0 */ - 0, 24, 42, 0, 2, 4, - 0, 24, /* snap_x */ - -42, -21, -15, 0, /* snap_y */ - 'm', 0, 0, - 'l', 0, -42, - 'l', 24, -42, - 'l', 24, 0, - 'l', 0, 0, - 'e', -/* 0x20 ' ' offset 28 */ - 0, 4, 0, 0, 2, 3, - -128, 0, /* snap_x */ - -21, -15, 0, /* snap_y */ - 'e', -/* 0x21 '!' offset 40 */ - 0, 4, 42, 0, 3, 3, - 0, 2, 4, /* snap_x */ - -21, -15, 0, /* snap_y */ - 'm', 2, -42, - 'l', 2, -14, - 'm', 2, -4, - 'c', 1, -4, 0, -3, 0, -2, - 'c', 0, -1, 1, 0, 2, 0, - 'c', 3, 0, 4, -1, 4, -2, - 'c', 4, -3, 3, -4, 2, -4, - 'e', -/* 0x22 '"' offset 90 */ - 0, 16, 42, -28, 2, 3, - 0, 16, /* snap_x */ - -21, -15, 0, /* snap_y */ - 'm', 0, -42, - 'l', 0, -28, - 'm', 16, -42, - 'l', 16, -28, - 'e', -/* 0x23 '#' offset 114 */ - 0, 30, 50, 14, 2, 5, - 0, 30, /* snap_x */ - -24, -21, -15, -12, 0, /* snap_y */ - 'm', 16, -50, - 'l', 2, 14, - 'm', 28, -50, - 'l', 14, 14, - 'm', 2, -24, - 'l', 30, -24, - 'm', 0, -12, - 'l', 28, -12, - 'e', -/* 0x24 '$' offset 152 */ - 0, 28, 50, 8, 4, 4, - 0, 10, 18, 28, /* snap_x */ - -42, -21, -15, 0, /* snap_y */ - 'm', 10, -50, - 'l', 10, 8, - 'm', 18, -50, - 'l', 18, 8, - 'm', 28, -36, - 'c', 24, -42, 18, -42, 14, -42, - 'c', 10, -42, 0, -42, 0, -34, - 'c', 0, -25, 8, -24, 14, -22, - 'c', 20, -20, 28, -19, 28, -9, - 'c', 28, 0, 18, 0, 14, 0, - 'c', 10, 0, 4, 0, 0, -6, - 'e', -/* 0x25 '%' offset 224 */ - 0, 36, 42, 0, 4, 7, - 0, 14, 22, 36, /* snap_x */ - -42, -38, -28, -21, -15, -14, 0, /* snap_y */ - 'm', 10, -42, - 'c', 12, -41, 14, -40, 14, -36, - 'c', 14, -30, 11, -28, 6, -28, - 'c', 2, -28, 0, -30, 0, -34, - 'c', 0, -39, 3, -42, 8, -42, - 'l', 10, -42, - 'c', 18, -37, 28, -37, 36, -42, - 'l', 0, 0, - 'm', 28, -14, - 'c', 24, -14, 22, -11, 22, -6, - 'c', 22, -2, 24, 0, 28, 0, - 'c', 33, 0, 36, -2, 36, -8, - 'c', 36, -12, 34, -14, 30, -14, - 'l', 28, -14, - 'e', - 'X', 'X', 'X', -/* 0x26 '&' offset 323 */ - 0, 40, 42, 0, 4, 4, - 0, 10, 22, 40, /* snap_x */ - -28, -21, -15, 0, /* snap_y */ - 'm', 40, -24, - 'c', 40, -27, 39, -28, 37, -28, - 'c', 29, -28, 32, 0, 12, 0, - 'c', 0, 0, 0, -8, 0, -10, - 'c', 0, -24, 22, -20, 22, -34, - 'c', 22, -45, 10, -45, 10, -34, - 'c', 10, -27, 25, 0, 36, 0, - 'c', 39, 0, 40, -1, 40, -4, - 'e', -/* 0x27 ''' offset 390 */ - 0, 4, 42, -30, 2, 3, - 0, 4, /* snap_x */ - -21, -15, 0, /* snap_y */ - 'm', 2, -38, - 'c', -1, -38, -1, -42, 2, -42, - 'c', 6, -42, 5, -33, 0, -30, - 'e', -/* 0x28 '(' offset 419 */ - 0, 14, 50, 14, 2, 3, - 0, 14, /* snap_x */ - -21, -15, 0, /* snap_y */ - 'm', 14, -50, - 'c', -5, -32, -5, -5, 14, 14, - 'e', -/* 0x29 ')' offset 441 */ - 0, 14, 50, 14, 2, 3, - 0, 14, /* snap_x */ - -21, -15, 0, /* snap_y */ - 'm', 0, -50, - 'c', 19, -34, 19, -2, 0, 14, - 'e', -/* 0x2a '*' offset 463 */ - 0, 20, 30, -6, 3, 3, - 0, 10, 20, /* snap_x */ - -21, -15, 0, /* snap_y */ - 'm', 10, -30, - 'l', 10, -6, - 'm', 0, -24, - 'l', 20, -12, - 'm', 20, -24, - 'l', 0, -12, - 'e', -/* 0x2b '+' offset 494 */ - 0, 36, 36, 0, 3, 4, - 0, 18, 36, /* snap_x */ - -21, -18, -15, 0, /* snap_y */ - 'm', 18, -36, - 'l', 18, 0, - 'm', 0, -18, - 'l', 36, -18, - 'e', -/* 0x2c ',' offset 520 */ - 0, 4, 4, 8, 2, 3, - 0, 4, /* snap_x */ - -21, -15, 0, /* snap_y */ - 'm', 4, -2, - 'c', 4, 1, 0, 1, 0, -2, - 'c', 0, -5, 4, -5, 4, -2, - 'c', 4, 4, 2, 6, 0, 8, - 'e', -/* 0x2d '-' offset 556 */ - 0, 36, 18, -18, 2, 4, - 0, 36, /* snap_x */ - -21, -18, -15, 0, /* snap_y */ - 'm', 0, -18, - 'l', 36, -18, - 'e', -/* 0x2e '.' offset 575 */ - 0, 4, 4, 0, 2, 3, - 0, 4, /* snap_x */ - -21, -15, 0, /* snap_y */ - 'm', 2, -4, - 'c', -1, -4, -1, 0, 2, 0, - 'c', 5, 0, 5, -4, 2, -4, - 'e', -/* 0x2f '/' offset 604 */ - 0, 36, 50, 14, 2, 3, - 0, 36, /* snap_x */ - -21, -15, 0, /* snap_y */ - 'm', 36, -50, - 'l', 0, 14, - 'e', -/* 0x30 '0' offset 622 */ - 0, 28, 42, 0, 2, 4, - 0, 28, /* snap_x */ - -42, -21, -15, 0, /* snap_y */ - 'm', 14, -42, - 'c', 9, -42, 0, -42, 0, -21, - 'c', 0, 0, 9, 0, 14, 0, - 'c', 19, 0, 28, 0, 28, -21, - 'c', 28, -42, 19, -42, 14, -42, - 'E', -/* 0x31 '1' offset 666 */ - 0, 28, 42, 0, 2, 3, - 0, 17, 28 /* snap_x */ - -21, -15, 0, /* snap_y */ - 'm', 7, -34, - 'c', 11, -35, 15, -38, 17, -42, - 'l', 17, 0, - 'e', -/* 0x32 '2' offset 691 */ - 0, 28, 42, 0, 4, 4, - 0, 2, 26, 28, /* snap_x */ - -42, -21, -15, 0, /* snap_y */ - 'm', 2, -32, - 'c', 2, -34, 2, -42, 14, -42, - 'c', 26, -42, 26, -34, 26, -32, - 'c', 26, -30, 25, -25, 10, -10, - 'l', 0, 0, - 'l', 28, 0, - 'e', -/* 0x33 '3' offset 736 */ - 0, 28, 42, 0, 2, 5, - 0, 28, /* snap_x */ - -42, -26, -21, -15, 0, /* snap_y */ - 'm', 4, -42, - 'l', 26, -42, - 'l', 14, -26, - 'c', 21, -26, 28, -26, 28, -14, - 'c', 28, 0, 17, 0, 13, 0, - 'c', 8, 0, 3, -1, 0, -8, - 'e', -/* 0x34 '4' offset 780 */ - 0, 28, 42, 0, 3, 4, - 0, 20, 30, /* snap_x */ - -21, -15, -14, 0, /* snap_y */ - 'm', 20, 0, - 'l', 20, -42, - 'l', 0, -14, - 'l', 30, -14, - 'e', - 'X', 'X', 'X', -/* 0x35 '5' offset 809 */ - 0, 28, 42, 0, 2, 5, - 0, 28, /* snap_x */ - -42, -28, -21, -15, 0, /* snap_y */ - 'm', 24, -42, - 'l', 4, -42, - 'l', 2, -24, - 'c', 5, -27, 10, -28, 13, -28, - 'c', 16, -28, 28, -28, 28, -14, - 'c', 28, 0, 16, 0, 13, 0, - 'c', 10, 0, 3, 0, 0, -8, - 'e', -/* 0x36 '6' offset 860 */ - 0, 28, 42, 0, 2, 5, - 0, 26, /* snap_x */ - -42, -26, -21, -15, 0, /* snap_y */ - 'm', 24, -36, - 'c', 22, -41, 19, -42, 14, -42, - 'c', 9, -42, 0, -41, 0, -19, - 'c', 0, -1, 9, 0, 13, 0, - 'c', 18, 0, 26, -3, 26, -13, - 'c', 26, -18, 23, -26, 13, -26, - 'c', 10, -26, 1, -24, 0, -14, - 'e', -/* 0x37 '7' offset 919 */ - 0, 28, 42, 0, 2, 4, - 0, 28, /* snap_x */ - -42, -21, -15, 0, /* snap_y */ - 'm', 0, -42, - 'l', 28, -42, - 'l', 8, 0, - 'e', - 'X', 'X', 'X', -/* 0x38 '8' offset 944 */ - 0, 28, 42, 0, 4, 4, - 0, 2, 26, 28, /* snap_x */ - -42, -21, -15, 0, /* snap_y */ - 'm', 14, -42, - 'c', 5, -42, 2, -40, 2, -34, - 'c', 2, -18, 28, -32, 28, -11, - 'c', 28, 0, 18, 0, 14, 0, - 'c', 10, 0, 0, 0, 0, -11, - 'c', 0, -32, 26, -18, 26, -34, - 'c', 26, -40, 23, -42, 14, -42, - 'E', -/* 0x39 '9' offset 1004 */ - 0, 28, 42, 0, 2, 5, - 0, 26, /* snap_x */ - -42, -21, -16, -15, 0, /* snap_y */ - 'm', 26, -28, - 'c', 25, -16, 13, -16, 13, -16, - 'c', 8, -16, 0, -19, 0, -29, - 'c', 0, -34, 3, -42, 13, -42, - 'c', 24, -42, 26, -32, 26, -23, - 'c', 26, -14, 24, 0, 12, 0, - 'c', 7, 0, 4, -2, 2, -6, - 'e', -/* 0x3a ':' offset 1063 */ - 0, 4, 28, 0, 2, 3, - 0, 4, /* snap_x */ - -21, -15, 0, /* snap_y */ - 'm', 2, -28, - 'c', -1, -28, -1, -24, 2, -24, - 'c', 5, -24, 5, -28, 2, -28, - 'm', 2, -4, - 'c', -1, -4, -1, 0, 2, 0, - 'c', 5, 0, 5, -4, 2, -4, - 'e', -/* 0x3b ';' offset 1109 */ - 0, 4, 28, 8, 2, 3, - 0, 4, /* snap_x */ - -21, -15, 0, /* snap_y */ - 'm', 2, -28, - 'c', -1, -28, -1, -24, 2, -24, - 'c', 5, -24, 5, -28, 2, -28, - 'm', 4, -2, - 'c', 4, 1, 0, 1, 0, -2, - 'c', 0, -5, 4, -5, 4, -2, - 'c', 4, 3, 2, 6, 0, 8, - 'e', -/* 0x3c '<' offset 1162 */ - 0, 32, 36, 0, 2, 3, - 0, 32, /* snap_x */ - -21, -15, 0, /* snap_y */ - 'm', 32, -36, - 'l', 0, -18, - 'l', 32, 0, - 'e', -/* 0x3d '=' offset 1183 */ - 0, 36, 24, -12, 2, 5, - 0, 36, /* snap_x */ - -24, -21, -15, -12, 0, /* snap_y */ - 'm', 0, -24, - 'l', 36, -24, - 'm', 0, -12, - 'l', 36, -12, - 'e', -/* 0x3e '>' offset 1209 */ - 0, 32, 36, 0, 2, 3, - 0, 32, /* snap_x */ - -21, -15, 0, /* snap_y */ - 'm', 0, -36, - 'l', 32, -18, - 'l', 0, 0, - 'e', -/* 0x3f '?' offset 1230 */ - 0, 24, 42, 0, 3, 4, - 0, 12, 24, /* snap_x */ - -42, -21, -15, 0, /* snap_y */ - 'm', 0, -32, - 'c', 0, -34, 0, -42, 12, -42, - 'c', 24, -42, 24, -34, 24, -32, - 'c', 24, -29, 24, -24, 12, -20, - 'l', 12, -14, - 'm', 12, -4, - 'c', 9, -4, 9, 0, 12, 0, - 'c', 15, 0, 15, -4, 12, -4, - 'e', -/* 0x40 '@' offset 1288 */ - 0, 42, 42, 0, 1, 6, - 30, /* snap_x */ - -42, -32, -21, -15, -10, 0, /* snap_y */ - 'm', 30, -26, - 'c', 28, -31, 24, -32, 21, -32, - 'c', 10, -32, 10, -23, 10, -19, - 'c', 10, -13, 11, -10, 19, -10, - 'c', 30, -10, 28, -21, 30, -32, - 'c', 27, -10, 30, -10, 34, -10, - 'c', 41, -10, 42, -19, 42, -22, - 'c', 42, -34, 34, -42, 21, -42, - 'c', 9, -42, 0, -34, 0, -21, - 'c', 0, -9, 8, 0, 21, 0, - 'c', 30, 0, 34, -3, 36, -6, - 'e', -/* 0x41 'A' offset 1375 */ - 0, 32, 42, 0, 2, 4, - 0, 32, /* snap_x */ - -21, -15, -14, 0, /* snap_y */ - 'm', 0, 0, - 'l', 16, -42, - 'l', 32, 0, - 'm', 6, -14, - 'l', 26, -14, - 'e', - 'X', 'X', 'X', -/* 0x42 'B' offset 1406 */ - 0, 28, 42, 0, 2, 5, - 0, 28, /* snap_x */ - -42, -22, -21, -15, 0, /* snap_y */ - 'm', 0, 0, - 'l', 0, -42, - 'l', 18, -42, - 'c', 32, -42, 32, -22, 18, -22, - 'l', 0, -22, - 'l', 18, -22, - 'c', 32, -22, 32, 0, 18, 0, - 'E', - 'X', 'X', 'X', - 'X', 'X', 'X', -/* 0x43 'C' offset 1455 */ - 0, 30, 42, 0, 2, 4, - 0, 30, /* snap_x */ - -42, -21, -15, 0, /* snap_y */ - 'm', 30, -32, - 'c', 26, -42, 21, -42, 16, -42, - 'c', 2, -42, 0, -29, 0, -21, - 'c', 0, -13, 2, 0, 16, 0, - 'c', 21, 0, 26, 0, 30, -10, - 'e', -/* 0x44 'D' offset 1499 */ - 0, 28, 42, 0, 2, 4, - 0, 28, /* snap_x */ - -42, -21, -15, 0, /* snap_y */ - 'm', 0, 0, - 'l', 0, -42, - 'l', 14, -42, - 'c', 33, -42, 33, 0, 14, 0, - 'E', - 'X', 'X', 'X', - 'X', 'X', 'X', -/* 0x45 'E' offset 1534 */ - 0, 26, 42, 0, 2, 5, - 0, 26, /* snap_x */ - -42, -22, -21, -15, 0, /* snap_y */ - 'm', 26, -42, - 'l', 0, -42, - 'l', 0, 0, - 'l', 26, 0, - 'm', 0, -22, - 'l', 16, -22, - 'e', - 'X', 'X', 'X', - 'X', 'X', 'X', -/* 0x46 'F' offset 1572 */ - 0, 26, 42, 0, 2, 5, - 0, 26, /* snap_x */ - -42, -22, -21, -15, 0, /* snap_y */ - 'm', 0, 0, - 'l', 0, -42, - 'l', 26, -42, - 'm', 0, -22, - 'l', 16, -22, - 'e', - 'X', 'X', 'X', -/* 0x47 'G' offset 1604 */ - 0, 30, 42, 0, 2, 5, - 0, 30, /* snap_x */ - -42, -21, -16, -15, 0, /* snap_y */ - 'm', 30, -32, - 'c', 26, -42, 21, -42, 16, -42, - 'c', 2, -42, 0, -29, 0, -21, - 'c', 0, -13, 2, 0, 16, 0, - 'c', 28, 0, 30, -7, 30, -16, - 'l', 20, -16, - 'e', - 'X', 'X', 'X', -/* 0x48 'H' offset 1655 */ - 0, 28, 42, 0, 2, 4, - 0, 28, /* snap_x */ - -22, -21, -15, 0, /* snap_y */ - 'm', 0, -42, - 'l', 0, 0, - 'm', 28, -42, - 'l', 28, 0, - 'm', 0, -22, - 'l', 28, -22, - 'e', -/* 0x49 'I' offset 1686 */ - 0, 0, 42, 0, 1, 3, - 0, /* snap_x */ - -21, -15, 0, /* snap_y */ - 'm', 0, -42, - 'l', 0, 0, - 'e', -/* 0x4a 'J' offset 1703 */ - 0, 20, 42, 0, 2, 3, - 0, 20, /* snap_x */ - -21, -15, 0, /* snap_y */ - 'm', 20, -42, - 'l', 20, -10, - 'c', 20, 3, 0, 3, 0, -10, - 'l', 0, -14, - 'e', -/* 0x4b 'K' offset 1731 */ - 0, 28, 42, 0, 2, 3, - 0, 28, /* snap_x */ - -21, -15, 0, /* snap_y */ - 'm', 0, -42, - 'l', 0, 0, - 'm', 28, -42, - 'l', 0, -14, - 'm', 10, -24, - 'l', 28, 0, - 'e', -/* 0x4c 'L' offset 1761 */ - 0, 24, 42, 0, 2, 3, - 0, 24, /* snap_x */ - -21, -15, 0, /* snap_y */ - 'm', 0, -42, - 'l', 0, 0, - 'l', 24, 0, - 'e', - 'X', 'X', 'X', -/* 0x4d 'M' offset 1785 */ - 0, 32, 42, 0, 2, 3, - 0, 32, /* snap_x */ - -21, -15, 0, /* snap_y */ - 'm', 0, 0, - 'l', 0, -42, - 'l', 16, 0, - 'l', 32, -42, - 'l', 32, 0, - 'e', - 'X', 'X', 'X', - 'X', 'X', 'X', - 'X', 'X', 'X', -/* 0x4e 'N' offset 1821 */ - 0, 28, 42, 0, 2, 3, - 0, 28, /* snap_x */ - -21, -15, 0, /* snap_y */ - 'm', 0, 0, - 'l', 0, -42, - 'l', 28, 0, - 'l', 28, -42, - 'e', - 'X', 'X', 'X', - 'X', 'X', 'X', -/* 0x4f 'O' offset 1851 */ - 0, 32, 42, 0, 2, 4, - 0, 32, /* snap_x */ - -42, -21, -15, 0, /* snap_y */ - 'm', 16, -42, - 'c', 2, -42, 0, -29, 0, -21, - 'c', 0, -13, 2, 0, 16, 0, - 'c', 30, 0, 32, -13, 32, -21, - 'c', 32, -29, 30, -42, 16, -42, - 'E', -/* 0x50 'P' offset 1895 */ - 0, 28, 42, 0, 2, 5, - 0, 28, /* snap_x */ - -42, -21, -20, -15, 0, /* snap_y */ - 'm', 0, 0, - 'l', 0, -42, - 'l', 18, -42, - 'c', 32, -42, 32, -20, 18, -20, - 'l', 0, -20, - 'e', - 'X', 'X', 'X', -/* 0x51 'Q' offset 1931 */ - 0, 32, 42, 4, 2, 4, - 0, 32, /* snap_x */ - -42, -21, -15, 0, /* snap_y */ - 'm', 16, -42, - 'c', 2, -42, 0, -29, 0, -21, - 'c', 0, -13, 2, 0, 16, 0, - 'c', 30, 0, 32, -13, 32, -21, - 'c', 32, -29, 30, -42, 16, -42, - 'm', 18, -8, - 'l', 30, 4, - 'e', -/* 0x52 'R' offset 1981 */ - 0, 28, 42, 0, 2, 5, - 0, 28, /* snap_x */ - -42, -22, -21, -15, 0, /* snap_y */ - 'm', 0, 0, - 'l', 0, -42, - 'l', 18, -42, - 'c', 32, -42, 31, -22, 18, -22, - 'l', 0, -22, - 'm', 14, -22, - 'l', 28, 0, - 'e', - 'X', 'X', 'X', -/* 0x53 'S' offset 2023 */ - 0, 28, 42, 0, 2, 4, - 0, 28, /* snap_x */ - -42, -21, -15, 0, /* snap_y */ - 'm', 28, -36, - 'c', 25, -41, 21, -42, 14, -42, - 'c', 10, -42, 0, -42, 0, -34, - 'c', 0, -17, 28, -28, 28, -9, - 'c', 28, 0, 19, 0, 14, 0, - 'c', 7, 0, 3, -1, 0, -6, - 'e', -/* 0x54 'T' offset 2074 */ - 0, 28, 42, 0, 3, 4, - 0, 14, 28, /* snap_x */ - -42, -21, -15, 0, /* snap_y */ - 'm', 14, -42, - 'l', 14, 0, - 'm', 0, -42, - 'l', 28, -42, - 'e', -/* 0x55 'U' offset 2100 */ - 0, 28, 42, 0, 2, 3, - 0, 28, /* snap_x */ - -21, -15, 0, /* snap_y */ - 'm', 0, -42, - 'l', 0, -12, - 'c', 0, 4, 28, 4, 28, -12, - 'l', 28, -42, - 'e', -/* 0x56 'V' offset 2128 */ - 0, 32, 42, 0, 2, 3, - 0, 32, /* snap_x */ - -21, -15, 0, /* snap_y */ - 'm', 0, -42, - 'l', 16, 0, - 'l', 32, -42, - 'e', - 'X', 'X', 'X', -/* 0x57 'W' offset 2152 */ - 0, 40, 42, 0, 2, 3, - 0, 40, /* snap_x */ - -21, -15, 0, /* snap_y */ - 'm', 0, -42, - 'l', 10, 0, - 'l', 20, -42, - 'l', 30, 0, - 'l', 40, -42, - 'e', - 'X', 'X', 'X', - 'X', 'X', 'X', - 'X', 'X', 'X', -/* 0x58 'X' offset 2188 */ - 0, 28, 42, 0, 2, 3, - 0, 28, /* snap_x */ - -21, -15, 0, /* snap_y */ - 'm', 0, -42, - 'l', 28, 0, - 'm', 28, -42, - 'l', 0, 0, - 'e', -/* 0x59 'Y' offset 2212 */ - 0, 32, 42, 0, 3, 3, - 0, 16, 32, /* snap_x */ - -21, -15, 0, /* snap_y */ - 'm', 0, -42, - 'l', 16, -22, - 'l', 16, 0, - 'm', 32, -42, - 'l', 16, -22, - 'e', -/* 0x5a 'Z' offset 2240 */ - 0, 28, 42, 0, 2, 4, - 0, 28, /* snap_x */ - -42, -21, -15, 0, /* snap_y */ - 'm', 28, 0, - 'l', 0, 0, - 'l', 28, -42, - 'l', 0, -42, - 'e', - 'X', 'X', 'X', - 'X', 'X', 'X', -/* 0x5b '[' offset 2271 */ - 0, 14, 44, 0, 2, 4, - 0, 14, /* snap_x */ - -44, -21, -15, 0, /* snap_y */ - 'm', 14, -44, - 'l', 0, -44, - 'l', 0, 0, - 'l', 14, 0, - 'e', -/* 0x5c '\' offset 2296 */ - 0, 36, 50, 14, 2, 3, - 0, 36, /* snap_x */ - -21, -15, 0, /* snap_y */ - 'm', 0, -50, - 'l', 36, 14, - 'e', -/* 0x5d ']' offset 2314 */ - 0, 14, 44, 0, 2, 4, - 0, 14, /* snap_x */ - -44, -21, -15, 0, /* snap_y */ - 'm', 0, -44, - 'l', 14, -44, - 'l', 14, 0, - 'l', 0, 0, - 'e', -/* 0x5e '^' offset 2339 */ - 0, 32, 46, -18, 2, 3, - 0, 32, /* snap_x */ - -21, -15, 0, /* snap_y */ - 'm', 0, -18, - 'l', 16, -46, - 'l', 32, -18, - 'e', - 'X', 'X', 'X', -/* 0x5f '_' offset 2363 */ - 0, 36, 0, 0, 2, 3, - 0, 36, /* snap_x */ - -21, -15, 0, /* snap_y */ - 'm', 0, 0, - 'l', 36, 0, - 'e', -/* 0x60 '`' offset 2381 */ - 0, 4, 42, -30, 2, 3, - 0, 4, /* snap_x */ - -21, -15, 0, /* snap_y */ - 'm', 4, -42, - 'c', 2, -40, 0, -39, 0, -32, - 'c', 0, -31, 1, -30, 2, -30, - 'c', 5, -30, 5, -34, 2, -34, - 'e', -/* 0x61 'a' offset 2417 */ - 0, 24, 28, 0, 2, 4, - 0, 24, /* snap_x */ - -28, -21, -15, 0, /* snap_y */ - 'm', 24, -28, - 'l', 24, 0, - 'm', 24, -22, - 'c', 21, -27, 18, -28, 13, -28, - 'c', 2, -28, 0, -19, 0, -14, - 'c', 0, -9, 2, 0, 13, 0, - 'c', 18, 0, 21, -1, 24, -6, - 'e', -/* 0x62 'b' offset 2467 */ - 0, 24, 42, 0, 2, 4, - 0, 24, /* snap_x */ - -28, -21, -15, 0, /* snap_y */ - 'm', 0, -42, - 'l', 0, 0, - 'm', 0, -22, - 'c', 3, -26, 6, -28, 11, -28, - 'c', 22, -28, 24, -19, 24, -14, - 'c', 24, -9, 22, 0, 11, 0, - 'c', 6, 0, 3, -2, 0, -6, - 'e', -/* 0x63 'c' offset 2517 */ - 0, 24, 28, 0, 2, 4, - 0, 24, /* snap_x */ - -28, -21, -15, 0, /* snap_y */ - 'm', 24, -22, - 'c', 21, -26, 18, -28, 13, -28, - 'c', 2, -28, 0, -19, 0, -14, - 'c', 0, -9, 2, 0, 13, 0, - 'c', 18, 0, 21, -2, 24, -6, - 'e', -/* 0x64 'd' offset 2561 */ - 0, 24, 42, 0, 2, 4, - 0, 24, /* snap_x */ - -28, -21, -15, 0, /* snap_y */ - 'm', 24, -42, - 'l', 24, 0, - 'm', 24, -22, - 'c', 21, -26, 18, -28, 13, -28, - 'c', 2, -28, 0, -19, 0, -14, - 'c', 0, -9, 2, 0, 13, 0, - 'c', 18, 0, 21, -2, 24, -6, - 'e', -/* 0x65 'e' offset 2611 */ - 0, 24, 28, 0, 2, 5, - 0, 24, /* snap_x */ - -28, -21, -16, -15, 0, /* snap_y */ - 'm', 0, -16, - 'l', 24, -16, - 'c', 24, -20, 24, -28, 13, -28, - 'c', 2, -28, 0, -19, 0, -14, - 'c', 0, -9, 2, 0, 13, 0, - 'c', 18, 0, 21, -2, 24, -6, - 'e', -/* 0x66 'f' offset 2659 */ - 0, 16, 42, 0, 3, 5, - 0, 6, 16, /* snap_x */ - -42, -28, -21, -15, 0, /* snap_y */ - 'm', 16, -42, - 'c', 8, -42, 6, -40, 6, -34, - 'l', 6, 0, - 'm', 0, -28, - 'l', 14, -28, - 'e', -/* 0x67 'g' offset 2693 */ - 0, 24, 28, 14, 2, 5, - 0, 24, /* snap_x */ - -28, -21, -15, 0, 14, /* snap_y */ - 'm', 24, -28, - 'l', 24, 4, - 'c', 23, 14, 16, 14, 13, 14, - 'c', 10, 14, 8, 14, 6, 12, - 'm', 24, -22, - 'c', 21, -26, 18, -28, 13, -28, - 'c', 2, -28, 0, -19, 0, -14, - 'c', 0, -9, 2, 0, 13, 0, - 'c', 18, 0, 21, -2, 24, -6, - 'e', -/* 0x68 'h' offset 2758 */ - 0, 22, 42, 0, 2, 4, - 0, 22, /* snap_x */ - -28, -21, -15, 0, /* snap_y */ - 'm', 0, -42, - 'l', 0, 0, - 'm', 0, -20, - 'c', 8, -32, 22, -31, 22, -20, - 'l', 22, 0, - 'e', -/* 0x69 'i' offset 2790 */ - 0, 4, 44, 0, 3, 3, - 0, 2, 4, /* snap_x */ - -21, -15, 0, /* snap_y */ - 'm', 0, -42, - 'c', 0, -39, 4, -39, 4, -42, - 'c', 4, -45, 0, -45, 0, -42, - 'm', 2, -28, - 'l', 2, 0, - 'e', -/* 0x6a 'j' offset 2826 */ - -8, 4, 44, 14, 3, 4, - 0, 2, 4, /* snap_x */ - -21, -15, 0, 14, /* snap_y */ - 'm', 0, -42, - 'c', 0, -39, 4, -39, 4, -42, - 'c', 4, -45, 0, -45, 0, -42, - 'm', 2, -28, - 'l', 2, 6, - 'c', 2, 13, -1, 14, -8, 14, - 'e', -/* 0x6b 'k' offset 2870 */ - 0, 22, 42, 0, 2, 3, - 0, 22, /* snap_x */ - -21, -15, 0, /* snap_y */ - 'm', 0, -42, - 'l', 0, 0, - 'm', 20, -28, - 'l', 0, -8, - 'm', 8, -16, - 'l', 22, 0, - 'e', -/* 0x6c 'l' offset 2900 */ - 0, 0, 42, 0, 1, 3, - 0, /* snap_x */ - -21, -15, 0, /* snap_y */ - 'm', 0, -42, - 'l', 0, 0, - 'e', -/* 0x6d 'm' offset 2917 */ - 0, 44, 28, 0, 3, 4, - 0, 22, 44, /* snap_x */ - -28, -21, -15, 0, /* snap_y */ - 'm', 0, -28, - 'l', 0, 0, - 'm', 0, -20, - 'c', 5, -29, 22, -33, 22, -20, - 'l', 22, 0, - 'm', 22, -20, - 'c', 27, -29, 44, -33, 44, -20, - 'l', 44, 0, - 'e', -/* 0x6e 'n' offset 2963 */ - 0, 22, 28, 0, 2, 4, - 0, 22, /* snap_x */ - -28, -21, -15, 0, /* snap_y */ - 'm', 0, -28, - 'l', 0, 0, - 'm', 0, -20, - 'c', 4, -28, 22, -34, 22, -20, - 'l', 22, 0, - 'e', -/* 0x6f 'o' offset 2995 */ - 0, 26, 28, 0, 2, 4, - 0, 26, /* snap_x */ - -28, -21, -15, 0, /* snap_y */ - 'm', 13, -28, - 'c', 2, -28, 0, -19, 0, -14, - 'c', 0, -9, 2, 0, 13, 0, - 'c', 24, 0, 26, -9, 26, -14, - 'c', 26, -19, 24, -28, 13, -28, - 'e', -/* 0x70 'p' offset 3039 */ - 0, 24, 28, 14, 2, 4, - 0, 24, /* snap_x */ - -28, -21, -15, 0, /* snap_y */ - 'm', 0, -28, - 'l', 0, 14, - 'm', 0, -22, - 'c', 3, -26, 6, -28, 11, -28, - 'c', 22, -28, 24, -19, 24, -14, - 'c', 24, -9, 22, 0, 11, 0, - 'c', 6, 0, 3, -2, 0, -6, - 'e', -/* 0x71 'q' offset 3089 */ - 0, 24, 28, 14, 2, 4, - 0, 24, /* snap_x */ - -28, -21, -15, 0, /* snap_y */ - 'm', 24, -28, - 'l', 24, 14, - 'm', 24, -22, - 'c', 21, -26, 18, -28, 13, -28, - 'c', 2, -28, 0, -19, 0, -14, - 'c', 0, -9, 2, 0, 13, 0, - 'c', 18, 0, 21, -2, 24, -6, - 'e', -/* 0x72 'r' offset 3139 */ - 0, 16, 28, 0, 2, 4, - 0, 16, /* snap_x */ - -28, -21, -15, 0, /* snap_y */ - 'm', 0, -28, - 'l', 0, 0, - 'm', 0, -16, - 'c', 2, -27, 7, -28, 16, -28, - 'e', -/* 0x73 's' offset 3168 */ - 0, 22, 28, 0, 2, 4, - 0, 22, /* snap_x */ - -28, -21, -15, 0, /* snap_y */ - 'm', 22, -22, - 'c', 22, -27, 16, -28, 11, -28, - 'c', 4, -28, 0, -26, 0, -22, - 'c', 0, -11, 22, -20, 22, -7, - 'c', 22, 0, 17, 0, 11, 0, - 'c', 6, 0, 0, -1, 0, -6, - 'e', -/* 0x74 't' offset 3219 */ - 0, 16, 42, 0, 3, 4, - 0, 6, 16, /* snap_x */ - -28, -21, -15, 0, /* snap_y */ - 'm', 6, -42, - 'l', 6, -8, - 'c', 6, -2, 8, 0, 16, 0, - 'm', 0, -28, - 'l', 14, -28, - 'e', -/* 0x75 'u' offset 3252 */ - 0, 22, 28, 0, 2, 3, - 0, 22, /* snap_x */ - -21, -15, 0, /* snap_y */ - 'm', 0, -28, - 'l', 0, -8, - 'c', 0, 6, 18, 0, 22, -8, - 'm', 22, -28, - 'l', 22, 0, - 'e', -/* 0x76 'v' offset 3283 */ - 0, 24, 28, 0, 2, 3, - 0, 24, /* snap_x */ - -21, -15, 0, /* snap_y */ - 'm', 0, -28, - 'l', 12, 0, - 'l', 24, -28, - 'e', - 'X', 'X', 'X', -/* 0x77 'w' offset 3307 */ - 0, 32, 28, 0, 2, 3, - 0, 32, /* snap_x */ - -21, -15, 0, /* snap_y */ - 'm', 0, -28, - 'l', 8, 0, - 'l', 16, -28, - 'l', 24, 0, - 'l', 32, -28, - 'e', - 'X', 'X', 'X', - 'X', 'X', 'X', - 'X', 'X', 'X', -/* 0x78 'x' offset 3343 */ - 0, 22, 28, 0, 2, 3, - 0, 22, /* snap_x */ - -21, -15, 0, /* snap_y */ - 'm', 0, -28, - 'l', 22, 0, - 'm', 22, -28, - 'l', 0, 0, - 'e', -/* 0x79 'y' offset 3367 */ - -2, 24, 28, 14, 2, 4, - 0, 24, /* snap_x */ - -21, -15, 0, 14, /* snap_y */ - 'm', 0, -28, - 'l', 12, 0, - 'm', 24, -28, - 'l', 12, 0, - 'c', 6, 13, 0, 14, -2, 14, - 'e', -/* 0x7a 'z' offset 3399 */ - 0, 22, 28, 0, 2, 4, - 0, 22, /* snap_x */ - -28, -21, -15, 0, /* snap_y */ - 'm', 22, 0, - 'l', 0, 0, - 'l', 22, -28, - 'l', 0, -28, - 'e', - 'X', 'X', 'X', - 'X', 'X', 'X', -/* 0x7b '{' offset 3430 */ - 0, 16, 44, 0, 3, 5, - 0, 6, 16, /* snap_x */ - -44, -24, -21, -15, 0, /* snap_y */ - 'm', 16, -44, - 'c', 10, -44, 6, -42, 6, -36, - 'l', 6, -24, - 'l', 0, -24, - 'l', 6, -24, - 'l', 6, -8, - 'c', 6, -2, 10, 0, 16, 0, - 'e', -/* 0x7c '|' offset 3474 */ - 0, 0, 50, 14, 1, 3, - 0, /* snap_x */ - -21, -15, 0, /* snap_y */ - 'm', 0, -50, - 'l', 0, 14, - 'e', -/* 0x7d '}' offset 3491 */ - 0, 16, 44, 0, 3, 5, - 0, 10, 16, /* snap_x */ - -44, -24, -21, -15, 0, /* snap_y */ - 'm', 0, -44, - 'c', 6, -44, 10, -42, 10, -36, - 'l', 10, -24, - 'l', 16, -24, - 'l', 10, -24, - 'l', 10, -8, - 'c', 10, -2, 6, 0, 0, 0, - 'e', -/* 0x7e '~' offset 3535 */ - 0, 36, 24, -12, 2, 5, - 0, 36, /* snap_x */ - -24, -21, -15, -12, 0, /* snap_y */ - 'm', 0, -14, - 'c', 1, -21, 4, -24, 8, -24, - 'c', 18, -24, 18, -12, 28, -12, - 'c', 32, -12, 35, -15, 36, -22, - 'e', -}; - -const uint16_t _cairo_twin_charmap[128] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 28, 40, 90, 114, 152, 224, 323, 390, - 419, 441, 463, 494, 520, 556, 575, 604, - 622, 666, 691, 736, 780, 809, 860, 919, - 944, 1004, 1063, 1109, 1162, 1183, 1209, 1230, - 1288, 1375, 1406, 1455, 1499, 1534, 1572, 1604, - 1655, 1686, 1703, 1731, 1761, 1785, 1821, 1851, - 1895, 1931, 1981, 2023, 2074, 2100, 2128, 2152, - 2188, 2212, 2240, 2271, 2296, 2314, 2339, 2363, - 2381, 2417, 2467, 2517, 2561, 2611, 2659, 2693, - 2758, 2790, 2826, 2870, 2900, 2917, 2963, 2995, - 3039, 3089, 3139, 3168, 3219, 3252, 3283, 3307, - 3343, 3367, 3399, 3430, 3474, 3491, 3535, 0, -}; - diff --git a/uppdev/plugin/cairo/lib/cairo-font-face-twin.c b/uppdev/plugin/cairo/lib/cairo-font-face-twin.c deleted file mode 100644 index d8e662f1f..000000000 --- a/uppdev/plugin/cairo/lib/cairo-font-face-twin.c +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright © 2004 Keith Packard - * Copyright © 2008 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Keith Packard - * - * Contributor(s): - * Keith Packard - * Behdad Esfahbod - */ - -#include "cairoint.h" - -/* - * This file implements a user-font rendering the decendant of the Hershey - * font coded by Keith Packard for use in the Twin window system. - * The actual font data is in cairo-font-face-twin-data.c - * - * Ported to cairo user font by Behdad Esfahbod. - */ - - -#define twin_glyph_left(g) ((g)[0]) -#define twin_glyph_right(g) ((g)[1]) -#define twin_glyph_ascent(g) ((g)[2]) -#define twin_glyph_descent(g) ((g)[3]) - -#define twin_glyph_n_snap_x(g) ((g)[4]) -#define twin_glyph_n_snap_y(g) ((g)[5]) -#define twin_glyph_snap_x(g) (&g[6]) -#define twin_glyph_snap_y(g) (twin_glyph_snap_x(g) + twin_glyph_n_snap_x(g)) -#define twin_glyph_draw(g) (twin_glyph_snap_y(g) + twin_glyph_n_snap_y(g)) - -#define SNAPI(p) (p) -#define SNAPH(p) (p) - -#define FX(g) ((g) / 64.) -#define FY(g) ((g) / 64.) - - -static cairo_status_t -twin_scaled_font_init (cairo_scaled_font_t *scaled_font, - cairo_t *cr, - cairo_font_extents_t *metrics) -{ - metrics->ascent = FY (50); - metrics->descent = FY (14); - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -twin_scaled_font_unicode_to_glyph (cairo_scaled_font_t *scaled_font, - unsigned long unicode, - unsigned long *glyph) -{ - /* We use an identity charmap. Which means we could live - * with no unicode_to_glyph method too. But we define this - * to map all unknown chars to a single unknown glyph to - * reduce pressure on cache. */ - - if (unicode < ARRAY_LENGTH (_cairo_twin_charmap)) - *glyph = unicode; - else - *glyph = 0; - - return CAIRO_STATUS_SUCCESS; -} - -#define SNAPX(p) _twin_snap (p, info.snap_x, info.n_snap_x) -#define SNAPY(p) _twin_snap (p, info.snap_y, info.n_snap_y) - -static double -_twin_snap (double v, int a, int b) -{ - return v; /* XXX */ -} - -static cairo_status_t -twin_scaled_font_render_glyph (cairo_scaled_font_t *scaled_font, - unsigned long glyph, - cairo_t *cr, - cairo_text_extents_t *metrics) -{ - double x1, y1, x2, y2, x3, y3; - const int8_t *b = _cairo_twin_outlines + - _cairo_twin_charmap[glyph >= ARRAY_LENGTH (_cairo_twin_charmap) ? 0 : glyph]; - const int8_t *g = twin_glyph_draw(b); - - struct { - cairo_bool_t snap; - int snap_x; - int snap_y; - int n_snap_x; - int n_snap_y; - } info = {FALSE}; - - cairo_set_line_width (cr, 0.06); - cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND); - cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); - - for (;;) { - switch (*g++) { - case 'M': - cairo_close_path (cr); - /* fall through */ - case 'm': - x1 = FX(*g++); - y1 = FY(*g++); - if (info.snap) - { - x1 = SNAPX (x1); - y1 = SNAPY (y1); - } - cairo_move_to (cr, x1, y1); - continue; - case 'L': - cairo_close_path (cr); - /* fall through */ - case 'l': - x1 = FX(*g++); - y1 = FY(*g++); - if (info.snap) - { - x1 = SNAPX (x1); - y1 = SNAPY (y1); - } - cairo_line_to (cr, x1, y1); - continue; - case 'C': - cairo_close_path (cr); - /* fall through */ - case 'c': - x1 = FX(*g++); - y1 = FY(*g++); - x2 = FX(*g++); - y2 = FY(*g++); - x3 = FX(*g++); - y3 = FY(*g++); - if (info.snap) - { - x1 = SNAPX (x1); - y1 = SNAPY (y1); - x2 = SNAPX (x2); - y2 = SNAPY (y2); - x3 = SNAPX (x3); - y3 = SNAPY (y3); - } - cairo_curve_to (cr, x1, y1, x2, y2, x3, y3); - continue; - case 'E': - cairo_close_path (cr); - /* fall through */ - case 'e': - cairo_stroke (cr); - break; - case 'X': - /* filler */ - continue; - } - break; - } - - metrics->x_advance = FX(twin_glyph_right(b)) + cairo_get_line_width (cr); - metrics->x_advance += cairo_get_line_width (cr)/* XXX 2*x.margin */; - if (info.snap) - metrics->x_advance = SNAPI (SNAPX (metrics->x_advance)); - - - return CAIRO_STATUS_SUCCESS; -} - -cairo_font_face_t * -_cairo_font_face_twin_create (cairo_font_slant_t slant, - cairo_font_weight_t weight) -{ - cairo_font_face_t *twin_font_face; - - twin_font_face = cairo_user_font_face_create (); - cairo_user_font_face_set_init_func (twin_font_face, twin_scaled_font_init); - cairo_user_font_face_set_render_glyph_func (twin_font_face, twin_scaled_font_render_glyph); - cairo_user_font_face_set_unicode_to_glyph_func (twin_font_face, twin_scaled_font_unicode_to_glyph); - - return twin_font_face; -} diff --git a/uppdev/plugin/cairo/lib/cairo-font-face.c b/uppdev/plugin/cairo/lib/cairo-font-face.c deleted file mode 100644 index 30c8d9fb3..000000000 --- a/uppdev/plugin/cairo/lib/cairo-font-face.c +++ /dev/null @@ -1,776 +0,0 @@ -/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - * Graydon Hoare - * Owen Taylor - */ - -#define _BSD_SOURCE /* for strdup() */ -#include "cairoint.h" - -static const cairo_font_face_backend_t _cairo_toy_font_face_backend; - -/* #cairo_font_face_t */ - -const cairo_toy_font_face_t _cairo_font_face_nil = { - { - { 0 }, /* hash_entry */ - CAIRO_STATUS_NO_MEMORY, /* status */ - CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */ - { 0, 0, 0, NULL }, /* user_data */ - &_cairo_toy_font_face_backend - }, - CAIRO_FONT_FAMILY_DEFAULT, /* family */ - TRUE, /* owns_family */ - CAIRO_FONT_SLANT_DEFAULT, /* slant */ - CAIRO_FONT_WEIGHT_DEFAULT /* weight */ -}; - -static const cairo_toy_font_face_t _cairo_font_face_null_pointer = { - { - { 0 }, /* hash_entry */ - CAIRO_STATUS_NULL_POINTER, /* status */ - CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */ - { 0, 0, 0, NULL }, /* user_data */ - &_cairo_toy_font_face_backend - }, - CAIRO_FONT_FAMILY_DEFAULT, /* family */ - TRUE, /* owns_family */ - CAIRO_FONT_SLANT_DEFAULT, /* slant */ - CAIRO_FONT_WEIGHT_DEFAULT /* weight */ -}; - -static const cairo_toy_font_face_t _cairo_font_face_invalid_string = { - { - { 0 }, /* hash_entry */ - CAIRO_STATUS_INVALID_STRING, /* status */ - CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */ - { 0, 0, 0, NULL }, /* user_data */ - &_cairo_toy_font_face_backend - }, - CAIRO_FONT_FAMILY_DEFAULT, /* family */ - TRUE, /* owns_family */ - CAIRO_FONT_SLANT_DEFAULT, /* slant */ - CAIRO_FONT_WEIGHT_DEFAULT /* weight */ -}; - -static const cairo_toy_font_face_t _cairo_font_face_invalid_slant = { - { - { 0 }, /* hash_entry */ - CAIRO_STATUS_INVALID_SLANT, /* status */ - CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */ - { 0, 0, 0, NULL }, /* user_data */ - &_cairo_toy_font_face_backend - }, - CAIRO_FONT_FAMILY_DEFAULT, /* family */ - TRUE, /* owns_family */ - CAIRO_FONT_SLANT_DEFAULT, /* slant */ - CAIRO_FONT_WEIGHT_DEFAULT /* weight */ -}; - -static const cairo_toy_font_face_t _cairo_font_face_invalid_weight = { - { - { 0 }, /* hash_entry */ - CAIRO_STATUS_INVALID_WEIGHT, /* status */ - CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */ - { 0, 0, 0, NULL }, /* user_data */ - &_cairo_toy_font_face_backend - }, - CAIRO_FONT_FAMILY_DEFAULT, /* family */ - TRUE, /* owns_family */ - CAIRO_FONT_SLANT_DEFAULT, /* slant */ - CAIRO_FONT_WEIGHT_DEFAULT /* weight */ -}; - -cairo_status_t -_cairo_font_face_set_error (cairo_font_face_t *font_face, - cairo_status_t status) -{ - if (status == CAIRO_STATUS_SUCCESS) - return status; - - /* Don't overwrite an existing error. This preserves the first - * error, which is the most significant. */ - _cairo_status_set_error (&font_face->status, status); - - return _cairo_error (status); -} - -void -_cairo_font_face_init (cairo_font_face_t *font_face, - const cairo_font_face_backend_t *backend) -{ - CAIRO_MUTEX_INITIALIZE (); - - font_face->status = CAIRO_STATUS_SUCCESS; - CAIRO_REFERENCE_COUNT_INIT (&font_face->ref_count, 1); - font_face->backend = backend; - - _cairo_user_data_array_init (&font_face->user_data); -} - -/** - * cairo_font_face_reference: - * @font_face: a #cairo_font_face_t, (may be %NULL in which case this - * function does nothing). - * - * Increases the reference count on @font_face by one. This prevents - * @font_face from being destroyed until a matching call to - * cairo_font_face_destroy() is made. - * - * The number of references to a #cairo_font_face_t can be get using - * cairo_font_face_get_reference_count(). - * - * Return value: the referenced #cairo_font_face_t. - **/ -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)) - return font_face; - - /* We would normally assert that we have a reference here but we - * can't get away with that due to the zombie case as documented - * in _cairo_ft_font_face_destroy. */ - - _cairo_reference_count_inc (&font_face->ref_count); - - return font_face; -} -slim_hidden_def (cairo_font_face_reference); - -/** - * cairo_font_face_destroy: - * @font_face: a #cairo_font_face_t - * - * Decreases the reference count on @font_face by one. If the result - * is zero, then @font_face and all associated resources are freed. - * See cairo_font_face_reference(). - **/ -void -cairo_font_face_destroy (cairo_font_face_t *font_face) -{ - if (font_face == NULL || - 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)) - return; - - _cairo_user_data_array_fini (&font_face->user_data); - - free (font_face); -} -slim_hidden_def (cairo_font_face_destroy); - -/** - * cairo_font_face_get_type: - * @font_face: a font face - * - * This function returns the type of the backend used to create - * a font face. See #cairo_font_type_t for available types. - * - * Return value: The type of @font_face. - * - * Since: 1.2 - **/ -cairo_font_type_t -cairo_font_face_get_type (cairo_font_face_t *font_face) -{ - return font_face->backend->type; -} - -/** - * cairo_font_face_get_reference_count: - * @font_face: a #cairo_font_face_t - * - * Returns the current reference count of @font_face. - * - * Return value: the current reference count of @font_face. If the - * object is a nil object, 0 will be returned. - * - * Since: 1.4 - **/ -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)) - return 0; - - return CAIRO_REFERENCE_COUNT_GET_VALUE (&font_face->ref_count); -} - -/** - * cairo_font_face_status: - * @font_face: a #cairo_font_face_t - * - * Checks whether an error has previously occurred for this - * font face - * - * Return value: %CAIRO_STATUS_SUCCESS or another error such as - * %CAIRO_STATUS_NO_MEMORY. - **/ -cairo_status_t -cairo_font_face_status (cairo_font_face_t *font_face) -{ - return font_face->status; -} - -/** - * cairo_font_face_get_user_data: - * @font_face: a #cairo_font_face_t - * @key: the address of the #cairo_user_data_key_t the user data was - * attached to - * - * Return user data previously attached to @font_face using the specified - * key. If no user data has been attached with the given key this - * function returns %NULL. - * - * Return value: the user data previously attached or %NULL. - **/ -void * -cairo_font_face_get_user_data (cairo_font_face_t *font_face, - const cairo_user_data_key_t *key) -{ - return _cairo_user_data_array_get_data (&font_face->user_data, - key); -} -slim_hidden_def (cairo_font_face_get_user_data); - -/** - * cairo_font_face_set_user_data: - * @font_face: a #cairo_font_face_t - * @key: the address of a #cairo_user_data_key_t to attach the user data to - * @user_data: the user data to attach to the font face - * @destroy: a #cairo_destroy_func_t which will be called when the - * font face is destroyed or when new user data is attached using the - * same key. - * - * Attach user data to @font_face. To remove user data from a font face, - * call this function with the key that was used to set it and %NULL - * for @data. - * - * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a - * slot could not be allocated for the user data. - **/ -cairo_status_t -cairo_font_face_set_user_data (cairo_font_face_t *font_face, - const cairo_user_data_key_t *key, - void *user_data, - cairo_destroy_func_t destroy) -{ - if (CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count)) - return font_face->status; - - return _cairo_user_data_array_set_data (&font_face->user_data, - key, user_data, destroy); -} -slim_hidden_def (cairo_font_face_set_user_data); - -static const cairo_font_face_backend_t _cairo_toy_font_face_backend; - -static int -_cairo_toy_font_face_keys_equal (const void *key_a, - const void *key_b); - -/* We maintain a hash table from family/weight/slant => - * #cairo_font_face_t for #cairo_toy_font_t. The primary purpose of - * this mapping is to provide unique #cairo_font_face_t values so that - * our cache and mapping from #cairo_font_face_t => #cairo_scaled_font_t - * works. Once the corresponding #cairo_font_face_t objects fall out of - * downstream caches, we don't need them in this hash table anymore. - * - * Modifications to this hash table are protected by - * _cairo_font_face_mutex. - */ -static cairo_hash_table_t *cairo_toy_font_face_hash_table = NULL; - -static cairo_hash_table_t * -_cairo_toy_font_face_hash_table_lock (void) -{ - CAIRO_MUTEX_LOCK (_cairo_font_face_mutex); - - if (cairo_toy_font_face_hash_table == NULL) - { - cairo_toy_font_face_hash_table = - _cairo_hash_table_create (_cairo_toy_font_face_keys_equal); - - if (cairo_toy_font_face_hash_table == NULL) { - CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex); - return NULL; - } - } - - return cairo_toy_font_face_hash_table; -} - -static void -_cairo_toy_font_face_hash_table_unlock (void) -{ - CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex); -} - -/** - * _cairo_toy_font_face_init_key: - * - * Initialize those portions of #cairo_toy_font_face_t needed to use - * it as a hash table key, including the hash code buried away in - * font_face->base.hash_entry. No memory allocation is performed here - * so that no fini call is needed. We do this to make it easier to use - * an automatic #cairo_toy_font_face_t variable as a key. - **/ -static void -_cairo_toy_font_face_init_key (cairo_toy_font_face_t *key, - const char *family, - cairo_font_slant_t slant, - cairo_font_weight_t weight) -{ - unsigned long hash; - - key->family = family; - key->owns_family = FALSE; - - key->slant = slant; - key->weight = weight; - - /* 1607 and 1451 are just a couple of arbitrary primes. */ - hash = _cairo_hash_string (family); - hash += ((unsigned long) slant) * 1607; - hash += ((unsigned long) weight) * 1451; - - assert (hash != 0); - key->base.hash_entry.hash = hash; -} - -static cairo_status_t -_cairo_toy_font_face_init (cairo_toy_font_face_t *font_face, - const char *family, - cairo_font_slant_t slant, - cairo_font_weight_t weight) -{ - char *family_copy; - - family_copy = strdup (family); - if (family_copy == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - _cairo_toy_font_face_init_key (font_face, family_copy, - slant, weight); - font_face->owns_family = TRUE; - - _cairo_font_face_init (&font_face->base, &_cairo_toy_font_face_backend); - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_toy_font_face_fini (cairo_toy_font_face_t *font_face) -{ - /* We assert here that we own font_face->family before casting - * away the const qualifer. */ - assert (font_face->owns_family); - free ((char*) font_face->family); -} - -static int -_cairo_toy_font_face_keys_equal (const void *key_a, - const void *key_b) -{ - const cairo_toy_font_face_t *face_a = key_a; - const cairo_toy_font_face_t *face_b = key_b; - - return (strcmp (face_a->family, face_b->family) == 0 && - face_a->slant == face_b->slant && - face_a->weight == face_b->weight); -} - -/** - * cairo_toy_font_face_create: - * @family: a font family name, encoded in UTF-8 - * @slant: the slant for the font - * @weight: the weight for the font - * - * Creates a font face from a triplet of family, slant, and weight. - * These font faces are used in implementation of the the #cairo_t "toy" - * font API. - * - * If @family is the zero-length string "", the platform-specific default - * family is assumed. The default family then can be queried using - * cairo_toy_font_face_get_family(). - * - * The cairo_select_font_face() function uses this to create font faces. - * See that function for limitations of toy font faces. - * - * Return value: a newly created #cairo_font_face_t. Free with - * cairo_font_face_destroy() when you are done using it. - * - * Since: 1.8 - **/ -cairo_font_face_t * -cairo_toy_font_face_create (const char *family, - cairo_font_slant_t slant, - cairo_font_weight_t weight) -{ - cairo_status_t status; - cairo_toy_font_face_t key, *font_face; - cairo_hash_table_t *hash_table; - - if (family == NULL) - return (cairo_font_face_t*) &_cairo_font_face_null_pointer; - - /* Make sure we've got valid UTF-8 for the family */ - status = _cairo_utf8_to_ucs4 (family, -1, NULL, NULL); - if (status == CAIRO_STATUS_INVALID_STRING) - return (cairo_font_face_t*) &_cairo_font_face_invalid_string; - else if (status) - return (cairo_font_face_t*) &_cairo_font_face_nil; - - switch (slant) { - case CAIRO_FONT_SLANT_NORMAL: - case CAIRO_FONT_SLANT_ITALIC: - case CAIRO_FONT_SLANT_OBLIQUE: - break; - default: - return (cairo_font_face_t*) &_cairo_font_face_invalid_slant; - } - - switch (weight) { - case CAIRO_FONT_WEIGHT_NORMAL: - case CAIRO_FONT_WEIGHT_BOLD: - break; - default: - return (cairo_font_face_t*) &_cairo_font_face_invalid_weight; - } - - if (*family == '\0') - family = CAIRO_FONT_FAMILY_DEFAULT; - - hash_table = _cairo_toy_font_face_hash_table_lock (); - if (hash_table == NULL) - goto UNWIND; - - _cairo_toy_font_face_init_key (&key, family, slant, weight); - - /* Return existing font_face if it exists in the hash table. */ - if (_cairo_hash_table_lookup (hash_table, - &key.base.hash_entry, - (cairo_hash_entry_t **) &font_face)) - { - if (! font_face->base.status) { - /* We increment the reference count here manually to avoid - double-locking. */ - _cairo_reference_count_inc (&font_face->base.ref_count); - _cairo_toy_font_face_hash_table_unlock (); - return &font_face->base; - } - - /* remove the bad font from the hash table */ - _cairo_hash_table_remove (hash_table, &key.base.hash_entry); - font_face->base.hash_entry.hash = 0; - } - - /* Otherwise create it and insert into hash table. */ - font_face = malloc (sizeof (cairo_toy_font_face_t)); - if (font_face == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto UNWIND_HASH_TABLE_LOCK; - } - - status = _cairo_toy_font_face_init (font_face, family, slant, weight); - if (status) - goto UNWIND_FONT_FACE_MALLOC; - - status = _cairo_hash_table_insert (hash_table, &font_face->base.hash_entry); - if (status) - goto UNWIND_FONT_FACE_INIT; - - _cairo_toy_font_face_hash_table_unlock (); - - return &font_face->base; - - UNWIND_FONT_FACE_INIT: - _cairo_toy_font_face_fini (font_face); - UNWIND_FONT_FACE_MALLOC: - free (font_face); - UNWIND_HASH_TABLE_LOCK: - _cairo_toy_font_face_hash_table_unlock (); - UNWIND: - return (cairo_font_face_t*) &_cairo_font_face_nil; -} -slim_hidden_def (cairo_toy_font_face_create); - -static void -_cairo_toy_font_face_destroy (void *abstract_face) -{ - cairo_toy_font_face_t *font_face = abstract_face; - cairo_hash_table_t *hash_table; - - if (font_face == NULL || - CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->base.ref_count)) - return; - - hash_table = _cairo_toy_font_face_hash_table_lock (); - /* All created objects must have been mapped in the hash table. */ - assert (hash_table != NULL); - - if (font_face->base.hash_entry.hash != 0) - _cairo_hash_table_remove (hash_table, &font_face->base.hash_entry); - - _cairo_toy_font_face_hash_table_unlock (); - - _cairo_toy_font_face_fini (font_face); -} - -static cairo_status_t -_cairo_toy_font_face_scaled_font_get_implementation (void *abstract_font_face, - cairo_font_face_t **font_face_out) -{ - cairo_toy_font_face_t *font_face = abstract_font_face; - cairo_status_t status; - - if (font_face->base.status) - return font_face->base.status; - - if (CAIRO_SCALED_FONT_BACKEND_DEFAULT != &_cairo_user_scaled_font_backend) - { - const cairo_scaled_font_backend_t * backend = CAIRO_SCALED_FONT_BACKEND_DEFAULT; - - if (backend->get_implementation == NULL) { - *font_face_out = &font_face->base; - return CAIRO_STATUS_SUCCESS; - } - - status = backend->get_implementation (font_face, - font_face_out); - - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return _cairo_font_face_set_error (&font_face->base, status); - } - - status = _cairo_user_scaled_font_backend.get_implementation (font_face, - font_face_out); - - return _cairo_font_face_set_error (&font_face->base, status); -} - -static cairo_status_t -_cairo_toy_font_face_scaled_font_create (void *abstract_font_face, - const cairo_matrix_t *font_matrix, - const cairo_matrix_t *ctm, - const cairo_font_options_t *options, - cairo_scaled_font_t **scaled_font) -{ - cairo_toy_font_face_t *font_face = abstract_font_face; - cairo_status_t status; - - if (font_face->base.status) - return font_face->base.status; - - status = cairo_font_options_status ((cairo_font_options_t *) options); - if (status) - return status; - - if (CAIRO_SCALED_FONT_BACKEND_DEFAULT != &_cairo_user_scaled_font_backend) - { - const cairo_scaled_font_backend_t * backend = CAIRO_SCALED_FONT_BACKEND_DEFAULT; - - *scaled_font = NULL; - status = backend->create_toy (font_face, - font_matrix, - ctm, - options, - scaled_font); - - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return _cairo_font_face_set_error (&font_face->base, status); - - if (*scaled_font) - cairo_scaled_font_destroy (*scaled_font); - } - - status = _cairo_user_scaled_font_backend.create_toy (font_face, - font_matrix, - ctm, - options, - scaled_font); - - return _cairo_font_face_set_error (&font_face->base, status); -} - -static cairo_bool_t -_cairo_font_face_is_toy (cairo_font_face_t *font_face) -{ - return font_face->backend == &_cairo_toy_font_face_backend; -} - -/** - * cairo_toy_font_face_get_family: - * @font_face: A toy font face - * - * Gets the familly name of a toy font. - * - * Return value: The family name. This string is owned by the font face - * and remains valid as long as the font face is alive (referenced). - * - * Since: 1.8 - **/ -const char * -cairo_toy_font_face_get_family (cairo_font_face_t *font_face) -{ - cairo_toy_font_face_t *toy_font_face = (cairo_toy_font_face_t *) font_face; - if (! _cairo_font_face_is_toy (font_face)) { - if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH)) - return CAIRO_FONT_FAMILY_DEFAULT; - } - assert (toy_font_face->owns_family); - return toy_font_face->family; -} - -/** - * cairo_toy_font_face_get_slant: - * @font_face: A toy font face - * - * Gets the slant a toy font. - * - * Return value: The slant value - * - * Since: 1.8 - **/ -cairo_font_slant_t -cairo_toy_font_face_get_slant (cairo_font_face_t *font_face) -{ - cairo_toy_font_face_t *toy_font_face = (cairo_toy_font_face_t *) font_face; - if (! _cairo_font_face_is_toy (font_face)) { - if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH)) - return CAIRO_FONT_SLANT_DEFAULT; - } - return toy_font_face->slant; -} -slim_hidden_def (cairo_toy_font_face_get_slant); - -/** - * cairo_toy_font_face_get_weight: - * @font_face: A toy font face - * - * Gets the weight a toy font. - * - * Return value: The weight value - * - * Since: 1.8 - **/ -cairo_font_weight_t -cairo_toy_font_face_get_weight (cairo_font_face_t *font_face) -{ - cairo_toy_font_face_t *toy_font_face = (cairo_toy_font_face_t *) font_face; - if (! _cairo_font_face_is_toy (font_face)) { - if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH)) - return CAIRO_FONT_WEIGHT_DEFAULT; - } - return toy_font_face->weight; -} -slim_hidden_def (cairo_toy_font_face_get_weight); - -static const cairo_font_face_backend_t _cairo_toy_font_face_backend = { - CAIRO_FONT_TYPE_TOY, - _cairo_toy_font_face_destroy, - _cairo_toy_font_face_scaled_font_get_implementation, - _cairo_toy_font_face_scaled_font_create -}; - -void -_cairo_unscaled_font_init (cairo_unscaled_font_t *unscaled_font, - const cairo_unscaled_font_backend_t *backend) -{ - CAIRO_REFERENCE_COUNT_INIT (&unscaled_font->ref_count, 1); - unscaled_font->backend = backend; -} - -cairo_unscaled_font_t * -_cairo_unscaled_font_reference (cairo_unscaled_font_t *unscaled_font) -{ - if (unscaled_font == NULL) - return NULL; - - assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&unscaled_font->ref_count)); - - _cairo_reference_count_inc (&unscaled_font->ref_count); - - return unscaled_font; -} - -void -_cairo_unscaled_font_destroy (cairo_unscaled_font_t *unscaled_font) -{ - if (unscaled_font == NULL) - return; - - assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&unscaled_font->ref_count)); - - if (! _cairo_reference_count_dec_and_test (&unscaled_font->ref_count)) - return; - - unscaled_font->backend->destroy (unscaled_font); - - free (unscaled_font); -} - -void -_cairo_font_face_reset_static_data (void) -{ - _cairo_scaled_font_map_destroy (); - - /* We manually acquire the lock rather than calling - * cairo_toy_font_face_hash_table_lock simply to avoid - * creating the table only to destroy it again. */ - CAIRO_MUTEX_LOCK (_cairo_font_face_mutex); - _cairo_hash_table_destroy (cairo_toy_font_face_hash_table); - cairo_toy_font_face_hash_table = NULL; - CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex); -} diff --git a/uppdev/plugin/cairo/lib/cairo-font-options.c b/uppdev/plugin/cairo/lib/cairo-font-options.c deleted file mode 100644 index dedd3379e..000000000 --- a/uppdev/plugin/cairo/lib/cairo-font-options.c +++ /dev/null @@ -1,406 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Owen Taylor - */ - -#include "cairoint.h" - -static const cairo_font_options_t _cairo_font_options_nil = { - CAIRO_ANTIALIAS_DEFAULT, - CAIRO_SUBPIXEL_ORDER_DEFAULT, - CAIRO_HINT_STYLE_DEFAULT, - CAIRO_HINT_METRICS_DEFAULT -}; - -/** - * _cairo_font_options_init_default: - * @options: a #cairo_font_options_t - * - * Initializes all fields of the font options object to default values. - **/ -void -_cairo_font_options_init_default (cairo_font_options_t *options) -{ - options->antialias = CAIRO_ANTIALIAS_DEFAULT; - options->subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT; - options->hint_style = CAIRO_HINT_STYLE_DEFAULT; - options->hint_metrics = CAIRO_HINT_METRICS_DEFAULT; -} - -void -_cairo_font_options_init_copy (cairo_font_options_t *options, - const cairo_font_options_t *other) -{ - options->antialias = other->antialias; - options->subpixel_order = other->subpixel_order; - options->hint_style = other->hint_style; - options->hint_metrics = other->hint_metrics; -} - -/** - * cairo_font_options_create: - * - * Allocates a new font options object with all options initialized - * to default values. - * - * Return value: a newly allocated #cairo_font_options_t. Free with - * cairo_font_options_destroy(). This function always returns a - * valid pointer; if memory cannot be allocated, then a special - * error object is returned where all operations on the object do nothing. - * You can check for this with cairo_font_options_status(). - **/ -cairo_font_options_t * -cairo_font_options_create (void) -{ - cairo_font_options_t *options; - - options = malloc (sizeof (cairo_font_options_t)); - if (!options) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_font_options_t *) &_cairo_font_options_nil; - } - - _cairo_font_options_init_default (options); - - return options; -} - -/** - * cairo_font_options_copy: - * @original: a #cairo_font_options_t - * - * Allocates a new font options object copying the option values from - * @original. - * - * Return value: a newly allocated #cairo_font_options_t. Free with - * cairo_font_options_destroy(). This function always returns a - * valid pointer; if memory cannot be allocated, then a special - * error object is returned where all operations on the object do nothing. - * You can check for this with cairo_font_options_status(). - **/ -cairo_font_options_t * -cairo_font_options_copy (const cairo_font_options_t *original) -{ - cairo_font_options_t *options; - - if (cairo_font_options_status ((cairo_font_options_t *) original)) - return (cairo_font_options_t *) &_cairo_font_options_nil; - - options = malloc (sizeof (cairo_font_options_t)); - if (!options) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_font_options_t *) &_cairo_font_options_nil; - } - - _cairo_font_options_init_copy (options, original); - - return options; -} - -/** - * cairo_font_options_destroy: - * @options: a #cairo_font_options_t - * - * Destroys a #cairo_font_options_t object created with with - * cairo_font_options_create() or cairo_font_options_copy(). - **/ -void -cairo_font_options_destroy (cairo_font_options_t *options) -{ - if (cairo_font_options_status (options)) - return; - - free (options); -} - -/** - * cairo_font_options_status: - * @options: a #cairo_font_options_t - * - * Checks whether an error has previously occurred for this - * font options object - * - * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY - **/ -cairo_status_t -cairo_font_options_status (cairo_font_options_t *options) -{ - if (options == NULL) - return CAIRO_STATUS_NULL_POINTER; - else if (options == (cairo_font_options_t *) &_cairo_font_options_nil) - return CAIRO_STATUS_NO_MEMORY; - else - return CAIRO_STATUS_SUCCESS; -} -slim_hidden_def (cairo_font_options_status); - -/** - * cairo_font_options_merge: - * @options: a #cairo_font_options_t - * @other: another #cairo_font_options_t - * - * Merges non-default options from @other into @options, replacing - * existing values. This operation can be thought of as somewhat - * similar to compositing @other onto @options with the operation - * of %CAIRO_OPERATION_OVER. - **/ -void -cairo_font_options_merge (cairo_font_options_t *options, - const cairo_font_options_t *other) -{ - if (cairo_font_options_status (options)) - return; - - if (cairo_font_options_status ((cairo_font_options_t *) other)) - return; - - if (other->antialias != CAIRO_ANTIALIAS_DEFAULT) - options->antialias = other->antialias; - if (other->subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT) - options->subpixel_order = other->subpixel_order; - if (other->hint_style != CAIRO_HINT_STYLE_DEFAULT) - options->hint_style = other->hint_style; - if (other->hint_metrics != CAIRO_HINT_METRICS_DEFAULT) - options->hint_metrics = other->hint_metrics; -} -slim_hidden_def (cairo_font_options_merge); - -/** - * cairo_font_options_equal: - * @options: a #cairo_font_options_t - * @other: another #cairo_font_options_t - * - * Compares two font options objects for equality. - * - * Return value: %TRUE if all fields of the two font options objects match. - * Note that this function will return %FALSE if either object is in - * error. - **/ -cairo_bool_t -cairo_font_options_equal (const cairo_font_options_t *options, - const cairo_font_options_t *other) -{ - if (cairo_font_options_status ((cairo_font_options_t *) options)) - return FALSE; - if (cairo_font_options_status ((cairo_font_options_t *) other)) - return FALSE; - - if (options == other) - return TRUE; - - return (options->antialias == other->antialias && - options->subpixel_order == other->subpixel_order && - options->hint_style == other->hint_style && - options->hint_metrics == other->hint_metrics); -} -slim_hidden_def (cairo_font_options_equal); - -/** - * cairo_font_options_hash: - * @options: a #cairo_font_options_t - * - * Compute a hash for the font options object; this value will - * be useful when storing an object containing a #cairo_font_options_t - * in a hash table. - * - * Return value: the hash value for the font options object. - * The return value can be cast to a 32-bit type if a - * 32-bit hash value is needed. - **/ -unsigned long -cairo_font_options_hash (const cairo_font_options_t *options) -{ - if (cairo_font_options_status ((cairo_font_options_t *) options)) - options = &_cairo_font_options_nil; /* force default values */ - - return ((options->antialias) | - (options->subpixel_order << 4) | - (options->hint_style << 8) | - (options->hint_metrics << 16)); -} -slim_hidden_def (cairo_font_options_hash); - -/** - * cairo_font_options_set_antialias: - * @options: a #cairo_font_options_t - * @antialias: the new antialiasing mode - * - * Sets the antialiasing mode for the font options object. This - * specifies the type of antialiasing to do when rendering text. - **/ -void -cairo_font_options_set_antialias (cairo_font_options_t *options, - cairo_antialias_t antialias) -{ - if (cairo_font_options_status (options)) - return; - - options->antialias = antialias; -} -slim_hidden_def (cairo_font_options_set_antialias); - -/** - * cairo_font_options_get_antialias: - * @options: a #cairo_font_options_t - * - * Gets the antialiasing mode for the font options object. - * - * Return value: the antialiasing mode - **/ -cairo_antialias_t -cairo_font_options_get_antialias (const cairo_font_options_t *options) -{ - if (cairo_font_options_status ((cairo_font_options_t *) options)) - return CAIRO_ANTIALIAS_DEFAULT; - - return options->antialias; -} - -/** - * cairo_font_options_set_subpixel_order: - * @options: a #cairo_font_options_t - * @subpixel_order: the new subpixel order - * - * Sets the subpixel order for the font options object. The subpixel - * order specifies the order of color elements within each pixel on - * the display device when rendering with an antialiasing mode of - * %CAIRO_ANTIALIAS_SUBPIXEL. See the documentation for - * #cairo_subpixel_order_t for full details. - **/ -void -cairo_font_options_set_subpixel_order (cairo_font_options_t *options, - cairo_subpixel_order_t subpixel_order) -{ - if (cairo_font_options_status (options)) - return; - - options->subpixel_order = subpixel_order; -} -slim_hidden_def (cairo_font_options_set_subpixel_order); - -/** - * cairo_font_options_get_subpixel_order: - * @options: a #cairo_font_options_t - * - * Gets the subpixel order for the font options object. - * See the documentation for #cairo_subpixel_order_t for full details. - * - * Return value: the subpixel order for the font options object - **/ -cairo_subpixel_order_t -cairo_font_options_get_subpixel_order (const cairo_font_options_t *options) -{ - if (cairo_font_options_status ((cairo_font_options_t *) options)) - return CAIRO_SUBPIXEL_ORDER_DEFAULT; - - return options->subpixel_order; -} - -/** - * cairo_font_options_set_hint_style: - * @options: a #cairo_font_options_t - * @hint_style: the new hint style - * - * Sets the hint style for font outlines for the font options object. - * This controls whether to fit font outlines to the pixel grid, - * and if so, whether to optimize for fidelity or contrast. - * See the documentation for #cairo_hint_style_t for full details. - **/ -void -cairo_font_options_set_hint_style (cairo_font_options_t *options, - cairo_hint_style_t hint_style) -{ - if (cairo_font_options_status (options)) - return; - - options->hint_style = hint_style; -} -slim_hidden_def (cairo_font_options_set_hint_style); - -/** - * cairo_font_options_get_hint_style: - * @options: a #cairo_font_options_t - * - * Gets the hint style for font outlines for the font options object. - * See the documentation for #cairo_hint_style_t for full details. - * - * Return value: the hint style for the font options object - **/ -cairo_hint_style_t -cairo_font_options_get_hint_style (const cairo_font_options_t *options) -{ - if (cairo_font_options_status ((cairo_font_options_t *) options)) - return CAIRO_HINT_STYLE_DEFAULT; - - return options->hint_style; -} - -/** - * cairo_font_options_set_hint_metrics: - * @options: a #cairo_font_options_t - * @hint_metrics: the new metrics hinting mode - * - * Sets the metrics hinting mode for the font options object. This - * controls whether metrics are quantized to integer values in - * device units. - * See the documentation for #cairo_hint_metrics_t for full details. - **/ -void -cairo_font_options_set_hint_metrics (cairo_font_options_t *options, - cairo_hint_metrics_t hint_metrics) -{ - if (cairo_font_options_status (options)) - return; - - options->hint_metrics = hint_metrics; -} -slim_hidden_def (cairo_font_options_set_hint_metrics); - -/** - * cairo_font_options_get_hint_metrics: - * @options: a #cairo_font_options_t - * - * Gets the metrics hinting mode for the font options object. - * See the documentation for #cairo_hint_metrics_t for full details. - * - * Return value: the metrics hinting mode for the font options object - **/ -cairo_hint_metrics_t -cairo_font_options_get_hint_metrics (const cairo_font_options_t *options) -{ - if (cairo_font_options_status ((cairo_font_options_t *) options)) - return CAIRO_HINT_METRICS_DEFAULT; - - return options->hint_metrics; -} diff --git a/uppdev/plugin/cairo/lib/cairo-freelist-private.h b/uppdev/plugin/cairo/lib/cairo-freelist-private.h deleted file mode 100644 index 48791c234..000000000 --- a/uppdev/plugin/cairo/lib/cairo-freelist-private.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright © 2006 Joonas Pihlaja - * - * 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 the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS 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. - */ -#ifndef CAIRO_FREELIST_H -#define CAIRO_FREELIST_H - -#include "cairo-types-private.h" -#include "cairo-compiler-private.h" - -/* Opaque implementation types. */ -typedef struct _cairo_freelist cairo_freelist_t; -typedef struct _cairo_freelist_node cairo_freelist_node_t; - -struct _cairo_freelist_node { - cairo_freelist_node_t *next; -}; - -struct _cairo_freelist { - cairo_freelist_node_t *first_free_node; - unsigned nodesize; -}; - - -/* Initialise a freelist that will be responsible for allocating - * nodes of size nodesize. */ -cairo_private void -_cairo_freelist_init (cairo_freelist_t *freelist, unsigned nodesize); - -/* Deallocate any nodes in the freelist. */ -cairo_private void -_cairo_freelist_fini (cairo_freelist_t *freelist); - -/* Allocate a new node from the freelist. If the freelist contains no - * nodes, a new one will be allocated using malloc(). The caller is - * responsible for calling _cairo_freelist_free() or free() on the - * returned node. Returns %NULL on memory allocation error. */ -cairo_private void * -_cairo_freelist_alloc (cairo_freelist_t *freelist); - -/* Allocate a new node from the freelist. If the freelist contains no - * nodes, a new one will be allocated using calloc(). The caller is - * responsible for calling _cairo_freelist_free() or free() on the - * returned node. Returns %NULL on memory allocation error. */ -cairo_private void * -_cairo_freelist_calloc (cairo_freelist_t *freelist); - -/* Return a node to the freelist. This does not deallocate the memory, - * but makes it available for later reuse by - * _cairo_freelist_alloc(). */ -cairo_private void -_cairo_freelist_free (cairo_freelist_t *freelist, void *node); - -#endif /* CAIRO_FREELIST_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-freelist.c b/uppdev/plugin/cairo/lib/cairo-freelist.c deleted file mode 100644 index 3887f4b5f..000000000 --- a/uppdev/plugin/cairo/lib/cairo-freelist.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright © 2006 Joonas Pihlaja - * - * 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 the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS 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-freelist-private.h" - -void -_cairo_freelist_init (cairo_freelist_t *freelist, unsigned nodesize) -{ - memset (freelist, 0, sizeof(cairo_freelist_t)); - freelist->nodesize = nodesize; -} - -void -_cairo_freelist_fini (cairo_freelist_t *freelist) -{ - cairo_freelist_node_t *node = freelist->first_free_node; - while (node) { - cairo_freelist_node_t *next = node->next; - free (node); - node = next; - } -} - -void * -_cairo_freelist_alloc (cairo_freelist_t *freelist) -{ - if (freelist->first_free_node) { - cairo_freelist_node_t *node = freelist->first_free_node; - freelist->first_free_node = node->next; - return (void*)node; - } - return malloc (freelist->nodesize); -} - -void * -_cairo_freelist_calloc (cairo_freelist_t *freelist) -{ - void *node = _cairo_freelist_alloc (freelist); - if (node) - memset (node, 0, freelist->nodesize); - return node; -} - -void -_cairo_freelist_free (cairo_freelist_t *freelist, void *voidnode) -{ - cairo_freelist_node_t *node = voidnode; - if (node) { - node->next = freelist->first_free_node; - freelist->first_free_node = node; - } -} diff --git a/uppdev/plugin/cairo/lib/cairo-ft-font.c b/uppdev/plugin/cairo/lib/cairo-ft-font.c deleted file mode 100644 index cd1125325..000000000 --- a/uppdev/plugin/cairo/lib/cairo-ft-font.c +++ /dev/null @@ -1,2746 +0,0 @@ -/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2000 Keith Packard - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Graydon Hoare - * Owen Taylor - * Keith Packard - * Carl Worth - */ - -#define _BSD_SOURCE /* for strdup() */ -#include "cairoint.h" - -#include "cairo-ft-private.h" - -#include - -#include -#include - -#include -#include FT_FREETYPE_H -#include FT_OUTLINE_H -#include FT_IMAGE_H -#include FT_TRUETYPE_TABLES_H -#if HAVE_FT_GLYPHSLOT_EMBOLDEN -#include FT_SYNTHESIS_H -#endif - -#define DOUBLE_TO_26_6(d) ((FT_F26Dot6)((d) * 64.0)) -#define DOUBLE_FROM_26_6(t) ((double)(t) / 64.0) -#define DOUBLE_TO_16_16(d) ((FT_Fixed)((d) * 65536.0)) -#define DOUBLE_FROM_16_16(t) ((double)(t) / 65536.0) - -/* This is the max number of FT_face objects we keep open at once - */ -#define MAX_OPEN_FACES 10 - -/* - * The simple 2x2 matrix is converted into separate scale and shape - * factors so that hinting works right - */ - -typedef struct _cairo_ft_font_transform { - double x_scale, y_scale; - double shape[2][2]; -} cairo_ft_font_transform_t; - -/* - * We create an object that corresponds to a single font on the disk; - * (identified by a filename/id pair) these are shared between all - * fonts using that file. For cairo_ft_font_face_create_for_ft_face(), we - * just create a one-off version with a permanent face value. - */ - -typedef struct _cairo_ft_font_face cairo_ft_font_face_t; - -struct _cairo_ft_unscaled_font { - cairo_unscaled_font_t base; - - cairo_bool_t from_face; /* was the FT_Face provided by user? */ - FT_Face face; /* provided or cached face */ - - /* only set if from_face is false */ - char *filename; - int id; - - /* We temporarily scale the unscaled font as needed */ - cairo_bool_t have_scale; - cairo_matrix_t current_scale; - double x_scale; /* Extracted X scale factor */ - double y_scale; /* Extracted Y scale factor */ - cairo_bool_t have_shape; /* true if the current scale has a non-scale component*/ - cairo_matrix_t current_shape; - FT_Matrix Current_Shape; - - cairo_mutex_t mutex; - int lock_count; - - cairo_ft_font_face_t *faces; /* Linked list of faces for this font */ -}; - -static int -_cairo_ft_unscaled_font_keys_equal (const void *key_a, - const void *key_b); - -static void -_cairo_ft_unscaled_font_fini (cairo_ft_unscaled_font_t *unscaled); - -static cairo_status_t -_cairo_ft_font_options_substitute (const cairo_font_options_t *options, - FcPattern *pattern); - -typedef enum _cairo_ft_extra_flags { - CAIRO_FT_OPTIONS_HINT_METRICS = (1 << 0), - CAIRO_FT_OPTIONS_EMBOLDEN = (1 << 1) -} cairo_ft_extra_flags_t; - -typedef struct _cairo_ft_options { - cairo_font_options_t base; - int load_flags; /* flags for FT_Load_Glyph */ - cairo_ft_extra_flags_t extra_flags; /* other flags that affect results */ -} cairo_ft_options_t; - -struct _cairo_ft_font_face { - cairo_font_face_t base; - cairo_ft_unscaled_font_t *unscaled; - cairo_ft_options_t ft_options; - cairo_ft_font_face_t *next; -}; - -static const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend; - -/* - * We maintain a hash table to map file/id => #cairo_ft_unscaled_font_t. - * The hash table itself isn't limited in size. However, we limit the - * number of FT_Face objects we keep around; when we've exceeded that - * limit and need to create a new FT_Face, we dump the FT_Face from a - * random #cairo_ft_unscaled_font_t which has an unlocked FT_Face, (if - * there are any). - */ - -typedef struct _cairo_ft_unscaled_font_map { - cairo_hash_table_t *hash_table; - FT_Library ft_library; - int num_open_faces; -} cairo_ft_unscaled_font_map_t; - -static cairo_ft_unscaled_font_map_t *cairo_ft_unscaled_font_map = NULL; - -static void -_font_map_release_face_lock_held (cairo_ft_unscaled_font_map_t *font_map, - cairo_ft_unscaled_font_t *unscaled) -{ - if (unscaled->face) { - FT_Done_Face (unscaled->face); - unscaled->face = NULL; - unscaled->have_scale = FALSE; - - font_map->num_open_faces--; - } -} - -static void -_cairo_ft_unscaled_font_map_create (void) -{ - cairo_ft_unscaled_font_map_t *font_map; - - /* This function is only intended to be called from - * _cairo_ft_unscaled_font_map_lock. So we'll crash if we can - * detect some other call path. */ - assert (cairo_ft_unscaled_font_map == NULL); - - font_map = malloc (sizeof (cairo_ft_unscaled_font_map_t)); - if (font_map == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - goto FAIL; - } - - font_map->hash_table = - _cairo_hash_table_create (_cairo_ft_unscaled_font_keys_equal); - - if (font_map->hash_table == NULL) - goto FAIL; - - if (FT_Init_FreeType (&font_map->ft_library)) - goto FAIL; - - font_map->num_open_faces = 0; - - cairo_ft_unscaled_font_map = font_map; - return; - -FAIL: - if (font_map) { - if (font_map->hash_table) - _cairo_hash_table_destroy (font_map->hash_table); - free (font_map); - } - cairo_ft_unscaled_font_map = NULL; -} - -static void -_cairo_ft_unscaled_font_map_destroy (void) -{ - cairo_ft_unscaled_font_t *unscaled; - cairo_ft_unscaled_font_map_t *font_map; - - CAIRO_MUTEX_LOCK (_cairo_ft_unscaled_font_map_mutex); - - if (cairo_ft_unscaled_font_map) { - font_map = cairo_ft_unscaled_font_map; - - /* This is rather inefficient, but destroying the hash table - * is something we only do during debugging, (during - * cairo_debug_reset_static_data), when efficiency is not - * relevant. */ - while (1) { - unscaled = _cairo_hash_table_random_entry (font_map->hash_table, - NULL); - if (unscaled == NULL) - break; - _cairo_hash_table_remove (font_map->hash_table, - &unscaled->base.hash_entry); - - _font_map_release_face_lock_held (font_map, unscaled); - _cairo_ft_unscaled_font_fini (unscaled); - free (unscaled); - } - - assert (font_map->num_open_faces == 0); - - FT_Done_FreeType (font_map->ft_library); - - _cairo_hash_table_destroy (font_map->hash_table); - - free (font_map); - - cairo_ft_unscaled_font_map = NULL; - } - - CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex); -} - -static cairo_ft_unscaled_font_map_t * -_cairo_ft_unscaled_font_map_lock (void) -{ - CAIRO_MUTEX_LOCK (_cairo_ft_unscaled_font_map_mutex); - - if (cairo_ft_unscaled_font_map == NULL) - { - _cairo_ft_unscaled_font_map_create (); - - if (cairo_ft_unscaled_font_map == NULL) { - CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex); - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return NULL; - } - } - - return cairo_ft_unscaled_font_map; -} - -static void -_cairo_ft_unscaled_font_map_unlock (void) -{ - CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex); -} - -static void -_cairo_ft_unscaled_font_init_key (cairo_ft_unscaled_font_t *key, - cairo_bool_t from_face, - char *filename, - int id, - FT_Face face) -{ - unsigned long hash; - - key->from_face = from_face; - key->filename = filename; - key->id = id; - key->face = face; - - hash = _cairo_hash_string (filename); - /* the constants are just arbitrary primes */ - hash += ((unsigned long) id) * 1607; - hash += ((unsigned long) face) * 2137; - - key->base.hash_entry.hash = hash; -} - -/** - * _cairo_ft_unscaled_font_init: - * - * Initialize a #cairo_ft_unscaled_font_t. - * - * There are two basic flavors of #cairo_ft_unscaled_font_t, one - * created from an FT_Face and the other created from a filename/id - * pair. These two flavors are identified as from_face and !from_face. - * - * To initialize a from_face font, pass filename==%NULL, id=0 and the - * desired face. - * - * To initialize a !from_face font, pass the filename/id as desired - * and face==%NULL. - * - * Note that the code handles these two flavors in very distinct - * ways. For example there is a hash_table mapping - * filename/id->#cairo_unscaled_font_t in the !from_face case, but no - * parallel in the from_face case, (where the calling code would have - * to do its own mapping to ensure similar sharing). - **/ -static cairo_status_t -_cairo_ft_unscaled_font_init (cairo_ft_unscaled_font_t *unscaled, - cairo_bool_t from_face, - const char *filename, - int id, - FT_Face face) -{ - _cairo_unscaled_font_init (&unscaled->base, - &cairo_ft_unscaled_font_backend); - - if (from_face) { - unscaled->from_face = TRUE; - _cairo_ft_unscaled_font_init_key (unscaled, TRUE, NULL, 0, face); - } else { - char *filename_copy; - - unscaled->from_face = FALSE; - unscaled->face = NULL; - - filename_copy = strdup (filename); - if (filename_copy == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - _cairo_ft_unscaled_font_init_key (unscaled, FALSE, filename_copy, id, NULL); - } - - unscaled->have_scale = FALSE; - CAIRO_MUTEX_INIT (unscaled->mutex); - unscaled->lock_count = 0; - - unscaled->faces = NULL; - - return CAIRO_STATUS_SUCCESS; -} - -/** - * _cairo_ft_unscaled_font_fini: - * - * Free all data associated with a #cairo_ft_unscaled_font_t. - * - * CAUTION: The unscaled->face field must be %NULL before calling this - * function. This is because the #cairo_ft_unscaled_font_t_map keeps a - * count of these faces (font_map->num_open_faces) so it maintains the - * unscaled->face field while it has its lock held. See - * _font_map_release_face_lock_held(). - **/ -static void -_cairo_ft_unscaled_font_fini (cairo_ft_unscaled_font_t *unscaled) -{ - assert (unscaled->face == NULL); - - if (unscaled->filename) { - free (unscaled->filename); - unscaled->filename = NULL; - } - - CAIRO_MUTEX_FINI (unscaled->mutex); -} - -static int -_cairo_ft_unscaled_font_keys_equal (const void *key_a, - const void *key_b) -{ - const cairo_ft_unscaled_font_t *unscaled_a = key_a; - const cairo_ft_unscaled_font_t *unscaled_b = key_b; - - if (unscaled_a->id == unscaled_b->id && - unscaled_a->from_face == unscaled_b->from_face) - { - if (unscaled_a->from_face) - return unscaled_a->face == unscaled_b->face; - - if (unscaled_a->filename == NULL && unscaled_b->filename == NULL) - return TRUE; - else if (unscaled_a->filename == NULL || unscaled_b->filename == NULL) - return FALSE; - else - return (strcmp (unscaled_a->filename, unscaled_b->filename) == 0); - } - - return FALSE; -} - -/* Finds or creates a #cairo_ft_unscaled_font_t for the filename/id from - * pattern. Returns a new reference to the unscaled font. - */ -static cairo_ft_unscaled_font_t * -_cairo_ft_unscaled_font_create_internal (cairo_bool_t from_face, - char *filename, - int id, - FT_Face font_face) -{ - cairo_ft_unscaled_font_t key, *unscaled; - cairo_ft_unscaled_font_map_t *font_map; - cairo_status_t status; - - font_map = _cairo_ft_unscaled_font_map_lock (); - if (font_map == NULL) - goto UNWIND; - - _cairo_ft_unscaled_font_init_key (&key, from_face, filename, id, font_face); - - /* Return existing unscaled font if it exists in the hash table. */ - if (_cairo_hash_table_lookup (font_map->hash_table, &key.base.hash_entry, - (cairo_hash_entry_t **) &unscaled)) - { - _cairo_unscaled_font_reference (&unscaled->base); - _cairo_ft_unscaled_font_map_unlock (); - return unscaled; - } - - /* Otherwise create it and insert into hash table. */ - unscaled = malloc (sizeof (cairo_ft_unscaled_font_t)); - if (unscaled == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - goto UNWIND_FONT_MAP_LOCK; - } - - status = _cairo_ft_unscaled_font_init (unscaled, from_face, filename, id, font_face); - if (status) - goto UNWIND_UNSCALED_MALLOC; - - status = _cairo_hash_table_insert (font_map->hash_table, - &unscaled->base.hash_entry); - if (status) - goto UNWIND_UNSCALED_FONT_INIT; - - _cairo_ft_unscaled_font_map_unlock (); - - return unscaled; - -UNWIND_UNSCALED_FONT_INIT: - _cairo_ft_unscaled_font_fini (unscaled); -UNWIND_UNSCALED_MALLOC: - free (unscaled); -UNWIND_FONT_MAP_LOCK: - _cairo_ft_unscaled_font_map_unlock (); -UNWIND: - return NULL; -} - - -static cairo_ft_unscaled_font_t * -_cairo_ft_unscaled_font_create_for_pattern (FcPattern *pattern) -{ - FT_Face font_face = NULL; - char *filename = NULL; - int id = 0; - - if (FcPatternGetFTFace (pattern, FC_FT_FACE, 0, &font_face) != FcResultMatch) { - FcChar8 *fc_filename = NULL; - - if (FcPatternGetString (pattern, FC_FILE, 0, &fc_filename) != FcResultMatch) - goto UNWIND; - filename = (char *) fc_filename; - - if (FcPatternGetInteger (pattern, FC_INDEX, 0, &id) != FcResultMatch) - goto UNWIND; - } - - return _cairo_ft_unscaled_font_create_internal (font_face != NULL, filename, id, font_face); - -UNWIND: - return NULL; -} - -static cairo_ft_unscaled_font_t * -_cairo_ft_unscaled_font_create_from_face (FT_Face face) -{ - return _cairo_ft_unscaled_font_create_internal (TRUE, NULL, 0, face); -} - -static void -_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); - - _cairo_hash_table_remove (font_map->hash_table, - &unscaled->base.hash_entry); - - if (unscaled->from_face) { - /* See comments in _ft_font_face_destroy about the "zombie" state - * for a _ft_font_face. - */ - if (unscaled->faces && !unscaled->faces->unscaled) - cairo_font_face_destroy (&unscaled->faces->base); - } else { - _font_map_release_face_lock_held (font_map, unscaled); - } - unscaled->face = NULL; - - _cairo_ft_unscaled_font_map_unlock (); - - _cairo_ft_unscaled_font_fini (unscaled); -} - -static cairo_bool_t -_has_unlocked_face (void *entry) -{ - cairo_ft_unscaled_font_t *unscaled = entry; - - return (unscaled->lock_count == 0 && unscaled->face); -} - -/* Ensures that an unscaled font has a face object. If we exceed - * MAX_OPEN_FACES, try to close some. - * - * This differs from _cairo_ft_scaled_font_lock_face in that it doesn't - * set the scale on the face, but just returns it at the last scale. - */ -cairo_warn FT_Face -_cairo_ft_unscaled_font_lock_face (cairo_ft_unscaled_font_t *unscaled) -{ - cairo_ft_unscaled_font_map_t *font_map; - FT_Face face = NULL; - - CAIRO_MUTEX_LOCK (unscaled->mutex); - unscaled->lock_count++; - - if (unscaled->face) - return unscaled->face; - - /* If this unscaled font was created from an FT_Face then we just - * returned it above. */ - assert (!unscaled->from_face); - - font_map = _cairo_ft_unscaled_font_map_lock (); - { - assert (font_map != NULL); - - while (font_map->num_open_faces >= MAX_OPEN_FACES) - { - cairo_ft_unscaled_font_t *entry; - - entry = _cairo_hash_table_random_entry (font_map->hash_table, - _has_unlocked_face); - if (entry == NULL) - break; - - _font_map_release_face_lock_held (font_map, entry); - } - } - _cairo_ft_unscaled_font_map_unlock (); - - if (FT_New_Face (font_map->ft_library, - unscaled->filename, - unscaled->id, - &face) != FT_Err_Ok) - { - unscaled->lock_count--; - CAIRO_MUTEX_UNLOCK (unscaled->mutex); - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return NULL; - } - - unscaled->face = face; - - font_map->num_open_faces++; - - return face; -} - - -/* Unlock unscaled font locked with _cairo_ft_unscaled_font_lock_face - */ -void -_cairo_ft_unscaled_font_unlock_face (cairo_ft_unscaled_font_t *unscaled) -{ - assert (unscaled->lock_count > 0); - - unscaled->lock_count--; - - CAIRO_MUTEX_UNLOCK (unscaled->mutex); -} - - -static cairo_status_t -_compute_transform (cairo_ft_font_transform_t *sf, - cairo_matrix_t *scale) -{ - cairo_status_t status; - double x_scale, y_scale; - cairo_matrix_t normalized = *scale; - - /* The font matrix has x and y "scale" components which we extract and - * use as character scale values. These influence the way freetype - * chooses hints, as well as selecting different bitmaps in - * hand-rendered fonts. We also copy the normalized matrix to - * freetype's transformation. - */ - - status = _cairo_matrix_compute_basis_scale_factors (scale, - &x_scale, &y_scale, - 1); - if (status) - return status; - - /* FreeType docs say this about x_scale and y_scale: - * "A character width or height smaller than 1pt is set to 1pt;" - * So, we cap them from below at 1.0 and let the FT transform - * take care of sub-1.0 scaling. */ - if (x_scale < 1.0) - x_scale = 1.0; - if (y_scale < 1.0) - y_scale = 1.0; - - sf->x_scale = x_scale; - sf->y_scale = y_scale; - - cairo_matrix_scale (&normalized, 1.0 / x_scale, 1.0 / y_scale); - - _cairo_matrix_get_affine (&normalized, - &sf->shape[0][0], &sf->shape[0][1], - &sf->shape[1][0], &sf->shape[1][1], - NULL, NULL); - - return CAIRO_STATUS_SUCCESS; -} - -/* Temporarily scales an unscaled font to the give scale. We catch - * scaling to the same size, since changing a FT_Face is expensive. - */ -static cairo_status_t -_cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled, - cairo_matrix_t *scale) -{ - cairo_status_t status; - cairo_ft_font_transform_t sf; - FT_Matrix mat; - FT_Error error; - - assert (unscaled->face != NULL); - - if (unscaled->have_scale && - scale->xx == unscaled->current_scale.xx && - scale->yx == unscaled->current_scale.yx && - scale->xy == unscaled->current_scale.xy && - scale->yy == unscaled->current_scale.yy) - return CAIRO_STATUS_SUCCESS; - - unscaled->have_scale = TRUE; - unscaled->current_scale = *scale; - - status = _compute_transform (&sf, scale); - if (status) - return status; - - unscaled->x_scale = sf.x_scale; - unscaled->y_scale = sf.y_scale; - - mat.xx = DOUBLE_TO_16_16(sf.shape[0][0]); - mat.yx = - DOUBLE_TO_16_16(sf.shape[0][1]); - mat.xy = - DOUBLE_TO_16_16(sf.shape[1][0]); - mat.yy = DOUBLE_TO_16_16(sf.shape[1][1]); - - unscaled->have_shape = (mat.xx != 0x10000 || - mat.yx != 0x00000 || - mat.xy != 0x00000 || - mat.yy != 0x10000); - - unscaled->Current_Shape = mat; - cairo_matrix_init (&unscaled->current_shape, - sf.shape[0][0], sf.shape[0][1], - sf.shape[1][0], sf.shape[1][1], - 0.0, 0.0); - - FT_Set_Transform(unscaled->face, &mat, NULL); - - if ((unscaled->face->face_flags & FT_FACE_FLAG_SCALABLE) != 0) { - error = FT_Set_Char_Size (unscaled->face, - sf.x_scale * 64.0 + .5, - sf.y_scale * 64.0 + .5, - 0, 0); - if (error) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } else { - double min_distance = DBL_MAX; - int i; - int best_i = 0; - - for (i = 0; i < unscaled->face->num_fixed_sizes; i++) { -#if HAVE_FT_BITMAP_SIZE_Y_PPEM - double size = unscaled->face->available_sizes[i].y_ppem / 64.; -#else - double size = unscaled->face->available_sizes[i].height; -#endif - double distance = fabs (size - sf.y_scale); - - if (distance <= min_distance) { - min_distance = distance; - best_i = i; - } - } -#if HAVE_FT_BITMAP_SIZE_Y_PPEM - error = FT_Set_Char_Size (unscaled->face, - unscaled->face->available_sizes[best_i].x_ppem, - unscaled->face->available_sizes[best_i].y_ppem, - 0, 0); - if (error) -#endif - error = FT_Set_Pixel_Sizes (unscaled->face, - unscaled->face->available_sizes[best_i].width, - unscaled->face->available_sizes[best_i].height); - if (error) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - return CAIRO_STATUS_SUCCESS; -} - -/* Empirically-derived subpixel filtering values thanks to Keith - * Packard and libXft. */ -static const int filters[3][3] = { - /* red */ -#if 0 - { 65538*4/7,65538*2/7,65538*1/7 }, - /* green */ - { 65536*1/4, 65536*2/4, 65537*1/4 }, - /* blue */ - { 65538*1/7,65538*2/7,65538*4/7 }, -#endif - { 65538*9/13,65538*3/13,65538*1/13 }, - /* green */ - { 65538*1/6, 65538*4/6, 65538*1/6 }, - /* blue */ - { 65538*1/13,65538*3/13,65538*9/13 }, -}; - -/* Fills in val->image with an image surface created from @bitmap - */ -static cairo_status_t -_get_bitmap_surface (FT_Bitmap *bitmap, - cairo_bool_t own_buffer, - cairo_font_options_t *font_options, - cairo_image_surface_t **surface) -{ - int width, height, stride; - unsigned char *data; - int format = CAIRO_FORMAT_A8; - cairo_bool_t subpixel = FALSE; - - width = bitmap->width; - height = bitmap->rows; - - if (width == 0 || height == 0) { - *surface = (cairo_image_surface_t *) - cairo_image_surface_create_for_data (NULL, format, 0, 0, 0); - return (*surface)->base.status; - } - - switch (bitmap->pixel_mode) { - case FT_PIXEL_MODE_MONO: - stride = (((width + 31) & ~31) >> 3); - if (own_buffer) { - data = bitmap->buffer; - assert (stride == bitmap->pitch); - } else { - data = _cairo_malloc_ab (height, stride); - if (!data) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - if (stride == bitmap->pitch) { - memcpy (data, bitmap->buffer, stride * height); - } else { - int i; - unsigned char *source, *dest; - - source = bitmap->buffer; - dest = data; - for (i = height; i; i--) { - memcpy (dest, source, bitmap->pitch); - memset (dest + bitmap->pitch, '\0', stride - bitmap->pitch); - - source += bitmap->pitch; - dest += stride; - } - } - } - -#ifndef WORDS_BIGENDIAN - { - uint8_t *d = data; - int count = stride * height; - - while (count--) { - *d = CAIRO_BITSWAP8 (*d); - d++; - } - } -#endif - format = CAIRO_FORMAT_A1; - break; - - case FT_PIXEL_MODE_LCD: - case FT_PIXEL_MODE_LCD_V: - case FT_PIXEL_MODE_GRAY: - switch (font_options->antialias) { - case CAIRO_ANTIALIAS_DEFAULT: - case CAIRO_ANTIALIAS_GRAY: - case CAIRO_ANTIALIAS_NONE: - default: - 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_A8; - break; - case CAIRO_ANTIALIAS_SUBPIXEL: { - int x, y; - unsigned char *in_line, *out_line, *in; - unsigned int *out; - unsigned int red, green, blue; - int rf, gf, bf; - int s; - int o, os; - unsigned char *data_rgba; - unsigned int width_rgba, stride_rgba; - int vmul = 1; - int hmul = 1; - - switch (font_options->subpixel_order) { - case CAIRO_SUBPIXEL_ORDER_DEFAULT: - case CAIRO_SUBPIXEL_ORDER_RGB: - case CAIRO_SUBPIXEL_ORDER_BGR: - default: - width /= 3; - hmul = 3; - break; - case CAIRO_SUBPIXEL_ORDER_VRGB: - case CAIRO_SUBPIXEL_ORDER_VBGR: - vmul = 3; - height /= 3; - break; - } - /* - * Filter the glyph to soften the color fringes - */ - width_rgba = width; - stride = bitmap->pitch; - stride_rgba = (width_rgba * 4 + 3) & ~3; - data_rgba = calloc (stride_rgba, height); - if (data_rgba == NULL) { - if (own_buffer) - free (bitmap->buffer); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - os = 1; - switch (font_options->subpixel_order) { - case CAIRO_SUBPIXEL_ORDER_VRGB: - os = stride; - case CAIRO_SUBPIXEL_ORDER_DEFAULT: - case CAIRO_SUBPIXEL_ORDER_RGB: - default: - rf = 0; - gf = 1; - bf = 2; - break; - case CAIRO_SUBPIXEL_ORDER_VBGR: - os = stride; - case CAIRO_SUBPIXEL_ORDER_BGR: - bf = 0; - gf = 1; - rf = 2; - break; - } - in_line = bitmap->buffer; - out_line = data_rgba; - for (y = 0; y < height; y++) - { - in = in_line; - out = (unsigned int *) out_line; - in_line += stride * vmul; - out_line += stride_rgba; - for (x = 0; x < width * hmul; x += hmul) - { - red = green = blue = 0; - o = 0; - for (s = 0; s < 3; s++) - { - red += filters[rf][s]*in[x+o]; - green += filters[gf][s]*in[x+o]; - blue += filters[bf][s]*in[x+o]; - o += os; - } - red = red / 65536; - green = green / 65536; - blue = blue / 65536; - *out++ = (green << 24) | (red << 16) | (green << 8) | blue; - } - } - - /* Images here are stored in native format. The - * backend must convert to its own format as needed - */ - - if (own_buffer) - free (bitmap->buffer); - data = data_rgba; - stride = stride_rgba; - format = CAIRO_FORMAT_ARGB32; - subpixel = TRUE; - break; - } - } - break; - case FT_PIXEL_MODE_GRAY2: - case FT_PIXEL_MODE_GRAY4: - /* These could be triggered by very rare types of TrueType fonts */ - default: - if (own_buffer) - free (bitmap->buffer); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - *surface = (cairo_image_surface_t *) - cairo_image_surface_create_for_data (data, - format, - width, height, stride); - if ((*surface)->base.status) { - free (data); - return (*surface)->base.status; - } - - if (subpixel) - pixman_image_set_component_alpha ((*surface)->pixman_image, TRUE); - - _cairo_image_surface_assume_ownership_of_data ((*surface)); - - return CAIRO_STATUS_SUCCESS; -} - -/* Converts an outline FT_GlyphSlot into an image - * - * This could go through _render_glyph_bitmap as well, letting - * FreeType convert the outline to a bitmap, but doing it ourselves - * has two minor advantages: first, we save a copy of the bitmap - * buffer: we can directly use the buffer that FreeType renders - * into. - * - * Second, it may help when we add support for subpixel - * rendering: the Xft code does it this way. (Keith thinks that - * it may also be possible to get the subpixel rendering with - * FT_Render_Glyph: something worth looking into in more detail - * when we add subpixel support. If so, we may want to eliminate - * this version of the code path entirely. - */ -static cairo_status_t -_render_glyph_outline (FT_Face face, - cairo_font_options_t *font_options, - cairo_image_surface_t **surface) -{ - FT_GlyphSlot glyphslot = face->glyph; - FT_Outline *outline = &glyphslot->outline; - FT_Bitmap bitmap; - FT_BBox cbox; - FT_Matrix matrix; - int hmul = 1; - int vmul = 1; - unsigned int width, height, stride; - cairo_bool_t subpixel = FALSE; - cairo_status_t status; - - FT_Outline_Get_CBox (outline, &cbox); - - cbox.xMin &= -64; - cbox.yMin &= -64; - cbox.xMax = (cbox.xMax + 63) & -64; - cbox.yMax = (cbox.yMax + 63) & -64; - - width = (unsigned int) ((cbox.xMax - cbox.xMin) >> 6); - height = (unsigned int) ((cbox.yMax - cbox.yMin) >> 6); - stride = (width * hmul + 3) & ~3; - - if (width * height == 0) { - cairo_format_t format; - /* Looks like fb handles zero-sized images just fine */ - switch (font_options->antialias) { - case CAIRO_ANTIALIAS_NONE: - format = CAIRO_FORMAT_A1; - break; - case CAIRO_ANTIALIAS_SUBPIXEL: - format= CAIRO_FORMAT_ARGB32; - break; - case CAIRO_ANTIALIAS_DEFAULT: - case CAIRO_ANTIALIAS_GRAY: - default: - format = CAIRO_FORMAT_A8; - break; - } - - (*surface) = (cairo_image_surface_t *) - cairo_image_surface_create_for_data (NULL, format, 0, 0, 0); - if ((*surface)->base.status) - return (*surface)->base.status; - } else { - - matrix.xx = matrix.yy = 0x10000L; - matrix.xy = matrix.yx = 0; - - switch (font_options->antialias) { - case CAIRO_ANTIALIAS_NONE: - bitmap.pixel_mode = FT_PIXEL_MODE_MONO; - bitmap.num_grays = 1; - stride = ((width + 31) & -32) >> 3; - break; - case CAIRO_ANTIALIAS_DEFAULT: - case CAIRO_ANTIALIAS_GRAY: - bitmap.pixel_mode = FT_PIXEL_MODE_GRAY; - bitmap.num_grays = 256; - stride = (width + 3) & -4; - break; - case CAIRO_ANTIALIAS_SUBPIXEL: - switch (font_options->subpixel_order) { - case CAIRO_SUBPIXEL_ORDER_RGB: - case CAIRO_SUBPIXEL_ORDER_BGR: - case CAIRO_SUBPIXEL_ORDER_DEFAULT: - default: - matrix.xx *= 3; - hmul = 3; - subpixel = TRUE; - break; - case CAIRO_SUBPIXEL_ORDER_VRGB: - case CAIRO_SUBPIXEL_ORDER_VBGR: - matrix.yy *= 3; - vmul = 3; - subpixel = TRUE; - break; - } - FT_Outline_Transform (outline, &matrix); - - bitmap.pixel_mode = FT_PIXEL_MODE_GRAY; - bitmap.num_grays = 256; - stride = (width * hmul + 3) & -4; - } - - bitmap.pitch = stride; - bitmap.width = width * hmul; - bitmap.rows = height * vmul; - bitmap.buffer = calloc (stride, bitmap.rows); - if (bitmap.buffer == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - FT_Outline_Translate (outline, -cbox.xMin*hmul, -cbox.yMin*vmul); - - if (FT_Outline_Get_Bitmap (glyphslot->library, outline, &bitmap) != 0) { - free (bitmap.buffer); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - status = _get_bitmap_surface (&bitmap, TRUE, font_options, surface); - if (status) - return status; - } - - /* - * Note: the font's coordinate system is upside down from ours, so the - * Y coordinate of the control box needs to be negated. Moreover, device - * offsets are position of glyph origin relative to top left while xMin - * and yMax are offsets of top left relative to origin. Another negation. - */ - cairo_surface_set_device_offset (&(*surface)->base, - floor (-(double) cbox.xMin / 64.0), - floor (+(double) cbox.yMax / 64.0)); - - return CAIRO_STATUS_SUCCESS; -} - -/* Converts a bitmap (or other) FT_GlyphSlot into an image */ -static cairo_status_t -_render_glyph_bitmap (FT_Face face, - cairo_font_options_t *font_options, - cairo_image_surface_t **surface) -{ - FT_GlyphSlot glyphslot = face->glyph; - cairo_status_t status = CAIRO_STATUS_SUCCESS; - FT_Error error; - - /* According to the FreeType docs, glyphslot->format could be - * something other than FT_GLYPH_FORMAT_OUTLINE or - * FT_GLYPH_FORMAT_BITMAP. Calling FT_Render_Glyph gives FreeType - * the opportunity to convert such to - * bitmap. FT_GLYPH_FORMAT_COMPOSITE will not be encountered since - * we avoid the FT_LOAD_NO_RECURSE flag. - */ - error = FT_Render_Glyph (glyphslot, FT_RENDER_MODE_NORMAL); - /* XXX ignoring all other errors for now. They are not fatal, typically - * just a glyph-not-found. */ - if (error == FT_Err_Out_Of_Memory) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - status = _get_bitmap_surface (&glyphslot->bitmap, FALSE, font_options, surface); - if (status) - return status; - - /* - * Note: the font's coordinate system is upside down from ours, so the - * Y coordinate of the control box needs to be negated. Moreover, device - * offsets are position of glyph origin relative to top left while - * bitmap_left and bitmap_top are offsets of top left relative to origin. - * Another negation. - */ - cairo_surface_set_device_offset (&(*surface)->base, - -glyphslot->bitmap_left, - +glyphslot->bitmap_top); - - return status; -} - -static cairo_status_t -_transform_glyph_bitmap (cairo_matrix_t * shape, - cairo_image_surface_t ** surface) -{ - cairo_matrix_t original_to_transformed; - cairo_matrix_t transformed_to_original; - cairo_image_surface_t *old_image; - cairo_surface_t *image; - double x[4], y[4]; - double origin_x, origin_y; - int orig_width, orig_height; - int i; - int x_min, y_min, x_max, y_max; - int width, height; - cairo_status_t status; - cairo_surface_pattern_t pattern; - - /* We want to compute a transform that takes the origin - * (device_x_offset, device_y_offset) to 0,0, then applies - * the "shape" portion of the font transform - */ - original_to_transformed = *shape; - - cairo_surface_get_device_offset (&(*surface)->base, &origin_x, &origin_y); - orig_width = cairo_image_surface_get_width (&(*surface)->base); - orig_height = cairo_image_surface_get_height (&(*surface)->base); - - cairo_matrix_translate (&original_to_transformed, - -origin_x, -origin_y); - - /* Find the bounding box of the original bitmap under that - * transform - */ - x[0] = 0; y[0] = 0; - x[1] = orig_width; y[1] = 0; - x[2] = orig_width; y[2] = orig_height; - x[3] = 0; y[3] = orig_height; - - for (i = 0; i < 4; i++) - cairo_matrix_transform_point (&original_to_transformed, - &x[i], &y[i]); - - x_min = floor (x[0]); y_min = floor (y[0]); - x_max = ceil (x[0]); y_max = ceil (y[0]); - - for (i = 1; i < 4; i++) { - if (x[i] < x_min) - x_min = floor (x[i]); - else if (x[i] > x_max) - x_max = ceil (x[i]); - if (y[i] < y_min) - y_min = floor (y[i]); - else if (y[i] > y_max) - y_max = ceil (y[i]); - } - - /* Adjust the transform so that the bounding box starts at 0,0 ... - * this gives our final transform from original bitmap to transformed - * bitmap. - */ - original_to_transformed.x0 -= x_min; - original_to_transformed.y0 -= y_min; - - /* Create the transformed bitmap - */ - width = x_max - x_min; - height = y_max - y_min; - - transformed_to_original = original_to_transformed; - status = cairo_matrix_invert (&transformed_to_original); - if (status) - return status; - - /* We need to pad out the width to 32-bit intervals for cairo-xlib-surface.c */ - width = (width + 3) & ~3; - image = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height); - if (image->status) - return image->status; - - /* Initialize it to empty - */ - status = _cairo_surface_fill_rectangle (image, CAIRO_OPERATOR_CLEAR, - CAIRO_COLOR_TRANSPARENT, - 0, 0, - width, height); - if (status) { - cairo_surface_destroy (image); - return status; - } - - /* Draw the original bitmap transformed into the new bitmap - */ - _cairo_pattern_init_for_surface (&pattern, &(*surface)->base); - cairo_pattern_set_matrix (&pattern.base, &transformed_to_original); - - status = _cairo_surface_composite (CAIRO_OPERATOR_OVER, - &pattern.base, NULL, image, - 0, 0, 0, 0, 0, 0, - width, - height); - - _cairo_pattern_fini (&pattern.base); - - if (status) { - cairo_surface_destroy (image); - return status; - } - - /* Now update the cache entry for the new bitmap, recomputing - * the origin based on the final transform. - */ - cairo_matrix_transform_point (&original_to_transformed, - &origin_x, &origin_y); - - old_image = (*surface); - (*surface) = (cairo_image_surface_t *)image; - cairo_surface_destroy (&old_image->base); - - cairo_surface_set_device_offset (&(*surface)->base, - _cairo_lround (origin_x), - _cairo_lround (origin_y)); - return status; -} - -static const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend = { - _cairo_ft_unscaled_font_destroy, -#if 0 - _cairo_ft_unscaled_font_create_glyph -#endif -}; - -/* #cairo_ft_scaled_font_t */ - -typedef struct _cairo_ft_scaled_font { - cairo_scaled_font_t base; - cairo_ft_unscaled_font_t *unscaled; - cairo_ft_options_t ft_options; -} cairo_ft_scaled_font_t; - -const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend; - -/* The load flags passed to FT_Load_Glyph control aspects like hinting and - * antialiasing. Here we compute them from the fields of a FcPattern. - */ -static void -_get_pattern_ft_options (FcPattern *pattern, cairo_ft_options_t *ret) -{ - FcBool antialias, vertical_layout, hinting, autohint, bitmap, embolden; - cairo_ft_options_t ft_options; - int rgba; -#ifdef FC_HINT_STYLE - int hintstyle; -#endif - - _cairo_font_options_init_default (&ft_options.base); - ft_options.load_flags = FT_LOAD_DEFAULT; - ft_options.extra_flags = 0; - -#ifndef FC_EMBEDDED_BITMAP -#define FC_EMBEDDED_BITMAP "embeddedbitmap" -#endif - - /* Check whether to force use of embedded bitmaps */ - if (FcPatternGetBool (pattern, - FC_EMBEDDED_BITMAP, 0, &bitmap) != FcResultMatch) - bitmap = FcFalse; - - /* disable antialiasing if requested */ - if (FcPatternGetBool (pattern, - FC_ANTIALIAS, 0, &antialias) != FcResultMatch) - antialias = FcTrue; - - if (antialias) { - cairo_subpixel_order_t subpixel_order; - - /* disable hinting if requested */ - if (FcPatternGetBool (pattern, - FC_HINTING, 0, &hinting) != FcResultMatch) - hinting = FcTrue; - - if (FcPatternGetInteger (pattern, - FC_RGBA, 0, &rgba) != FcResultMatch) - rgba = FC_RGBA_UNKNOWN; - - switch (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; - break; - } - - if (subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT) { - ft_options.base.subpixel_order = subpixel_order; - ft_options.base.antialias = CAIRO_ANTIALIAS_SUBPIXEL; - } - -#ifdef FC_HINT_STYLE - if (FcPatternGetInteger (pattern, - FC_HINT_STYLE, 0, &hintstyle) != FcResultMatch) - hintstyle = FC_HINT_FULL; - - if (!hinting) - hintstyle = FC_HINT_NONE; - - switch (hintstyle) { - case FC_HINT_NONE: - ft_options.base.hint_style = CAIRO_HINT_STYLE_NONE; - break; - case FC_HINT_SLIGHT: - ft_options.base.hint_style = CAIRO_HINT_STYLE_SLIGHT; - break; - case FC_HINT_MEDIUM: - default: - ft_options.base.hint_style = CAIRO_HINT_STYLE_MEDIUM; - break; - case FC_HINT_FULL: - ft_options.base.hint_style = CAIRO_HINT_STYLE_FULL; - break; - } -#else /* !FC_HINT_STYLE */ - if (!hinting) { - ft_options.base.hint_style = CAIRO_HINT_STYLE_NONE; - } -#endif /* FC_HINT_STYLE */ - - /* Force embedded bitmaps off if no hinting requested */ - if (ft_options.base.hint_style == CAIRO_HINT_STYLE_NONE) - bitmap = FcFalse; - - if (!bitmap) - ft_options.load_flags |= FT_LOAD_NO_BITMAP; - - } else { - ft_options.base.antialias = CAIRO_ANTIALIAS_NONE; - } - - /* force autohinting if requested */ - if (FcPatternGetBool (pattern, - FC_AUTOHINT, 0, &autohint) != FcResultMatch) - autohint = FcFalse; - - if (autohint) - ft_options.load_flags |= FT_LOAD_FORCE_AUTOHINT; - - if (FcPatternGetBool (pattern, - FC_VERTICAL_LAYOUT, 0, &vertical_layout) != FcResultMatch) - vertical_layout = FcFalse; - - if (vertical_layout) - ft_options.load_flags |= FT_LOAD_VERTICAL_LAYOUT; - -#ifndef FC_EMBOLDEN -#define FC_EMBOLDEN "embolden" -#endif - if (FcPatternGetBool (pattern, - FC_EMBOLDEN, 0, &embolden) != FcResultMatch) - embolden = FcFalse; - - if (embolden) - ft_options.extra_flags |= CAIRO_FT_OPTIONS_EMBOLDEN; - - *ret = ft_options; -} - -static void -_cairo_ft_options_merge (cairo_ft_options_t *options, - cairo_ft_options_t *other) -{ - int load_flags = other->load_flags; - int load_target = FT_LOAD_TARGET_NORMAL; - - /* clear load target mode */ - load_flags &= ~(FT_LOAD_TARGET_(FT_LOAD_TARGET_MODE(other->load_flags))); - - if (load_flags & FT_LOAD_NO_HINTING) - other->base.hint_style = CAIRO_HINT_STYLE_NONE; - - if (other->base.antialias == CAIRO_ANTIALIAS_NONE || - options->base.antialias == CAIRO_ANTIALIAS_NONE) { - options->base.antialias = CAIRO_ANTIALIAS_NONE; - options->base.subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT; - } - - if (other->base.antialias == CAIRO_ANTIALIAS_SUBPIXEL && - (options->base.antialias == CAIRO_ANTIALIAS_DEFAULT || - options->base.antialias == CAIRO_ANTIALIAS_GRAY)) { - options->base.antialias = CAIRO_ANTIALIAS_SUBPIXEL; - options->base.subpixel_order = other->base.subpixel_order; - } - - if (options->base.hint_style == CAIRO_HINT_STYLE_DEFAULT) - options->base.hint_style = other->base.hint_style; - - if (other->base.hint_style == CAIRO_HINT_STYLE_NONE) - options->base.hint_style = CAIRO_HINT_STYLE_NONE; - - if (options->base.antialias == CAIRO_ANTIALIAS_NONE) { - if (options->base.hint_style == CAIRO_HINT_STYLE_NONE) - load_flags |= FT_LOAD_NO_HINTING; - else - load_target = FT_LOAD_TARGET_MONO; - load_flags |= FT_LOAD_MONOCHROME; - } else { - switch (options->base.hint_style) { - case CAIRO_HINT_STYLE_NONE: - load_flags |= FT_LOAD_NO_HINTING; - break; - case CAIRO_HINT_STYLE_SLIGHT: - load_target = FT_LOAD_TARGET_LIGHT; - break; - case CAIRO_HINT_STYLE_MEDIUM: - break; - case CAIRO_HINT_STYLE_FULL: - case CAIRO_HINT_STYLE_DEFAULT: - if (options->base.antialias == CAIRO_ANTIALIAS_SUBPIXEL) { - switch (options->base.subpixel_order) { - case CAIRO_SUBPIXEL_ORDER_DEFAULT: - case CAIRO_SUBPIXEL_ORDER_RGB: - case CAIRO_SUBPIXEL_ORDER_BGR: - load_target |= FT_LOAD_TARGET_LCD; - break; - case CAIRO_SUBPIXEL_ORDER_VRGB: - case CAIRO_SUBPIXEL_ORDER_VBGR: - load_target |= FT_LOAD_TARGET_LCD_V; - break; - } - } - break; - } - } - - options->load_flags = load_flags | load_target; - options->extra_flags = other->extra_flags; - if (options->base.hint_metrics != CAIRO_HINT_METRICS_OFF) - options->extra_flags |= CAIRO_FT_OPTIONS_HINT_METRICS; -} - -static cairo_status_t -_cairo_ft_scaled_font_create (cairo_ft_unscaled_font_t *unscaled, - cairo_font_face_t *font_face, - const cairo_matrix_t *font_matrix, - const cairo_matrix_t *ctm, - const cairo_font_options_t *options, - cairo_ft_options_t ft_options, - cairo_scaled_font_t **font_out) -{ - cairo_ft_scaled_font_t *scaled_font; - FT_Face face; - FT_Size_Metrics *metrics; - cairo_font_extents_t fs_metrics; - cairo_status_t status; - - face = _cairo_ft_unscaled_font_lock_face (unscaled); - if (!face) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - scaled_font = malloc (sizeof(cairo_ft_scaled_font_t)); - if (scaled_font == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto FAIL; - } - - _cairo_unscaled_font_reference (&unscaled->base); - scaled_font->unscaled = unscaled; - - _cairo_font_options_init_copy (&scaled_font->ft_options.base, options); - _cairo_ft_options_merge (&scaled_font->ft_options, &ft_options); - - status = _cairo_scaled_font_init (&scaled_font->base, - font_face, - font_matrix, ctm, options, - &_cairo_ft_scaled_font_backend); - if (status) { - _cairo_unscaled_font_destroy (&unscaled->base); - free (scaled_font); - goto FAIL; - } - - status = _cairo_ft_unscaled_font_set_scale (unscaled, - &scaled_font->base.scale); - if (status) { - _cairo_unscaled_font_destroy (&unscaled->base); - free (scaled_font); - goto FAIL; - } - - - metrics = &face->size->metrics; - - /* - * Get to unscaled metrics so that the upper level can get back to - * user space - * - * Also use this path for bitmap-only fonts. The other branch uses - * face members that are only relevant for scalable fonts. This is - * detected by simply checking for units_per_EM==0. - */ - if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF || - face->units_per_EM == 0) { - double x_factor, y_factor; - - if (unscaled->x_scale == 0) - x_factor = 0; - else - x_factor = 1 / unscaled->x_scale; - - if (unscaled->y_scale == 0) - y_factor = 0; - else - y_factor = 1 / unscaled->y_scale; - - fs_metrics.ascent = DOUBLE_FROM_26_6(metrics->ascender) * y_factor; - fs_metrics.descent = DOUBLE_FROM_26_6(- metrics->descender) * y_factor; - fs_metrics.height = DOUBLE_FROM_26_6(metrics->height) * y_factor; - if (!_cairo_ft_scaled_font_is_vertical (&scaled_font->base)) { - fs_metrics.max_x_advance = DOUBLE_FROM_26_6(metrics->max_advance) * x_factor; - fs_metrics.max_y_advance = 0; - } else { - fs_metrics.max_x_advance = 0; - fs_metrics.max_y_advance = DOUBLE_FROM_26_6(metrics->max_advance) * y_factor; - } - } else { - double scale = face->units_per_EM; - - fs_metrics.ascent = face->ascender / scale; - fs_metrics.descent = - face->descender / scale; - fs_metrics.height = face->height / scale; - if (!_cairo_ft_scaled_font_is_vertical (&scaled_font->base)) { - fs_metrics.max_x_advance = face->max_advance_width / scale; - fs_metrics.max_y_advance = 0; - } else { - fs_metrics.max_x_advance = 0; - fs_metrics.max_y_advance = face->max_advance_height / scale; - } - } - - status = _cairo_scaled_font_set_metrics (&scaled_font->base, &fs_metrics); - - *font_out = &scaled_font->base; - - FAIL: - _cairo_ft_unscaled_font_unlock_face (unscaled); - - return status; -} - -cairo_bool_t -_cairo_scaled_font_is_ft (cairo_scaled_font_t *scaled_font) -{ - return scaled_font->backend == &_cairo_ft_scaled_font_backend; -} - -static cairo_status_t -_cairo_ft_scaled_font_create_toy (cairo_toy_font_face_t *toy_face, - const cairo_matrix_t *font_matrix, - const cairo_matrix_t *ctm, - const cairo_font_options_t *font_options, - cairo_scaled_font_t **font) -{ - FcPattern *pattern, *resolved; - cairo_ft_unscaled_font_t *unscaled; - FcResult result; - int fcslant; - int fcweight; - cairo_matrix_t scale; - cairo_status_t status; - cairo_ft_font_transform_t sf; - cairo_ft_options_t ft_options; - - cairo_matrix_multiply (&scale, font_matrix, ctm); - status = _compute_transform (&sf, &scale); - if (status) - return status; - - pattern = FcPatternCreate (); - if (!pattern) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - if (!FcPatternAddString (pattern, - FC_FAMILY, (unsigned char *) toy_face->family)) - { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto FREE_PATTERN; - } - - switch (toy_face->slant) - { - case CAIRO_FONT_SLANT_ITALIC: - fcslant = FC_SLANT_ITALIC; - break; - case CAIRO_FONT_SLANT_OBLIQUE: - fcslant = FC_SLANT_OBLIQUE; - break; - case CAIRO_FONT_SLANT_NORMAL: - default: - fcslant = FC_SLANT_ROMAN; - break; - } - - if (!FcPatternAddInteger (pattern, FC_SLANT, fcslant)) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto FREE_PATTERN; - } - - switch (toy_face->weight) - { - case CAIRO_FONT_WEIGHT_BOLD: - fcweight = FC_WEIGHT_BOLD; - break; - case CAIRO_FONT_WEIGHT_NORMAL: - default: - fcweight = FC_WEIGHT_MEDIUM; - break; - } - - if (!FcPatternAddInteger (pattern, FC_WEIGHT, fcweight)) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto FREE_PATTERN; - } - - if (! FcPatternAddDouble (pattern, FC_PIXEL_SIZE, sf.y_scale)) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto FREE_PATTERN; - } - - if (! FcConfigSubstitute (NULL, pattern, FcMatchPattern)) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto FREE_PATTERN; - } - - status = _cairo_ft_font_options_substitute (font_options, pattern); - if (status) - goto FREE_PATTERN; - - FcDefaultSubstitute (pattern); - - resolved = FcFontMatch (NULL, pattern, &result); - if (!resolved) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto FREE_PATTERN; - } - - unscaled = _cairo_ft_unscaled_font_create_for_pattern (resolved); - if (!unscaled) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto FREE_RESOLVED; - } - - _get_pattern_ft_options (resolved, &ft_options); - - status = _cairo_ft_scaled_font_create (unscaled, - &toy_face->base, - font_matrix, ctm, - font_options, ft_options, - font); - - _cairo_unscaled_font_destroy (&unscaled->base); - - FREE_RESOLVED: - FcPatternDestroy (resolved); - - FREE_PATTERN: - FcPatternDestroy (pattern); - - return status; -} - -static void -_cairo_ft_scaled_font_fini (void *abstract_font) -{ - cairo_ft_scaled_font_t *scaled_font = abstract_font; - - if (scaled_font == NULL) - return; - - _cairo_unscaled_font_destroy (&scaled_font->unscaled->base); -} - -static int -_move_to (FT_Vector *to, void *closure) -{ - cairo_path_fixed_t *path = closure; - cairo_fixed_t x, y; - - x = _cairo_fixed_from_26_6 (to->x); - y = _cairo_fixed_from_26_6 (to->y); - - if (_cairo_path_fixed_close_path (path) != CAIRO_STATUS_SUCCESS) - return 1; - if (_cairo_path_fixed_move_to (path, x, y) != CAIRO_STATUS_SUCCESS) - return 1; - - return 0; -} - -static int -_line_to (FT_Vector *to, void *closure) -{ - cairo_path_fixed_t *path = closure; - cairo_fixed_t x, y; - - x = _cairo_fixed_from_26_6 (to->x); - y = _cairo_fixed_from_26_6 (to->y); - - if (_cairo_path_fixed_line_to (path, x, y) != CAIRO_STATUS_SUCCESS) - return 1; - - return 0; -} - -static int -_conic_to (FT_Vector *control, FT_Vector *to, void *closure) -{ - cairo_path_fixed_t *path = closure; - - cairo_fixed_t x0, y0; - cairo_fixed_t x1, y1; - cairo_fixed_t x2, y2; - cairo_fixed_t x3, y3; - cairo_point_t conic; - - if (! _cairo_path_fixed_get_current_point (path, &x0, &y0)) - return 1; - - conic.x = _cairo_fixed_from_26_6 (control->x); - conic.y = _cairo_fixed_from_26_6 (control->y); - - x3 = _cairo_fixed_from_26_6 (to->x); - y3 = _cairo_fixed_from_26_6 (to->y); - - x1 = x0 + 2.0/3.0 * (conic.x - x0); - y1 = y0 + 2.0/3.0 * (conic.y - y0); - - x2 = x3 + 2.0/3.0 * (conic.x - x3); - y2 = y3 + 2.0/3.0 * (conic.y - y3); - - if (_cairo_path_fixed_curve_to (path, - x1, y1, - x2, y2, - x3, y3) != CAIRO_STATUS_SUCCESS) - return 1; - - return 0; -} - -static int -_cubic_to (FT_Vector *control1, FT_Vector *control2, - FT_Vector *to, void *closure) -{ - cairo_path_fixed_t *path = closure; - cairo_fixed_t x0, y0; - cairo_fixed_t x1, y1; - cairo_fixed_t x2, y2; - - x0 = _cairo_fixed_from_26_6 (control1->x); - y0 = _cairo_fixed_from_26_6 (control1->y); - - x1 = _cairo_fixed_from_26_6 (control2->x); - y1 = _cairo_fixed_from_26_6 (control2->y); - - x2 = _cairo_fixed_from_26_6 (to->x); - y2 = _cairo_fixed_from_26_6 (to->y); - - if (_cairo_path_fixed_curve_to (path, - x0, y0, - x1, y1, - x2, y2) != CAIRO_STATUS_SUCCESS) - return 1; - - return 0; -} - -static cairo_status_t -_decompose_glyph_outline (FT_Face face, - cairo_font_options_t *options, - cairo_path_fixed_t **pathp) -{ - static const FT_Outline_Funcs outline_funcs = { - (FT_Outline_MoveToFunc)_move_to, - (FT_Outline_LineToFunc)_line_to, - (FT_Outline_ConicToFunc)_conic_to, - (FT_Outline_CubicToFunc)_cubic_to, - 0, /* shift */ - 0, /* delta */ - }; - static const FT_Matrix invert_y = { - DOUBLE_TO_16_16 (1.0), 0, - 0, DOUBLE_TO_16_16 (-1.0), - }; - - FT_GlyphSlot glyph; - cairo_path_fixed_t *path; - cairo_status_t status; - - path = _cairo_path_fixed_create (); - if (!path) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - glyph = face->glyph; - - /* Font glyphs have an inverted Y axis compared to cairo. */ - FT_Outline_Transform (&glyph->outline, &invert_y); - if (FT_Outline_Decompose (&glyph->outline, &outline_funcs, path)) { - _cairo_path_fixed_destroy (path); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - status = _cairo_path_fixed_close_path (path); - if (status) { - _cairo_path_fixed_destroy (path); - return status; - } - - *pathp = path; - - return CAIRO_STATUS_SUCCESS; -} - -/* - * Translate glyph to match its metrics. - */ -static void -_cairo_ft_scaled_glyph_vertical_layout_bearing_fix (void *abstract_font, - FT_GlyphSlot glyph) -{ - cairo_ft_scaled_font_t *scaled_font = abstract_font; - FT_Vector vector; - - vector.x = glyph->metrics.vertBearingX - glyph->metrics.horiBearingX; - vector.y = -glyph->metrics.vertBearingY - glyph->metrics.horiBearingY; - - if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) { - FT_Vector_Transform (&vector, &scaled_font->unscaled->Current_Shape); - FT_Outline_Translate(&glyph->outline, vector.x, vector.y); - } else if (glyph->format == FT_GLYPH_FORMAT_BITMAP) { - glyph->bitmap_left += vector.x / 64; - glyph->bitmap_top += vector.y / 64; - } -} - -static cairo_int_status_t -_cairo_ft_scaled_glyph_init (void *abstract_font, - cairo_scaled_glyph_t *scaled_glyph, - cairo_scaled_glyph_info_t info) -{ - cairo_text_extents_t fs_metrics; - cairo_ft_scaled_font_t *scaled_font = abstract_font; - cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled; - FT_GlyphSlot glyph; - FT_Face face; - FT_Error error; - int load_flags = scaled_font->ft_options.load_flags; - FT_Glyph_Metrics *metrics; - double x_factor, y_factor; - cairo_bool_t vertical_layout = FALSE; - cairo_status_t status; - - face = _cairo_ft_unscaled_font_lock_face (unscaled); - if (!face) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - status = _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled, - &scaled_font->base.scale); - if (status) - goto FAIL; - - /* Ignore global advance unconditionally */ - load_flags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH; - - if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0 && - (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) == 0) - load_flags |= FT_LOAD_NO_BITMAP; - - /* - * Don't pass FT_LOAD_VERTICAL_LAYOUT to FT_Load_Glyph here as - * suggested by freetype people. - */ - if (load_flags & FT_LOAD_VERTICAL_LAYOUT) { - load_flags &= ~FT_LOAD_VERTICAL_LAYOUT; - vertical_layout = TRUE; - } - - error = FT_Load_Glyph (scaled_font->unscaled->face, - _cairo_scaled_glyph_index(scaled_glyph), - load_flags); - /* XXX ignoring all other errors for now. They are not fatal, typically - * just a glyph-not-found. */ - if (error == FT_Err_Out_Of_Memory) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto FAIL; - } - - glyph = face->glyph; - -#if HAVE_FT_GLYPHSLOT_EMBOLDEN - /* - * embolden glyphs if requested - */ - if (scaled_font->ft_options.extra_flags & CAIRO_FT_OPTIONS_EMBOLDEN) - FT_GlyphSlot_Embolden (glyph); -#endif - - if (vertical_layout) - _cairo_ft_scaled_glyph_vertical_layout_bearing_fix (scaled_font, glyph); - - if (info & CAIRO_SCALED_GLYPH_INFO_METRICS) { - - cairo_bool_t hint_metrics = scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF; - /* - * Compute font-space metrics - */ - metrics = &glyph->metrics; - - if (unscaled->x_scale == 0) - x_factor = 0; - else - x_factor = 1 / unscaled->x_scale; - - if (unscaled->y_scale == 0) - y_factor = 0; - else - y_factor = 1 / unscaled->y_scale; - - /* - * Note: Y coordinates of the horizontal bearing need to be negated. - * - * Scale metrics back to glyph space from the scaled glyph space returned - * by FreeType - * - * If we want hinted metrics but aren't asking for hinted glyphs from - * FreeType, then we need to do the metric hinting ourselves. - */ - - if (hint_metrics && (load_flags & FT_LOAD_NO_HINTING)) - { - FT_Pos x1, x2; - FT_Pos y1, y2; - FT_Pos advance; - - if (!vertical_layout) { - x1 = (metrics->horiBearingX) & -64; - x2 = (metrics->horiBearingX + metrics->width + 63) & -64; - y1 = (-metrics->horiBearingY) & -64; - y2 = (-metrics->horiBearingY + metrics->height + 63) & -64; - - advance = ((metrics->horiAdvance + 32) & -64); - - fs_metrics.x_bearing = DOUBLE_FROM_26_6 (x1) * x_factor; - fs_metrics.y_bearing = DOUBLE_FROM_26_6 (y1) * y_factor; - - fs_metrics.width = DOUBLE_FROM_26_6 (x2 - x1) * x_factor; - fs_metrics.height = DOUBLE_FROM_26_6 (y2 - y1) * y_factor; - - fs_metrics.x_advance = DOUBLE_FROM_26_6 (advance) * x_factor; - fs_metrics.y_advance = 0; - } else { - x1 = (metrics->vertBearingX) & -64; - x2 = (metrics->vertBearingX + metrics->width + 63) & -64; - y1 = (metrics->vertBearingY) & -64; - y2 = (metrics->vertBearingY + metrics->height + 63) & -64; - - advance = ((metrics->vertAdvance + 32) & -64); - - fs_metrics.x_bearing = DOUBLE_FROM_26_6 (x1) * x_factor; - fs_metrics.y_bearing = DOUBLE_FROM_26_6 (y1) * y_factor; - - fs_metrics.width = DOUBLE_FROM_26_6 (x2 - x1) * x_factor; - fs_metrics.height = DOUBLE_FROM_26_6 (y2 - y1) * y_factor; - - fs_metrics.x_advance = 0; - fs_metrics.y_advance = DOUBLE_FROM_26_6 (advance) * y_factor; - } - } else { - fs_metrics.width = DOUBLE_FROM_26_6 (metrics->width) * x_factor; - fs_metrics.height = DOUBLE_FROM_26_6 (metrics->height) * y_factor; - - if (!vertical_layout) { - fs_metrics.x_bearing = DOUBLE_FROM_26_6 (metrics->horiBearingX) * x_factor; - fs_metrics.y_bearing = DOUBLE_FROM_26_6 (-metrics->horiBearingY) * y_factor; - - if (hint_metrics || glyph->format != FT_GLYPH_FORMAT_OUTLINE) - fs_metrics.x_advance = DOUBLE_FROM_26_6 (metrics->horiAdvance) * x_factor; - else - fs_metrics.x_advance = DOUBLE_FROM_16_16 (glyph->linearHoriAdvance) * x_factor; - fs_metrics.y_advance = 0 * y_factor; - } else { - fs_metrics.x_bearing = DOUBLE_FROM_26_6 (metrics->vertBearingX) * x_factor; - fs_metrics.y_bearing = DOUBLE_FROM_26_6 (metrics->vertBearingY) * y_factor; - - fs_metrics.x_advance = 0 * x_factor; - if (hint_metrics || glyph->format != FT_GLYPH_FORMAT_OUTLINE) - fs_metrics.y_advance = DOUBLE_FROM_26_6 (metrics->vertAdvance) * y_factor; - else - fs_metrics.y_advance = DOUBLE_FROM_26_6 (glyph->linearVertAdvance) * y_factor; - } - } - - _cairo_scaled_glyph_set_metrics (scaled_glyph, - &scaled_font->base, - &fs_metrics); - } - - if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0) { - cairo_image_surface_t *surface; - - if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) { - status = _render_glyph_outline (face, &scaled_font->ft_options.base, - &surface); - } else { - status = _render_glyph_bitmap (face, &scaled_font->ft_options.base, - &surface); - if (status == CAIRO_STATUS_SUCCESS && unscaled->have_shape) { - status = _transform_glyph_bitmap (&unscaled->current_shape, - &surface); - if (status) - cairo_surface_destroy (&surface->base); - } - } - if (status) - goto FAIL; - - _cairo_scaled_glyph_set_surface (scaled_glyph, - &scaled_font->base, - surface); - } - - if (info & CAIRO_SCALED_GLYPH_INFO_PATH) { - cairo_path_fixed_t *path = NULL; /* hide compiler warning */ - - /* - * A kludge -- the above code will trash the outline, - * so reload it. This will probably never occur though - */ - if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0) { - error = FT_Load_Glyph (face, - _cairo_scaled_glyph_index(scaled_glyph), - load_flags | FT_LOAD_NO_BITMAP); - /* XXX ignoring all other errors for now. They are not fatal, typically - * just a glyph-not-found. */ - if (error == FT_Err_Out_Of_Memory) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto FAIL; - } -#if HAVE_FT_GLYPHSLOT_EMBOLDEN - /* - * embolden glyphs if requested - */ - if (scaled_font->ft_options.extra_flags & CAIRO_FT_OPTIONS_EMBOLDEN) - FT_GlyphSlot_Embolden (glyph); -#endif - if (vertical_layout) - _cairo_ft_scaled_glyph_vertical_layout_bearing_fix (scaled_font, glyph); - - } - if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) - status = _decompose_glyph_outline (face, &scaled_font->ft_options.base, - &path); - else - status = CAIRO_INT_STATUS_UNSUPPORTED; - - if (status) - goto FAIL; - - _cairo_scaled_glyph_set_path (scaled_glyph, - &scaled_font->base, - path); - } - FAIL: - _cairo_ft_unscaled_font_unlock_face (unscaled); - - return status; -} - -static unsigned long -_cairo_ft_ucs4_to_index (void *abstract_font, - uint32_t ucs4) -{ - cairo_ft_scaled_font_t *scaled_font = abstract_font; - cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled; - FT_Face face; - FT_UInt index; - - face = _cairo_ft_unscaled_font_lock_face (unscaled); - if (!face) - return 0; - - /* If making this compile without fontconfig, use: - * index = FT_Get_Char_Index (face, ucs4); */ - index = FcFreeTypeCharIndex (face, ucs4); - - _cairo_ft_unscaled_font_unlock_face (unscaled); - return index; -} - -static cairo_int_status_t -_cairo_ft_load_truetype_table (void *abstract_font, - unsigned long tag, - long offset, - unsigned char *buffer, - unsigned long *length) -{ - cairo_ft_scaled_font_t *scaled_font = abstract_font; - cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled; - FT_Face face; - cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED; - - if (_cairo_ft_scaled_font_is_vertical (&scaled_font->base)) - return CAIRO_INT_STATUS_UNSUPPORTED; - -#if HAVE_FT_LOAD_SFNT_TABLE - face = _cairo_ft_unscaled_font_lock_face (unscaled); - if (!face) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - if (FT_IS_SFNT (face) && - FT_Load_Sfnt_Table (face, tag, offset, buffer, length) == 0) - status = CAIRO_STATUS_SUCCESS; - - _cairo_ft_unscaled_font_unlock_face (unscaled); -#endif - - return status; -} - -static cairo_int_status_t -_cairo_ft_index_to_ucs4(void *abstract_font, - unsigned long index, - uint32_t *ucs4) -{ - cairo_ft_scaled_font_t *scaled_font = abstract_font; - cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled; - FT_Face face; - FT_ULong charcode; - FT_UInt gindex; - - face = _cairo_ft_unscaled_font_lock_face (unscaled); - if (!face) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - *ucs4 = (uint32_t) -1; - charcode = FT_Get_First_Char(face, &gindex); - while (gindex != 0) { - charcode = FT_Get_Next_Char (face, charcode, &gindex); - if (gindex == index) { - *ucs4 = charcode; - break; - } - } - - _cairo_ft_unscaled_font_unlock_face (unscaled); - - return CAIRO_STATUS_SUCCESS; -} - -const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend = { - CAIRO_FONT_TYPE_FT, - NULL, - _cairo_ft_scaled_font_create_toy, - _cairo_ft_scaled_font_fini, - _cairo_ft_scaled_glyph_init, - NULL, /* text_to_glyphs */ - _cairo_ft_ucs4_to_index, - NULL, /* show_glyphs */ - _cairo_ft_load_truetype_table, - _cairo_ft_index_to_ucs4 -}; - -/* #cairo_ft_font_face_t */ - -static void -_cairo_ft_font_face_destroy (void *abstract_face) -{ - cairo_ft_font_face_t *font_face = abstract_face; - - cairo_ft_font_face_t *tmp_face = NULL; - cairo_ft_font_face_t *last_face = NULL; - - if (font_face == NULL) - return; - - /* When destroying the face created by cairo_ft_font_face_create_for_ft_face, - * we have a special "zombie" state for the face when the unscaled font - * is still alive but there are no public references to the font face. - * - * We go from: - * - * font_face ------> unscaled - * <-....weak....../ - * - * To: - * - * font_face <------- unscaled - */ - - if (font_face->unscaled && - font_face->unscaled->from_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; - } - - if (font_face->unscaled) { - /* Remove face from linked list */ - for (tmp_face = font_face->unscaled->faces; - tmp_face; - tmp_face = tmp_face->next) - { - if (tmp_face == font_face) { - if (last_face) - last_face->next = tmp_face->next; - else - font_face->unscaled->faces = tmp_face->next; - } - - last_face = tmp_face; - } - - _cairo_unscaled_font_destroy (&font_face->unscaled->base); - font_face->unscaled = NULL; - } -} - -static cairo_status_t -_cairo_ft_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 **scaled_font) -{ - cairo_ft_font_face_t *font_face = abstract_face; - cairo_ft_options_t ft_options; - - /* The handling of font options is different depending on how the - * font face was created. When the user creates a font face with - * cairo_ft_font_face_create_for_ft_face(), then the load flags - * passed in augment the load flags for the options. But for - * cairo_ft_font_face_create_for_pattern(), the load flags are - * derived from a pattern where the user has called - * cairo_ft_font_options_substitute(), so *just* use those load - * flags and ignore the options. - * - * XXX two points about the above comment: - * 1. I don't see how the comment is relevant here, - * 2. What if the face is coming from FC_FT_FACE of a pattern? - */ - - ft_options = font_face->ft_options; - - return _cairo_ft_scaled_font_create (font_face->unscaled, - &font_face->base, - font_matrix, ctm, - options, ft_options, - scaled_font); -} - -static const cairo_font_face_backend_t _cairo_ft_font_face_backend = { - CAIRO_FONT_TYPE_FT, - _cairo_ft_font_face_destroy, - NULL, /* direct implementation */ - _cairo_ft_font_face_scaled_font_create -}; - -static cairo_font_face_t * -_cairo_ft_font_face_create (cairo_ft_unscaled_font_t *unscaled, - cairo_ft_options_t *ft_options) -{ - cairo_ft_font_face_t *font_face, **prev_font_face; - - /* Looked for an existing matching font face */ - for (font_face = unscaled->faces, prev_font_face = &unscaled->faces; - font_face; - prev_font_face = &font_face->next, font_face = font_face->next) - { - if (font_face->ft_options.load_flags == ft_options->load_flags && - font_face->ft_options.extra_flags == ft_options->extra_flags && - cairo_font_options_equal (&font_face->ft_options.base, &ft_options->base)) - { - if (font_face->base.status == CAIRO_STATUS_SUCCESS) - return cairo_font_face_reference (&font_face->base); - - /* The font_face has been left in an error state, abandon it. */ - *prev_font_face = font_face->next; - break; - } - } - - /* No match found, create a new one */ - font_face = malloc (sizeof (cairo_ft_font_face_t)); - if (!font_face) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_font_face_t *)&_cairo_font_face_nil; - } - - font_face->unscaled = unscaled; - _cairo_unscaled_font_reference (&unscaled->base); - - font_face->ft_options = *ft_options; - - font_face->next = unscaled->faces; - unscaled->faces = font_face; - - _cairo_font_face_init (&font_face->base, &_cairo_ft_font_face_backend); - - return &font_face->base; -} - -/* implement the platform-specific interface */ - -static cairo_status_t -_cairo_ft_font_options_substitute (const cairo_font_options_t *options, - FcPattern *pattern) -{ - FcValue v; - - if (options->antialias != CAIRO_ANTIALIAS_DEFAULT) - { - if (FcPatternGet (pattern, FC_ANTIALIAS, 0, &v) == FcResultNoMatch) - { - if (! FcPatternAddBool (pattern, - FC_ANTIALIAS, - options->antialias != CAIRO_ANTIALIAS_NONE)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - if (options->antialias != CAIRO_ANTIALIAS_SUBPIXEL) { - FcPatternDel (pattern, FC_RGBA); - if (! FcPatternAddInteger (pattern, FC_RGBA, FC_RGBA_NONE)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - } - } - - if (options->antialias != CAIRO_ANTIALIAS_DEFAULT) - { - if (FcPatternGet (pattern, FC_RGBA, 0, &v) == FcResultNoMatch) - { - int rgba; - - if (options->antialias == CAIRO_ANTIALIAS_SUBPIXEL) { - switch (options->subpixel_order) { - case CAIRO_SUBPIXEL_ORDER_DEFAULT: - case CAIRO_SUBPIXEL_ORDER_RGB: - default: - rgba = FC_RGBA_RGB; - break; - case CAIRO_SUBPIXEL_ORDER_BGR: - rgba = FC_RGBA_BGR; - break; - case CAIRO_SUBPIXEL_ORDER_VRGB: - rgba = FC_RGBA_VRGB; - break; - case CAIRO_SUBPIXEL_ORDER_VBGR: - rgba = FC_RGBA_VBGR; - break; - } - } else { - rgba = FC_RGBA_NONE; - } - - if (! FcPatternAddInteger (pattern, FC_RGBA, rgba)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - } - - if (options->hint_style != CAIRO_HINT_STYLE_DEFAULT) - { - if (FcPatternGet (pattern, FC_HINTING, 0, &v) == FcResultNoMatch) - { - if (! FcPatternAddBool (pattern, - FC_HINTING, - options->hint_style != CAIRO_HINT_STYLE_NONE)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - -#ifdef FC_HINT_STYLE - if (FcPatternGet (pattern, FC_HINT_STYLE, 0, &v) == FcResultNoMatch) - { - int hint_style; - - switch (options->hint_style) { - case CAIRO_HINT_STYLE_NONE: - hint_style = FC_HINT_NONE; - break; - case CAIRO_HINT_STYLE_SLIGHT: - hint_style = FC_HINT_SLIGHT; - break; - case CAIRO_HINT_STYLE_MEDIUM: - hint_style = FC_HINT_MEDIUM; - break; - case CAIRO_HINT_STYLE_FULL: - case CAIRO_HINT_STYLE_DEFAULT: - default: - hint_style = FC_HINT_FULL; - break; - } - - if (! FcPatternAddInteger (pattern, FC_HINT_STYLE, hint_style)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } -#endif - } - - return CAIRO_STATUS_SUCCESS; -} - -/** - * cairo_ft_font_options_substitute: - * @options: a #cairo_font_options_t object - * @pattern: an existing #FcPattern - * - * Add options to a #FcPattern based on a #cairo_font_options_t font - * options object. Options that are already in the pattern, are not overridden, - * so you should call this function after calling FcConfigSubstitute() (the - * user's settings should override options based on the surface type), but - * before calling FcDefaultSubstitute(). - **/ -void -cairo_ft_font_options_substitute (const cairo_font_options_t *options, - FcPattern *pattern) -{ - if (cairo_font_options_status ((cairo_font_options_t *) options)) - return; - - _cairo_ft_font_options_substitute (options, pattern); -} - -/** - * cairo_ft_font_face_create_for_pattern: - * @pattern: A fully resolved fontconfig - * pattern. A pattern can be resolved, by, among other things, calling - * FcConfigSubstitute(), FcDefaultSubstitute(), then - * FcFontMatch(). Cairo will call FcPatternReference() on this - * pattern, so you should not further modify the pattern, but you can - * release your reference to the pattern with FcPatternDestroy() if - * you no longer need to access it. - * - * Creates a new font face for the FreeType font backend based on a - * fontconfig pattern. This font can then be used with - * cairo_set_font_face() or cairo_scaled_font_create(). The - * #cairo_scaled_font_t returned from cairo_scaled_font_create() is - * also for the FreeType backend and can be used with functions such - * as cairo_ft_scaled_font_lock_face(). - * - * Font rendering options are represented both here and when you - * call cairo_scaled_font_create(). Font options that have a representation - * in a #FcPattern must be passed in here; to modify #FcPattern - * appropriately to reflect the options in a #cairo_font_options_t, call - * cairo_ft_font_options_substitute(). - * - * The pattern's FC_FT_FACE element is inspected first and if that is set, - * that will be the FreeType font face associated with the returned cairo - * font face. Otherwise the FC_FILE and FC_INDEX elements of @pattern are - * used to load a font face from file. - * - * If the FC_FT_FACE element of @pattern is set, the user is responsible - * for making sure that the referenced FT_Face remains valid for the life - * time of the returned #cairo_font_face_t. See - * cairo_ft_font_face_create_for_ft_face() for an exmaple of how to couple - * the life time of the FT_Face to that of the cairo font-face. - * - * Return value: a newly created #cairo_font_face_t. Free with - * cairo_font_face_destroy() when you are done using it. - **/ -cairo_font_face_t * -cairo_ft_font_face_create_for_pattern (FcPattern *pattern) -{ - cairo_ft_unscaled_font_t *unscaled; - cairo_font_face_t *font_face; - cairo_ft_options_t ft_options; - - unscaled = _cairo_ft_unscaled_font_create_for_pattern (pattern); - if (unscaled == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_font_face_t *)&_cairo_font_face_nil; - } - - _get_pattern_ft_options (pattern, &ft_options); - font_face = _cairo_ft_font_face_create (unscaled, &ft_options); - _cairo_unscaled_font_destroy (&unscaled->base); - - return font_face; -} - -/** - * cairo_ft_font_face_create_for_ft_face: - * @face: A FreeType face object, already opened. This must - * be kept around until the face's ref_count drops to - * zero and it is freed. Since the face may be referenced - * internally to Cairo, the best way to determine when it - * is safe to free the face is to pass a - * #cairo_destroy_func_t to cairo_font_face_set_user_data() - * @load_flags: flags to pass to FT_Load_Glyph when loading - * glyphs from the font. These flags are OR'ed together with - * the flags derived from the #cairo_font_options_t passed - * to cairo_scaled_font_create(), so only a few values such - * as %FT_LOAD_VERTICAL_LAYOUT, and %FT_LOAD_FORCE_AUTOHINT - * are useful. You should not pass any of the flags affecting - * the load target, such as %FT_LOAD_TARGET_LIGHT. - * - * Creates a new font face for the FreeType font backend from a - * pre-opened FreeType face. This font can then be used with - * cairo_set_font_face() or cairo_scaled_font_create(). The - * #cairo_scaled_font_t returned from cairo_scaled_font_create() is - * also for the FreeType backend and can be used with functions such - * as cairo_ft_scaled_font_lock_face(). Note that Cairo may keep a reference - * to the FT_Face alive in a font-cache and the exact lifetime of the reference - * depends highly upon the exact usage pattern and is subject to external - * factors. You must not call FT_Done_Face() before the last reference to the - * #cairo_font_face_t has been dropped. - * - * As an example, below is how one might correctly couple the lifetime of - * the FreeType face object to the #cairo_font_face_t. - * - * - * static const cairo_user_data_key_t key; - * - * font_face = cairo_ft_font_face_create_for_ft_face (ft_face, 0); - * status = cairo_font_face_set_user_data (font_face, &key, - * ft_face, (cairo_destroy_func_t) FT_Done_Face); - * if (status) { - * cairo_font_face_destroy (font_face); - * FT_Done_Face (ft_face); - * return ERROR; - * } - * - * - * Return value: a newly created #cairo_font_face_t. Free with - * cairo_font_face_destroy() when you are done using it. - **/ -cairo_font_face_t * -cairo_ft_font_face_create_for_ft_face (FT_Face face, - int load_flags) -{ - cairo_ft_unscaled_font_t *unscaled; - cairo_font_face_t *font_face; - cairo_ft_options_t ft_options; - - unscaled = _cairo_ft_unscaled_font_create_from_face (face); - if (unscaled == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_font_face_t *)&_cairo_font_face_nil; - } - - ft_options.load_flags = load_flags; - ft_options.extra_flags = 0; - _cairo_font_options_init_default (&ft_options.base); - - font_face = _cairo_ft_font_face_create (unscaled, &ft_options); - _cairo_unscaled_font_destroy (&unscaled->base); - - return font_face; -} - -/** - * cairo_ft_scaled_font_lock_face: - * @scaled_font: A #cairo_scaled_font_t from the FreeType font backend. Such an - * object can be created by calling cairo_scaled_font_create() on a - * FreeType backend font face (see cairo_ft_font_face_create_for_pattern(), - * cairo_ft_font_face_create_for_ft_face()). - * - * cairo_ft_scaled_font_lock_face() gets the #FT_Face object from a FreeType - * backend font and scales it appropriately for the font. You must - * release the face with cairo_ft_scaled_font_unlock_face() - * when you are done using it. Since the #FT_Face object can be - * shared between multiple #cairo_scaled_font_t objects, you must not - * lock any other font objects until you unlock this one. A count is - * kept of the number of times cairo_ft_scaled_font_lock_face() is - * called. cairo_ft_scaled_font_unlock_face() must be called the same number - * of times. - * - * You must be careful when using this function in a library or in a - * threaded application, because freetype's design makes it unsafe to - * call freetype functions simultaneously from multiple threads, (even - * if using distinct FT_Face objects). Because of this, application - * code that acquires an FT_Face object with this call must add it's - * own locking to protect any use of that object, (and which also must - * protect any other calls into cairo as almost any cairo function - * might result in a call into the freetype library). - * - * Return value: The #FT_Face object for @font, scaled appropriately, - * or %NULL if @scaled_font is in an error state (see - * cairo_scaled_font_status()) or there is insufficient memory. - **/ -FT_Face -cairo_ft_scaled_font_lock_face (cairo_scaled_font_t *abstract_font) -{ - cairo_ft_scaled_font_t *scaled_font = (cairo_ft_scaled_font_t *) abstract_font; - FT_Face face; - cairo_status_t status; - - if (! _cairo_scaled_font_is_ft (abstract_font)) { - _cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH); - return NULL; - } - - if (scaled_font->base.status) - return NULL; - - face = _cairo_ft_unscaled_font_lock_face (scaled_font->unscaled); - if (face == NULL) { - status = _cairo_scaled_font_set_error (&scaled_font->base, CAIRO_STATUS_NO_MEMORY); - return NULL; - } - - status = _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled, - &scaled_font->base.scale); - if (status) { - _cairo_ft_unscaled_font_unlock_face (scaled_font->unscaled); - status = _cairo_scaled_font_set_error (&scaled_font->base, status); - return NULL; - } - - /* Note: We deliberately release the unscaled font's mutex here, - * so that we are not holding a lock across two separate calls to - * cairo function, (which would give the application some - * opportunity for creating deadlock. This is obviously unsafe, - * but as documented, the user must add manual locking when using - * this function. */ - CAIRO_MUTEX_UNLOCK (scaled_font->unscaled->mutex); - - return face; -} - -/** - * cairo_ft_scaled_font_unlock_face: - * @scaled_font: A #cairo_scaled_font_t from the FreeType font backend. Such an - * object can be created by calling cairo_scaled_font_create() on a - * FreeType backend font face (see cairo_ft_font_face_create_for_pattern(), - * cairo_ft_font_face_create_for_ft_face()). - * - * Releases a face obtained with cairo_ft_scaled_font_lock_face(). - **/ -void -cairo_ft_scaled_font_unlock_face (cairo_scaled_font_t *abstract_font) -{ - cairo_ft_scaled_font_t *scaled_font = (cairo_ft_scaled_font_t *) abstract_font; - - if (! _cairo_scaled_font_is_ft (abstract_font)) { - _cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH); - return; - } - - if (scaled_font->base.status) - return; - - /* Note: We released the unscaled font's mutex at the end of - * cairo_ft_scaled_font_lock_face, so we have to acquire it again - * as _cairo_ft_unscaled_font_unlock_face expects it to be held - * when we call into it. */ - CAIRO_MUTEX_LOCK (scaled_font->unscaled->mutex); - - _cairo_ft_unscaled_font_unlock_face (scaled_font->unscaled); -} - -/* We expose our unscaled font implementation internally for the the - * PDF backend, which needs to keep track of the the different - * fonts-on-disk used by a document, so it can embed them. - */ -cairo_unscaled_font_t * -_cairo_ft_scaled_font_get_unscaled_font (cairo_scaled_font_t *abstract_font) -{ - cairo_ft_scaled_font_t *scaled_font = (cairo_ft_scaled_font_t *) abstract_font; - - return &scaled_font->unscaled->base; -} - -cairo_bool_t -_cairo_ft_scaled_font_is_vertical (cairo_scaled_font_t *scaled_font) -{ - cairo_ft_scaled_font_t *ft_scaled_font; - - if (!_cairo_scaled_font_is_ft (scaled_font)) - return FALSE; - - ft_scaled_font = (cairo_ft_scaled_font_t *) scaled_font; - if (ft_scaled_font->ft_options.load_flags & FT_LOAD_VERTICAL_LAYOUT) - return TRUE; - return FALSE; -} - -void -_cairo_ft_font_reset_static_data (void) -{ - _cairo_ft_unscaled_font_map_destroy (); -} diff --git a/uppdev/plugin/cairo/lib/cairo-ft-private.h b/uppdev/plugin/cairo/lib/cairo-ft-private.h deleted file mode 100644 index 3e7d3de02..000000000 --- a/uppdev/plugin/cairo/lib/cairo-ft-private.h +++ /dev/null @@ -1,70 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Graydon Hoare - * Owen Taylor - */ - -#ifndef CAIRO_FT_PRIVATE_H -#define CAIRO_FT_PRIVATE_H - -#include "cairo-ft.h" -#include "cairoint.h" - -#if CAIRO_HAS_FT_FONT - -CAIRO_BEGIN_DECLS - -typedef struct _cairo_ft_unscaled_font cairo_ft_unscaled_font_t; - -cairo_private cairo_bool_t -_cairo_scaled_font_is_ft (cairo_scaled_font_t *scaled_font); - -/* These functions are needed by the PDF backend, which needs to keep track of the - * the different fonts-on-disk used by a document, so it can embed them - */ -cairo_private cairo_unscaled_font_t * -_cairo_ft_scaled_font_get_unscaled_font (cairo_scaled_font_t *scaled_font); - -cairo_private FT_Face -_cairo_ft_unscaled_font_lock_face (cairo_ft_unscaled_font_t *unscaled); - -cairo_private void -_cairo_ft_unscaled_font_unlock_face (cairo_ft_unscaled_font_t *unscaled); - -cairo_private cairo_bool_t -_cairo_ft_scaled_font_is_vertical (cairo_scaled_font_t *scaled_font); - -CAIRO_END_DECLS - -#endif /* CAIRO_HAS_FT_FONT */ -#endif /* CAIRO_FT_PRIVATE_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-ft.h b/uppdev/plugin/cairo/lib/cairo-ft.h deleted file mode 100644 index 91e2db895..000000000 --- a/uppdev/plugin/cairo/lib/cairo-ft.h +++ /dev/null @@ -1,75 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Graydon Hoare - * Owen Taylor - */ - -#ifndef CAIRO_FT_H -#define CAIRO_FT_H - -#include "cairo.h" - -#if CAIRO_HAS_FT_FONT - -/* Fontconfig/Freetype platform-specific font interface */ - -#include -#include -#include FT_FREETYPE_H - -CAIRO_BEGIN_DECLS - -cairo_public cairo_font_face_t * -cairo_ft_font_face_create_for_pattern (FcPattern *pattern); - -cairo_public void -cairo_ft_font_options_substitute (const cairo_font_options_t *options, - FcPattern *pattern); - -cairo_public cairo_font_face_t * -cairo_ft_font_face_create_for_ft_face (FT_Face face, - int load_flags); - -cairo_public FT_Face -cairo_ft_scaled_font_lock_face (cairo_scaled_font_t *scaled_font); - -cairo_public void -cairo_ft_scaled_font_unlock_face (cairo_scaled_font_t *scaled_font); - -CAIRO_END_DECLS - -#else /* CAIRO_HAS_FT_FONT */ -# error Cairo was not compiled with support for the freetype font backend -#endif /* CAIRO_HAS_FT_FONT */ - -#endif /* CAIRO_FT_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-glitz-private.h b/uppdev/plugin/cairo/lib/cairo-glitz-private.h deleted file mode 100644 index 8a876eeab..000000000 --- a/uppdev/plugin/cairo/lib/cairo-glitz-private.h +++ /dev/null @@ -1,41 +0,0 @@ -/* Cairo - a vector graphics library with display and print output - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - */ - -#ifndef CAIRO_GLITZ_PRIVATE_H -#define CAIRO_GLITZ_PRIVATE_H - -#include "cairoint.h" -#include "cairo-glitz.h" - -slim_hidden_proto (cairo_glitz_surface_create); - -#endif /* CAIRO_GLITZ_PRIVATE_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-glitz-surface.c b/uppdev/plugin/cairo/lib/cairo-glitz-surface.c deleted file mode 100644 index 784bff984..000000000 --- a/uppdev/plugin/cairo/lib/cairo-glitz-surface.c +++ /dev/null @@ -1,2495 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2004 David Reveman - * - * 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 David - * Reveman not be used in advertising or publicity pertaining to - * distribution of the software without specific, written prior - * permission. David Reveman makes no representations about the - * suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, - * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER - * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR - * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Author: David Reveman - */ - -#include "cairoint.h" -#include "cairo-glitz.h" -#include "cairo-glitz-private.h" - -typedef struct _cairo_glitz_surface { - cairo_surface_t base; - - glitz_surface_t *surface; - glitz_format_t *format; - cairo_bool_t has_clip; - cairo_region_t clip; -} cairo_glitz_surface_t; - -static const cairo_surface_backend_t * -_cairo_glitz_surface_get_backend (void); - -static cairo_status_t -_cairo_glitz_surface_finish (void *abstract_surface) -{ - cairo_glitz_surface_t *surface = abstract_surface; - - if (surface->has_clip) { - glitz_surface_set_clip_region (surface->surface, 0, 0, NULL, 0); - _cairo_region_fini (&surface->clip); - } - - glitz_surface_destroy (surface->surface); - - return CAIRO_STATUS_SUCCESS; -} - -static glitz_format_name_t -_glitz_format_from_content (cairo_content_t content) -{ - switch (content) { - case CAIRO_CONTENT_COLOR: - return GLITZ_STANDARD_RGB24; - case CAIRO_CONTENT_ALPHA: - return GLITZ_STANDARD_A8; - case CAIRO_CONTENT_COLOR_ALPHA: - return GLITZ_STANDARD_ARGB32; - } - - ASSERT_NOT_REACHED; - return GLITZ_STANDARD_ARGB32; -} - -static cairo_surface_t * -_cairo_glitz_surface_create_similar (void *abstract_src, - cairo_content_t content, - int width, - int height) -{ - cairo_glitz_surface_t *src = abstract_src; - cairo_surface_t *crsurface; - glitz_drawable_t *drawable; - glitz_surface_t *surface; - glitz_format_t *gformat; - - drawable = glitz_surface_get_drawable (src->surface); - - gformat = - glitz_find_standard_format (drawable, - _glitz_format_from_content (content)); - if (!gformat) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - surface = glitz_surface_create (drawable, gformat, - width <= 0 ? 1 : width, - height <= 0 ? 1 : height, - 0, NULL); - - if (surface == NULL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - crsurface = cairo_glitz_surface_create (surface); - - glitz_surface_destroy (surface); - - return crsurface; -} - -static cairo_bool_t -_CAIRO_MASK_FORMAT (cairo_format_masks_t *masks, cairo_format_t *format) -{ - switch (masks->bpp) { - case 32: - if (masks->alpha_mask == 0xff000000 && - masks->red_mask == 0x00ff0000 && - masks->green_mask == 0x0000ff00 && - masks->blue_mask == 0x000000ff) - { - *format = CAIRO_FORMAT_ARGB32; - return TRUE; - } - if (masks->alpha_mask == 0x00000000 && - masks->red_mask == 0x00ff0000 && - masks->green_mask == 0x0000ff00 && - masks->blue_mask == 0x000000ff) - { - *format = CAIRO_FORMAT_RGB24; - return TRUE; - } - break; - case 8: - if (masks->alpha_mask == 0xff) - { - *format = CAIRO_FORMAT_A8; - return TRUE; - } - break; - case 1: - if (masks->alpha_mask == 0x1) - { - *format = CAIRO_FORMAT_A1; - return TRUE; - } - break; - } - return FALSE; -} - -static cairo_status_t -_cairo_glitz_get_boxes_from_region (cairo_region_t *region, glitz_box_t **boxes, int *nboxes) -{ - cairo_box_int_t *cboxes; - cairo_status_t status; - int n, i; - - status = _cairo_region_get_boxes (region, &n, &cboxes); - if (status) - return status; - - if (n == 0) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto done; - } - - *boxes = _cairo_malloc_ab (n, sizeof(glitz_box_t)); - if (*boxes == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto done; - } - - for (i = 0; i < n; i++) { - (*boxes)[i].x1 = cboxes[i].p1.x; - (*boxes)[i].y1 = cboxes[i].p1.y; - (*boxes)[i].x2 = cboxes[i].p2.x; - (*boxes)[i].y2 = cboxes[i].p2.y; - } - - *nboxes = n; -done: - _cairo_region_boxes_fini (region, cboxes); - return status; -} - -static cairo_status_t -_cairo_glitz_surface_get_image (cairo_glitz_surface_t *surface, - cairo_rectangle_int_t *interest, - cairo_image_surface_t **image_out, - cairo_rectangle_int_t *rect_out) -{ - cairo_image_surface_t *image; - int x1, y1, x2, y2; - int width, height; - unsigned char *pixels; - cairo_format_masks_t masks; - glitz_buffer_t *buffer; - glitz_pixel_format_t pf; - cairo_format_t format; - - x1 = 0; - y1 = 0; - x2 = glitz_surface_get_width (surface->surface); - y2 = glitz_surface_get_height (surface->surface); - - if (interest) - { - if (interest->x > x1) - x1 = interest->x; - if (interest->y > y1) - y1 = interest->y; - if (interest->x + interest->width < x2) - x2 = interest->x + interest->width; - if (interest->y + interest->height < y2) - y2 = interest->y + interest->height; - - if (x1 >= x2 || y1 >= y2) - { - *image_out = NULL; - return CAIRO_STATUS_SUCCESS; - } - } - - width = x2 - x1; - height = y2 - y1; - - if (rect_out) - { - rect_out->x = x1; - rect_out->y = y1; - rect_out->width = width; - rect_out->height = height; - } - - if (surface->format->color.fourcc == GLITZ_FOURCC_RGB) { - if (surface->format->color.red_size > 0) { - masks.bpp = 32; - - if (surface->format->color.alpha_size > 0) - masks.alpha_mask = 0xff000000; - else - masks.alpha_mask = 0x0; - - masks.red_mask = 0xff0000; - masks.green_mask = 0xff00; - masks.blue_mask = 0xff; - } else { - masks.bpp = 8; - masks.blue_mask = masks.green_mask = masks.red_mask = 0x0; - masks.alpha_mask = 0xff; - } - } else { - masks.bpp = 32; - masks.alpha_mask = 0xff000000; - masks.red_mask = 0xff0000; - masks.green_mask = 0xff00; - masks.blue_mask = 0xff; - } - - pf.fourcc = GLITZ_FOURCC_RGB; - pf.masks.bpp = masks.bpp; - pf.masks.alpha_mask = masks.alpha_mask; - pf.masks.red_mask = masks.red_mask; - pf.masks.green_mask = masks.green_mask; - pf.masks.blue_mask = masks.blue_mask; - pf.xoffset = 0; - pf.skip_lines = 0; - - /* XXX: we should eventually return images with negative stride, - need to verify that libpixman have no problem with this first. */ - pf.bytes_per_line = (((width * masks.bpp) / 8) + 3) & -4; - pf.scanline_order = GLITZ_PIXEL_SCANLINE_ORDER_TOP_DOWN; - - pixels = _cairo_malloc_ab (height, pf.bytes_per_line); - if (!pixels) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - buffer = glitz_buffer_create_for_data (pixels); - if (!buffer) { - free (pixels); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - /* clear out the glitz clip; the clip affects glitz_get_pixels */ - if (surface->has_clip) - glitz_surface_set_clip_region (surface->surface, - 0, 0, NULL, 0); - - glitz_get_pixels (surface->surface, - x1, y1, - width, height, - &pf, - buffer); - - glitz_buffer_destroy (buffer); - - /* restore the clip, if any */ - if (surface->has_clip) { - glitz_box_t *box; - cairo_status_t status; - int n; - - status = _cairo_glitz_get_boxes_from_region (&surface->clip, &box, &n); - if (status) { - free (pixels); - return status; - } - - glitz_surface_set_clip_region (surface->surface, 0, 0, box, n); - - free (box); - } - - /* - * Prefer to use a standard pixman format instead of the - * general masks case. - */ - if (_CAIRO_MASK_FORMAT (&masks, &format)) { - image = (cairo_image_surface_t *) - cairo_image_surface_create_for_data (pixels, - format, - x2 - x1, - y2 - y1, - pf.bytes_per_line); - if (image->base.status) - goto FAIL; - } else { - /* - * XXX This can't work. We must convert the data to one of the - * supported pixman formats. Pixman needs another function - * which takes data in an arbitrary format and converts it - * to something supported by that library. - */ - image = (cairo_image_surface_t *) - _cairo_image_surface_create_with_masks (pixels, - &masks, - x2 - x1, - y2 - y1, - pf.bytes_per_line); - if (image->base.status) - goto FAIL; - } - - _cairo_image_surface_assume_ownership_of_data (image); - - *image_out = image; - - return CAIRO_STATUS_SUCCESS; - -FAIL: - free (pixels); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); -} - -static void -cairo_format_get_masks (cairo_format_t format, - uint32_t *bpp, - uint32_t *alpha, - uint32_t *red, - uint32_t *green, - uint32_t *blue) -{ - *red = 0x0; - *green = 0x0; - *blue = 0x0; - *alpha = 0x0; - - switch (format) - { - case CAIRO_FORMAT_ARGB32: - *alpha = 0xff000000; - case CAIRO_FORMAT_RGB24: - default: - *bpp = 32; - *red = 0x00ff0000; - *green = 0x0000ff00; - *blue = 0x000000ff; - break; - - case CAIRO_FORMAT_A8: - *bpp = 8; - *alpha = 0xff; - break; - - case CAIRO_FORMAT_A1: - *bpp = 1; - *alpha = 0x1; - break; - } -} - -static cairo_status_t -_cairo_glitz_surface_set_image (void *abstract_surface, - cairo_image_surface_t *image, - int src_x, - int src_y, - int width, - int height, - int x_dst, - int y_dst) -{ - cairo_glitz_surface_t *surface = abstract_surface; - glitz_buffer_t *buffer; - glitz_pixel_format_t pf; - uint32_t bpp, am, rm, gm, bm; - char *data; - - cairo_format_get_masks (image->format, &bpp, &am, &rm, &gm, &bm); - - pf.fourcc = GLITZ_FOURCC_RGB; - pf.masks.bpp = bpp; - pf.masks.alpha_mask = am; - pf.masks.red_mask = rm; - pf.masks.green_mask = gm; - pf.masks.blue_mask = bm; - pf.xoffset = src_x; - pf.skip_lines = src_y; - - /* check for negative stride */ - if (image->stride < 0) - { - pf.bytes_per_line = -image->stride; - pf.scanline_order = GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP; - data = (char *) image->data + image->stride * (image->height - 1); - } - else - { - pf.bytes_per_line = image->stride; - pf.scanline_order = GLITZ_PIXEL_SCANLINE_ORDER_TOP_DOWN; - data = (char *) image->data; - } - - buffer = glitz_buffer_create_for_data (data); - if (!buffer) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - glitz_set_pixels (surface->surface, - x_dst, y_dst, - width, height, - &pf, - buffer); - - glitz_buffer_destroy (buffer); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_glitz_surface_acquire_source_image (void *abstract_surface, - cairo_image_surface_t **image_out, - void **image_extra) -{ - cairo_glitz_surface_t *surface = abstract_surface; - - *image_extra = NULL; - - return _cairo_glitz_surface_get_image (surface, NULL, image_out, NULL); -} - -static void -_cairo_glitz_surface_release_source_image (void *abstract_surface, - cairo_image_surface_t *image, - void *image_extra) -{ - cairo_surface_destroy (&image->base); -} - -static cairo_status_t -_cairo_glitz_surface_acquire_dest_image (void *abstract_surface, - cairo_rectangle_int_t *interest_rect, - cairo_image_surface_t **image_out, - cairo_rectangle_int_t *image_rect_out, - void **image_extra) -{ - cairo_glitz_surface_t *surface = abstract_surface; - cairo_image_surface_t *image; - cairo_status_t status; - - status = _cairo_glitz_surface_get_image (surface, interest_rect, &image, - image_rect_out); - if (status) - return status; - - *image_out = image; - *image_extra = NULL; - - return status; -} - -static void -_cairo_glitz_surface_release_dest_image (void *abstract_surface, - cairo_rectangle_int_t *interest_rect, - cairo_image_surface_t *image, - cairo_rectangle_int_t *image_rect, - void *image_extra) -{ - cairo_glitz_surface_t *surface = abstract_surface; - cairo_status_t status; - - status = _cairo_glitz_surface_set_image (surface, image, 0, 0, - image->width, image->height, - image_rect->x, image_rect->y); - if (status) - status = _cairo_surface_set_error (&surface->base, status); - - cairo_surface_destroy (&image->base); -} - -static cairo_status_t -_cairo_glitz_surface_clone_similar (void *abstract_surface, - cairo_surface_t *src, - int src_x, - int src_y, - int width, - int height, - int *clone_offset_x, - int *clone_offset_y, - cairo_surface_t **clone_out) -{ - cairo_glitz_surface_t *surface = abstract_surface; - cairo_glitz_surface_t *clone; - cairo_status_t status; - - if (surface->base.status) - return surface->base.status; - - if (src->backend == surface->base.backend) - { - *clone_offset_x = 0; - *clone_offset_y = 0; - *clone_out = cairo_surface_reference (src); - - return CAIRO_STATUS_SUCCESS; - } - else if (_cairo_surface_is_image (src)) - { - cairo_image_surface_t *image_src = (cairo_image_surface_t *) src; - cairo_content_t content; - cairo_rectangle_int_t image_extent; - cairo_rectangle_int_t extent; - - content = _cairo_content_from_format (image_src->format); - - clone = (cairo_glitz_surface_t *) - _cairo_glitz_surface_create_similar (surface, content, - image_src->width, - image_src->height); - if (clone == NULL) - return CAIRO_INT_STATUS_UNSUPPORTED; - if (clone->base.status) - return clone->base.status; - - image_extent.x = 0; - image_extent.y = 0; - image_extent.width = image_src->width; - image_extent.height = image_src->height; - extent.x = src_x; - extent.y = src_y; - extent.width = width; - extent.height = height; - - _cairo_rectangle_intersect(&extent, &image_extent); - - status = _cairo_glitz_surface_set_image (clone, image_src, - extent.x, extent.y, - extent.width, extent.height, - extent.x, extent.y); - if (status) { - cairo_surface_destroy (&clone->base); - return status; - } - - *clone_out = &clone->base; - - return CAIRO_STATUS_SUCCESS; - } - - return CAIRO_INT_STATUS_UNSUPPORTED; -} - -static void -_cairo_glitz_surface_set_matrix (cairo_glitz_surface_t *surface, - cairo_matrix_t *matrix) -{ - glitz_transform_t transform; - - transform.matrix[0][0] = _cairo_fixed_from_double (matrix->xx); - transform.matrix[0][1] = _cairo_fixed_from_double (matrix->xy); - transform.matrix[0][2] = _cairo_fixed_from_double (matrix->x0); - - transform.matrix[1][0] = _cairo_fixed_from_double (matrix->yx); - transform.matrix[1][1] = _cairo_fixed_from_double (matrix->yy); - transform.matrix[1][2] = _cairo_fixed_from_double (matrix->y0); - - transform.matrix[2][0] = 0; - transform.matrix[2][1] = 0; - transform.matrix[2][2] = _cairo_fixed_from_double (1); - - glitz_surface_set_transform (surface->surface, &transform); -} - -static glitz_operator_t -_glitz_operator (cairo_operator_t op) -{ - switch (op) { - case CAIRO_OPERATOR_CLEAR: - return GLITZ_OPERATOR_CLEAR; - - case CAIRO_OPERATOR_SOURCE: - return GLITZ_OPERATOR_SRC; - case CAIRO_OPERATOR_OVER: - return GLITZ_OPERATOR_OVER; - case CAIRO_OPERATOR_IN: - return GLITZ_OPERATOR_IN; - case CAIRO_OPERATOR_OUT: - return GLITZ_OPERATOR_OUT; - case CAIRO_OPERATOR_ATOP: - return GLITZ_OPERATOR_ATOP; - - case CAIRO_OPERATOR_DEST: - return GLITZ_OPERATOR_DST; - case CAIRO_OPERATOR_DEST_OVER: - return GLITZ_OPERATOR_OVER_REVERSE; - case CAIRO_OPERATOR_DEST_IN: - return GLITZ_OPERATOR_IN_REVERSE; - case CAIRO_OPERATOR_DEST_OUT: - return GLITZ_OPERATOR_OUT_REVERSE; - case CAIRO_OPERATOR_DEST_ATOP: - return GLITZ_OPERATOR_ATOP_REVERSE; - - case CAIRO_OPERATOR_XOR: - return GLITZ_OPERATOR_XOR; - case CAIRO_OPERATOR_ADD: - return GLITZ_OPERATOR_ADD; - case CAIRO_OPERATOR_SATURATE: - /* XXX: This line should never be reached. Glitz backend should bail - out earlier if saturate operator is used. OpenGL can't do saturate - with pre-multiplied colors. Solid colors can still be done as we - can just un-pre-multiply them. However, support for that will have - to be added to glitz. */ - - /* fall-through */ - break; - } - - ASSERT_NOT_REACHED; - - /* Something's very broken if this line of code can be reached, so - we want to return something that would give a noticeably - incorrect result. The XOR operator seems so rearely desired - that it should fit the bill here. */ - return CAIRO_OPERATOR_XOR; -} - -#define CAIRO_GLITZ_FEATURE_OK(surface, name) \ - (glitz_drawable_get_features (glitz_surface_get_drawable (surface)) & \ - (GLITZ_FEATURE_ ## name ## _MASK)) - -static glitz_status_t -_glitz_ensure_target (glitz_surface_t *surface) -{ - if (!glitz_surface_get_attached_drawable (surface)) - { - glitz_drawable_format_t *target_format, templ; - glitz_format_t *format; - glitz_drawable_t *drawable, *target; - unsigned int width, height; - unsigned long mask; - - drawable = glitz_surface_get_drawable (surface); - format = glitz_surface_get_format (surface); - width = glitz_surface_get_width (surface); - height = glitz_surface_get_height (surface); - - if (format->color.fourcc != GLITZ_FOURCC_RGB) - return CAIRO_INT_STATUS_UNSUPPORTED; - - templ.color = format->color; - templ.depth_size = 0; - templ.stencil_size = 0; - templ.doublebuffer = 0; - templ.samples = 1; - - mask = - GLITZ_FORMAT_RED_SIZE_MASK | - GLITZ_FORMAT_GREEN_SIZE_MASK | - GLITZ_FORMAT_BLUE_SIZE_MASK | - GLITZ_FORMAT_ALPHA_SIZE_MASK | - GLITZ_FORMAT_DEPTH_SIZE_MASK | - GLITZ_FORMAT_STENCIL_SIZE_MASK | - GLITZ_FORMAT_DOUBLEBUFFER_MASK | - GLITZ_FORMAT_SAMPLES_MASK; - - target_format = glitz_find_drawable_format (drawable, mask, &templ, 0); - if (!target_format) - return CAIRO_INT_STATUS_UNSUPPORTED; - - target = glitz_create_drawable (drawable, target_format, - width, height); - if (!target) - return CAIRO_INT_STATUS_UNSUPPORTED; - - glitz_surface_attach (surface, target, - GLITZ_DRAWABLE_BUFFER_FRONT_COLOR); - - glitz_drawable_destroy (target); - } - - return CAIRO_STATUS_SUCCESS; -} - -typedef struct _cairo_glitz_surface_attributes { - cairo_surface_attributes_t base; - - glitz_fill_t fill; - glitz_filter_t filter; - glitz_fixed16_16_t *params; - int n_params; - cairo_bool_t acquired; -} cairo_glitz_surface_attributes_t; - -static cairo_int_status_t -_cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern, - cairo_glitz_surface_t *dst, - int x, - int y, - unsigned int width, - unsigned int height, - cairo_glitz_surface_t **surface_out, - cairo_glitz_surface_attributes_t *attr) -{ - cairo_glitz_surface_t *src = NULL; - - attr->acquired = FALSE; - - switch (pattern->type) { - case CAIRO_PATTERN_TYPE_LINEAR: - case CAIRO_PATTERN_TYPE_RADIAL: { - cairo_gradient_pattern_t *gradient = - (cairo_gradient_pattern_t *) pattern; - char *data; - glitz_fixed16_16_t *params; - unsigned int n_params; - unsigned int *pixels; - unsigned int i, n_base_params; - glitz_buffer_t *buffer; - static const glitz_pixel_format_t format = { - GLITZ_FOURCC_RGB, - { - 32, - 0xff000000, - 0x00ff0000, - 0x0000ff00, - 0x000000ff - }, - 0, 0, 0, - GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP - }; - - /* XXX: the current color gradient acceleration provided by glitz is - * experimental, it's been proven inappropriate in a number of ways, - * most importantly, it's currently implemented as filters and - * gradients are not filters. eventually, it will be replaced with - * something more appropriate. - */ - - if (gradient->n_stops < 2) - break; - - if (!CAIRO_GLITZ_FEATURE_OK (dst->surface, FRAGMENT_PROGRAM)) - break; - - if (pattern->type == CAIRO_PATTERN_TYPE_RADIAL) - n_base_params = 6; - else - n_base_params = 4; - - n_params = gradient->n_stops * 3 + n_base_params; - - /* check for int overflow */ - { - int size1, size2; - if (n_params >= INT32_MAX / sizeof (glitz_fixed16_16_t) || - gradient->n_stops >= INT32_MAX / sizeof (unsigned int)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - size1 = n_params * sizeof (glitz_fixed16_16_t); - size2 = gradient->n_stops * sizeof (unsigned int); - - if (size1 >= INT32_MAX - size2) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - data = malloc (size1 + size2); - } - - if (!data) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - params = (glitz_fixed16_16_t *) data; - pixels = (unsigned int *) - (data + sizeof (glitz_fixed16_16_t) * n_params); - - buffer = glitz_buffer_create_for_data (pixels); - if (!buffer) { - free (data); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - src = (cairo_glitz_surface_t *) - _cairo_surface_create_similar_scratch (&dst->base, - CAIRO_CONTENT_COLOR_ALPHA, - gradient->n_stops, 1); - if (src->base.status) { - glitz_buffer_destroy (buffer); - free (data); - return src->base.status; - } - - for (i = 0; i < gradient->n_stops; i++) - { - pixels[i] = - (((int) (gradient->stops[i].color.alpha_short >> 8)) << 24) | - (((int) (gradient->stops[i].color.red_short >> 8)) << 16) | - (((int) (gradient->stops[i].color.green_short >> 8)) << 8) | - (((int) (gradient->stops[i].color.blue_short >> 8))); - - params[n_base_params + 3 * i + 0] = _cairo_fixed_16_16_from_double (gradient->stops[i].offset); - params[n_base_params + 3 * i + 1] = i << 16; - params[n_base_params + 3 * i + 2] = 0; - } - - glitz_set_pixels (src->surface, 0, 0, gradient->n_stops, 1, - (glitz_pixel_format_t *)&format, buffer); - - glitz_buffer_destroy (buffer); - - if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR) - { - cairo_linear_pattern_t *grad = (cairo_linear_pattern_t *) pattern; - - params[0] = grad->p1.x; - params[1] = grad->p1.y; - params[2] = grad->p2.x; - params[3] = grad->p2.y; - attr->filter = GLITZ_FILTER_LINEAR_GRADIENT; - } - else - { - cairo_radial_pattern_t *grad = (cairo_radial_pattern_t *) pattern; - - params[0] = grad->c1.x; - params[1] = grad->c1.y; - params[2] = grad->r1; - params[3] = grad->c2.x; - params[4] = grad->c2.y; - params[5] = grad->r2; - attr->filter = GLITZ_FILTER_RADIAL_GRADIENT; - } - - switch (pattern->extend) { - case CAIRO_EXTEND_NONE: - attr->fill = GLITZ_FILL_TRANSPARENT; - break; - case CAIRO_EXTEND_REPEAT: - attr->fill = GLITZ_FILL_REPEAT; - break; - case CAIRO_EXTEND_REFLECT: - attr->fill = GLITZ_FILL_REFLECT; - break; - case CAIRO_EXTEND_PAD: - attr->fill = GLITZ_FILL_NEAREST; - break; - } - - attr->params = params; - attr->n_params = n_params; - attr->base.matrix = pattern->matrix; - attr->base.x_offset = 0; - attr->base.y_offset = 0; - } break; - case CAIRO_PATTERN_TYPE_SOLID: - case CAIRO_PATTERN_TYPE_SURFACE: - default: - break; - } - - if (!src) - { - cairo_int_status_t status; - - status = _cairo_pattern_acquire_surface (pattern, &dst->base, - x, y, width, height, - (cairo_surface_t **) &src, - &attr->base); - if (status) - return status; - - if (src) - { - switch (attr->base.extend) { - case CAIRO_EXTEND_NONE: - attr->fill = GLITZ_FILL_TRANSPARENT; - break; - case CAIRO_EXTEND_REPEAT: - attr->fill = GLITZ_FILL_REPEAT; - break; - case CAIRO_EXTEND_REFLECT: - attr->fill = GLITZ_FILL_REFLECT; - break; - case CAIRO_EXTEND_PAD: - default: - attr->fill = GLITZ_FILL_NEAREST; - break; - } - - switch (attr->base.filter) { - case CAIRO_FILTER_FAST: - case CAIRO_FILTER_NEAREST: - attr->filter = GLITZ_FILTER_NEAREST; - break; - case CAIRO_FILTER_GOOD: - case CAIRO_FILTER_BEST: - case CAIRO_FILTER_BILINEAR: - case CAIRO_FILTER_GAUSSIAN: - default: - attr->filter = GLITZ_FILTER_BILINEAR; - break; - } - - attr->params = NULL; - attr->n_params = 0; - attr->acquired = TRUE; - } - } - - *surface_out = src; - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_glitz_pattern_release_surface (cairo_pattern_t *pattern, - cairo_glitz_surface_t *surface, - cairo_glitz_surface_attributes_t *attr) -{ - if (attr->acquired) - _cairo_pattern_release_surface (pattern, &surface->base, &attr->base); - else - cairo_surface_destroy (&surface->base); -} - -static cairo_int_status_t -_cairo_glitz_pattern_acquire_surfaces (cairo_pattern_t *src, - cairo_pattern_t *mask, - cairo_glitz_surface_t *dst, - int src_x, - int src_y, - int mask_x, - int mask_y, - unsigned int width, - unsigned int height, - cairo_glitz_surface_t **src_out, - cairo_glitz_surface_t **mask_out, - cairo_glitz_surface_attributes_t *sattr, - cairo_glitz_surface_attributes_t *mattr) -{ - cairo_int_status_t status; - cairo_solid_pattern_t tmp; - - /* If src and mask are both solid, then the mask alpha can be - * combined into src and mask can be ignored. */ - - /* XXX: This optimization assumes that there is no color - * information in mask, so this will need to change when we - * support RENDER-style 4-channel masks. */ - - if (src->type == CAIRO_PATTERN_TYPE_SOLID && - mask->type == CAIRO_PATTERN_TYPE_SOLID) - { - cairo_color_t combined; - cairo_solid_pattern_t *src_solid = (cairo_solid_pattern_t *) src; - cairo_solid_pattern_t *mask_solid = (cairo_solid_pattern_t *) mask; - - combined = src_solid->color; - _cairo_color_multiply_alpha (&combined, mask_solid->color.alpha); - - _cairo_pattern_init_solid (&tmp, &combined, CAIRO_CONTENT_COLOR_ALPHA); - - mask = NULL; - } else { - status = _cairo_pattern_init_copy (&tmp.base, src); - if (status) - return status; - } - - status = _cairo_glitz_pattern_acquire_surface (&tmp.base, dst, - src_x, src_y, - width, height, - src_out, sattr); - - _cairo_pattern_fini (&tmp.base); - - if (status) - return status; - - if (mask) - { - status = _cairo_pattern_init_copy (&tmp.base, mask); - if (status) - return status; - - status = _cairo_glitz_pattern_acquire_surface (&tmp.base, dst, - mask_x, mask_y, - width, height, - mask_out, mattr); - - if (status) - _cairo_glitz_pattern_release_surface (&tmp.base, *src_out, sattr); - - _cairo_pattern_fini (&tmp.base); - - return status; - } - else - { - *mask_out = NULL; - } - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_glitz_surface_set_attributes (cairo_glitz_surface_t *surface, - cairo_glitz_surface_attributes_t *a) -{ - _cairo_glitz_surface_set_matrix (surface, &a->base.matrix); - glitz_surface_set_fill (surface->surface, a->fill); - glitz_surface_set_filter (surface->surface, a->filter, - a->params, a->n_params); -} - -static cairo_int_status_t -_cairo_glitz_surface_composite (cairo_operator_t op, - cairo_pattern_t *src_pattern, - cairo_pattern_t *mask_pattern, - void *abstract_dst, - 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_glitz_surface_attributes_t src_attr, mask_attr; - cairo_glitz_surface_t *dst = abstract_dst; - cairo_glitz_surface_t *src; - cairo_glitz_surface_t *mask; - cairo_int_status_t status; - - if (op == CAIRO_OPERATOR_SATURATE) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (_glitz_ensure_target (dst->surface)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - status = _cairo_glitz_pattern_acquire_surfaces (src_pattern, mask_pattern, - dst, - src_x, src_y, - mask_x, mask_y, - width, height, - &src, &mask, - &src_attr, &mask_attr); - if (status) - return status; - - _cairo_glitz_surface_set_attributes (src, &src_attr); - if (mask) - { - _cairo_glitz_surface_set_attributes (mask, &mask_attr); - glitz_composite (_glitz_operator (op), - src->surface, - mask->surface, - dst->surface, - src_x + src_attr.base.x_offset, - src_y + src_attr.base.y_offset, - mask_x + mask_attr.base.x_offset, - mask_y + mask_attr.base.y_offset, - dst_x, dst_y, - width, height); - - if (mask_attr.n_params) - free (mask_attr.params); - - _cairo_glitz_pattern_release_surface (mask_pattern, mask, &mask_attr); - } - else - { - glitz_composite (_glitz_operator (op), - src->surface, - NULL, - dst->surface, - src_x + src_attr.base.x_offset, - src_y + src_attr.base.y_offset, - 0, 0, - dst_x, dst_y, - width, height); - } - - if (src_attr.n_params) - free (src_attr.params); - - _cairo_glitz_pattern_release_surface (src_pattern, src, &src_attr); - - if (glitz_surface_get_status (dst->surface) == GLITZ_STATUS_NOT_SUPPORTED) - return CAIRO_INT_STATUS_UNSUPPORTED; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_glitz_surface_fill_rectangles (void *abstract_dst, - cairo_operator_t op, - const cairo_color_t *color, - cairo_rectangle_int_t *rects, - int n_rects) -{ - cairo_glitz_surface_t *dst = abstract_dst; - cairo_glitz_surface_t *src; - - switch (op) { - case CAIRO_OPERATOR_SOURCE: { - glitz_color_t glitz_color; - - glitz_color.red = color->red_short; - glitz_color.green = color->green_short; - glitz_color.blue = color->blue_short; - glitz_color.alpha = color->alpha_short; - - glitz_set_rectangles (dst->surface, &glitz_color, - (glitz_rectangle_t *) rects, n_rects); - } break; - case CAIRO_OPERATOR_CLEAR: { - static const glitz_color_t glitz_color = { 0, 0, 0, 0 }; - - glitz_set_rectangles (dst->surface, &glitz_color, - (glitz_rectangle_t *) rects, n_rects); - } break; - case CAIRO_OPERATOR_SATURATE: - return CAIRO_INT_STATUS_UNSUPPORTED; - case CAIRO_OPERATOR_OVER: - case CAIRO_OPERATOR_IN: - case CAIRO_OPERATOR_OUT: - case CAIRO_OPERATOR_ATOP: - case CAIRO_OPERATOR_DEST: - case CAIRO_OPERATOR_DEST_OVER: - case CAIRO_OPERATOR_DEST_IN: - case CAIRO_OPERATOR_DEST_OUT: - case CAIRO_OPERATOR_DEST_ATOP: - case CAIRO_OPERATOR_XOR: - case CAIRO_OPERATOR_ADD: - default: - if (_glitz_ensure_target (dst->surface)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - src = (cairo_glitz_surface_t *) - _cairo_surface_create_similar_solid (&dst->base, - CAIRO_CONTENT_COLOR_ALPHA, - 1, 1, - (cairo_color_t *) color); - if (src->base.status) - return src->base.status; - - glitz_surface_set_fill (src->surface, GLITZ_FILL_REPEAT); - - while (n_rects--) - { - glitz_composite (_glitz_operator (op), - src->surface, - NULL, - dst->surface, - 0, 0, - 0, 0, - rects->x, rects->y, - rects->width, rects->height); - rects++; - } - - cairo_surface_destroy (&src->base); - break; - } - - if (glitz_surface_get_status (dst->surface) == GLITZ_STATUS_NOT_SUPPORTED) - return CAIRO_INT_STATUS_UNSUPPORTED; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_glitz_surface_composite_trapezoids (cairo_operator_t op, - cairo_pattern_t *pattern, - void *abstract_dst, - cairo_antialias_t antialias, - int src_x, - int src_y, - int dst_x, - int dst_y, - unsigned int width, - unsigned int height, - cairo_trapezoid_t *traps, - int n_traps) -{ - cairo_pattern_union_t tmp_src_pattern; - cairo_pattern_t *src_pattern; - cairo_glitz_surface_attributes_t attributes; - cairo_glitz_surface_t *dst = abstract_dst; - cairo_glitz_surface_t *src; - cairo_glitz_surface_t *mask = NULL; - glitz_buffer_t *buffer = NULL; - void *data = NULL; - cairo_int_status_t status; - unsigned short alpha; - - if (antialias != CAIRO_ANTIALIAS_DEFAULT && - antialias != CAIRO_ANTIALIAS_GRAY) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (dst->base.status) - return dst->base.status; - - if (op == CAIRO_OPERATOR_SATURATE) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (_glitz_ensure_target (dst->surface)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) - { - status = _cairo_pattern_init_copy (&tmp_src_pattern.base, pattern); - if (status) - return status; - - status = _cairo_glitz_pattern_acquire_surface (&tmp_src_pattern.base, - dst, - src_x, src_y, - width, height, - &src, &attributes); - src_pattern = &tmp_src_pattern.base; - } - else - { - status = _cairo_glitz_pattern_acquire_surface (pattern, dst, - src_x, src_y, - width, height, - &src, &attributes); - src_pattern = pattern; - } - alpha = 0xffff; - - if (status) - return status; - - if (op == CAIRO_OPERATOR_ADD || n_traps <= 1) - { - static const glitz_color_t clear_black = { 0, 0, 0, 0 }; - glitz_color_t color; - glitz_geometry_format_t format; - int n_trap_added; - int offset = 0; - int data_size = 0; - int size = 30 * n_traps; /* just a guess */ - - format.vertex.primitive = GLITZ_PRIMITIVE_QUADS; - format.vertex.type = GLITZ_DATA_TYPE_FLOAT; - format.vertex.bytes_per_vertex = 3 * sizeof (glitz_float_t); - format.vertex.attributes = GLITZ_VERTEX_ATTRIBUTE_MASK_COORD_MASK; - format.vertex.mask.type = GLITZ_DATA_TYPE_FLOAT; - format.vertex.mask.size = GLITZ_COORDINATE_SIZE_X; - format.vertex.mask.offset = 2 * sizeof (glitz_float_t); - - mask = (cairo_glitz_surface_t *) - _cairo_glitz_surface_create_similar (&dst->base, - CAIRO_CONTENT_ALPHA, - 2, 1); - if (mask == NULL) { - _cairo_glitz_pattern_release_surface (src_pattern, src, &attributes); - if (src_pattern == &tmp_src_pattern.base) - _cairo_pattern_fini (&tmp_src_pattern.base); - return CAIRO_INT_STATUS_UNSUPPORTED; - } - if (mask->base.status) { - _cairo_glitz_pattern_release_surface (src_pattern, src, &attributes); - if (src_pattern == &tmp_src_pattern.base) - _cairo_pattern_fini (&tmp_src_pattern.base); - - return mask->base.status; - } - - color.red = color.green = color.blue = color.alpha = 0xffff; - - glitz_set_rectangle (mask->surface, &clear_black, 0, 0, 1, 1); - glitz_set_rectangle (mask->surface, &color, 1, 0, 1, 1); - - glitz_surface_set_fill (mask->surface, GLITZ_FILL_NEAREST); - glitz_surface_set_filter (mask->surface, - GLITZ_FILTER_BILINEAR, - NULL, 0); - - size *= format.vertex.bytes_per_vertex; - - while (n_traps) - { - if (data_size < size) - { - void *p; - data_size = size; - p = realloc (data, data_size); - if (!p) - { - _cairo_glitz_pattern_release_surface (src_pattern, src, - &attributes); - if (src_pattern == &tmp_src_pattern.base) - _cairo_pattern_fini (&tmp_src_pattern.base); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - data = p; - - if (buffer) - glitz_buffer_destroy (buffer); - - buffer = glitz_buffer_create_for_data (data); - if (!buffer) { - free (data); - _cairo_glitz_pattern_release_surface (src_pattern, src, - &attributes); - if (src_pattern == &tmp_src_pattern.base) - _cairo_pattern_fini (&tmp_src_pattern.base); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - } - - offset += - glitz_add_trapezoids (buffer, - offset, size - offset, - format.vertex.type, mask->surface, - (glitz_trapezoid_t *) traps, n_traps, - &n_trap_added); - - n_traps -= n_trap_added; - traps += n_trap_added; - size *= 2; - } - - glitz_set_geometry (dst->surface, - GLITZ_GEOMETRY_TYPE_VERTEX, - &format, buffer); - glitz_set_array (dst->surface, 0, 3, - offset / format.vertex.bytes_per_vertex, - 0, 0); - } - else - { - cairo_image_surface_t *image; - unsigned char *ptr; - int stride; - - stride = (width + 3) & -4; - data = calloc (stride, height); - if (!data) - { - _cairo_glitz_pattern_release_surface (src_pattern, src, &attributes); - if (src_pattern == &tmp_src_pattern.base) - _cairo_pattern_fini (&tmp_src_pattern.base); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - /* using negative stride */ - ptr = (unsigned char *) data + stride * (height - 1); - - image = (cairo_image_surface_t *) - cairo_image_surface_create_for_data (ptr, - CAIRO_FORMAT_A8, - width, height, - -stride); - if (image->base.status) - { - cairo_surface_destroy (&src->base); - free (data); - return image->base.status; - } - - pixman_add_trapezoids (image->pixman_image, -dst_x, -dst_y, - n_traps, (pixman_trapezoid_t *) traps); - - mask = (cairo_glitz_surface_t *) - _cairo_surface_create_similar_scratch (&dst->base, - CAIRO_CONTENT_ALPHA, - width, height); - if (mask->base.status) { - _cairo_glitz_pattern_release_surface (src_pattern, src, &attributes); - free (data); - cairo_surface_destroy (&image->base); - return mask->base.status; - } - - status = _cairo_glitz_surface_set_image (mask, image, - 0, 0, width, height, 0, 0); - - cairo_surface_destroy(&image->base); - - if (status) - return status; - } - - _cairo_glitz_surface_set_attributes (src, &attributes); - - glitz_composite (_glitz_operator (op), - src->surface, - mask->surface, - dst->surface, - src_x + attributes.base.x_offset, - src_y + attributes.base.y_offset, - 0, 0, - dst_x, dst_y, - width, height); - - if (attributes.n_params) - free (attributes.params); - - glitz_set_geometry (dst->surface, - GLITZ_GEOMETRY_TYPE_NONE, - NULL, NULL); - - if (buffer) - glitz_buffer_destroy (buffer); - - free (data); - - _cairo_glitz_pattern_release_surface (src_pattern, src, &attributes); - if (src_pattern == &tmp_src_pattern.base) - _cairo_pattern_fini (&tmp_src_pattern.base); - - if (mask) - cairo_surface_destroy (&mask->base); - - if (glitz_surface_get_status (dst->surface) == GLITZ_STATUS_NOT_SUPPORTED) - return CAIRO_INT_STATUS_UNSUPPORTED; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_glitz_surface_set_clip_region (void *abstract_surface, - cairo_region_t *region) -{ - cairo_glitz_surface_t *surface = abstract_surface; - - if (region) - { - glitz_box_t *box; - int n; - cairo_status_t status; - - if (!surface->has_clip) { - _cairo_region_init (&surface->clip); - surface->has_clip = TRUE; - } - - status = _cairo_region_copy (&surface->clip, region); - if (status) { - _cairo_region_fini (&surface->clip); - surface->has_clip = FALSE; - return status; - } - - status = _cairo_glitz_get_boxes_from_region (&surface->clip, &box, &n); - if (status) { - _cairo_region_fini (&surface->clip); - surface->has_clip = FALSE; - return status; - } - - glitz_surface_set_clip_region (surface->surface, 0, 0, box, n); - - free (box); - } - else - { - glitz_surface_set_clip_region (surface->surface, 0, 0, NULL, 0); - - if (surface->has_clip) { - _cairo_region_fini (&surface->clip); - surface->has_clip = FALSE; - } - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_glitz_surface_get_extents (void *abstract_surface, - cairo_rectangle_int_t *rectangle) -{ - cairo_glitz_surface_t *surface = abstract_surface; - - rectangle->x = 0; - rectangle->y = 0; - rectangle->width = glitz_surface_get_width (surface->surface); - rectangle->height = glitz_surface_get_height (surface->surface); - - return CAIRO_STATUS_SUCCESS; -} - -#define CAIRO_GLITZ_AREA_AVAILABLE 0 -#define CAIRO_GLITZ_AREA_DIVIDED 1 -#define CAIRO_GLITZ_AREA_OCCUPIED 2 - -typedef struct _cairo_glitz_root_area cairo_glitz_root_area_t; - -typedef struct _cairo_glitz_area { - int state; - int level; - int x, y; - int width, height; - struct _cairo_glitz_area *area[4]; - cairo_glitz_root_area_t *root; - void *closure; -} cairo_glitz_area_t; - -static cairo_glitz_area_t _empty_area = { - 0, 0, 0, 0, 0, 0, - { NULL, NULL, NULL, NULL }, - NULL, - NULL -}; - -typedef struct _cairo_glitz_area_funcs { - cairo_status_t (*move_in) (cairo_glitz_area_t *area, - void *closure); - - void (*move_out) (cairo_glitz_area_t *area, - void *closure); - - int (*compare_score) (cairo_glitz_area_t *area, - void *closure1, - void *closure2); -} cairo_glitz_area_funcs_t; - -struct _cairo_glitz_root_area { - int max_level; - int width, height; - cairo_glitz_area_t *area; - const cairo_glitz_area_funcs_t *funcs; -}; - -static cairo_status_t -_cairo_glitz_area_move_in (cairo_glitz_area_t *area, - void *closure) -{ - area->closure = closure; - area->state = CAIRO_GLITZ_AREA_OCCUPIED; - - return (*area->root->funcs->move_in) (area, area->closure); -} - -static void -_cairo_glitz_area_move_out (cairo_glitz_area_t *area) -{ - if (area->root) - { - (*area->root->funcs->move_out) (area, area->closure); - - area->closure = NULL; - area->state = CAIRO_GLITZ_AREA_AVAILABLE; - } -} - -static cairo_glitz_area_t * -_cairo_glitz_area_create (cairo_glitz_root_area_t *root, - int level, - int x, - int y, - int width, - int height) -{ - cairo_glitz_area_t *area; - int n = 4; - - area = malloc (sizeof (cairo_glitz_area_t)); - if (!area) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return NULL; - } - - area->level = level; - area->x = x; - area->y = y; - area->width = width; - area->height = height; - area->root = root; - area->closure = NULL; - area->state = CAIRO_GLITZ_AREA_AVAILABLE; - - while (n--) - area->area[n] = NULL; - - return area; -} - -static void -_cairo_glitz_area_destroy (cairo_glitz_area_t *area) -{ - if (area == NULL) - return; - - if (area->state == CAIRO_GLITZ_AREA_OCCUPIED) - { - _cairo_glitz_area_move_out (area); - } - else - { - int n = 4; - - while (n--) - _cairo_glitz_area_destroy (area->area[n]); - } - - free (area); -} - -static cairo_glitz_area_t * -_cairo_glitz_area_get_top_scored_sub_area (cairo_glitz_area_t *area) -{ - if (!area) - return NULL; - - switch (area->state) { - case CAIRO_GLITZ_AREA_OCCUPIED: - return area; - case CAIRO_GLITZ_AREA_AVAILABLE: - break; - case CAIRO_GLITZ_AREA_DIVIDED: { - cairo_glitz_area_t *tmp, *top = NULL; - int i; - - for (i = 0; i < 4; i++) - { - tmp = _cairo_glitz_area_get_top_scored_sub_area (area->area[i]); - if (tmp && top) - { - if ((*area->root->funcs->compare_score) (tmp, - tmp->closure, - top->closure) > 0) - top = tmp; - } - else if (tmp) - { - top = tmp; - } - } - return top; - } - } - - return NULL; -} - -static cairo_int_status_t -_cairo_glitz_area_find (cairo_glitz_area_t *area, - int width, - int height, - cairo_bool_t kick_out, - void *closure) -{ - cairo_status_t status; - - if (area->width < width || area->height < height) - return CAIRO_INT_STATUS_UNSUPPORTED; - - switch (area->state) { - case CAIRO_GLITZ_AREA_OCCUPIED: - if (kick_out) - { - if ((*area->root->funcs->compare_score) (area, - area->closure, - closure) >= 0) - return CAIRO_INT_STATUS_UNSUPPORTED; - - _cairo_glitz_area_move_out (area); - } else { - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - /* fall-through */ - case CAIRO_GLITZ_AREA_AVAILABLE: { - if (area->level == area->root->max_level || - (area->width == width && area->height == height)) - { - return _cairo_glitz_area_move_in (area, closure); - } - else - { - int dx[4], dy[4], w[4], h[4], i; - - dx[0] = dx[2] = dy[0] = dy[1] = 0; - - w[0] = w[2] = dx[1] = dx[3] = width; - h[0] = h[1] = dy[2] = dy[3] = height; - - w[1] = w[3] = area->width - width; - h[2] = h[3] = area->height - height; - - for (i = 0; i < 2; i++) - { - if (w[i]) - area->area[i] = - _cairo_glitz_area_create (area->root, - area->level + 1, - area->x + dx[i], - area->y + dy[i], - w[i], h[i]); - } - - for (; i < 4; i++) - { - if (w[i] && h[i]) - area->area[i] = - _cairo_glitz_area_create (area->root, - area->level + 1, - area->x + dx[i], - area->y + dy[i], - w[i], h[i]); - } - - area->state = CAIRO_GLITZ_AREA_DIVIDED; - - status = _cairo_glitz_area_find (area->area[0], - width, height, - kick_out, closure); - if (status == CAIRO_STATUS_SUCCESS) - return CAIRO_STATUS_SUCCESS; - } - } break; - case CAIRO_GLITZ_AREA_DIVIDED: { - cairo_glitz_area_t *to_area; - int i, rejected = FALSE; - - for (i = 0; i < 4; i++) - { - if (area->area[i]) - { - if (area->area[i]->width >= width && - area->area[i]->height >= height) - { - status = _cairo_glitz_area_find (area->area[i], - width, height, - kick_out, closure); - if (status == CAIRO_STATUS_SUCCESS) - return CAIRO_STATUS_SUCCESS; - - rejected = TRUE; - } - } - } - - if (rejected) - return CAIRO_INT_STATUS_UNSUPPORTED; - - to_area = _cairo_glitz_area_get_top_scored_sub_area (area); - if (to_area) - { - if (kick_out) - { - if ((*area->root->funcs->compare_score) (to_area, - to_area->closure, - closure) >= 0) - return CAIRO_INT_STATUS_UNSUPPORTED; - } else { - return CAIRO_INT_STATUS_UNSUPPORTED; - } - } - - for (i = 0; i < 4; i++) - { - _cairo_glitz_area_destroy (area->area[i]); - area->area[i] = NULL; - } - - area->closure = NULL; - area->state = CAIRO_GLITZ_AREA_AVAILABLE; - - status = _cairo_glitz_area_find (area, width, height, - TRUE, closure); - if (status == CAIRO_STATUS_SUCCESS) - return CAIRO_STATUS_SUCCESS; - - } break; - } - - return CAIRO_INT_STATUS_UNSUPPORTED; -} - -static cairo_status_t -_cairo_glitz_root_area_init (cairo_glitz_root_area_t *root, - int max_level, - int width, - int height, - const cairo_glitz_area_funcs_t *funcs) -{ - root->max_level = max_level; - root->funcs = funcs; - - root->area = _cairo_glitz_area_create (root, 0, 0, 0, width, height); - if (!root->area) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_glitz_root_area_fini (cairo_glitz_root_area_t *root) -{ - _cairo_glitz_area_destroy (root->area); -} - -typedef struct _cairo_glitz_surface_font_private { - cairo_glitz_root_area_t root; - glitz_surface_t *surface; -} cairo_glitz_surface_font_private_t; - -typedef struct _cairo_glitz_surface_glyph_private { - cairo_glitz_area_t *area; - cairo_bool_t locked; - cairo_point_double_t p1, p2; -} cairo_glitz_surface_glyph_private_t; - -static cairo_status_t -_cairo_glitz_glyph_move_in (cairo_glitz_area_t *area, - void *closure) -{ - cairo_glitz_surface_glyph_private_t *glyph_private = closure; - - glyph_private->area = area; - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_glitz_glyph_move_out (cairo_glitz_area_t *area, - void *closure) -{ - cairo_glitz_surface_glyph_private_t *glyph_private = closure; - - glyph_private->area = NULL; -} - -static int -_cairo_glitz_glyph_compare (cairo_glitz_area_t *area, - void *closure1, - void *closure2) -{ - cairo_glitz_surface_glyph_private_t *glyph_private = closure1; - - if (glyph_private->locked) - return 1; - - return -1; -} - -static const cairo_glitz_area_funcs_t _cairo_glitz_area_funcs = { - _cairo_glitz_glyph_move_in, - _cairo_glitz_glyph_move_out, - _cairo_glitz_glyph_compare -}; - -#define GLYPH_CACHE_TEXTURE_SIZE 512 -#define GLYPH_CACHE_MAX_LEVEL 64 -#define GLYPH_CACHE_MAX_HEIGHT 96 -#define GLYPH_CACHE_MAX_WIDTH 96 - -#define WRITE_VEC2(ptr, _x, _y) \ - *(ptr)++ = (_x); \ - *(ptr)++ = (_y) - -#define WRITE_BOX(ptr, _vx1, _vy1, _vx2, _vy2, p1, p2) \ - WRITE_VEC2 (ptr, _vx1, _vy1); \ - WRITE_VEC2 (ptr, (p1)->x, (p2)->y); \ - WRITE_VEC2 (ptr, _vx2, _vy1); \ - WRITE_VEC2 (ptr, (p2)->x, (p2)->y); \ - WRITE_VEC2 (ptr, _vx2, _vy2); \ - WRITE_VEC2 (ptr, (p2)->x, (p1)->y); \ - WRITE_VEC2 (ptr, _vx1, _vy2); \ - WRITE_VEC2 (ptr, (p1)->x, (p1)->y) - -static cairo_status_t -_cairo_glitz_surface_font_init (cairo_glitz_surface_t *surface, - cairo_scaled_font_t *scaled_font, - cairo_format_t format) -{ - cairo_glitz_surface_font_private_t *font_private; - glitz_drawable_t *drawable; - glitz_format_t *surface_format = NULL; - cairo_int_status_t status; - - drawable = glitz_surface_get_drawable (surface->surface); - - switch (format) { - case CAIRO_FORMAT_A1: - case CAIRO_FORMAT_A8: - surface_format = - glitz_find_standard_format (drawable, GLITZ_STANDARD_A8); - break; - case CAIRO_FORMAT_RGB24: - ASSERT_NOT_REACHED; - break; - case CAIRO_FORMAT_ARGB32: - surface_format = - glitz_find_standard_format (drawable, GLITZ_STANDARD_ARGB32); - default: - break; - } - - if (!surface_format) - return CAIRO_INT_STATUS_UNSUPPORTED; - - font_private = malloc (sizeof (cairo_glitz_surface_font_private_t)); - if (!font_private) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - font_private->surface = glitz_surface_create (drawable, surface_format, - GLYPH_CACHE_TEXTURE_SIZE, - GLYPH_CACHE_TEXTURE_SIZE, - 0, NULL); - if (font_private->surface == NULL) - { - free (font_private); - - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - if (format == CAIRO_FORMAT_ARGB32) - glitz_surface_set_component_alpha (font_private->surface, 1); - - status = _cairo_glitz_root_area_init (&font_private->root, - GLYPH_CACHE_MAX_LEVEL, - GLYPH_CACHE_TEXTURE_SIZE, - GLYPH_CACHE_TEXTURE_SIZE, - &_cairo_glitz_area_funcs); - if (status != CAIRO_STATUS_SUCCESS) - { - glitz_surface_destroy (font_private->surface); - free (font_private); - - return status; - } - - scaled_font->surface_private = font_private; - scaled_font->surface_backend = _cairo_glitz_surface_get_backend (); - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_glitz_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font) -{ - cairo_glitz_surface_font_private_t *font_private; - - font_private = scaled_font->surface_private; - if (font_private) - { - _cairo_glitz_root_area_fini (&font_private->root); - glitz_surface_destroy (font_private->surface); - free (font_private); - } -} - -static void -_cairo_glitz_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph, - cairo_scaled_font_t *scaled_font) -{ - cairo_glitz_surface_glyph_private_t *glyph_private; - - glyph_private = scaled_glyph->surface_private; - if (glyph_private) - { - if (glyph_private->area) - _cairo_glitz_area_move_out (glyph_private->area); - - free (glyph_private); - } -} - -#define FIXED_TO_FLOAT(f) (((glitz_float_t) (f)) / 65536) - -static cairo_status_t -_cairo_glitz_surface_add_glyph (cairo_glitz_surface_t *surface, - cairo_scaled_font_t *scaled_font, - cairo_scaled_glyph_t *scaled_glyph) -{ - cairo_image_surface_t *glyph_surface = scaled_glyph->surface; - cairo_glitz_surface_font_private_t *font_private; - cairo_glitz_surface_glyph_private_t *glyph_private; - glitz_point_fixed_t p1, p2; - glitz_pixel_format_t pf; - glitz_buffer_t *buffer; - unsigned int bpp, am, rm, gm, bm; - cairo_int_status_t status; - - glyph_private = scaled_glyph->surface_private; - if (glyph_private == NULL) - { - glyph_private = malloc (sizeof (cairo_glitz_surface_glyph_private_t)); - if (!glyph_private) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - glyph_private->area = NULL; - glyph_private->locked = FALSE; - - scaled_glyph->surface_private = (void *) glyph_private; - } - - if (glyph_surface->width > GLYPH_CACHE_MAX_WIDTH || - glyph_surface->height > GLYPH_CACHE_MAX_HEIGHT) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (scaled_font->surface_private == NULL) - { - status = _cairo_glitz_surface_font_init (surface, scaled_font, - glyph_surface->format); - if (status) - return status; - } - - font_private = scaled_font->surface_private; - - if (glyph_surface->width == 0 || glyph_surface->height == 0) - { - glyph_private->area = &_empty_area; - return CAIRO_STATUS_SUCCESS; - } - - if (_cairo_glitz_area_find (font_private->root.area, - glyph_surface->width, - glyph_surface->height, - FALSE, glyph_private)) - { - if (_cairo_glitz_area_find (font_private->root.area, - glyph_surface->width, - glyph_surface->height, - TRUE, glyph_private)) - return CAIRO_STATUS_SUCCESS; - } - - buffer = glitz_buffer_create_for_data (glyph_surface->data); - if (!buffer) - { - _cairo_glitz_area_move_out (glyph_private->area); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - cairo_format_get_masks (glyph_surface->format, &bpp, &am, &rm, &gm, &bm); - - pf.fourcc = GLITZ_FOURCC_RGB; - pf.masks.bpp = bpp; - pf.masks.alpha_mask = am; - pf.masks.red_mask = rm; - pf.masks.green_mask = gm; - pf.masks.blue_mask = bm; - - pf.bytes_per_line = glyph_surface->stride; - pf.scanline_order = GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP; - pf.xoffset = 0; - pf.skip_lines = 0; - - glitz_set_pixels (font_private->surface, - glyph_private->area->x, - glyph_private->area->y, - glyph_surface->width, - glyph_surface->height, - &pf, buffer); - - glitz_buffer_destroy (buffer); - - p1.x = glyph_private->area->x << 16; - p1.y = glyph_private->area->y << 16; - p2.x = (glyph_private->area->x + glyph_surface->width) << 16; - p2.y = (glyph_private->area->y + glyph_surface->height) << 16; - - glitz_surface_translate_point (font_private->surface, &p1, &p1); - glitz_surface_translate_point (font_private->surface, &p2, &p2); - - glyph_private->p1.x = FIXED_TO_FLOAT (p1.x); - glyph_private->p1.y = FIXED_TO_FLOAT (p1.y); - glyph_private->p2.x = FIXED_TO_FLOAT (p2.x); - glyph_private->p2.y = FIXED_TO_FLOAT (p2.y); - - return CAIRO_STATUS_SUCCESS; -} - -#define N_STACK_BUF 256 - -static cairo_int_status_t -_cairo_glitz_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font, - cairo_operator_t op, - cairo_pattern_t *pattern, - void *abstract_surface, - int src_x, - int src_y, - int dst_x, - int dst_y, - unsigned int width, - unsigned int height, - cairo_glyph_t *glyphs, - int num_glyphs) -{ - cairo_glitz_surface_attributes_t attributes; - cairo_glitz_surface_glyph_private_t *glyph_private; - cairo_glitz_surface_t *dst = abstract_surface; - cairo_glitz_surface_t *src; - cairo_scaled_glyph_t *stack_scaled_glyphs[N_STACK_BUF]; - cairo_scaled_glyph_t **scaled_glyphs; - glitz_float_t stack_vertices[N_STACK_BUF * 16]; - glitz_float_t *vertices; - glitz_buffer_t *buffer; - cairo_int_status_t status; - int x_offset, y_offset; - int i, cached_glyphs = 0; - int remaining_glyps = num_glyphs; - glitz_float_t x1, y1, x2, y2; - static const glitz_vertex_format_t format = { - GLITZ_PRIMITIVE_QUADS, - GLITZ_DATA_TYPE_FLOAT, - sizeof (glitz_float_t) * 4, - GLITZ_VERTEX_ATTRIBUTE_MASK_COORD_MASK, - { 0 }, - { - GLITZ_DATA_TYPE_FLOAT, - GLITZ_COORDINATE_SIZE_XY, - sizeof (glitz_float_t) * 2, - } - }; - - if (scaled_font->surface_backend != NULL && - scaled_font->surface_backend != _cairo_glitz_surface_get_backend ()) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (op == CAIRO_OPERATOR_SATURATE) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (_glitz_ensure_target (dst->surface)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - status = _cairo_glitz_pattern_acquire_surface (pattern, dst, - src_x, src_y, - width, height, - &src, &attributes); - if (status) - return status; - - _cairo_glitz_surface_set_attributes (src, &attributes); - - if (num_glyphs > N_STACK_BUF) - { - char *data; - size_t size1, size2; - - if ((size_t)num_glyphs >= INT32_MAX / sizeof(void*) || - (size_t)num_glyphs >= INT32_MAX / sizeof(glitz_float_t) || - ((size_t)num_glyphs * sizeof(glitz_float_t)) >= INT32_MAX / 16) - goto FAIL1; - - size1 = num_glyphs * sizeof(void *); - size2 = num_glyphs * sizeof(glitz_float_t) * 16; - if (size1 >= INT32_MAX - size2) - goto FAIL1; - - data = malloc (size1 + size2); - if (!data) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - goto FAIL1; - } - - scaled_glyphs = (cairo_scaled_glyph_t **) data; - vertices = (glitz_float_t *) (data + num_glyphs * sizeof (void *)); - } - else - { - scaled_glyphs = stack_scaled_glyphs; - vertices = stack_vertices; - } - - buffer = glitz_buffer_create_for_data (vertices); - if (!buffer) - goto FAIL2; - - _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_SURFACE, - &scaled_glyphs[i]); - if (status != CAIRO_STATUS_SUCCESS) - { - num_glyphs = i; - goto UNLOCK; - } - - glyph_private = scaled_glyphs[i]->surface_private; - if (!glyph_private || !glyph_private->area) - { - status = _cairo_glitz_surface_add_glyph (dst, - scaled_font, - scaled_glyphs[i]); - if (status != CAIRO_STATUS_SUCCESS) { - num_glyphs = i; - goto UNLOCK; - } - } - glyph_private = scaled_glyphs[i]->surface_private; - if (glyph_private && glyph_private->area) - { - remaining_glyps--; - - if (glyph_private->area->width) - { - x_offset = scaled_glyphs[i]->surface->base.device_transform.x0; - y_offset = scaled_glyphs[i]->surface->base.device_transform.y0; - - x1 = _cairo_lround (glyphs[i].x - x_offset); - y1 = _cairo_lround (glyphs[i].y - y_offset); - x2 = x1 + glyph_private->area->width; - y2 = y1 + glyph_private->area->height; - - WRITE_BOX (vertices, x1, y1, x2, y2, - &glyph_private->p1, &glyph_private->p2); - - glyph_private->locked = TRUE; - - cached_glyphs++; - } - } - } - - if (remaining_glyps) - { - cairo_surface_t *image; - cairo_glitz_surface_t *clone; - - for (i = 0; i < num_glyphs; i++) - { - glyph_private = scaled_glyphs[i]->surface_private; - if (!glyph_private || !glyph_private->area) - { - int glyph_width, glyph_height; - int clone_offset_x, clone_offset_y; - - image = &scaled_glyphs[i]->surface->base; - glyph_width = scaled_glyphs[i]->surface->width; - glyph_height = scaled_glyphs[i]->surface->height; - status = - _cairo_glitz_surface_clone_similar (abstract_surface, - image, - 0, - 0, - glyph_width, - glyph_height, - &clone_offset_x, - &clone_offset_y, - (cairo_surface_t **) - &clone); - if (status) - goto UNLOCK; - - assert (clone_offset_x == 0); - assert (clone_offset_y == 0); - - x_offset = scaled_glyphs[i]->surface->base.device_transform.x0; - y_offset = scaled_glyphs[i]->surface->base.device_transform.y0; - x1 = _cairo_lround (glyphs[i].x - x_offset); - y1 = _cairo_lround (glyphs[i].y - y_offset); - - glitz_composite (_glitz_operator (op), - src->surface, - clone->surface, - dst->surface, - src_x + attributes.base.x_offset + x1, - src_y + attributes.base.y_offset + y1, - 0, 0, - x1, y1, - glyph_width, - glyph_height); - - cairo_surface_destroy (&clone->base); - - if (glitz_surface_get_status (dst->surface) == - GLITZ_STATUS_NOT_SUPPORTED) - { - status = CAIRO_INT_STATUS_UNSUPPORTED; - goto UNLOCK; - } - } - } - } - - if (cached_glyphs) - { - cairo_glitz_surface_font_private_t *font_private; - - glitz_set_geometry (dst->surface, - GLITZ_GEOMETRY_TYPE_VERTEX, - (glitz_geometry_format_t *) &format, - buffer); - - glitz_set_array (dst->surface, 0, 4, cached_glyphs * 4, 0, 0); - - font_private = scaled_font->surface_private; - - glitz_composite (_glitz_operator (op), - src->surface, - font_private->surface, - dst->surface, - src_x + attributes.base.x_offset, - src_y + attributes.base.y_offset, - 0, 0, - dst_x, dst_y, - width, height); - - glitz_set_geometry (dst->surface, - GLITZ_GEOMETRY_TYPE_NONE, - NULL, NULL); - } - -UNLOCK: - if (cached_glyphs) - { - for (i = 0; i < num_glyphs; i++) - { - glyph_private = scaled_glyphs[i]->surface_private; - if (glyph_private) - glyph_private->locked = FALSE; - } - } - - _cairo_scaled_font_thaw_cache (scaled_font); - - glitz_buffer_destroy (buffer); - - FAIL2: - if (num_glyphs > N_STACK_BUF) - free (scaled_glyphs); - - FAIL1: - if (attributes.n_params) - free (attributes.params); - - _cairo_glitz_pattern_release_surface (pattern, src, &attributes); - - if (status) - return status; - - if (glitz_surface_get_status (dst->surface) == GLITZ_STATUS_NOT_SUPPORTED) - return CAIRO_INT_STATUS_UNSUPPORTED; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_glitz_surface_flush (void *abstract_surface) -{ - cairo_glitz_surface_t *surface = abstract_surface; - - glitz_surface_flush (surface->surface); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_bool_t -_cairo_glitz_surface_is_similar (void *surface_a, - void *surface_b, - cairo_content_t content) -{ - cairo_glitz_surface_t *a = (cairo_glitz_surface_t *) surface_a; - cairo_glitz_surface_t *b = (cairo_glitz_surface_t *) surface_b; - - glitz_drawable_t *drawable_a = glitz_surface_get_drawable (a->surface); - glitz_drawable_t *drawable_b = glitz_surface_get_drawable (b->surface); - - /* XXX Disable caching of glitz surfaces by the solid pattern cache. - * Until glitz has a mechanism for releasing resources on connection - * closure, we will attempt to access invalid pointers when evicting - * old surfaces from the solid pattern cache. - */ - return FALSE; - - return drawable_a == drawable_b; -} - -static cairo_status_t -_cairo_glitz_surface_reset (void *abstract_surface) -{ - cairo_glitz_surface_t *surface = abstract_surface; - cairo_status_t status; - - status = _cairo_glitz_surface_set_clip_region (surface, NULL); - if (status) - return status; - - return CAIRO_STATUS_SUCCESS; -} - -static const cairo_surface_backend_t cairo_glitz_surface_backend = { - CAIRO_SURFACE_TYPE_GLITZ, - _cairo_glitz_surface_create_similar, - _cairo_glitz_surface_finish, - _cairo_glitz_surface_acquire_source_image, - _cairo_glitz_surface_release_source_image, - _cairo_glitz_surface_acquire_dest_image, - _cairo_glitz_surface_release_dest_image, - _cairo_glitz_surface_clone_similar, - _cairo_glitz_surface_composite, - _cairo_glitz_surface_fill_rectangles, - _cairo_glitz_surface_composite_trapezoids, - NULL, /* copy_page */ - NULL, /* show_page */ - _cairo_glitz_surface_set_clip_region, - NULL, /* intersect_clip_path */ - _cairo_glitz_surface_get_extents, - _cairo_glitz_surface_old_show_glyphs, - NULL, /* get_font_options */ - _cairo_glitz_surface_flush, - NULL, /* mark_dirty_rectangle */ - _cairo_glitz_surface_scaled_font_fini, - _cairo_glitz_surface_scaled_glyph_fini, - - NULL, /* paint */ - NULL, /* mask */ - NULL, /* stroke */ - NULL, /* fill */ - NULL, /* show_glyphs */ - - NULL, /* snapshot */ - _cairo_glitz_surface_is_similar, - - _cairo_glitz_surface_reset -}; - -static const cairo_surface_backend_t * -_cairo_glitz_surface_get_backend (void) -{ - return &cairo_glitz_surface_backend; -} - -static cairo_content_t -_glitz_format_to_content (glitz_format_t * format) -{ - assert (format->color.fourcc == GLITZ_FOURCC_RGB); - - if (format->color.alpha_size != 0) { - if (format->color.red_size != 0 && - format->color.green_size != 0 && - format->color.blue_size != 0) - return CAIRO_CONTENT_COLOR_ALPHA; - else - return CAIRO_CONTENT_ALPHA; - } - return CAIRO_CONTENT_COLOR; -} - -cairo_surface_t * -cairo_glitz_surface_create (glitz_surface_t *surface) -{ - cairo_glitz_surface_t *crsurface; - glitz_format_t *format; - - if (surface == NULL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NULL_POINTER)); - - crsurface = malloc (sizeof (cairo_glitz_surface_t)); - if (crsurface == NULL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - format = glitz_surface_get_format (surface); - _cairo_surface_init (&crsurface->base, &cairo_glitz_surface_backend, - _glitz_format_to_content(format)); - - glitz_surface_reference (surface); - - crsurface->surface = surface; - crsurface->format = format; - crsurface->has_clip = FALSE; - - return (cairo_surface_t *) crsurface; -} -slim_hidden_def (cairo_glitz_surface_create); diff --git a/uppdev/plugin/cairo/lib/cairo-glitz.h b/uppdev/plugin/cairo/lib/cairo-glitz.h deleted file mode 100644 index 08519dcbd..000000000 --- a/uppdev/plugin/cairo/lib/cairo-glitz.h +++ /dev/null @@ -1,57 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - */ - -#ifndef CAIRO_GLITZ_H -#define CAIRO_GLITZ_H - -#include "cairo.h" - -#if CAIRO_HAS_GLITZ_SURFACE - -#include - -CAIRO_BEGIN_DECLS - -cairo_public cairo_surface_t * -cairo_glitz_surface_create (glitz_surface_t *surface); - -CAIRO_END_DECLS - -#else /* CAIRO_HAS_GLITZ_SURFACE */ -# error Cairo was not compiled with support for the glitz backend -#endif /* CAIRO_HAS_GLITZ_SURFACE */ - -#endif /* CAIRO_GLITZ_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-gstate-private.h b/uppdev/plugin/cairo/lib/cairo-gstate-private.h deleted file mode 100644 index 25900482c..000000000 --- a/uppdev/plugin/cairo/lib/cairo-gstate-private.h +++ /dev/null @@ -1,71 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Carl D. Worth - */ - -#ifndef CAIRO_GSTATE_PRIVATE_H -#define CAIRO_GSTATE_PRIVATE_H - -#include "cairo-clip-private.h" - -struct _cairo_gstate { - cairo_operator_t op; - - double tolerance; - cairo_antialias_t antialias; - - cairo_stroke_style_t stroke_style; - - cairo_fill_rule_t fill_rule; - - cairo_font_face_t *font_face; - cairo_scaled_font_t *scaled_font; /* Specific to the current CTM */ - cairo_matrix_t font_matrix; - cairo_font_options_t font_options; - - cairo_clip_t clip; - - cairo_surface_t *target; /* The target to which all rendering is directed */ - cairo_surface_t *parent_target; /* The previous target which was receiving rendering */ - cairo_surface_t *original_target; /* The original target the initial gstate was created with */ - - cairo_matrix_t ctm; - cairo_matrix_t ctm_inverse; - cairo_matrix_t source_ctm_inverse; /* At the time ->source was set */ - - cairo_pattern_t *source; - - struct _cairo_gstate *next; -}; - -#endif /* CAIRO_GSTATE_PRIVATE_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-gstate.c b/uppdev/plugin/cairo/lib/cairo-gstate.c deleted file mode 100644 index fe8d2792f..000000000 --- a/uppdev/plugin/cairo/lib/cairo-gstate.c +++ /dev/null @@ -1,1858 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - */ - -#define _GNU_SOURCE - -#include "cairoint.h" - -#include "cairo-clip-private.h" -#include "cairo-gstate-private.h" - -#if _XOPEN_SOURCE >= 600 || defined (_ISOC99_SOURCE) -#define ISFINITE(x) isfinite (x) -#else -#define ISFINITE(x) ((x) * (x) >= 0.) /* check for NaNs */ -#endif - -static cairo_status_t -_cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other); - -static cairo_status_t -_cairo_gstate_ensure_font_face (cairo_gstate_t *gstate); - -static cairo_status_t -_cairo_gstate_ensure_scaled_font (cairo_gstate_t *gstate); - -static void -_cairo_gstate_unset_scaled_font (cairo_gstate_t *gstate); - -static cairo_status_t -_cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate, - const cairo_glyph_t *glyphs, - int num_glyphs, - cairo_glyph_t *transformed_glyphs, - int *num_transformed_glyphs); - -cairo_status_t -_cairo_gstate_init (cairo_gstate_t *gstate, - cairo_surface_t *target) -{ - cairo_status_t status; - - gstate->next = NULL; - - gstate->op = CAIRO_GSTATE_OPERATOR_DEFAULT; - - gstate->tolerance = CAIRO_GSTATE_TOLERANCE_DEFAULT; - gstate->antialias = CAIRO_ANTIALIAS_DEFAULT; - - _cairo_stroke_style_init (&gstate->stroke_style); - - gstate->fill_rule = CAIRO_GSTATE_FILL_RULE_DEFAULT; - - gstate->font_face = NULL; - gstate->scaled_font = NULL; - - cairo_matrix_init_scale (&gstate->font_matrix, - CAIRO_GSTATE_DEFAULT_FONT_SIZE, - CAIRO_GSTATE_DEFAULT_FONT_SIZE); - - _cairo_font_options_init_default (&gstate->font_options); - - _cairo_clip_init (&gstate->clip, target); - - gstate->target = cairo_surface_reference (target); - gstate->parent_target = NULL; - gstate->original_target = cairo_surface_reference (target); - - cairo_matrix_init_identity (&gstate->ctm); - gstate->ctm_inverse = gstate->ctm; - gstate->source_ctm_inverse = gstate->ctm; - - gstate->source = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK, - CAIRO_CONTENT_COLOR); - - /* Now that the gstate is fully initialized and ready for the eventual - * _cairo_gstate_fini(), we can check for errors (and not worry about - * the resource deallocation). */ - - if (target == NULL) - return _cairo_error (CAIRO_STATUS_NULL_POINTER); - - status = target->status; - if (status) - return status; - - status = gstate->source->status; - if (status) - return status; - - return CAIRO_STATUS_SUCCESS; -} - -/** - * _cairo_gstate_init_copy: - * - * Initialize @gstate by performing a deep copy of state fields from - * @other. Note that gstate->next is not copied but is set to %NULL by - * this function. - **/ -static cairo_status_t -_cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other) -{ - cairo_status_t status; - - gstate->op = other->op; - - gstate->tolerance = other->tolerance; - gstate->antialias = other->antialias; - - status = _cairo_stroke_style_init_copy (&gstate->stroke_style, - &other->stroke_style); - if (status) - return status; - - gstate->fill_rule = other->fill_rule; - - gstate->font_face = cairo_font_face_reference (other->font_face); - gstate->scaled_font = cairo_scaled_font_reference (other->scaled_font); - - gstate->font_matrix = other->font_matrix; - - _cairo_font_options_init_copy (&gstate->font_options , &other->font_options); - - status = _cairo_clip_init_copy (&gstate->clip, &other->clip); - if (status) { - _cairo_stroke_style_fini (&gstate->stroke_style); - cairo_font_face_destroy (gstate->font_face); - cairo_scaled_font_destroy (gstate->scaled_font); - return status; - } - - gstate->target = cairo_surface_reference (other->target); - /* parent_target is always set to NULL; it's only ever set by redirect_target */ - gstate->parent_target = NULL; - gstate->original_target = cairo_surface_reference (other->original_target); - - gstate->ctm = other->ctm; - gstate->ctm_inverse = other->ctm_inverse; - gstate->source_ctm_inverse = other->source_ctm_inverse; - - gstate->source = cairo_pattern_reference (other->source); - - gstate->next = NULL; - - return CAIRO_STATUS_SUCCESS; -} - -void -_cairo_gstate_fini (cairo_gstate_t *gstate) -{ - _cairo_stroke_style_fini (&gstate->stroke_style); - - cairo_font_face_destroy (gstate->font_face); - gstate->font_face = NULL; - - cairo_scaled_font_destroy (gstate->scaled_font); - gstate->scaled_font = NULL; - - _cairo_clip_reset (&gstate->clip); - - cairo_surface_destroy (gstate->target); - gstate->target = NULL; - - cairo_surface_destroy (gstate->parent_target); - gstate->parent_target = NULL; - - cairo_surface_destroy (gstate->original_target); - gstate->original_target = NULL; - - cairo_pattern_destroy (gstate->source); - gstate->source = NULL; -} - -/** - * _cairo_gstate_save: - * @gstate: input/output gstate pointer - * - * Makes a copy of the current state of @gstate and saves it - * to @gstate->next, then put the address of the newly allcated - * copy into @gstate. _cairo_gstate_restore() reverses this. - **/ -cairo_status_t -_cairo_gstate_save (cairo_gstate_t **gstate, cairo_gstate_t **freelist) -{ - cairo_gstate_t *top; - cairo_status_t status; - - top = *freelist; - if (top == NULL) { - top = malloc (sizeof (cairo_gstate_t)); - if (top == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } else - *freelist = top->next; - - status = _cairo_gstate_init_copy (top, *gstate); - if (status) { - top->next = *freelist; - *freelist = top; - return status; - } - - top->next = *gstate; - *gstate = top; - - return CAIRO_STATUS_SUCCESS; -} - -/** - * _cairo_gstate_restore: - * @gstate: input/output gstate pointer - * - * Reverses the effects of one _cairo_gstate_save() call. - **/ -cairo_status_t -_cairo_gstate_restore (cairo_gstate_t **gstate, cairo_gstate_t **freelist) -{ - cairo_gstate_t *top; - - top = *gstate; - if (top->next == NULL) - return _cairo_error (CAIRO_STATUS_INVALID_RESTORE); - - *gstate = top->next; - - _cairo_gstate_fini (top); - top->next = *freelist; - *freelist = top; - - return CAIRO_STATUS_SUCCESS; -} - -/** - * _cairo_gstate_redirect_target: - * @gstate: a #cairo_gstate_t - * @child: the new child target - * - * Redirect @gstate rendering to a "child" target. The original - * "parent" target with which the gstate was created will not be - * affected. See _cairo_gstate_get_target(). - * - * Unless the redirected target has the same device offsets as the - * original #cairo_t target, the clip will be INVALID after this call, - * and the caller should either recreate or reset the clip. - **/ -cairo_status_t -_cairo_gstate_redirect_target (cairo_gstate_t *gstate, cairo_surface_t *child) -{ - cairo_status_t status; - - /* If this gstate is already redirected, this is an error; we need a - * new gstate to be able to redirect */ - assert (gstate->parent_target == NULL); - - /* Set up our new parent_target based on our current target; - * gstate->parent_target will take the ref that is held by gstate->target - */ - cairo_surface_destroy (gstate->parent_target); - gstate->parent_target = gstate->target; - - /* Now set up our new target; we overwrite gstate->target directly, - * since its ref is now owned by gstate->parent_target */ - gstate->target = cairo_surface_reference (child); - - _cairo_clip_reset (&gstate->clip); - status = _cairo_clip_init_deep_copy (&gstate->clip, &gstate->next->clip, child); - if (status) - return status; - - /* The clip is in surface backend coordinates for the previous target; - * translate it into the child's backend coordinates. */ - _cairo_clip_translate (&gstate->clip, - _cairo_fixed_from_double (child->device_transform.x0 - gstate->parent_target->device_transform.x0), - _cairo_fixed_from_double (child->device_transform.y0 - gstate->parent_target->device_transform.y0)); - - return CAIRO_STATUS_SUCCESS; -} - -/** - * _cairo_gstate_is_redirected - * @gstate: a #cairo_gstate_t - * - * This space left intentionally blank. - * - * Return value: %TRUE if the gstate is redirected to a target - * different than the original, %FALSE otherwise. - **/ -cairo_bool_t -_cairo_gstate_is_redirected (cairo_gstate_t *gstate) -{ - return (gstate->target != gstate->original_target); -} - -/** - * _cairo_gstate_get_target: - * @gstate: a #cairo_gstate_t - * - * Return the current drawing target; if drawing is not redirected, - * this will be the same as _cairo_gstate_get_original_target(). - * - * Return value: the current target surface - **/ -cairo_surface_t * -_cairo_gstate_get_target (cairo_gstate_t *gstate) -{ - return gstate->target; -} - -/** - * _cairo_gstate_get_parent_target: - * @gstate: a #cairo_gstate_t - * - * Return the parent surface of the current drawing target surface; - * if this particular gstate isn't a redirect gstate, this will return %NULL. - **/ -cairo_surface_t * -_cairo_gstate_get_parent_target (cairo_gstate_t *gstate) -{ - return gstate->parent_target; -} - -/** - * _cairo_gstate_get_original_target: - * @gstate: a #cairo_gstate_t - * - * Return the original target with which @gstate was created. This - * function always returns the original target independent of any - * child target that may have been set with - * _cairo_gstate_redirect_target. - * - * Return value: the original target surface - **/ -cairo_surface_t * -_cairo_gstate_get_original_target (cairo_gstate_t *gstate) -{ - return gstate->original_target; -} - -/** - * _cairo_gstate_get_clip: - * @gstate: a #cairo_gstate_t - * - * This space left intentionally blank. - * - * Return value: a pointer to the gstate's #cairo_clip_t structure. - */ -cairo_clip_t * -_cairo_gstate_get_clip (cairo_gstate_t *gstate) -{ - return &gstate->clip; -} - -cairo_status_t -_cairo_gstate_set_source (cairo_gstate_t *gstate, - cairo_pattern_t *source) -{ - if (source->status) - return source->status; - - source = cairo_pattern_reference (source); - cairo_pattern_destroy (gstate->source); - gstate->source = source; - gstate->source_ctm_inverse = gstate->ctm_inverse; - - return CAIRO_STATUS_SUCCESS; -} - -cairo_pattern_t * -_cairo_gstate_get_source (cairo_gstate_t *gstate) -{ - return gstate->source; -} - -cairo_status_t -_cairo_gstate_set_operator (cairo_gstate_t *gstate, cairo_operator_t op) -{ - gstate->op = op; - - return CAIRO_STATUS_SUCCESS; -} - -cairo_operator_t -_cairo_gstate_get_operator (cairo_gstate_t *gstate) -{ - return gstate->op; -} - -cairo_status_t -_cairo_gstate_set_tolerance (cairo_gstate_t *gstate, double tolerance) -{ - gstate->tolerance = tolerance; - - return CAIRO_STATUS_SUCCESS; -} - -double -_cairo_gstate_get_tolerance (cairo_gstate_t *gstate) -{ - return gstate->tolerance; -} - -cairo_status_t -_cairo_gstate_set_fill_rule (cairo_gstate_t *gstate, cairo_fill_rule_t fill_rule) -{ - gstate->fill_rule = fill_rule; - - return CAIRO_STATUS_SUCCESS; -} - -cairo_fill_rule_t -_cairo_gstate_get_fill_rule (cairo_gstate_t *gstate) -{ - return gstate->fill_rule; -} - -cairo_status_t -_cairo_gstate_set_line_width (cairo_gstate_t *gstate, double width) -{ - gstate->stroke_style.line_width = width; - - return CAIRO_STATUS_SUCCESS; -} - -double -_cairo_gstate_get_line_width (cairo_gstate_t *gstate) -{ - return gstate->stroke_style.line_width; -} - -cairo_status_t -_cairo_gstate_set_line_cap (cairo_gstate_t *gstate, cairo_line_cap_t line_cap) -{ - gstate->stroke_style.line_cap = line_cap; - - return CAIRO_STATUS_SUCCESS; -} - -cairo_line_cap_t -_cairo_gstate_get_line_cap (cairo_gstate_t *gstate) -{ - return gstate->stroke_style.line_cap; -} - -cairo_status_t -_cairo_gstate_set_line_join (cairo_gstate_t *gstate, cairo_line_join_t line_join) -{ - gstate->stroke_style.line_join = line_join; - - return CAIRO_STATUS_SUCCESS; -} - -cairo_line_join_t -_cairo_gstate_get_line_join (cairo_gstate_t *gstate) -{ - return gstate->stroke_style.line_join; -} - -cairo_status_t -_cairo_gstate_set_dash (cairo_gstate_t *gstate, const double *dash, int num_dashes, double offset) -{ - unsigned int i; - double dash_total; - - if (gstate->stroke_style.dash) - free (gstate->stroke_style.dash); - - gstate->stroke_style.num_dashes = num_dashes; - - if (gstate->stroke_style.num_dashes == 0) { - gstate->stroke_style.dash = NULL; - gstate->stroke_style.dash_offset = 0.0; - return CAIRO_STATUS_SUCCESS; - } - - gstate->stroke_style.dash = _cairo_malloc_ab (gstate->stroke_style.num_dashes, sizeof (double)); - if (gstate->stroke_style.dash == NULL) { - gstate->stroke_style.num_dashes = 0; - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - memcpy (gstate->stroke_style.dash, dash, gstate->stroke_style.num_dashes * sizeof (double)); - - dash_total = 0.0; - for (i = 0; i < gstate->stroke_style.num_dashes; i++) { - if (gstate->stroke_style.dash[i] < 0) - return _cairo_error (CAIRO_STATUS_INVALID_DASH); - dash_total += gstate->stroke_style.dash[i]; - } - - if (dash_total == 0.0) - return _cairo_error (CAIRO_STATUS_INVALID_DASH); - - /* A single dash value indicate symmetric repeating, so the total - * is twice as long. */ - if (gstate->stroke_style.num_dashes == 1) - dash_total *= 2; - - /* The dashing code doesn't like a negative offset, so we compute - * the equivalent positive offset. */ - if (offset < 0) - offset += ceil (-offset / dash_total + 0.5) * dash_total; - - gstate->stroke_style.dash_offset = offset; - - return CAIRO_STATUS_SUCCESS; -} - -void -_cairo_gstate_get_dash (cairo_gstate_t *gstate, - double *dashes, - int *num_dashes, - double *offset) -{ - if (dashes) - memcpy (dashes, - gstate->stroke_style.dash, - sizeof (double) * gstate->stroke_style.num_dashes); - - if (num_dashes) - *num_dashes = gstate->stroke_style.num_dashes; - - if (offset) - *offset = gstate->stroke_style.dash_offset; -} - -cairo_status_t -_cairo_gstate_set_miter_limit (cairo_gstate_t *gstate, double limit) -{ - gstate->stroke_style.miter_limit = limit; - - return CAIRO_STATUS_SUCCESS; -} - -double -_cairo_gstate_get_miter_limit (cairo_gstate_t *gstate) -{ - return gstate->stroke_style.miter_limit; -} - -void -_cairo_gstate_get_matrix (cairo_gstate_t *gstate, cairo_matrix_t *matrix) -{ - *matrix = gstate->ctm; -} - -cairo_status_t -_cairo_gstate_translate (cairo_gstate_t *gstate, double tx, double ty) -{ - cairo_matrix_t tmp; - - if (! ISFINITE (tx) || ! ISFINITE (ty)) - return _cairo_error (CAIRO_STATUS_INVALID_MATRIX); - - _cairo_gstate_unset_scaled_font (gstate); - - cairo_matrix_init_translate (&tmp, tx, ty); - cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm); - - /* paranoid check against gradual numerical instability */ - if (! _cairo_matrix_is_invertible (&gstate->ctm)) - return _cairo_error (CAIRO_STATUS_INVALID_MATRIX); - - cairo_matrix_init_translate (&tmp, -tx, -ty); - cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp); - - return CAIRO_STATUS_SUCCESS; -} - -cairo_status_t -_cairo_gstate_scale (cairo_gstate_t *gstate, double sx, double sy) -{ - cairo_matrix_t tmp; - - if (sx * sy == 0.) /* either sx or sy is 0, or det == 0 due to underflow */ - return _cairo_error (CAIRO_STATUS_INVALID_MATRIX); - if (! ISFINITE (sx) || ! ISFINITE (sy)) - return _cairo_error (CAIRO_STATUS_INVALID_MATRIX); - - _cairo_gstate_unset_scaled_font (gstate); - - cairo_matrix_init_scale (&tmp, sx, sy); - cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm); - - /* paranoid check against gradual numerical instability */ - if (! _cairo_matrix_is_invertible (&gstate->ctm)) - return _cairo_error (CAIRO_STATUS_INVALID_MATRIX); - - cairo_matrix_init_scale (&tmp, 1/sx, 1/sy); - cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp); - - return CAIRO_STATUS_SUCCESS; -} - -cairo_status_t -_cairo_gstate_rotate (cairo_gstate_t *gstate, double angle) -{ - cairo_matrix_t tmp; - - if (angle == 0.) - return CAIRO_STATUS_SUCCESS; - - if (! ISFINITE (angle)) - return _cairo_error (CAIRO_STATUS_INVALID_MATRIX); - - _cairo_gstate_unset_scaled_font (gstate); - - cairo_matrix_init_rotate (&tmp, angle); - cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm); - - /* paranoid check against gradual numerical instability */ - if (! _cairo_matrix_is_invertible (&gstate->ctm)) - return _cairo_error (CAIRO_STATUS_INVALID_MATRIX); - - cairo_matrix_init_rotate (&tmp, -angle); - cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp); - - return CAIRO_STATUS_SUCCESS; -} - -cairo_status_t -_cairo_gstate_transform (cairo_gstate_t *gstate, - const cairo_matrix_t *matrix) -{ - cairo_matrix_t tmp; - cairo_status_t status; - - if (_cairo_matrix_is_identity (matrix)) - return CAIRO_STATUS_SUCCESS; - - tmp = *matrix; - status = cairo_matrix_invert (&tmp); - if (status) - return status; - - _cairo_gstate_unset_scaled_font (gstate); - - cairo_matrix_multiply (&gstate->ctm, matrix, &gstate->ctm); - cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp); - - /* paranoid check against gradual numerical instability */ - if (! _cairo_matrix_is_invertible (&gstate->ctm)) - return _cairo_error (CAIRO_STATUS_INVALID_MATRIX); - - return CAIRO_STATUS_SUCCESS; -} - -cairo_status_t -_cairo_gstate_set_matrix (cairo_gstate_t *gstate, - const cairo_matrix_t *matrix) -{ - cairo_status_t status; - - if (memcmp (matrix, &gstate->ctm, sizeof (cairo_matrix_t)) == 0) - return CAIRO_STATUS_SUCCESS; - - if (! _cairo_matrix_is_invertible (matrix)) - return _cairo_error (CAIRO_STATUS_INVALID_MATRIX); - - _cairo_gstate_unset_scaled_font (gstate); - - gstate->ctm = *matrix; - gstate->ctm_inverse = *matrix; - status = cairo_matrix_invert (&gstate->ctm_inverse); - assert (status == CAIRO_STATUS_SUCCESS); - - return CAIRO_STATUS_SUCCESS; -} - -void -_cairo_gstate_identity_matrix (cairo_gstate_t *gstate) -{ - if (_cairo_matrix_is_identity (&gstate->ctm)) - return; - - _cairo_gstate_unset_scaled_font (gstate); - - cairo_matrix_init_identity (&gstate->ctm); - cairo_matrix_init_identity (&gstate->ctm_inverse); -} - -void -_cairo_gstate_user_to_device (cairo_gstate_t *gstate, double *x, double *y) -{ - cairo_matrix_transform_point (&gstate->ctm, x, y); -} - -void -_cairo_gstate_user_to_device_distance (cairo_gstate_t *gstate, - double *dx, double *dy) -{ - cairo_matrix_transform_distance (&gstate->ctm, dx, dy); -} - -void -_cairo_gstate_device_to_user (cairo_gstate_t *gstate, double *x, double *y) -{ - cairo_matrix_transform_point (&gstate->ctm_inverse, x, y); -} - -void -_cairo_gstate_device_to_user_distance (cairo_gstate_t *gstate, - double *dx, double *dy) -{ - cairo_matrix_transform_distance (&gstate->ctm_inverse, dx, dy); -} - -void -_cairo_gstate_user_to_backend (cairo_gstate_t *gstate, double *x, double *y) -{ - cairo_matrix_transform_point (&gstate->ctm, x, y); - cairo_matrix_transform_point (&gstate->target->device_transform, x, y); -} - -void -_cairo_gstate_backend_to_user (cairo_gstate_t *gstate, double *x, double *y) -{ - cairo_matrix_transform_point (&gstate->target->device_transform_inverse, x, y); - cairo_matrix_transform_point (&gstate->ctm_inverse, x, y); -} - -void -_cairo_gstate_backend_to_user_rectangle (cairo_gstate_t *gstate, - double *x1, double *y1, - double *x2, double *y2, - cairo_bool_t *is_tight) -{ - cairo_matrix_t matrix_inverse; - - cairo_matrix_multiply (&matrix_inverse, - &gstate->target->device_transform_inverse, - &gstate->ctm_inverse); - _cairo_matrix_transform_bounding_box (&matrix_inverse, - x1, y1, x2, y2, is_tight); -} - -/* XXX: NYI -cairo_status_t -_cairo_gstate_stroke_to_path (cairo_gstate_t *gstate) -{ - cairo_status_t status; - - _cairo_pen_init (&gstate); - return CAIRO_STATUS_SUCCESS; -} -*/ - -cairo_status_t -_cairo_gstate_path_extents (cairo_gstate_t *gstate, - cairo_path_fixed_t *path, - double *x1, double *y1, - double *x2, double *y2) -{ - cairo_status_t status; - double px1, py1, px2, py2; - - status = _cairo_path_fixed_bounds (path, - &px1, &py1, &px2, &py2, - gstate->tolerance); - if (status) - return status; - - _cairo_gstate_backend_to_user_rectangle (gstate, - &px1, &py1, &px2, &py2, - NULL); - if (x1) - *x1 = px1; - if (y1) - *y1 = py1; - if (x2) - *x2 = px2; - if (y2) - *y2 = py2; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_gstate_copy_transformed_pattern (cairo_gstate_t *gstate, - cairo_pattern_t *pattern, - cairo_pattern_t *original, - cairo_matrix_t *ctm_inverse) -{ - cairo_surface_pattern_t *surface_pattern; - cairo_surface_t *surface; - cairo_status_t status; - - status = _cairo_pattern_init_copy (pattern, original); - if (status) - return status; - - /* apply device_transform first so that it is transformed by ctm_inverse */ - if (cairo_pattern_get_type (original) == CAIRO_PATTERN_TYPE_SURFACE) { - surface_pattern = (cairo_surface_pattern_t *) original; - surface = surface_pattern->surface; - if (_cairo_surface_has_device_transform (surface)) - _cairo_pattern_transform (pattern, &surface->device_transform); - } - - _cairo_pattern_transform (pattern, ctm_inverse); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_gstate_copy_transformed_source (cairo_gstate_t *gstate, - cairo_pattern_t *pattern) -{ - return _cairo_gstate_copy_transformed_pattern (gstate, pattern, - gstate->source, - &gstate->source_ctm_inverse); -} - -static cairo_status_t -_cairo_gstate_copy_transformed_mask (cairo_gstate_t *gstate, - cairo_pattern_t *pattern, - cairo_pattern_t *mask) -{ - return _cairo_gstate_copy_transformed_pattern (gstate, pattern, - mask, - &gstate->ctm_inverse); -} - -cairo_status_t -_cairo_gstate_paint (cairo_gstate_t *gstate) -{ - cairo_status_t status; - cairo_pattern_union_t pattern; - - if (gstate->source->status) - return gstate->source->status; - - status = _cairo_surface_set_clip (gstate->target, &gstate->clip); - if (status) - return status; - - status = _cairo_gstate_copy_transformed_source (gstate, &pattern.base); - if (status) - return status; - - status = _cairo_surface_paint (gstate->target, - gstate->op, - &pattern.base); - - _cairo_pattern_fini (&pattern.base); - - return status; -} - -cairo_status_t -_cairo_gstate_mask (cairo_gstate_t *gstate, - cairo_pattern_t *mask) -{ - cairo_status_t status; - cairo_pattern_union_t source_pattern, mask_pattern; - - if (mask->status) - return mask->status; - - if (gstate->source->status) - return gstate->source->status; - - status = _cairo_surface_set_clip (gstate->target, &gstate->clip); - if (status) - return status; - - status = _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base); - if (status) - return status; - - status = _cairo_gstate_copy_transformed_mask (gstate, &mask_pattern.base, mask); - if (status) - goto CLEANUP_SOURCE; - - status = _cairo_surface_mask (gstate->target, - gstate->op, - &source_pattern.base, - &mask_pattern.base); - - _cairo_pattern_fini (&mask_pattern.base); -CLEANUP_SOURCE: - _cairo_pattern_fini (&source_pattern.base); - - return status; -} - -cairo_status_t -_cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path) -{ - cairo_status_t status; - cairo_pattern_union_t source_pattern; - - if (gstate->source->status) - return gstate->source->status; - - if (gstate->stroke_style.line_width <= 0.0) - return CAIRO_STATUS_SUCCESS; - - status = _cairo_surface_set_clip (gstate->target, &gstate->clip); - if (status) - return status; - - status = _cairo_gstate_copy_transformed_source (gstate, - &source_pattern.base); - if (status) - return status; - - status = _cairo_surface_stroke (gstate->target, - gstate->op, - &source_pattern.base, - path, - &gstate->stroke_style, - &gstate->ctm, - &gstate->ctm_inverse, - gstate->tolerance, - gstate->antialias); - - _cairo_pattern_fini (&source_pattern.base); - - return status; - -} - -cairo_status_t -_cairo_gstate_in_stroke (cairo_gstate_t *gstate, - cairo_path_fixed_t *path, - double x, - double y, - cairo_bool_t *inside_ret) -{ - cairo_status_t status; - cairo_box_t limit; - cairo_traps_t traps; - - if (gstate->stroke_style.line_width <= 0.0) { - *inside_ret = FALSE; - return CAIRO_STATUS_SUCCESS; - } - - _cairo_gstate_user_to_backend (gstate, &x, &y); - - limit.p1.x = _cairo_fixed_from_double (x) - 1; - limit.p1.y = _cairo_fixed_from_double (y) - 1; - limit.p2.x = limit.p1.x + 2; - limit.p2.y = limit.p1.y + 2; - - _cairo_traps_init (&traps); - _cairo_traps_limit (&traps, &limit); - - status = _cairo_path_fixed_stroke_to_traps (path, - &gstate->stroke_style, - &gstate->ctm, - &gstate->ctm_inverse, - gstate->tolerance, - &traps); - if (status) - goto BAIL; - - *inside_ret = _cairo_traps_contain (&traps, x, y); - -BAIL: - _cairo_traps_fini (&traps); - - return status; -} - -cairo_status_t -_cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path) -{ - cairo_status_t status; - cairo_pattern_union_t pattern; - - if (gstate->source->status) - return gstate->source->status; - - status = _cairo_surface_set_clip (gstate->target, &gstate->clip); - if (status) - return status; - - status = _cairo_gstate_copy_transformed_source (gstate, &pattern.base); - if (status) - return status; - - status = _cairo_surface_fill (gstate->target, - gstate->op, - &pattern.base, - path, - gstate->fill_rule, - gstate->tolerance, - gstate->antialias); - - _cairo_pattern_fini (&pattern.base); - - return status; -} - -cairo_status_t -_cairo_gstate_in_fill (cairo_gstate_t *gstate, - cairo_path_fixed_t *path, - double x, - double y, - cairo_bool_t *inside_ret) -{ - cairo_status_t status; - cairo_box_t limit; - cairo_traps_t traps; - - _cairo_gstate_user_to_backend (gstate, &x, &y); - - limit.p1.x = _cairo_fixed_from_double (x) - 1; - limit.p1.y = _cairo_fixed_from_double (y) - 1; - limit.p2.x = limit.p1.x + 2; - limit.p2.y = limit.p1.y + 2; - - _cairo_traps_init (&traps); - _cairo_traps_limit (&traps, &limit); - - status = _cairo_path_fixed_fill_to_traps (path, - gstate->fill_rule, - gstate->tolerance, - &traps); - if (status) - goto BAIL; - - *inside_ret = _cairo_traps_contain (&traps, x, y); - -BAIL: - _cairo_traps_fini (&traps); - - return status; -} - -cairo_status_t -_cairo_gstate_copy_page (cairo_gstate_t *gstate) -{ - cairo_surface_copy_page (gstate->target); - return cairo_surface_status (gstate->target); -} - -cairo_status_t -_cairo_gstate_show_page (cairo_gstate_t *gstate) -{ - cairo_surface_show_page (gstate->target); - return cairo_surface_status (gstate->target); -} - -static void -_cairo_gstate_traps_extents_to_user_rectangle (cairo_gstate_t *gstate, - cairo_traps_t *traps, - double *x1, double *y1, - double *x2, double *y2) -{ - cairo_box_t extents; - - if (traps->num_traps == 0) { - /* no traps, so we actually won't draw anything */ - if (x1) - *x1 = 0.0; - if (y1) - *y1 = 0.0; - if (x2) - *x2 = 0.0; - if (y2) - *y2 = 0.0; - } else { - double px1, py1, px2, py2; - - _cairo_traps_extents (traps, &extents); - - px1 = _cairo_fixed_to_double (extents.p1.x); - py1 = _cairo_fixed_to_double (extents.p1.y); - px2 = _cairo_fixed_to_double (extents.p2.x); - py2 = _cairo_fixed_to_double (extents.p2.y); - - _cairo_gstate_backend_to_user_rectangle (gstate, - &px1, &py1, &px2, &py2, - NULL); - if (x1) - *x1 = px1; - if (y1) - *y1 = py1; - if (x2) - *x2 = px2; - if (y2) - *y2 = py2; - } -} - -cairo_status_t -_cairo_gstate_stroke_extents (cairo_gstate_t *gstate, - cairo_path_fixed_t *path, - double *x1, double *y1, - double *x2, double *y2) -{ - cairo_status_t status; - cairo_traps_t traps; - - if (gstate->stroke_style.line_width <= 0.0) { - if (x1) - *x1 = 0.0; - if (y1) - *y1 = 0.0; - if (x2) - *x2 = 0.0; - if (y2) - *y2 = 0.0; - return CAIRO_STATUS_SUCCESS; - } - - _cairo_traps_init (&traps); - - status = _cairo_path_fixed_stroke_to_traps (path, - &gstate->stroke_style, - &gstate->ctm, - &gstate->ctm_inverse, - gstate->tolerance, - &traps); - if (status == CAIRO_STATUS_SUCCESS) { - _cairo_gstate_traps_extents_to_user_rectangle (gstate, &traps, - x1, y1, x2, y2); - } - - _cairo_traps_fini (&traps); - - return status; -} - -cairo_status_t -_cairo_gstate_fill_extents (cairo_gstate_t *gstate, - cairo_path_fixed_t *path, - double *x1, double *y1, - double *x2, double *y2) -{ - cairo_status_t status; - cairo_traps_t traps; - - _cairo_traps_init (&traps); - - status = _cairo_path_fixed_fill_to_traps (path, - gstate->fill_rule, - gstate->tolerance, - &traps); - if (status == CAIRO_STATUS_SUCCESS) { - _cairo_gstate_traps_extents_to_user_rectangle (gstate, &traps, - x1, y1, x2, y2); - } - - _cairo_traps_fini (&traps); - - return status; -} - -cairo_status_t -_cairo_gstate_reset_clip (cairo_gstate_t *gstate) -{ - _cairo_clip_reset (&gstate->clip); - - return CAIRO_STATUS_SUCCESS; -} - -cairo_status_t -_cairo_gstate_clip (cairo_gstate_t *gstate, cairo_path_fixed_t *path) -{ - return _cairo_clip_clip (&gstate->clip, - path, gstate->fill_rule, gstate->tolerance, - gstate->antialias, gstate->target); -} - -static cairo_status_t -_cairo_gstate_int_clip_extents (cairo_gstate_t *gstate, - cairo_rectangle_int_t *extents) -{ - cairo_status_t status; - - status = _cairo_surface_get_extents (gstate->target, extents); - if (status) - return status; - - status = _cairo_clip_intersect_to_rectangle (&gstate->clip, extents); - - return status; -} - -cairo_status_t -_cairo_gstate_clip_extents (cairo_gstate_t *gstate, - double *x1, - double *y1, - double *x2, - double *y2) -{ - cairo_rectangle_int_t extents; - double px1, py1, px2, py2; - cairo_status_t status; - - status = _cairo_gstate_int_clip_extents (gstate, &extents); - if (status) - return status; - - px1 = extents.x; - py1 = extents.y; - px2 = extents.x + (int) extents.width; - py2 = extents.y + (int) extents.height; - - _cairo_gstate_backend_to_user_rectangle (gstate, - &px1, &py1, &px2, &py2, - NULL); - - if (x1) - *x1 = px1; - if (y1) - *y1 = py1; - if (x2) - *x2 = px2; - if (y2) - *y2 = py2; - - return CAIRO_STATUS_SUCCESS; -} - -cairo_rectangle_list_t* -_cairo_gstate_copy_clip_rectangle_list (cairo_gstate_t *gstate) -{ - return _cairo_clip_copy_rectangle_list (&gstate->clip, gstate); -} - -static void -_cairo_gstate_unset_scaled_font (cairo_gstate_t *gstate) -{ - if (gstate->scaled_font) { - cairo_scaled_font_destroy (gstate->scaled_font); - gstate->scaled_font = NULL; - } -} - -cairo_status_t -_cairo_gstate_select_font_face (cairo_gstate_t *gstate, - const char *family, - cairo_font_slant_t slant, - cairo_font_weight_t weight) -{ - cairo_font_face_t *font_face; - cairo_status_t status; - - font_face = cairo_toy_font_face_create (family, slant, weight); - if (font_face->status) - return font_face->status; - - status = _cairo_gstate_set_font_face (gstate, font_face); - cairo_font_face_destroy (font_face); - - return status; -} - -cairo_status_t -_cairo_gstate_set_font_size (cairo_gstate_t *gstate, - double size) -{ - _cairo_gstate_unset_scaled_font (gstate); - - cairo_matrix_init_scale (&gstate->font_matrix, size, size); - - return CAIRO_STATUS_SUCCESS; -} - -cairo_status_t -_cairo_gstate_set_font_matrix (cairo_gstate_t *gstate, - const cairo_matrix_t *matrix) -{ - if (memcmp (matrix, &gstate->font_matrix, sizeof (cairo_matrix_t)) == 0) - return CAIRO_STATUS_SUCCESS; - - if (! _cairo_matrix_is_invertible (matrix)) - return _cairo_error (CAIRO_STATUS_INVALID_MATRIX); - - _cairo_gstate_unset_scaled_font (gstate); - - gstate->font_matrix = *matrix; - - return CAIRO_STATUS_SUCCESS; -} - -void -_cairo_gstate_get_font_matrix (cairo_gstate_t *gstate, - cairo_matrix_t *matrix) -{ - *matrix = gstate->font_matrix; -} - -void -_cairo_gstate_set_font_options (cairo_gstate_t *gstate, - const cairo_font_options_t *options) -{ - if (memcmp (options, &gstate->font_options, sizeof (cairo_font_options_t)) == 0) - return; - - _cairo_gstate_unset_scaled_font (gstate); - - _cairo_font_options_init_copy (&gstate->font_options, options); -} - -void -_cairo_gstate_get_font_options (cairo_gstate_t *gstate, - cairo_font_options_t *options) -{ - *options = gstate->font_options; -} - -cairo_status_t -_cairo_gstate_get_font_face (cairo_gstate_t *gstate, - cairo_font_face_t **font_face) -{ - cairo_status_t status; - - status = _cairo_gstate_ensure_font_face (gstate); - if (status) - return status; - - *font_face = gstate->font_face; - - return CAIRO_STATUS_SUCCESS; -} - -cairo_status_t -_cairo_gstate_get_scaled_font (cairo_gstate_t *gstate, - cairo_scaled_font_t **scaled_font) -{ - cairo_status_t status; - - status = _cairo_gstate_ensure_scaled_font (gstate); - if (status) - return status; - - *scaled_font = gstate->scaled_font; - - return CAIRO_STATUS_SUCCESS; -} - -/* - * Like everything else in this file, fonts involve Too Many Coordinate Spaces; - * it is easy to get confused about what's going on. - * - * The user's view - * --------------- - * - * Users ask for things in user space. When cairo starts, a user space unit - * is about 1/96 inch, which is similar to (but importantly different from) - * the normal "point" units most users think in terms of. When a user - * selects a font, its scale is set to "one user unit". The user can then - * independently scale the user coordinate system *or* the font matrix, in - * order to adjust the rendered size of the font. - * - * Metrics are returned in user space, whether they are obtained from - * the currently selected font in a #cairo_t or from a #cairo_scaled_font_t - * which is a font specialized to a particular scale matrix, CTM, and target - * surface. - * - * The font's view - * --------------- - * - * Fonts are designed and stored (in say .ttf files) in "font space", which - * describes an "EM Square" (a design tile) and has some abstract number - * such as 1000, 1024, or 2048 units per "EM". This is basically an - * uninteresting space for us, but we need to remember that it exists. - * - * Font resources (from libraries or operating systems) render themselves - * to a particular device. Since they do not want to make most programmers - * worry about the font design space, the scaling API is simplified to - * involve just telling the font the required pixel size of the EM square - * (that is, in device space). - * - * - * Cairo's gstate view - * ------------------- - * - * In addition to the CTM and CTM inverse, we keep a matrix in the gstate - * called the "font matrix" which describes the user's most recent - * font-scaling or font-transforming request. This is kept in terms of an - * abstract scale factor, composed with the CTM and used to set the font's - * pixel size. So if the user asks to "scale the font by 12", the matrix - * is: - * - * [ 12.0, 0.0, 0.0, 12.0, 0.0, 0.0 ] - * - * It is an affine matrix, like all cairo matrices, where its tx and ty - * components are used to "nudging" fonts around and are handled in gstate - * and then ignored by the "scaled-font" layer. - * - * In order to perform any action on a font, we must build an object - * called a #cairo_font_scale_t; this contains the central 2x2 matrix - * resulting from "font matrix * CTM" (sans the font matrix translation - * components as stated in the previous paragraph). - * - * We pass this to the font when making requests of it, which causes it to - * reply for a particular [user request, device] combination, under the CTM - * (to accommodate the "zoom in" == "bigger fonts" issue above). - * - * The other terms in our communication with the font are therefore in - * device space. When we ask it to perform text->glyph conversion, it will - * produce a glyph string in device space. Glyph vectors we pass to it for - * measuring or rendering should be in device space. The metrics which we - * get back from the font will be in device space. The contents of the - * global glyph image cache will be in device space. - * - * - * Cairo's public view - * ------------------- - * - * Since the values entering and leaving via public API calls are in user - * space, the gstate functions typically need to multiply arguments by the - * CTM (for user-input glyph vectors), and return values by the CTM inverse - * (for font responses such as metrics or glyph vectors). - * - */ - -static cairo_status_t -_cairo_gstate_ensure_font_face (cairo_gstate_t *gstate) -{ - cairo_font_face_t *font_face; - - if (gstate->font_face != NULL) - return gstate->font_face->status; - - - font_face = cairo_toy_font_face_create (CAIRO_FONT_FAMILY_DEFAULT, - CAIRO_FONT_SLANT_DEFAULT, - CAIRO_FONT_WEIGHT_DEFAULT); - if (font_face->status) - return font_face->status; - - gstate->font_face = font_face; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_gstate_ensure_scaled_font (cairo_gstate_t *gstate) -{ - cairo_status_t status; - cairo_font_options_t options; - cairo_scaled_font_t *scaled_font; - - if (gstate->scaled_font != NULL) - return gstate->scaled_font->status; - - status = _cairo_gstate_ensure_font_face (gstate); - if (status) - return status; - - cairo_surface_get_font_options (gstate->target, &options); - cairo_font_options_merge (&options, &gstate->font_options); - - scaled_font = cairo_scaled_font_create (gstate->font_face, - &gstate->font_matrix, - &gstate->ctm, - &options); - - status = cairo_scaled_font_status (scaled_font); - if (status) - return status; - - gstate->scaled_font = scaled_font; - - return CAIRO_STATUS_SUCCESS; -} - -cairo_status_t -_cairo_gstate_get_font_extents (cairo_gstate_t *gstate, - cairo_font_extents_t *extents) -{ - cairo_status_t status = _cairo_gstate_ensure_scaled_font (gstate); - if (status) - return status; - - cairo_scaled_font_extents (gstate->scaled_font, extents); - - return cairo_scaled_font_status (gstate->scaled_font); -} - -cairo_status_t -_cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate, - double x, - double y, - const char *utf8, - int utf8_len, - cairo_glyph_t **glyphs, - int *num_glyphs, - cairo_text_cluster_t **clusters, - int *num_clusters, - cairo_text_cluster_flags_t *cluster_flags) -{ - cairo_status_t status; - - status = _cairo_gstate_ensure_scaled_font (gstate); - if (status) - return status; - - return cairo_scaled_font_text_to_glyphs (gstate->scaled_font, x, y, - utf8, utf8_len, - glyphs, num_glyphs, - clusters, num_clusters, - cluster_flags); -} - -cairo_status_t -_cairo_gstate_set_font_face (cairo_gstate_t *gstate, - cairo_font_face_t *font_face) -{ - if (font_face && font_face->status) - return font_face->status; - - if (font_face == gstate->font_face) - return CAIRO_STATUS_SUCCESS; - - cairo_font_face_destroy (gstate->font_face); - gstate->font_face = cairo_font_face_reference (font_face); - - _cairo_gstate_unset_scaled_font (gstate); - - return CAIRO_STATUS_SUCCESS; -} - -cairo_status_t -_cairo_gstate_glyph_extents (cairo_gstate_t *gstate, - const cairo_glyph_t *glyphs, - int num_glyphs, - cairo_text_extents_t *extents) -{ - cairo_status_t status; - - status = _cairo_gstate_ensure_scaled_font (gstate); - if (status) - return status; - - cairo_scaled_font_glyph_extents (gstate->scaled_font, - glyphs, num_glyphs, - extents); - - return cairo_scaled_font_status (gstate->scaled_font); -} - -cairo_status_t -_cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate, - const char *utf8, - int utf8_len, - const cairo_glyph_t *glyphs, - int num_glyphs, - const cairo_text_cluster_t *clusters, - int num_clusters, - cairo_text_cluster_flags_t cluster_flags) -{ - cairo_status_t status; - cairo_pattern_union_t source_pattern; - cairo_glyph_t *transformed_glyphs; - cairo_glyph_t stack_transformed_glyphs[CAIRO_STACK_ARRAY_LENGTH (cairo_glyph_t)]; - - if (gstate->source->status) - return gstate->source->status; - - status = _cairo_surface_set_clip (gstate->target, &gstate->clip); - if (status) - return status; - - status = _cairo_gstate_ensure_scaled_font (gstate); - if (status) - return status; - - if (num_glyphs <= ARRAY_LENGTH (stack_transformed_glyphs)) { - transformed_glyphs = stack_transformed_glyphs; - } else { - transformed_glyphs = cairo_glyph_allocate (num_glyphs); - if (transformed_glyphs == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - status = _cairo_gstate_transform_glyphs_to_backend (gstate, - glyphs, num_glyphs, - transformed_glyphs, - &num_glyphs); - - if (status || num_glyphs == 0) - goto CLEANUP_GLYPHS; - - status = _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base); - if (status) - goto CLEANUP_GLYPHS; - - /* Just in case */ - if (!clusters) - num_clusters = 0; - - /* For really huge font sizes, we can just do path;fill instead of - * show_glyphs, as show_glyphs would put excess pressure on the cache, - * and moreover, not all components below us correctly handle huge font - * sizes. I wanted to set the limit at 256. But alas, seems like cairo's - * rasterizer is something like ten times slower than freetype's for huge - * sizes. So, no win just yet. For now, do it for insanely-huge sizes, - * just to make sure we don't make anyone unhappy. When we get a really - * fast rasterizer in cairo, we may want to readjust this. - * - * Needless to say, do this only if show_text_glyphs is not available. */ - if (cairo_surface_has_show_text_glyphs (gstate->target) || - _cairo_scaled_font_get_max_scale (gstate->scaled_font) <= 10240) { - status = _cairo_surface_show_text_glyphs (gstate->target, - gstate->op, - &source_pattern.base, - utf8, utf8_len, - transformed_glyphs, num_glyphs, - clusters, num_clusters, - cluster_flags, - gstate->scaled_font); - } else { - cairo_path_fixed_t path; - - _cairo_path_fixed_init (&path); - - status = _cairo_scaled_font_glyph_path (gstate->scaled_font, - transformed_glyphs, num_glyphs, - &path); - - if (status == CAIRO_STATUS_SUCCESS) - status = _cairo_surface_fill (gstate->target, - gstate->op, - &source_pattern.base, - &path, - CAIRO_FILL_RULE_WINDING, - gstate->tolerance, - gstate->scaled_font->options.antialias); - - _cairo_path_fixed_fini (&path); - } - - _cairo_pattern_fini (&source_pattern.base); - -CLEANUP_GLYPHS: - if (transformed_glyphs != stack_transformed_glyphs) - cairo_glyph_free (transformed_glyphs); - - return status; -} - -cairo_status_t -_cairo_gstate_glyph_path (cairo_gstate_t *gstate, - const cairo_glyph_t *glyphs, - int num_glyphs, - cairo_path_fixed_t *path) -{ - cairo_status_t status; - cairo_glyph_t *transformed_glyphs; - cairo_glyph_t stack_transformed_glyphs[CAIRO_STACK_ARRAY_LENGTH (cairo_glyph_t)]; - - status = _cairo_gstate_ensure_scaled_font (gstate); - if (status) - return status; - - if (num_glyphs < ARRAY_LENGTH (stack_transformed_glyphs)) - transformed_glyphs = stack_transformed_glyphs; - else - transformed_glyphs = cairo_glyph_allocate (num_glyphs); - if (transformed_glyphs == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - status = _cairo_gstate_transform_glyphs_to_backend (gstate, - glyphs, num_glyphs, - transformed_glyphs, - NULL); - if (status) - goto CLEANUP_GLYPHS; - - status = _cairo_scaled_font_glyph_path (gstate->scaled_font, - transformed_glyphs, num_glyphs, - path); - - CLEANUP_GLYPHS: - if (transformed_glyphs != stack_transformed_glyphs) - cairo_glyph_free (transformed_glyphs); - - return status; -} - -cairo_status_t -_cairo_gstate_set_antialias (cairo_gstate_t *gstate, - cairo_antialias_t antialias) -{ - gstate->antialias = antialias; - - return CAIRO_STATUS_SUCCESS; -} - -cairo_antialias_t -_cairo_gstate_get_antialias (cairo_gstate_t *gstate) -{ - return gstate->antialias; -} - -/** - * _cairo_gstate_transform_glyphs_to_backend: - * @gstate: a #cairo_gstate_t - * @glyphs: the array of #cairo_glyph_t objects to be transformed - * @num_glyphs: the number of elements in @glyphs - * @transformed_glyphs: a pre-allocated array of at least @num_glyphs - * #cairo_glyph_t objects - * @num_transformed_glyphs: the number of elements in @transformed_glyphs - * after dropping out of bounds glyphs, or %NULL if glyphs shouldn't be - * dropped - * - * Transform an array of glyphs to backend space by first adding the offset - * of the font matrix, then transforming from user space to backend space. - * The result of the transformation is placed in @transformed_glyphs. - * - * This also uses information from the scaled font and the surface to - * cull/drop glyphs that will not be visible. - **/ -static cairo_status_t -_cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate, - const cairo_glyph_t *glyphs, - int num_glyphs, - cairo_glyph_t *transformed_glyphs, - int *num_transformed_glyphs) -{ - int i, j; - cairo_matrix_t *ctm = &gstate->ctm; - cairo_matrix_t *font_matrix = &gstate->font_matrix; - cairo_matrix_t *device_transform = &gstate->target->device_transform; - cairo_bool_t drop = FALSE; - double x1 = 0, x2 = 0, y1 = 0, y2 = 0; - cairo_status_t status; - - if (num_transformed_glyphs != NULL) { - cairo_rectangle_int_t surface_extents; - double scale = _cairo_scaled_font_get_max_scale (gstate->scaled_font); - - drop = TRUE; - status = _cairo_gstate_int_clip_extents (gstate, &surface_extents); - if (_cairo_status_is_error (status)) - return status; - - if (status == CAIRO_INT_STATUS_UNSUPPORTED) { - drop = FALSE; /* unbounded surface */ - } else { - if (surface_extents.width == 0 || surface_extents.height == 0) { - /* No visible area. Don't draw anything */ - *num_transformed_glyphs = 0; - return CAIRO_STATUS_SUCCESS; - } - /* XXX We currently drop any glyphs that has its position outside - * of the surface boundaries by a safety margin depending on the - * font scale. This however can fail in extreme cases where the - * font has really long swashes for example... We can correctly - * handle that by looking the glyph up and using its device bbox - * to device if it's going to be visible, but I'm not inclined to - * do that now. - */ - x1 = surface_extents.x - 2*scale; - y1 = surface_extents.y - 2*scale; - x2 = surface_extents.x + (int) surface_extents.width + scale; - y2 = surface_extents.y + (int) surface_extents.height + scale; - } - - if (!drop) - *num_transformed_glyphs = num_glyphs; - } else - num_transformed_glyphs = &j; - -#define KEEP_GLYPH(glyph) (x1 <= glyph.x && glyph.x <= x2 && y1 <= glyph.y && glyph.y <= y2) - - if (_cairo_matrix_is_identity (ctm) && - _cairo_matrix_is_identity (device_transform) && - font_matrix->x0 == 0 && font_matrix->y0 == 0) - { - if (!drop) - memcpy (transformed_glyphs, glyphs, num_glyphs * sizeof (cairo_glyph_t)); - else { - for (j = 0, i = 0; i < num_glyphs; i++) - { - transformed_glyphs[j].index = glyphs[i].index; - transformed_glyphs[j].x = glyphs[i].x; - transformed_glyphs[j].y = glyphs[i].y; - if (KEEP_GLYPH (transformed_glyphs[j])) - j++; - } - *num_transformed_glyphs = j; - } - } - else if (_cairo_matrix_is_translation (ctm) && - _cairo_matrix_is_translation (device_transform)) - { - double tx = font_matrix->x0 + ctm->x0 + device_transform->x0; - double ty = font_matrix->y0 + ctm->y0 + device_transform->y0; - - for (j = 0, i = 0; i < num_glyphs; i++) - { - transformed_glyphs[j].index = glyphs[i].index; - transformed_glyphs[j].x = glyphs[i].x + tx; - transformed_glyphs[j].y = glyphs[i].y + ty; - if (!drop || KEEP_GLYPH (transformed_glyphs[j])) - j++; - } - *num_transformed_glyphs = j; - } - else - { - cairo_matrix_t aggregate_transform; - - cairo_matrix_init_translate (&aggregate_transform, - gstate->font_matrix.x0, - gstate->font_matrix.y0); - cairo_matrix_multiply (&aggregate_transform, - &aggregate_transform, ctm); - cairo_matrix_multiply (&aggregate_transform, - &aggregate_transform, device_transform); - - for (j = 0, i = 0; i < num_glyphs; i++) - { - transformed_glyphs[j] = glyphs[i]; - cairo_matrix_transform_point (&aggregate_transform, - &transformed_glyphs[j].x, - &transformed_glyphs[j].y); - if (!drop || KEEP_GLYPH (transformed_glyphs[j])) - j++; - } - *num_transformed_glyphs = j; - } - - return CAIRO_STATUS_SUCCESS; -} diff --git a/uppdev/plugin/cairo/lib/cairo-hash-private.h b/uppdev/plugin/cairo/lib/cairo-hash-private.h deleted file mode 100644 index 9101f2ed7..000000000 --- a/uppdev/plugin/cairo/lib/cairo-hash-private.h +++ /dev/null @@ -1,88 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2004 Red Hat, Inc. - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Keith Packard - * Graydon Hoare - * Carl Worth - */ - -#ifndef CAIRO_HASH_PRIVATE_H -#define CAIRO_HASH_PRIVATE_H - -#include "cairo-compiler-private.h" -#include "cairo-types-private.h" - -/* XXX: I'd like this file to be self-contained in terms of - * includeability, but that's not really possible with the current - * monolithic cairoint.h. So, for now, just include cairoint.h instead - * if you want to include this file. */ - -typedef cairo_bool_t -(*cairo_hash_keys_equal_func_t) (const void *key_a, const void *key_b); - -typedef cairo_bool_t -(*cairo_hash_predicate_func_t) (void *entry); - -typedef void -(*cairo_hash_callback_func_t) (void *entry, - void *closure); - -cairo_private cairo_hash_table_t * -_cairo_hash_table_create (cairo_hash_keys_equal_func_t keys_equal); - -cairo_private void -_cairo_hash_table_destroy (cairo_hash_table_t *hash_table); - -cairo_private cairo_bool_t -_cairo_hash_table_lookup (cairo_hash_table_t *hash_table, - cairo_hash_entry_t *key, - cairo_hash_entry_t **entry_return); - -cairo_private void * -_cairo_hash_table_random_entry (cairo_hash_table_t *hash_table, - cairo_hash_predicate_func_t predicate); - -cairo_private cairo_status_t -_cairo_hash_table_insert (cairo_hash_table_t *hash_table, - cairo_hash_entry_t *entry); - -cairo_private void -_cairo_hash_table_remove (cairo_hash_table_t *hash_table, - cairo_hash_entry_t *key); - -cairo_private void -_cairo_hash_table_foreach (cairo_hash_table_t *hash_table, - cairo_hash_callback_func_t hash_callback, - void *closure); - -#endif diff --git a/uppdev/plugin/cairo/lib/cairo-hash.c b/uppdev/plugin/cairo/lib/cairo-hash.c deleted file mode 100644 index 2317eb17d..000000000 --- a/uppdev/plugin/cairo/lib/cairo-hash.c +++ /dev/null @@ -1,576 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2004 Red Hat, Inc. - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Keith Packard - * Graydon Hoare - * Carl Worth - */ - -#include "cairoint.h" - -/* - * An entry can be in one of three states: - * - * FREE: Entry has never been used, terminates all searches. - * Appears in the table as a %NULL pointer. - * - * DEAD: Entry had been live in the past. A dead entry can be reused - * but does not terminate a search for an exact entry. - * Appears in the table as a pointer to DEAD_ENTRY. - * - * LIVE: Entry is currently being used. - * Appears in the table as any non-%NULL, non-DEAD_ENTRY pointer. - */ - -static cairo_hash_entry_t dead_entry = { 0 }; -#define DEAD_ENTRY (&dead_entry) - -#define ENTRY_IS_FREE(entry) ((entry) == NULL) -#define ENTRY_IS_DEAD(entry) ((entry) == DEAD_ENTRY) -#define ENTRY_IS_LIVE(entry) ((entry) && ! ENTRY_IS_DEAD(entry)) - -/* We expect keys will not be destroyed frequently, so our table does not - * contain any explicit shrinking code nor any chain-coalescing code for - * entries randomly deleted by memory pressure (except during rehashing, of - * course). These assumptions are potentially bad, but they make the - * implementation straightforward. - * - * Revisit later if evidence appears that we're using excessive memory from - * a mostly-dead table. - * - * This table is open-addressed with double hashing. Each table size is a - * prime chosen to be a little more than double the high water mark for a - * given arrangement, so the tables should remain < 50% full. The table - * size makes for the "first" hash modulus; a second prime (2 less than the - * first prime) serves as the "second" hash modulus, which is co-prime and - * thus guarantees a complete permutation of table indices. - * - * This structure, and accompanying table, is borrowed/modified from the - * file xserver/render/glyph.c in the freedesktop.org x server, with - * permission (and suggested modification of doubling sizes) by Keith - * Packard. - */ - -typedef struct _cairo_hash_table_arrangement { - unsigned long high_water_mark; - unsigned long size; - unsigned long rehash; -} cairo_hash_table_arrangement_t; - -static const cairo_hash_table_arrangement_t hash_table_arrangements [] = { - { 16, 43, 41 }, - { 32, 73, 71 }, - { 64, 151, 149 }, - { 128, 283, 281 }, - { 256, 571, 569 }, - { 512, 1153, 1151 }, - { 1024, 2269, 2267 }, - { 2048, 4519, 4517 }, - { 4096, 9013, 9011 }, - { 8192, 18043, 18041 }, - { 16384, 36109, 36107 }, - { 32768, 72091, 72089 }, - { 65536, 144409, 144407 }, - { 131072, 288361, 288359 }, - { 262144, 576883, 576881 }, - { 524288, 1153459, 1153457 }, - { 1048576, 2307163, 2307161 }, - { 2097152, 4613893, 4613891 }, - { 4194304, 9227641, 9227639 }, - { 8388608, 18455029, 18455027 }, - { 16777216, 36911011, 36911009 }, - { 33554432, 73819861, 73819859 }, - { 67108864, 147639589, 147639587 }, - { 134217728, 295279081, 295279079 }, - { 268435456, 590559793, 590559791 } -}; - -#define NUM_HASH_TABLE_ARRANGEMENTS ARRAY_LENGTH (hash_table_arrangements) - -struct _cairo_hash_table { - cairo_hash_keys_equal_func_t keys_equal; - - const cairo_hash_table_arrangement_t *arrangement; - cairo_hash_entry_t **entries; - - unsigned long live_entries; - unsigned long iterating; /* Iterating, no insert, no resize */ -}; - -/** - * _cairo_hash_table_create: - * @keys_equal: a function to return %TRUE if two keys are equal - * - * Creates a new hash table which will use the keys_equal() function - * to compare hash keys. Data is provided to the hash table in the - * form of user-derived versions of #cairo_hash_entry_t. A hash entry - * must be able to hold both a key (including a hash code) and a - * value. Sometimes only the key will be necessary, (as in - * _cairo_hash_table_remove), and other times both a key and a value - * will be necessary, (as in _cairo_hash_table_insert). - * - * See #cairo_hash_entry_t for more details. - * - * Return value: the new hash table or %NULL if out of memory. - **/ -cairo_hash_table_t * -_cairo_hash_table_create (cairo_hash_keys_equal_func_t keys_equal) -{ - cairo_hash_table_t *hash_table; - - hash_table = malloc (sizeof (cairo_hash_table_t)); - if (hash_table == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return NULL; - } - - hash_table->keys_equal = keys_equal; - - hash_table->arrangement = &hash_table_arrangements[0]; - - hash_table->entries = calloc (hash_table->arrangement->size, - sizeof(cairo_hash_entry_t *)); - if (hash_table->entries == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - free (hash_table); - return NULL; - } - - hash_table->live_entries = 0; - hash_table->iterating = 0; - - return hash_table; -} - -/** - * _cairo_hash_table_destroy: - * @hash_table: an empty hash table to destroy - * - * Immediately destroys the given hash table, freeing all resources - * associated with it. - * - * WARNING: The hash_table must have no live entries in it before - * _cairo_hash_table_destroy is called. It is a fatal error otherwise, - * and this function will halt. The rationale for this behavior is to - * avoid memory leaks and to avoid needless complication of the API - * with destroy notifiy callbacks. - * - * WARNING: The hash_table must have no running iterators in it when - * _cairo_hash_table_destroy is called. It is a fatal error otherwise, - * and this function will halt. - **/ -void -_cairo_hash_table_destroy (cairo_hash_table_t *hash_table) -{ - if (hash_table == NULL) - return; - - /* The hash table must be empty. Otherwise, halt. */ - assert (hash_table->live_entries == 0); - /* No iterators can be running. Otherwise, halt. */ - assert (hash_table->iterating == 0); - - free (hash_table->entries); - hash_table->entries = NULL; - - free (hash_table); -} - -/** - * _cairo_hash_table_lookup_internal: - * - * @hash_table: a #cairo_hash_table_t to search - * @key: the key to search on - * @hash_code: the hash_code for @key - * @key_unique: If %TRUE, then caller asserts that no key already - * exists that will compare equal to #key, so search can be - * optimized. If unsure, set to %FALSE and the code will always work. - * - * Search the hashtable for a live entry for which - * hash_table->keys_equal returns true. If no such entry exists then - * return the first available (free or dead entry). - * - * If the key_unique flag is set, then the search will never call - * hash_table->keys_equal and will act as if it always returned - * false. This is useful as a performance optimization in special - * circumstances where the caller knows that there is no existing - * entry in the hash table with a matching key. - * - * Return value: The matching entry in the hash table (if - * any). Otherwise, the first available entry. The caller should check - * entry->state to check whether a match was found or not. - **/ -static cairo_hash_entry_t ** -_cairo_hash_table_lookup_internal (cairo_hash_table_t *hash_table, - cairo_hash_entry_t *key, - cairo_bool_t key_is_unique) -{ - cairo_hash_entry_t **entry, **first_available = NULL; - unsigned long table_size, i, idx, step; - - table_size = hash_table->arrangement->size; - - idx = key->hash % table_size; - step = 0; - - for (i = 0; i < table_size; ++i) - { - entry = &hash_table->entries[idx]; - - if (ENTRY_IS_FREE(*entry)) - { - return entry; - } - else if (ENTRY_IS_DEAD(*entry)) - { - if (key_is_unique) { - return entry; - } else { - if (! first_available) - first_available = entry; - } - } - else /* ENTRY_IS_LIVE(*entry) */ - { - if (! key_is_unique) - if (hash_table->keys_equal (key, *entry)) - return entry; - } - - if (step == 0) { - step = key->hash % hash_table->arrangement->rehash; - if (step == 0) - step = 1; - } - - idx += step; - if (idx >= table_size) - idx -= table_size; - } - - /* - * The table should not have permitted you to get here if you were just - * looking for a free slot: there should have been room. - */ - assert (key_is_unique == 0); - - return first_available; -} - -/** - * _cairo_hash_table_resize: - * @hash_table: a hash table - * - * Resize the hash table if the number of entries has gotten much - * bigger or smaller than the ideal number of entries for the current - * size. - * - * Return value: %CAIRO_STATUS_SUCCESS if successful or - * %CAIRO_STATUS_NO_MEMORY if out of memory. - **/ -static cairo_status_t -_cairo_hash_table_resize (cairo_hash_table_t *hash_table) -{ - cairo_hash_table_t tmp; - cairo_hash_entry_t **entry; - unsigned long new_size, i; - - /* This keeps the hash table between 25% and 50% full. */ - unsigned long high = hash_table->arrangement->high_water_mark; - unsigned long low = high >> 2; - - if (hash_table->live_entries >= low && hash_table->live_entries <= high) - return CAIRO_STATUS_SUCCESS; - - tmp = *hash_table; - - if (hash_table->live_entries > high) - { - tmp.arrangement = hash_table->arrangement + 1; - /* This code is being abused if we can't make a table big enough. */ - assert (tmp.arrangement - hash_table_arrangements < - NUM_HASH_TABLE_ARRANGEMENTS); - } - else /* hash_table->live_entries < low */ - { - /* Can't shrink if we're at the smallest size */ - if (hash_table->arrangement == &hash_table_arrangements[0]) - return CAIRO_STATUS_SUCCESS; - tmp.arrangement = hash_table->arrangement - 1; - } - - new_size = tmp.arrangement->size; - tmp.entries = calloc (new_size, sizeof (cairo_hash_entry_t*)); - if (tmp.entries == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - for (i = 0; i < hash_table->arrangement->size; ++i) { - if (ENTRY_IS_LIVE (hash_table->entries[i])) { - entry = _cairo_hash_table_lookup_internal (&tmp, - hash_table->entries[i], - TRUE); - assert (ENTRY_IS_FREE(*entry)); - *entry = hash_table->entries[i]; - } - } - - free (hash_table->entries); - hash_table->entries = tmp.entries; - hash_table->arrangement = tmp.arrangement; - - return CAIRO_STATUS_SUCCESS; -} - -/** - * _cairo_hash_table_lookup: - * @hash_table: a hash table - * @key: the key of interest - * @entry_return: pointer for return value. - * - * Performs a lookup in @hash_table looking for an entry which has a - * key that matches @key, (as determined by the keys_equal() function - * passed to _cairo_hash_table_create). - * - * Return value: %TRUE if there is an entry in the hash table that - * matches the given key, (which will now be in *entry_return). %FALSE - * otherwise, (in which case *entry_return will be %NULL). - **/ -cairo_bool_t -_cairo_hash_table_lookup (cairo_hash_table_t *hash_table, - cairo_hash_entry_t *key, - cairo_hash_entry_t **entry_return) -{ - cairo_hash_entry_t **entry; - - /* See if we have an entry in the table already. */ - entry = _cairo_hash_table_lookup_internal (hash_table, key, FALSE); - if (ENTRY_IS_LIVE(*entry)) { - *entry_return = *entry; - return TRUE; - } - - *entry_return = NULL; - return FALSE; -} - -/** - * _cairo_hash_table_random_entry: - * @hash_table: a hash table - * @predicate: a predicate function, or %NULL for any entry. - * - * Find a random entry in the hash table satisfying the given - * @predicate. A %NULL @predicate is taken as equivalent to a function - * which always returns %TRUE, (eg. any entry in the table will do). - * - * We use the same algorithm as the lookup algorithm to walk over the - * entries in the hash table in a pseudo-random order. Walking - * linearly would favor entries following gaps in the hash table. We - * could also call rand() repeatedly, which works well for almost-full - * tables, but degrades when the table is almost empty, or predicate - * returns %TRUE for most entries. - * - * Return value: a random live entry or %NULL if there are no entries - * that match the given predicate. In particular, if predicate is - * %NULL, a %NULL return value indicates that the table is empty. - **/ -void * -_cairo_hash_table_random_entry (cairo_hash_table_t *hash_table, - cairo_hash_predicate_func_t predicate) -{ - cairo_hash_entry_t **entry; - unsigned long hash; - unsigned long table_size, i, idx, step; - - table_size = hash_table->arrangement->size; - - hash = rand (); - idx = hash % table_size; - step = 0; - - for (i = 0; i < table_size; ++i) - { - entry = &hash_table->entries[idx]; - - if (ENTRY_IS_LIVE (*entry) && - (predicate == NULL || predicate (*entry))) - { - return *entry; - } - - if (step == 0) { - step = hash % hash_table->arrangement->rehash; - if (step == 0) - step = 1; - } - - idx += step; - if (idx >= table_size) - idx -= table_size; - } - - return NULL; -} - -/** - * _cairo_hash_table_insert: - * @hash_table: a hash table - * @key_and_value: an entry to be inserted - * - * Insert the entry #key_and_value into the hash table. - * - * WARNING: It is a fatal error if an entry exists in the hash table - * with a matching key, (this function will halt). - * - * WARNING: It is a fatal error to insert an element while - * an iterator is running - * - * Instead of using insert to replace an entry, consider just editing - * the entry obtained with _cairo_hash_table_lookup. Or if absolutely - * necessary, use _cairo_hash_table_remove first. - * - * Return value: %CAIRO_STATUS_SUCCESS if successful or - * %CAIRO_STATUS_NO_MEMORY if insufficient memory is available. - **/ -cairo_status_t -_cairo_hash_table_insert (cairo_hash_table_t *hash_table, - cairo_hash_entry_t *key_and_value) -{ - cairo_status_t status; - cairo_hash_entry_t **entry; - - /* Insert is illegal while an iterator is running. */ - assert (hash_table->iterating == 0); - - entry = _cairo_hash_table_lookup_internal (hash_table, - key_and_value, FALSE); - - if (ENTRY_IS_LIVE(*entry)) - { - /* User is being bad, let's crash. */ - ASSERT_NOT_REACHED; - } - - *entry = key_and_value; - hash_table->live_entries++; - - status = _cairo_hash_table_resize (hash_table); - if (status) { - /* abort the insert... */ - *entry = DEAD_ENTRY; - hash_table->live_entries--; - return status; - } - - return CAIRO_STATUS_SUCCESS; -} - -/** - * _cairo_hash_table_remove: - * @hash_table: a hash table - * @key: key of entry to be removed - * - * Remove an entry from the hash table which has a key that matches - * @key, if any (as determined by the keys_equal() function passed to - * _cairo_hash_table_create). - * - * Return value: %CAIRO_STATUS_SUCCESS if successful or - * %CAIRO_STATUS_NO_MEMORY if out of memory. - **/ -void -_cairo_hash_table_remove (cairo_hash_table_t *hash_table, - cairo_hash_entry_t *key) -{ - cairo_hash_entry_t **entry; - - entry = _cairo_hash_table_lookup_internal (hash_table, key, FALSE); - if (! ENTRY_IS_LIVE(*entry)) - return; - - *entry = DEAD_ENTRY; - hash_table->live_entries--; - - /* Check for table resize. Don't do this when iterating as this will - * reorder elements of the table and cause the iteration to potentially - * skip some elements. */ - if (hash_table->iterating == 0) { - /* This call _can_ fail, but only in failing to allocate new - * memory to shrink the hash table. It does leave the table in a - * consistent state, and we've already succeeded in removing the - * entry, so we don't examine the failure status of this call. */ - _cairo_hash_table_resize (hash_table); - } -} - -/** - * _cairo_hash_table_foreach: - * @hash_table: a hash table - * @hash_callback: function to be called for each live entry - * @closure: additional argument to be passed to @hash_callback - * - * Call @hash_callback for each live entry in the hash table, in a - * non-specified order. - * - * Entries in @hash_table may be removed by code executed from @hash_callback. - * - * Entries may not be inserted to @hash_table, nor may @hash_table - * be destroyed by code executed from @hash_callback. The relevant - * functions will halt in these cases. - **/ -void -_cairo_hash_table_foreach (cairo_hash_table_t *hash_table, - cairo_hash_callback_func_t hash_callback, - void *closure) -{ - unsigned long i; - cairo_hash_entry_t *entry; - - if (hash_table == NULL) - return; - - /* Mark the table for iteration */ - ++hash_table->iterating; - for (i = 0; i < hash_table->arrangement->size; i++) { - entry = hash_table->entries[i]; - if (ENTRY_IS_LIVE(entry)) - hash_callback (entry, closure); - } - /* If some elements were deleted during the iteration, - * the table may need resizing. Just do this every time - * as the check is inexpensive. - */ - if (--hash_table->iterating == 0) { - /* Should we fail to shrink the hash table, it is left unaltered, - * and we don't need to propagate the error status. */ - _cairo_hash_table_resize (hash_table); - } -} diff --git a/uppdev/plugin/cairo/lib/cairo-hull.c b/uppdev/plugin/cairo/lib/cairo-hull.c deleted file mode 100644 index 008ba7fda..000000000 --- a/uppdev/plugin/cairo/lib/cairo-hull.c +++ /dev/null @@ -1,222 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2003 University of Southern California - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - */ - -#include "cairoint.h" - -typedef struct cairo_hull { - cairo_point_t point; - cairo_slope_t slope; - int discard; - int id; -} cairo_hull_t; - -static void -_cairo_hull_init (cairo_hull_t *hull, - cairo_pen_vertex_t *vertices, - int num_vertices) -{ - cairo_point_t *p, *extremum, tmp; - int i; - - extremum = &vertices[0].point; - for (i = 1; i < num_vertices; i++) { - p = &vertices[i].point; - if (p->y < extremum->y || (p->y == extremum->y && p->x < extremum->x)) - extremum = p; - } - /* Put the extremal point at the beginning of the array */ - tmp = *extremum; - *extremum = vertices[0].point; - vertices[0].point = tmp; - - for (i = 0; i < num_vertices; i++) { - hull[i].point = vertices[i].point; - _cairo_slope_init (&hull[i].slope, &hull[0].point, &hull[i].point); - - /* give each point a unique id for later comparison */ - hull[i].id = i; - - /* Don't discard by default */ - hull[i].discard = 0; - - /* Discard all points coincident with the extremal point */ - if (i != 0 && hull[i].slope.dx == 0 && hull[i].slope.dy == 0) - hull[i].discard = 1; - } -} - -static inline cairo_int64_t -_slope_length (cairo_slope_t *slope) -{ - return _cairo_int64_add (_cairo_int32x32_64_mul (slope->dx, slope->dx), - _cairo_int32x32_64_mul (slope->dy, slope->dy)); -} - -static int -_cairo_hull_vertex_compare (const void *av, const void *bv) -{ - cairo_hull_t *a = (cairo_hull_t *) av; - cairo_hull_t *b = (cairo_hull_t *) bv; - int ret; - - ret = _cairo_slope_compare (&a->slope, &b->slope); - - /* - * In the case of two vertices with identical slope from the - * extremal point discard the nearer point. - */ - if (ret == 0) { - int cmp; - - cmp = _cairo_int64_cmp (_slope_length (&a->slope), - _slope_length (&b->slope)); - - /* - * Use the points' ids to ensure a well-defined ordering, - * and avoid setting discard on both points. - */ - if (cmp < 0 || (cmp == 0 && a->id < b->id)) { - a->discard = 1; - ret = -1; - } else { - b->discard = 1; - ret = 1; - } - } - - return ret; -} - -static int -_cairo_hull_prev_valid (cairo_hull_t *hull, int num_hull, int index) -{ - /* hull[0] is always valid, and we never need to wraparound, (if - * we are passed an index of 0 here, then the calling loop is just - * about to terminate). */ - if (index == 0) - return 0; - - do { - index--; - } while (hull[index].discard); - - return index; -} - -static int -_cairo_hull_next_valid (cairo_hull_t *hull, int num_hull, int index) -{ - do { - index = (index + 1) % num_hull; - } while (hull[index].discard); - - return index; -} - -static void -_cairo_hull_eliminate_concave (cairo_hull_t *hull, int num_hull) -{ - int i, j, k; - cairo_slope_t slope_ij, slope_jk; - - i = 0; - j = _cairo_hull_next_valid (hull, num_hull, i); - k = _cairo_hull_next_valid (hull, num_hull, j); - - do { - _cairo_slope_init (&slope_ij, &hull[i].point, &hull[j].point); - _cairo_slope_init (&slope_jk, &hull[j].point, &hull[k].point); - - /* Is the angle formed by ij and jk concave? */ - if (_cairo_slope_compare (&slope_ij, &slope_jk) >= 0) { - if (i == k) - return; - hull[j].discard = 1; - j = i; - i = _cairo_hull_prev_valid (hull, num_hull, j); - } else { - i = j; - j = k; - k = _cairo_hull_next_valid (hull, num_hull, j); - } - } while (j != 0); -} - -static void -_cairo_hull_to_pen (cairo_hull_t *hull, cairo_pen_vertex_t *vertices, int *num_vertices) -{ - int i, j = 0; - - for (i = 0; i < *num_vertices; i++) { - if (hull[i].discard) - continue; - vertices[j++].point = hull[i].point; - } - - *num_vertices = j; -} - -/* Given a set of vertices, compute the convex hull using the Graham - scan algorithm. */ -cairo_status_t -_cairo_hull_compute (cairo_pen_vertex_t *vertices, int *num_vertices) -{ - cairo_hull_t hull_stack[CAIRO_STACK_ARRAY_LENGTH (cairo_hull_t)]; - cairo_hull_t *hull; - int num_hull = *num_vertices; - - if (num_hull > ARRAY_LENGTH (hull_stack)) { - hull = _cairo_malloc_ab (num_hull, sizeof (cairo_hull_t)); - if (hull == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } else { - hull = hull_stack; - } - - _cairo_hull_init (hull, vertices, num_hull); - - qsort (hull + 1, num_hull - 1, - sizeof (cairo_hull_t), _cairo_hull_vertex_compare); - - _cairo_hull_eliminate_concave (hull, num_hull); - - _cairo_hull_to_pen (hull, vertices, num_vertices); - - if (hull != hull_stack) - free (hull); - - return CAIRO_STATUS_SUCCESS; -} diff --git a/uppdev/plugin/cairo/lib/cairo-image-surface.c b/uppdev/plugin/cairo/lib/cairo-image-surface.c deleted file mode 100644 index 4aad77f05..000000000 --- a/uppdev/plugin/cairo/lib/cairo-image-surface.c +++ /dev/null @@ -1,1388 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2003 University of Southern California - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - */ - -#include "cairoint.h" - -static cairo_format_t -_cairo_format_from_pixman_format (pixman_format_code_t pixman_format) -{ - switch (pixman_format) { - case PIXMAN_a8r8g8b8: - return CAIRO_FORMAT_ARGB32; - case PIXMAN_x8r8g8b8: - return CAIRO_FORMAT_RGB24; - case PIXMAN_a8: - return CAIRO_FORMAT_A8; - case PIXMAN_a1: - return CAIRO_FORMAT_A1; - case PIXMAN_a8b8g8r8: case PIXMAN_x8b8g8r8: case PIXMAN_r8g8b8: - case PIXMAN_b8g8r8: case PIXMAN_r5g6b5: case PIXMAN_b5g6r5: - case PIXMAN_a1r5g5b5: case PIXMAN_x1r5g5b5: case PIXMAN_a1b5g5r5: - case PIXMAN_x1b5g5r5: case PIXMAN_a4r4g4b4: case PIXMAN_x4r4g4b4: - case PIXMAN_a4b4g4r4: case PIXMAN_x4b4g4r4: case PIXMAN_r3g3b2: - case PIXMAN_b2g3r3: case PIXMAN_a2r2g2b2: case PIXMAN_a2b2g2r2: - case PIXMAN_c8: case PIXMAN_g8: case PIXMAN_x4a4: - case PIXMAN_a4: case PIXMAN_r1g2b1: case PIXMAN_b1g2r1: - case PIXMAN_a1r1g1b1: case PIXMAN_a1b1g1r1: case PIXMAN_c4: - case PIXMAN_g4: case PIXMAN_g1: - case PIXMAN_yuy2: case PIXMAN_yv12: -#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,11,9) - case PIXMAN_x2b10g10r10: - case PIXMAN_a2b10g10r10: -#endif - default: - return CAIRO_FORMAT_INVALID; - } - - return CAIRO_FORMAT_INVALID; -} - -static cairo_content_t -_cairo_content_from_pixman_format (pixman_format_code_t pixman_format) -{ - switch (pixman_format) { - case PIXMAN_a8r8g8b8: - case PIXMAN_a8b8g8r8: - case PIXMAN_a1r5g5b5: - case PIXMAN_a1b5g5r5: - case PIXMAN_a4r4g4b4: - case PIXMAN_a4b4g4r4: - case PIXMAN_a2r2g2b2: - case PIXMAN_a2b2g2r2: - case PIXMAN_a1r1g1b1: - case PIXMAN_a1b1g1r1: -#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,11,9) - case PIXMAN_a2b10g10r10: -#endif - return CAIRO_CONTENT_COLOR_ALPHA; - case PIXMAN_x8r8g8b8: - case PIXMAN_x8b8g8r8: - case PIXMAN_r8g8b8: - case PIXMAN_b8g8r8: - case PIXMAN_r5g6b5: - case PIXMAN_b5g6r5: - case PIXMAN_x1r5g5b5: - case PIXMAN_x1b5g5r5: - case PIXMAN_x4r4g4b4: - case PIXMAN_x4b4g4r4: - case PIXMAN_r3g3b2: - case PIXMAN_b2g3r3: - case PIXMAN_c8: - case PIXMAN_g8: - case PIXMAN_r1g2b1: - case PIXMAN_b1g2r1: - case PIXMAN_c4: - case PIXMAN_g4: - case PIXMAN_g1: - case PIXMAN_yuy2: - case PIXMAN_yv12: -#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,11,9) - case PIXMAN_x2b10g10r10: -#endif - return CAIRO_CONTENT_COLOR; - case PIXMAN_a8: - case PIXMAN_a1: - case PIXMAN_x4a4: - case PIXMAN_a4: - return CAIRO_CONTENT_ALPHA; - } - - return CAIRO_CONTENT_COLOR_ALPHA; -} - -cairo_surface_t * -_cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image, - pixman_format_code_t pixman_format) -{ - cairo_image_surface_t *surface; - - surface = malloc (sizeof (cairo_image_surface_t)); - if (surface == NULL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - _cairo_surface_init (&surface->base, &_cairo_image_surface_backend, - _cairo_content_from_pixman_format (pixman_format)); - - surface->pixman_image = pixman_image; - - surface->pixman_format = pixman_format; - surface->format = _cairo_format_from_pixman_format (pixman_format); - surface->data = (unsigned char *) pixman_image_get_data (pixman_image); - surface->owns_data = FALSE; - surface->has_clip = FALSE; - surface->transparency = CAIRO_IMAGE_UNKNOWN; - - surface->width = pixman_image_get_width (pixman_image); - surface->height = pixman_image_get_height (pixman_image); - surface->stride = pixman_image_get_stride (pixman_image); - surface->depth = pixman_image_get_depth (pixman_image); - - return &surface->base; -} - -cairo_bool_t -_pixman_format_from_masks (cairo_format_masks_t *masks, - pixman_format_code_t *format_ret) -{ - pixman_format_code_t format; - int format_type; - int a, r, g, b; - cairo_format_masks_t format_masks; - - a = _cairo_popcount (masks->alpha_mask); - r = _cairo_popcount (masks->red_mask); - g = _cairo_popcount (masks->green_mask); - b = _cairo_popcount (masks->blue_mask); - - if (masks->red_mask) { - if (masks->red_mask > masks->blue_mask) - format_type = PIXMAN_TYPE_ARGB; - else - format_type = PIXMAN_TYPE_ABGR; - } else if (masks->alpha_mask) { - format_type = PIXMAN_TYPE_A; - } else { - return FALSE; - } - - format = PIXMAN_FORMAT (masks->bpp, format_type, a, r, g, b); - - if (! pixman_format_supported_destination (format)) - return FALSE; - - /* Sanity check that we got out of PIXMAN_FORMAT exactly what we - * expected. This avoid any problems from something bizarre like - * alpha in the least-significant bits, or insane channel order, - * or whatever. */ - _pixman_format_to_masks (format, &format_masks); - - if (masks->bpp != format_masks.bpp || - masks->red_mask != format_masks.red_mask || - masks->green_mask != format_masks.green_mask || - masks->blue_mask != format_masks.blue_mask) - { - return FALSE; - } - - *format_ret = format; - return TRUE; -} - -/* A mask consisting of N bits set to 1. */ -#define MASK(N) ((1 << (N))-1) - -void -_pixman_format_to_masks (pixman_format_code_t format, - cairo_format_masks_t *masks) -{ - int a, r, g, b; - - masks->bpp = PIXMAN_FORMAT_BPP (format); - - /* Number of bits in each channel */ - a = PIXMAN_FORMAT_A (format); - r = PIXMAN_FORMAT_R (format); - g = PIXMAN_FORMAT_G (format); - b = PIXMAN_FORMAT_B (format); - - switch (PIXMAN_FORMAT_TYPE (format)) { - case PIXMAN_TYPE_ARGB: - masks->alpha_mask = MASK (a) << (r + g + b); - masks->red_mask = MASK (r) << (g + b); - masks->green_mask = MASK (g) << (b); - masks->blue_mask = MASK (b); - return; - case PIXMAN_TYPE_ABGR: - masks->alpha_mask = MASK (a) << (b + g + r); - masks->blue_mask = MASK (b) << (g +r); - masks->green_mask = MASK (g) << (r); - masks->red_mask = MASK (r); - return; - case PIXMAN_TYPE_A: - masks->alpha_mask = MASK (a); - masks->red_mask = 0; - masks->green_mask = 0; - masks->blue_mask = 0; - return; - case PIXMAN_TYPE_OTHER: - case PIXMAN_TYPE_COLOR: - case PIXMAN_TYPE_GRAY: - case PIXMAN_TYPE_YUY2: - case PIXMAN_TYPE_YV12: - default: - masks->alpha_mask = 0; - masks->red_mask = 0; - masks->green_mask = 0; - masks->blue_mask = 0; - return; - } -} - -/* XXX: This function really should be eliminated. We don't really - * want to advertise a cairo image surface that supports any possible - * format. A minimal step would be to replace this function with one - * that accepts a #cairo_internal_format_t rather than mask values. */ -cairo_surface_t * -_cairo_image_surface_create_with_masks (unsigned char *data, - cairo_format_masks_t *masks, - int width, - int height, - int stride) -{ - pixman_format_code_t pixman_format; - - if (! _pixman_format_from_masks (masks, &pixman_format)) { - fprintf (stderr, - "Error: Cairo %s does not yet support the requested image format:\n" - "\tDepth: %d\n" - "\tAlpha mask: 0x%08lx\n" - "\tRed mask: 0x%08lx\n" - "\tGreen mask: 0x%08lx\n" - "\tBlue mask: 0x%08lx\n" -#ifdef PACKAGE_BUGGREPORT - "Please file an enhancement request (quoting the above) at:\n" - PACKAGE_BUGREPORT"\n" -#endif - , - cairo_version_string (), - masks->bpp, masks->alpha_mask, - masks->red_mask, masks->green_mask, masks->blue_mask); - - ASSERT_NOT_REACHED; - } - - return _cairo_image_surface_create_with_pixman_format (data, - pixman_format, - width, - height, - stride); -} - -static pixman_format_code_t -_cairo_format_to_pixman_format_code (cairo_format_t format) -{ - pixman_format_code_t ret; - switch (format) { - case CAIRO_FORMAT_A1: - ret = PIXMAN_a1; - break; - case CAIRO_FORMAT_A8: - ret = PIXMAN_a8; - break; - case CAIRO_FORMAT_RGB24: - ret = PIXMAN_x8r8g8b8; - break; - case CAIRO_FORMAT_ARGB32: - default: - ret = PIXMAN_a8r8g8b8; - break; - } - return ret; -} - -cairo_surface_t * -_cairo_image_surface_create_with_pixman_format (unsigned char *data, - pixman_format_code_t pixman_format, - int width, - int height, - int stride) -{ - cairo_surface_t *surface; - pixman_image_t *pixman_image; - - pixman_image = pixman_image_create_bits (pixman_format, width, height, - (uint32_t *) data, stride); - - if (pixman_image == NULL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - surface = _cairo_image_surface_create_for_pixman_image (pixman_image, - pixman_format); - if (cairo_surface_status (surface)) - pixman_image_unref (pixman_image); - - return surface; -} - -/** - * cairo_image_surface_create: - * @format: format of pixels in the surface to create - * @width: width of the surface, in pixels - * @height: height of the surface, in pixels - * - * Creates an image surface of the specified format and - * dimensions. Initially the surface contents are all - * 0. (Specifically, within each pixel, each color or alpha channel - * belonging to format will be 0. The contents of bits within a pixel, - * but not belonging to the given format are undefined). - * - * Return value: a pointer to the newly created surface. The caller - * owns the surface and should call cairo_surface_destroy() when done - * with it. - * - * This function always returns a valid pointer, but it will return a - * pointer to a "nil" surface if an error such as out of memory - * occurs. You can use cairo_surface_status() to check for this. - **/ -cairo_surface_t * -cairo_image_surface_create (cairo_format_t format, - int width, - int height) -{ - pixman_format_code_t pixman_format; - - if (! CAIRO_FORMAT_VALID (format)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); - - pixman_format = _cairo_format_to_pixman_format_code (format); - - return _cairo_image_surface_create_with_pixman_format (NULL, pixman_format, - width, height, -1); -} -slim_hidden_def (cairo_image_surface_create); - -cairo_surface_t * -_cairo_image_surface_create_with_content (cairo_content_t content, - int width, - int height) -{ - if (! CAIRO_CONTENT_VALID (content)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_CONTENT)); - - return cairo_image_surface_create (_cairo_format_from_content (content), - width, height); -} - -/** - * cairo_format_stride_for_width: - * @format: A #cairo_format_t value - * @width: The desired width of an image surface to be created. - * - * This function provides a stride value that will respect all - * alignment requirements of the accelerated image-rendering code - * within cairo. Typical usage will be of the form: - * - * - * int stride; - * unsigned char *data; - * #cairo_surface_t *surface; - * - * stride = cairo_format_stride_for_width (format, width); - * data = malloc (stride * height); - * surface = cairo_image_surface_create_for_data (data, format, - * width, height, - * stride); - * - * - * Return value: the appropriate stride to use given the desired - * format and width, or -1 if either the format is invalid or the width - * too large. - * - * Since: 1.6 - **/ -int -cairo_format_stride_for_width (cairo_format_t format, - int width) -{ - int bpp; - - if (! CAIRO_FORMAT_VALID (format)) { - _cairo_error_throw (CAIRO_STATUS_INVALID_FORMAT); - return -1; - } - - bpp = _cairo_format_bits_per_pixel (format); - if ((unsigned) (width) >= (INT32_MAX - 7) / (unsigned) (bpp)) - return -1; - - return CAIRO_STRIDE_FOR_WIDTH_BPP (width, bpp); -} -slim_hidden_def (cairo_format_stride_for_width); - -/** - * cairo_image_surface_create_for_data: - * @data: a pointer to a buffer supplied by the application in which - * to write contents. This pointer must be suitably aligned for any - * kind of variable, (for example, a pointer returned by malloc). - * @format: the format of pixels in the buffer - * @width: the width of the image to be stored in the buffer - * @height: the height of the image to be stored in the buffer - * @stride: the number of bytes between the start of rows in the - * buffer as allocated. This value should always be computed by - * cairo_format_stride_for_width() before allocating the data - * buffer. - * - * Creates an image surface for the provided pixel data. The output - * buffer must be kept around until the #cairo_surface_t is destroyed - * or cairo_surface_finish() is called on the surface. The initial - * contents of @buffer will be used as the initial image contents; you - * must explicitly clear the buffer, using, for example, - * cairo_rectangle() and cairo_fill() if you want it cleared. - * - * Note that the stride may be larger than - * width*bytes_per_pixel to provide proper alignment for each pixel - * and row. This alignment is required to allow high-performance rendering - * within cairo. The correct way to obtain a legal stride value is to - * call cairo_format_stride_for_width() with the desired format and - * maximum image width value, and the use the resulting stride value - * to allocate the data and to create the image surface. See - * cairo_format_stride_for_width() for example code. - * - * Return value: a pointer to the newly created surface. The caller - * owns the surface and should call cairo_surface_destroy() when done - * with it. - * - * This function always returns a valid pointer, but it will return a - * pointer to a "nil" surface in the case of an error such as out of - * memory or an invalid stride value. In case of invalid stride value - * the error status of the returned surface will be - * %CAIRO_STATUS_INVALID_STRIDE. You can use - * cairo_surface_status() to check for this. - * - * See cairo_surface_set_user_data() for a means of attaching a - * destroy-notification fallback to the surface if necessary. - **/ -cairo_surface_t * -cairo_image_surface_create_for_data (unsigned char *data, - cairo_format_t format, - int width, - int height, - int stride) -{ - pixman_format_code_t pixman_format; - int minstride; - - if (! CAIRO_FORMAT_VALID (format)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); - - if ((stride & (CAIRO_STRIDE_ALIGNMENT-1)) != 0) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE)); - - minstride = cairo_format_stride_for_width (format, width); - if (stride < 0) { - if (stride > -minstride) { - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE)); - } - } else { - if (stride < minstride) { - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE)); - } - } - - pixman_format = _cairo_format_to_pixman_format_code (format); - - return _cairo_image_surface_create_with_pixman_format (data, pixman_format, - width, height, stride); -} -slim_hidden_def (cairo_image_surface_create_for_data); - -cairo_surface_t * -_cairo_image_surface_create_for_data_with_content (unsigned char *data, - cairo_content_t content, - int width, - int height, - int stride) -{ - if (! CAIRO_CONTENT_VALID (content)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_CONTENT)); - - return cairo_image_surface_create_for_data (data, - _cairo_format_from_content (content), - width, height, stride); -} - -/** - * cairo_image_surface_get_data: - * @surface: a #cairo_image_surface_t - * - * Get a pointer to the data of the image surface, for direct - * inspection or modification. - * - * Return value: a pointer to the image data of this surface or %NULL - * if @surface is not an image surface, or if cairo_surface_finish() - * has been called. - * - * Since: 1.2 - **/ -unsigned char * -cairo_image_surface_get_data (cairo_surface_t *surface) -{ - cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface; - - if (! _cairo_surface_is_image (surface)) { - _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - return NULL; - } - - return image_surface->data; -} -slim_hidden_def (cairo_image_surface_get_data); - -/** - * cairo_image_surface_get_format: - * @surface: a #cairo_image_surface_t - * - * Get the format of the surface. - * - * Return value: the format of the surface - * - * Since: 1.2 - **/ -cairo_format_t -cairo_image_surface_get_format (cairo_surface_t *surface) -{ - cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface; - - if (! _cairo_surface_is_image (surface)) { - _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - return 0; - } - - return image_surface->format; -} - -/** - * cairo_image_surface_get_width: - * @surface: a #cairo_image_surface_t - * - * Get the width of the image surface in pixels. - * - * Return value: the width of the surface in pixels. - **/ -int -cairo_image_surface_get_width (cairo_surface_t *surface) -{ - cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface; - - if (! _cairo_surface_is_image (surface)) { - _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - return 0; - } - - return image_surface->width; -} -slim_hidden_def (cairo_image_surface_get_width); - -/** - * cairo_image_surface_get_height: - * @surface: a #cairo_image_surface_t - * - * Get the height of the image surface in pixels. - * - * Return value: the height of the surface in pixels. - **/ -int -cairo_image_surface_get_height (cairo_surface_t *surface) -{ - cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface; - - if (! _cairo_surface_is_image (surface)) { - _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - return 0; - } - - return image_surface->height; -} -slim_hidden_def (cairo_image_surface_get_height); - -/** - * cairo_image_surface_get_stride: - * @surface: a #cairo_image_surface_t - * - * Get the stride of the image surface in bytes - * - * Return value: the stride of the image surface in bytes (or 0 if - * @surface is not an image surface). The stride is the distance in - * bytes from the beginning of one row of the image data to the - * beginning of the next row. - * - * Since: 1.2 - **/ -int -cairo_image_surface_get_stride (cairo_surface_t *surface) -{ - - cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface; - - if (! _cairo_surface_is_image (surface)) { - _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - return 0; - } - - return image_surface->stride; -} -slim_hidden_def (cairo_image_surface_get_stride); - -cairo_format_t -_cairo_format_from_content (cairo_content_t content) -{ - switch (content) { - case CAIRO_CONTENT_COLOR: - return CAIRO_FORMAT_RGB24; - case CAIRO_CONTENT_ALPHA: - return CAIRO_FORMAT_A8; - case CAIRO_CONTENT_COLOR_ALPHA: - return CAIRO_FORMAT_ARGB32; - } - - ASSERT_NOT_REACHED; - return CAIRO_FORMAT_ARGB32; -} - -cairo_content_t -_cairo_content_from_format (cairo_format_t format) -{ - switch (format) { - case CAIRO_FORMAT_ARGB32: - return CAIRO_CONTENT_COLOR_ALPHA; - case CAIRO_FORMAT_RGB24: - return CAIRO_CONTENT_COLOR; - case CAIRO_FORMAT_A8: - case CAIRO_FORMAT_A1: - return CAIRO_CONTENT_ALPHA; - } - - ASSERT_NOT_REACHED; - return CAIRO_CONTENT_COLOR_ALPHA; -} - -int -_cairo_format_bits_per_pixel (cairo_format_t format) -{ - switch (format) { - case CAIRO_FORMAT_ARGB32: - return 32; - case CAIRO_FORMAT_RGB24: - return 32; - case CAIRO_FORMAT_A8: - return 8; - case CAIRO_FORMAT_A1: - return 1; - default: - ASSERT_NOT_REACHED; - return 0; - } -} - -static cairo_surface_t * -_cairo_image_surface_create_similar (void *abstract_src, - cairo_content_t content, - int width, - int height) -{ - assert (CAIRO_CONTENT_VALID (content)); - - return _cairo_image_surface_create_with_content (content, - width, height); -} - -static cairo_status_t -_cairo_image_surface_finish (void *abstract_surface) -{ - cairo_image_surface_t *surface = abstract_surface; - - if (surface->pixman_image) { - pixman_image_unref (surface->pixman_image); - surface->pixman_image = NULL; - } - - if (surface->owns_data) { - free (surface->data); - surface->data = NULL; - } - - return CAIRO_STATUS_SUCCESS; -} - -void -_cairo_image_surface_assume_ownership_of_data (cairo_image_surface_t *surface) -{ - surface->owns_data = 1; -} - -static cairo_status_t -_cairo_image_surface_acquire_source_image (void *abstract_surface, - cairo_image_surface_t **image_out, - void **image_extra) -{ - *image_out = abstract_surface; - *image_extra = NULL; - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_image_surface_release_source_image (void *abstract_surface, - cairo_image_surface_t *image, - void *image_extra) -{ -} - -static cairo_status_t -_cairo_image_surface_acquire_dest_image (void *abstract_surface, - cairo_rectangle_int_t *interest_rect, - cairo_image_surface_t **image_out, - cairo_rectangle_int_t *image_rect_out, - void **image_extra) -{ - cairo_image_surface_t *surface = abstract_surface; - - image_rect_out->x = 0; - image_rect_out->y = 0; - image_rect_out->width = surface->width; - image_rect_out->height = surface->height; - - *image_out = surface; - *image_extra = NULL; - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_image_surface_release_dest_image (void *abstract_surface, - cairo_rectangle_int_t *interest_rect, - cairo_image_surface_t *image, - cairo_rectangle_int_t *image_rect, - void *image_extra) -{ -} - -static cairo_status_t -_cairo_image_surface_clone_similar (void *abstract_surface, - cairo_surface_t *src, - int src_x, - int src_y, - int width, - int height, - int *clone_offset_x, - int *clone_offset_y, - cairo_surface_t **clone_out) -{ - cairo_image_surface_t *surface = abstract_surface; - - if (src->backend == surface->base.backend) { - *clone_offset_x = *clone_offset_y = 0; - *clone_out = cairo_surface_reference (src); - - return CAIRO_STATUS_SUCCESS; - } - - return CAIRO_INT_STATUS_UNSUPPORTED; -} - -static cairo_status_t -_cairo_image_surface_set_matrix (cairo_image_surface_t *surface, - const cairo_matrix_t *matrix) -{ - pixman_transform_t pixman_transform; - - _cairo_matrix_to_pixman_matrix (matrix, &pixman_transform); - - if (! pixman_image_set_transform (surface->pixman_image, &pixman_transform)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_image_surface_set_filter (cairo_image_surface_t *surface, - cairo_filter_t filter) -{ - pixman_filter_t pixman_filter; - - switch (filter) { - case CAIRO_FILTER_FAST: - pixman_filter = PIXMAN_FILTER_FAST; - break; - case CAIRO_FILTER_GOOD: - pixman_filter = PIXMAN_FILTER_GOOD; - break; - case CAIRO_FILTER_BEST: - pixman_filter = PIXMAN_FILTER_BEST; - break; - case CAIRO_FILTER_NEAREST: - pixman_filter = PIXMAN_FILTER_NEAREST; - break; - case CAIRO_FILTER_BILINEAR: - pixman_filter = PIXMAN_FILTER_BILINEAR; - break; - case CAIRO_FILTER_GAUSSIAN: - /* XXX: The GAUSSIAN value has no implementation in cairo - * whatsoever, so it was really a mistake to have it in the - * API. We could fix this by officially deprecating it, or - * else inventing semantics and providing an actual - * implementation for it. */ - default: - pixman_filter = PIXMAN_FILTER_BEST; - } - - if (! pixman_image_set_filter (surface->pixman_image, - pixman_filter, - NULL, 0)) - { - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_image_surface_set_attributes (cairo_image_surface_t *surface, - cairo_surface_attributes_t *attributes) -{ - cairo_int_status_t status; - - status = _cairo_image_surface_set_matrix (surface, &attributes->matrix); - if (status) - return status; - - switch (attributes->extend) { - case CAIRO_EXTEND_NONE: - pixman_image_set_repeat (surface->pixman_image, PIXMAN_REPEAT_NONE); - break; - case CAIRO_EXTEND_REPEAT: - pixman_image_set_repeat (surface->pixman_image, PIXMAN_REPEAT_NORMAL); - break; - case CAIRO_EXTEND_REFLECT: - pixman_image_set_repeat (surface->pixman_image, PIXMAN_REPEAT_REFLECT); - break; - case CAIRO_EXTEND_PAD: - pixman_image_set_repeat (surface->pixman_image, PIXMAN_REPEAT_PAD); - break; - } - - status = _cairo_image_surface_set_filter (surface, attributes->filter); - if (status) - return status; - - return CAIRO_STATUS_SUCCESS; -} - -/* XXX: I think we should fix pixman to match the names/order of the - * cairo operators, but that will likely be better done at the same - * time the X server is ported to pixman, (which will change a lot of - * things in pixman I think). - */ -static pixman_op_t -_pixman_operator (cairo_operator_t op) -{ - switch (op) { - case CAIRO_OPERATOR_CLEAR: - return PIXMAN_OP_CLEAR; - - case CAIRO_OPERATOR_SOURCE: - return PIXMAN_OP_SRC; - case CAIRO_OPERATOR_OVER: - return PIXMAN_OP_OVER; - case CAIRO_OPERATOR_IN: - return PIXMAN_OP_IN; - case CAIRO_OPERATOR_OUT: - return PIXMAN_OP_OUT; - case CAIRO_OPERATOR_ATOP: - return PIXMAN_OP_ATOP; - - case CAIRO_OPERATOR_DEST: - return PIXMAN_OP_DST; - case CAIRO_OPERATOR_DEST_OVER: - return PIXMAN_OP_OVER_REVERSE; - case CAIRO_OPERATOR_DEST_IN: - return PIXMAN_OP_IN_REVERSE; - case CAIRO_OPERATOR_DEST_OUT: - return PIXMAN_OP_OUT_REVERSE; - case CAIRO_OPERATOR_DEST_ATOP: - return PIXMAN_OP_ATOP_REVERSE; - - case CAIRO_OPERATOR_XOR: - return PIXMAN_OP_XOR; - case CAIRO_OPERATOR_ADD: - return PIXMAN_OP_ADD; - case CAIRO_OPERATOR_SATURATE: - return PIXMAN_OP_SATURATE; - default: - return PIXMAN_OP_OVER; - } -} - -static cairo_int_status_t -_cairo_image_surface_composite (cairo_operator_t op, - cairo_pattern_t *src_pattern, - cairo_pattern_t *mask_pattern, - void *abstract_dst, - 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_surface_attributes_t src_attr, mask_attr; - cairo_image_surface_t *dst = abstract_dst; - cairo_image_surface_t *src; - cairo_image_surface_t *mask; - cairo_int_status_t status; - - status = _cairo_pattern_acquire_surfaces (src_pattern, mask_pattern, - &dst->base, - src_x, src_y, - mask_x, mask_y, - width, height, - (cairo_surface_t **) &src, - (cairo_surface_t **) &mask, - &src_attr, &mask_attr); - if (status) - return status; - - status = _cairo_image_surface_set_attributes (src, &src_attr); - if (status) - goto CLEANUP_SURFACES; - - if (mask) - { - status = _cairo_image_surface_set_attributes (mask, &mask_attr); - if (status) - goto CLEANUP_SURFACES; - - pixman_image_composite (_pixman_operator (op), - src->pixman_image, - mask->pixman_image, - dst->pixman_image, - src_x + src_attr.x_offset, - src_y + src_attr.y_offset, - mask_x + mask_attr.x_offset, - mask_y + mask_attr.y_offset, - dst_x, dst_y, - width, height); - } - else - { - pixman_image_composite (_pixman_operator (op), - src->pixman_image, - NULL, - dst->pixman_image, - src_x + src_attr.x_offset, - src_y + src_attr.y_offset, - 0, 0, - dst_x, dst_y, - width, height); - } - - if (! _cairo_operator_bounded_by_source (op)) - status = _cairo_surface_composite_fixup_unbounded (&dst->base, - &src_attr, src->width, src->height, - mask ? &mask_attr : NULL, - mask ? mask->width : 0, - mask ? mask->height : 0, - src_x, src_y, - mask_x, mask_y, - dst_x, dst_y, width, height); - - CLEANUP_SURFACES: - if (mask) - _cairo_pattern_release_surface (mask_pattern, &mask->base, &mask_attr); - - _cairo_pattern_release_surface (src_pattern, &src->base, &src_attr); - - return status; -} - -static cairo_int_status_t -_cairo_image_surface_fill_rectangles (void *abstract_surface, - cairo_operator_t op, - const cairo_color_t *color, - cairo_rectangle_int_t *rects, - int num_rects) -{ - cairo_image_surface_t *surface = abstract_surface; - - pixman_color_t pixman_color; - pixman_rectangle16_t stack_rects[CAIRO_STACK_ARRAY_LENGTH (pixman_rectangle16_t)]; - pixman_rectangle16_t *pixman_rects = stack_rects; - int i; - - cairo_int_status_t status = CAIRO_STATUS_SUCCESS; - - pixman_color.red = color->red_short; - pixman_color.green = color->green_short; - pixman_color.blue = color->blue_short; - pixman_color.alpha = color->alpha_short; - - if (num_rects > ARRAY_LENGTH (stack_rects)) { - pixman_rects = _cairo_malloc_ab (num_rects, sizeof (pixman_rectangle16_t)); - if (pixman_rects == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - for (i = 0; i < num_rects; i++) { - pixman_rects[i].x = rects[i].x; - pixman_rects[i].y = rects[i].y; - pixman_rects[i].width = rects[i].width; - pixman_rects[i].height = rects[i].height; - } - - /* XXX: pixman_fill_rectangles() should be implemented */ - if (! pixman_image_fill_rectangles (_pixman_operator (op), - surface->pixman_image, - &pixman_color, - num_rects, - pixman_rects)) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - if (pixman_rects != stack_rects) - free (pixman_rects); - - return status; -} - -static cairo_int_status_t -_cairo_image_surface_composite_trapezoids (cairo_operator_t op, - cairo_pattern_t *pattern, - void *abstract_dst, - cairo_antialias_t antialias, - int src_x, - int src_y, - int dst_x, - int dst_y, - unsigned int width, - unsigned int height, - cairo_trapezoid_t *traps, - int num_traps) -{ - cairo_surface_attributes_t attributes; - cairo_image_surface_t *dst = abstract_dst; - cairo_image_surface_t *src; - cairo_int_status_t status; - pixman_image_t *mask; - pixman_format_code_t format; - uint32_t *mask_data; - pixman_trapezoid_t stack_traps[CAIRO_STACK_ARRAY_LENGTH (pixman_trapezoid_t)]; - pixman_trapezoid_t *pixman_traps = stack_traps; - int mask_stride; - int i; - - if (height == 0 || width == 0) - return CAIRO_STATUS_SUCCESS; - - /* Convert traps to pixman traps */ - if (num_traps > ARRAY_LENGTH (stack_traps)) { - pixman_traps = _cairo_malloc_ab (num_traps, sizeof (pixman_trapezoid_t)); - if (pixman_traps == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - for (i = 0; i < num_traps; i++) { - pixman_traps[i].top = _cairo_fixed_to_16_16 (traps[i].top); - pixman_traps[i].bottom = _cairo_fixed_to_16_16 (traps[i].bottom); - pixman_traps[i].left.p1.x = _cairo_fixed_to_16_16 (traps[i].left.p1.x); - pixman_traps[i].left.p1.y = _cairo_fixed_to_16_16 (traps[i].left.p1.y); - pixman_traps[i].left.p2.x = _cairo_fixed_to_16_16 (traps[i].left.p2.x); - pixman_traps[i].left.p2.y = _cairo_fixed_to_16_16 (traps[i].left.p2.y); - pixman_traps[i].right.p1.x = _cairo_fixed_to_16_16 (traps[i].right.p1.x); - pixman_traps[i].right.p1.y = _cairo_fixed_to_16_16 (traps[i].right.p1.y); - pixman_traps[i].right.p2.x = _cairo_fixed_to_16_16 (traps[i].right.p2.x); - pixman_traps[i].right.p2.y = _cairo_fixed_to_16_16 (traps[i].right.p2.y); - } - - /* Special case adding trapezoids onto a mask surface; we want to avoid - * creating an intermediate temporary mask unnecessarily. - * - * We make the assumption here that the portion of the trapezoids - * contained within the surface is bounded by [dst_x,dst_y,width,height]; - * the Cairo core code passes bounds based on the trapezoid extents. - * - * Currently the check surface->has_clip is needed for correct - * functioning, since pixman_add_trapezoids() doesn't obey the - * surface clip, which is a libpixman bug , but there's no harm in - * falling through to the general case when the surface is clipped - * since libpixman would have to generate an intermediate mask anyways. - */ - if (op == CAIRO_OPERATOR_ADD && - _cairo_pattern_is_opaque_solid (pattern) && - dst->base.content == CAIRO_CONTENT_ALPHA && - ! dst->has_clip && - antialias != CAIRO_ANTIALIAS_NONE) - { - pixman_add_trapezoids (dst->pixman_image, 0, 0, - num_traps, pixman_traps); - status = CAIRO_STATUS_SUCCESS; - goto finish; - } - - status = _cairo_pattern_acquire_surface (pattern, &dst->base, - src_x, src_y, width, height, - (cairo_surface_t **) &src, - &attributes); - if (status) - goto finish; - - status = _cairo_image_surface_set_attributes (src, &attributes); - if (status) - goto CLEANUP_SOURCE; - - switch (antialias) { - case CAIRO_ANTIALIAS_NONE: - format = PIXMAN_a1; - mask_stride = ((width + 31) / 8) & ~0x03; - break; - case CAIRO_ANTIALIAS_GRAY: - case CAIRO_ANTIALIAS_SUBPIXEL: - case CAIRO_ANTIALIAS_DEFAULT: - default: - format = PIXMAN_a8; - mask_stride = (width + 3) & ~3; - break; - } - - /* The image must be initially transparent */ - mask_data = calloc (mask_stride, height); - if (mask_data == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto CLEANUP_SOURCE; - } - - mask = pixman_image_create_bits (format, width, height, - mask_data, mask_stride); - if (mask == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto CLEANUP_IMAGE_DATA; - } - - pixman_add_trapezoids (mask, - dst_x, - dst_y, - num_traps, pixman_traps); - - pixman_image_composite (_pixman_operator (op), - src->pixman_image, - mask, - dst->pixman_image, - src_x + attributes.x_offset, - src_y + attributes.y_offset, - 0, 0, - dst_x, dst_y, - width, height); - - if (! _cairo_operator_bounded_by_mask (op)) - status = _cairo_surface_composite_shape_fixup_unbounded (&dst->base, - &attributes, src->width, src->height, - width, height, - src_x, src_y, - 0, 0, - dst_x, dst_y, width, height); - pixman_image_unref (mask); - - CLEANUP_IMAGE_DATA: - free (mask_data); - - CLEANUP_SOURCE: - _cairo_pattern_release_surface (pattern, &src->base, &attributes); - - finish: - if (pixman_traps != stack_traps) - free (pixman_traps); - - return status; -} - -cairo_int_status_t -_cairo_image_surface_set_clip_region (void *abstract_surface, - cairo_region_t *region) -{ - cairo_image_surface_t *surface = (cairo_image_surface_t *) abstract_surface; - - if (! pixman_image_set_clip_region32 (surface->pixman_image, ®ion->rgn)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - surface->has_clip = region != NULL; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_image_surface_get_extents (void *abstract_surface, - cairo_rectangle_int_t *rectangle) -{ - cairo_image_surface_t *surface = abstract_surface; - - rectangle->x = 0; - rectangle->y = 0; - rectangle->width = surface->width; - rectangle->height = surface->height; - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_image_surface_get_font_options (void *abstract_surface, - cairo_font_options_t *options) -{ - _cairo_font_options_init_default (options); - - cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_ON); -} - -static cairo_status_t -_cairo_image_surface_reset (void *abstract_surface) -{ - cairo_image_surface_t *surface = abstract_surface; - cairo_status_t status; - - status = _cairo_image_surface_set_clip_region (surface, NULL); - assert (status == CAIRO_STATUS_SUCCESS); - - return CAIRO_STATUS_SUCCESS; -} - -/** - * _cairo_surface_is_image: - * @surface: a #cairo_surface_t - * - * Checks if a surface is an #cairo_image_surface_t - * - * Return value: %TRUE if the surface is an image surface - **/ -cairo_bool_t -_cairo_surface_is_image (const cairo_surface_t *surface) -{ - return surface->backend == &_cairo_image_surface_backend; -} - -const cairo_surface_backend_t _cairo_image_surface_backend = { - CAIRO_SURFACE_TYPE_IMAGE, - _cairo_image_surface_create_similar, - _cairo_image_surface_finish, - _cairo_image_surface_acquire_source_image, - _cairo_image_surface_release_source_image, - _cairo_image_surface_acquire_dest_image, - _cairo_image_surface_release_dest_image, - _cairo_image_surface_clone_similar, - _cairo_image_surface_composite, - _cairo_image_surface_fill_rectangles, - _cairo_image_surface_composite_trapezoids, - NULL, /* copy_page */ - NULL, /* show_page */ - _cairo_image_surface_set_clip_region, - NULL, /* intersect_clip_path */ - _cairo_image_surface_get_extents, - NULL, /* old_show_glyphs */ - _cairo_image_surface_get_font_options, - NULL, /* flush */ - NULL, /* mark_dirty_rectangle */ - NULL, /* font_fini */ - NULL, /* glyph_fini */ - - NULL, /* paint */ - NULL, /* mask */ - NULL, /* stroke */ - NULL, /* fill */ - NULL, /* show_glyphs */ - NULL, /* snapshot */ - NULL, /* is_similar */ - - _cairo_image_surface_reset -}; - -/* A convenience function for when one needs to coerce an image - * surface to an alternate format. */ -cairo_image_surface_t * -_cairo_image_surface_clone (cairo_image_surface_t *surface, - cairo_format_t format) -{ - cairo_image_surface_t *clone; - cairo_status_t status; - cairo_t *cr; - double x, y; - - clone = (cairo_image_surface_t *) - cairo_image_surface_create (format, - surface->width, surface->height); - - cairo_surface_get_device_offset (&surface->base, &x, &y); - cairo_surface_set_device_offset (&clone->base, x, y); - clone->transparency = CAIRO_IMAGE_UNKNOWN; - - /* XXX Use _cairo_surface_composite directly */ - cr = cairo_create (&clone->base); - cairo_set_source_surface (cr, &surface->base, 0, 0); - cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); - cairo_paint (cr); - status = cairo_status (cr); - cairo_destroy (cr); - - if (status) { - cairo_surface_destroy (&clone->base); - return (cairo_image_surface_t *) _cairo_surface_create_in_error (status); - } - - return clone; -} - -cairo_image_transparency_t -_cairo_image_analyze_transparency (cairo_image_surface_t *image) -{ - int x, y; - - if (image->transparency != CAIRO_IMAGE_UNKNOWN) - return image->transparency; - - if (image->format == CAIRO_FORMAT_RGB24) { - image->transparency = CAIRO_IMAGE_IS_OPAQUE; - return CAIRO_IMAGE_IS_OPAQUE; - } - - if (image->format != CAIRO_FORMAT_ARGB32) { - image->transparency = CAIRO_IMAGE_HAS_ALPHA; - return CAIRO_IMAGE_HAS_ALPHA; - } - - image->transparency = CAIRO_IMAGE_IS_OPAQUE; - for (y = 0; y < image->height; y++) { - uint32_t *pixel = (uint32_t *) (image->data + y * image->stride); - - for (x = 0; x < image->width; x++, pixel++) { - int a = (*pixel & 0xff000000) >> 24; - if (a > 0 && a < 255) { - image->transparency = CAIRO_IMAGE_HAS_ALPHA; - return CAIRO_IMAGE_HAS_ALPHA; - } else if (a == 0) { - image->transparency = CAIRO_IMAGE_HAS_BILEVEL_ALPHA; - } - } - } - - return image->transparency; -} diff --git a/uppdev/plugin/cairo/lib/cairo-lzw.c b/uppdev/plugin/cairo/lib/cairo-lzw.c deleted file mode 100644 index 1241225d4..000000000 --- a/uppdev/plugin/cairo/lib/cairo-lzw.c +++ /dev/null @@ -1,403 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2006 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - */ - -#include "cairoint.h" - -typedef struct _lzw_buf { - cairo_status_t status; - - unsigned char *data; - int data_size; - int num_data; - uint32_t pending; - unsigned int pending_bits; -} lzw_buf_t; - -/* An lzw_buf_t is a simple, growable chunk of memory for holding - * variable-size objects of up to 16 bits each. - * - * Initialize an lzw_buf_t to the given size in bytes. - * - * To store objects into the lzw_buf_t, call _lzw_buf_store_bits and - * when finished, call _lzw_buf_store_pending, (which flushes out the - * last few bits that hadn't yet made a complete byte yet). - * - * Instead of returning failure from any functions, lzw_buf_t provides - * a status value that the caller can query, (and should query at - * least once when done with the object). The status value will be - * either %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY; - */ -static void -_lzw_buf_init (lzw_buf_t *buf, int size) -{ - if (size == 0) - size = 16; - - buf->status = CAIRO_STATUS_SUCCESS; - buf->data_size = size; - buf->num_data = 0; - buf->pending = 0; - buf->pending_bits = 0; - - buf->data = malloc (size); - if (buf->data == NULL) { - buf->data_size = 0; - buf->status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - return; - } -} - -/* Increase the buffer size by doubling. - * - * Returns %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY - */ -static cairo_status_t -_lzw_buf_grow (lzw_buf_t *buf) -{ - int new_size = buf->data_size * 2; - unsigned char *new_data; - - if (buf->status) - return buf->status; - - new_data = NULL; - /* check for integer overflow */ - if (new_size / 2 == buf->data_size) - new_data = realloc (buf->data, new_size); - - if (new_data == NULL) { - free (buf->data); - buf->data_size = 0; - buf->status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - return buf->status; - } - - buf->data = new_data; - buf->data_size = new_size; - - return CAIRO_STATUS_SUCCESS; -} - -/* Store the lowest num_bits bits of values into buf. - * - * Note: The bits of value above size_in_bits must be 0, (so don't lie - * about the size). - * - * See also _lzw_buf_store_pending which must be called after the last - * call to _lzw_buf_store_bits. - * - * Sets buf->status to either %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY. - */ -static void -_lzw_buf_store_bits (lzw_buf_t *buf, uint16_t value, int num_bits) -{ - cairo_status_t status; - - assert (value <= (1 << num_bits) - 1); - - if (buf->status) - return; - - buf->pending = (buf->pending << num_bits) | value; - buf->pending_bits += num_bits; - - while (buf->pending_bits >= 8) { - if (buf->num_data >= buf->data_size) { - status = _lzw_buf_grow (buf); - if (status) - return; - } - buf->data[buf->num_data++] = buf->pending >> (buf->pending_bits - 8); - buf->pending_bits -= 8; - } -} - -/* Store the last remaining pending bits into the buffer. - * - * Note: This function must be called after the last call to - * _lzw_buf_store_bits. - * - * Sets buf->status to either %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY. - */ -static void -_lzw_buf_store_pending (lzw_buf_t *buf) -{ - cairo_status_t status; - - if (buf->status) - return; - - if (buf->pending_bits == 0) - return; - - assert (buf->pending_bits < 8); - - if (buf->num_data >= buf->data_size) { - status = _lzw_buf_grow (buf); - if (status) - return; - } - - buf->data[buf->num_data++] = buf->pending << (8 - buf->pending_bits); - buf->pending_bits = 0; -} - -/* LZW defines a few magic code values */ -#define LZW_CODE_CLEAR_TABLE 256 -#define LZW_CODE_EOD 257 -#define LZW_CODE_FIRST 258 - -/* We pack three separate values into a symbol as follows: - * - * 12 bits (31 down to 20): CODE: code value used to represent this symbol - * 12 bits (19 down to 8): PREV: previous code value in chain - * 8 bits ( 7 down to 0): NEXT: next byte value in chain - */ -typedef uint32_t lzw_symbol_t; - -#define LZW_SYMBOL_SET(sym, prev, next) ((sym) = ((prev) << 8)|(next)) -#define LZW_SYMBOL_SET_CODE(sym, code, prev, next) ((sym) = ((code << 20)|(prev) << 8)|(next)) -#define LZW_SYMBOL_GET_CODE(sym) (((sym) >> 20)) -#define LZW_SYMBOL_GET_PREV(sym) (((sym) >> 8) & 0x7ff) -#define LZW_SYMBOL_GET_BYTE(sym) (((sym) >> 0) & 0x0ff) - -/* The PREV+NEXT fields can be seen as the key used to fetch values - * from the hash table, while the code is the value fetched. - */ -#define LZW_SYMBOL_KEY_MASK 0x000fffff - -/* Since code values are only stored starting with 258 we can safely - * use a zero value to represent free slots in the hash table. */ -#define LZW_SYMBOL_FREE 0x00000000 - -/* These really aren't very free for modifying. First, the PostScript - * specification sets the 9-12 bit range. Second, the encoding of - * lzw_symbol_t above also relies on 2 of LZW_BITS_MAX plus one byte - * fitting within 32 bits. - * - * But other than that, the LZW compression scheme could function with - * more bits per code. - */ -#define LZW_BITS_MIN 9 -#define LZW_BITS_MAX 12 -#define LZW_BITS_BOUNDARY(bits) ((1<<(bits))-1) -#define LZW_MAX_SYMBOLS (1<table, 0, LZW_SYMBOL_TABLE_SIZE * sizeof (lzw_symbol_t)); -} - -/* Lookup a symbol in the symbol table. The PREV and NEXT fields of - * symbol form the key for the lookup. - * - * If successful, then this function returns %TRUE and slot_ret will be - * left pointing at the result that will have the CODE field of - * interest. - * - * If the lookup fails, then this function returns %FALSE and slot_ret - * will be pointing at the location in the table to which a new CODE - * value should be stored along with PREV and NEXT. - */ -static cairo_bool_t -_lzw_symbol_table_lookup (lzw_symbol_table_t *table, - lzw_symbol_t symbol, - lzw_symbol_t **slot_ret) -{ - /* The algorithm here is identical to that in cairo-hash.c. We - * copy it here to allow for a rather more efficient - * implementation due to several circumstances that do not apply - * to the more general case: - * - * 1) We have a known bound on the total number of symbols, so we - * have a fixed-size table without any copying when growing - * - * 2) We never delete any entries, so we don't need to - * support/check for DEAD entries during lookup. - * - * 3) The object fits in 32 bits so we store each object in its - * entirety within the table rather than storing objects - * externally and putting pointers in the table, (which here - * would just double the storage requirements and have negative - * impacts on memory locality). - */ - int i, idx, step, hash = symbol & LZW_SYMBOL_KEY_MASK; - lzw_symbol_t candidate; - - idx = hash % LZW_SYMBOL_MOD1; - step = 0; - - *slot_ret = NULL; - for (i = 0; i < LZW_SYMBOL_TABLE_SIZE; i++) - { - candidate = table->table[idx]; - if (candidate == LZW_SYMBOL_FREE) - { - *slot_ret = &table->table[idx]; - return FALSE; - } - else /* candidate is LIVE */ - { - if ((candidate & LZW_SYMBOL_KEY_MASK) == - (symbol & LZW_SYMBOL_KEY_MASK)) - { - *slot_ret = &table->table[idx]; - return TRUE; - } - } - - if (step == 0) { - step = hash % LZW_SYMBOL_MOD2; - if (step == 0) - step = 1; - } - - idx += step; - if (idx >= LZW_SYMBOL_TABLE_SIZE) - idx -= LZW_SYMBOL_TABLE_SIZE; - } - - return FALSE; -} - -/* Compress a bytestream using the LZW algorithm. - * - * This is an original implementation based on reading the - * specification of the LZWDecode filter in the PostScript Language - * Reference. The free parameters in the LZW algorithm are set to the - * values mandated by PostScript, (symbols encoded with widths from 9 - * to 12 bits). - * - * This function returns a pointer to a newly allocated buffer holding - * the compressed data, or %NULL if an out-of-memory situation - * occurs. - * - * Notice that any one of the _lzw_buf functions called here could - * trigger an out-of-memory condition. But lzw_buf_t uses cairo's - * shutdown-on-error idiom, so it's safe to continue to call into - * lzw_buf without having to check for errors, (until a final check at - * the end). - */ -unsigned char * -_cairo_lzw_compress (unsigned char *data, unsigned long *size_in_out) -{ - int bytes_remaining = *size_in_out; - lzw_buf_t buf; - lzw_symbol_table_t table; - lzw_symbol_t symbol, *slot = NULL; /* just to squelch a warning */ - int code_next = LZW_CODE_FIRST; - int code_bits = LZW_BITS_MIN; - int prev, next = 0; /* just to squelch a warning */ - - if (*size_in_out == 0) - return NULL; - - _lzw_buf_init (&buf, *size_in_out); - - _lzw_symbol_table_init (&table); - - /* The LZW header is a clear table code. */ - _lzw_buf_store_bits (&buf, LZW_CODE_CLEAR_TABLE, code_bits); - - while (1) { - - /* Find the longest existing code in the symbol table that - * matches the current input, if any. */ - prev = *data++; - bytes_remaining--; - if (bytes_remaining) { - do - { - next = *data++; - bytes_remaining--; - LZW_SYMBOL_SET (symbol, prev, next); - if (_lzw_symbol_table_lookup (&table, symbol, &slot)) - prev = LZW_SYMBOL_GET_CODE (*slot); - } while (bytes_remaining && *slot != LZW_SYMBOL_FREE); - if (*slot == LZW_SYMBOL_FREE) { - data--; - bytes_remaining++; - } - } - - /* Write the code into the output. This is either a byte read - * directly from the input, or a code from the last successful - * lookup. */ - _lzw_buf_store_bits (&buf, prev, code_bits); - - if (bytes_remaining == 0) - break; - - LZW_SYMBOL_SET_CODE (*slot, code_next++, prev, next); - - if (code_next > LZW_BITS_BOUNDARY(code_bits)) - { - code_bits++; - if (code_bits > LZW_BITS_MAX) { - _lzw_symbol_table_init (&table); - _lzw_buf_store_bits (&buf, LZW_CODE_CLEAR_TABLE, code_bits - 1); - code_bits = LZW_BITS_MIN; - code_next = LZW_CODE_FIRST; - } - } - } - - /* The LZW footer is an end-of-data code. */ - _lzw_buf_store_bits (&buf, LZW_CODE_EOD, code_bits); - - _lzw_buf_store_pending (&buf); - - /* See if we ever ran out of memory while writing to buf. */ - if (buf.status == CAIRO_STATUS_NO_MEMORY) { - *size_in_out = 0; - return NULL; - } - - assert (buf.status == CAIRO_STATUS_SUCCESS); - - *size_in_out = buf.num_data; - return buf.data; -} diff --git a/uppdev/plugin/cairo/lib/cairo-malloc-private.h b/uppdev/plugin/cairo/lib/cairo-malloc-private.h deleted file mode 100644 index f8094f911..000000000 --- a/uppdev/plugin/cairo/lib/cairo-malloc-private.h +++ /dev/null @@ -1,141 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* Cairo - a vector graphics library with display and print output - * - * Copyright © 2007 Mozilla Corporation - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Mozilla Corporation - * - * Contributor(s): - * Vladimir Vukicevic - */ - -#ifndef CAIRO_MALLOC_PRIVATE_H -#define CAIRO_MALLOC_PRIVATE_H - -#include "cairo-wideint-private.h" - -/** - * _cairo_malloc: - * @size: size in bytes - * - * Allocate @size memory using malloc(). - * The memory should be freed using free(). - * malloc is skipped, if 0 bytes are requested, and %NULL will be returned. - * - * Return value: A pointer to the newly allocated memory, or %NULL in - * case of malloc() failure or size is 0. - */ - -#define _cairo_malloc(size) \ - ((size) ? malloc((unsigned) (size)) : NULL) - -/** - * _cairo_malloc_ab: - * @n: number of elements to allocate - * @size: size of each element - * - * Allocates @n*@size memory using _cairo_malloc(), taking care to not - * overflow when doing the multiplication. Behaves much like - * calloc(), except that the returned memory is not set to zero. - * The memory should be freed using free(). - * - * @size should be a constant so that the compiler can optimize - * out a constant division. - * - * Return value: A pointer to the newly allocated memory, or %NULL in - * case of malloc() failure or overflow. - */ - -#define _cairo_malloc_ab(a, size) \ - ((size) && (unsigned) (a) >= INT32_MAX / (unsigned) (size) ? NULL : \ - _cairo_malloc((unsigned) (a) * (unsigned) (size))) - -/** - * _cairo_realloc_ab: - * @ptr: original pointer to block of memory to be resized - * @n: number of elements to allocate - * @size: size of each element - * - * Reallocates @ptr a block of @n*@size memory using realloc(), taking - * care to not overflow when doing the multiplication. The memory - * should be freed using free(). - * - * @size should be a constant so that the compiler can optimize - * out a constant division. - * - * Return value: A pointer to the newly allocated memory, or %NULL in - * case of realloc() failure or overflow (whereupon the original block - * of memory * is left untouched). - */ - -#define _cairo_realloc_ab(ptr, a, size) \ - ((size) && (unsigned) (a) >= INT32_MAX / (unsigned) (size) ? NULL : \ - realloc(ptr, (unsigned) (a) * (unsigned) (size))) - -/** - * _cairo_malloc_abc: - * @n: first factor of number of elements to allocate - * @b: second factor of number of elements to allocate - * @size: size of each element - * - * Allocates @n*@b*@size memory using _cairo_malloc(), taking care to not - * overflow when doing the multiplication. Behaves like - * _cairo_malloc_ab(). The memory should be freed using free(). - * - * @size should be a constant so that the compiler can optimize - * out a constant division. - * - * Return value: A pointer to the newly allocated memory, or %NULL in - * case of malloc() failure or overflow. - */ - -#define _cairo_malloc_abc(a, b, size) \ - ((b) && (unsigned) (a) >= INT32_MAX / (unsigned) (b) ? NULL : \ - (size) && (unsigned) ((a)*(b)) >= INT32_MAX / (unsigned) (size) ? NULL : \ - _cairo_malloc((unsigned) (a) * (unsigned) (b) * (unsigned) (size))) - -/** - * _cairo_malloc_ab_plus_c: - * @n: number of elements to allocate - * @size: size of each element - * @k: additional size to allocate - * - * Allocates @n*@ksize+@k memory using _cairo_malloc(), taking care to not - * overflow when doing the arithmetic. Behaves like - * _cairo_malloc_ab(). The memory should be freed using free(). - * - * Return value: A pointer to the newly allocated memory, or %NULL in - * case of malloc() failure or overflow. - */ - -#define _cairo_malloc_ab_plus_c(n, size, k) \ - ((size) && (unsigned) (n) >= INT32_MAX / (unsigned) (size) ? NULL : \ - (unsigned) (k) >= INT32_MAX - (unsigned) (n) * (unsigned) (size) ? NULL : \ - _cairo_malloc((unsigned) (n) * (unsigned) (size) + (unsigned) (k))) - -#endif /* CAIRO_MALLOC_PRIVATE_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-matrix.c b/uppdev/plugin/cairo/lib/cairo-matrix.c deleted file mode 100644 index ca1832306..000000000 --- a/uppdev/plugin/cairo/lib/cairo-matrix.c +++ /dev/null @@ -1,863 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - */ - -#define _GNU_SOURCE - -#include "cairoint.h" - -#if _XOPEN_SOURCE >= 600 || defined (_ISOC99_SOURCE) -#define ISFINITE(x) isfinite (x) -#else -#define ISFINITE(x) ((x) * (x) >= 0.) /* check for NaNs */ -#endif - -static void -_cairo_matrix_scalar_multiply (cairo_matrix_t *matrix, double scalar); - -static void -_cairo_matrix_compute_adjoint (cairo_matrix_t *matrix); - -/** - * cairo_matrix_init_identity: - * @matrix: a #cairo_matrix_t - * - * Modifies @matrix to be an identity transformation. - **/ -void -cairo_matrix_init_identity (cairo_matrix_t *matrix) -{ - cairo_matrix_init (matrix, - 1, 0, - 0, 1, - 0, 0); -} -slim_hidden_def(cairo_matrix_init_identity); - -/** - * cairo_matrix_init: - * @matrix: a #cairo_matrix_t - * @xx: xx component of the affine transformation - * @yx: yx component of the affine transformation - * @xy: xy component of the affine transformation - * @yy: yy component of the affine transformation - * @x0: X translation component of the affine transformation - * @y0: Y translation component of the affine transformation - * - * Sets @matrix to be the affine transformation given by - * @xx, @yx, @xy, @yy, @x0, @y0. The transformation is given - * by: - * - * x_new = xx * x + xy * y + x0; - * y_new = yx * x + yy * y + y0; - * - **/ -void -cairo_matrix_init (cairo_matrix_t *matrix, - double xx, double yx, - - double xy, double yy, - double x0, double y0) -{ - matrix->xx = xx; matrix->yx = yx; - matrix->xy = xy; matrix->yy = yy; - matrix->x0 = x0; matrix->y0 = y0; -} -slim_hidden_def(cairo_matrix_init); - -/** - * _cairo_matrix_get_affine: - * @matrix: a #cairo_matrix_t - * @xx: location to store xx component of matrix - * @yx: location to store yx component of matrix - * @xy: location to store xy component of matrix - * @yy: location to store yy component of matrix - * @x0: location to store x0 (X-translation component) of matrix, or %NULL - * @y0: location to store y0 (Y-translation component) of matrix, or %NULL - * - * Gets the matrix values for the affine transformation that @matrix represents. - * See cairo_matrix_init(). - * - * - * This function is a leftover from the old public API, but is still - * mildly useful as an internal means for getting at the matrix - * members in a positional way. For example, when reassigning to some - * external matrix type, or when renaming members to more meaningful - * names (such as a,b,c,d,e,f) for particular manipulations. - **/ -void -_cairo_matrix_get_affine (const cairo_matrix_t *matrix, - double *xx, double *yx, - double *xy, double *yy, - double *x0, double *y0) -{ - *xx = matrix->xx; - *yx = matrix->yx; - - *xy = matrix->xy; - *yy = matrix->yy; - - if (x0) - *x0 = matrix->x0; - if (y0) - *y0 = matrix->y0; -} - -/** - * cairo_matrix_init_translate: - * @matrix: a #cairo_matrix_t - * @tx: amount to translate in the X direction - * @ty: amount to translate in the Y direction - * - * Initializes @matrix to a transformation that translates by @tx and - * @ty in the X and Y dimensions, respectively. - **/ -void -cairo_matrix_init_translate (cairo_matrix_t *matrix, - double tx, double ty) -{ - cairo_matrix_init (matrix, - 1, 0, - 0, 1, - tx, ty); -} -slim_hidden_def(cairo_matrix_init_translate); - -/** - * cairo_matrix_translate: - * @matrix: a #cairo_matrix_t - * @tx: amount to translate in the X direction - * @ty: amount to translate in the Y direction - * - * Applies a translation by @tx, @ty to the transformation in - * @matrix. The effect of the new transformation is to first translate - * the coordinates by @tx and @ty, then apply the original transformation - * to the coordinates. - **/ -void -cairo_matrix_translate (cairo_matrix_t *matrix, double tx, double ty) -{ - cairo_matrix_t tmp; - - cairo_matrix_init_translate (&tmp, tx, ty); - - cairo_matrix_multiply (matrix, &tmp, matrix); -} -slim_hidden_def (cairo_matrix_translate); - -/** - * cairo_matrix_init_scale: - * @matrix: a #cairo_matrix_t - * @sx: scale factor in the X direction - * @sy: scale factor in the Y direction - * - * Initializes @matrix to a transformation that scales by @sx and @sy - * in the X and Y dimensions, respectively. - **/ -void -cairo_matrix_init_scale (cairo_matrix_t *matrix, - double sx, double sy) -{ - cairo_matrix_init (matrix, - sx, 0, - 0, sy, - 0, 0); -} -slim_hidden_def(cairo_matrix_init_scale); - -/** - * cairo_matrix_scale: - * @matrix: a #cairo_matrix_t - * @sx: scale factor in the X direction - * @sy: scale factor in the Y direction - * - * Applies scaling by @sx, @sy to the transformation in @matrix. The - * effect of the new transformation is to first scale the coordinates - * by @sx and @sy, then apply the original transformation to the coordinates. - **/ -void -cairo_matrix_scale (cairo_matrix_t *matrix, double sx, double sy) -{ - cairo_matrix_t tmp; - - cairo_matrix_init_scale (&tmp, sx, sy); - - cairo_matrix_multiply (matrix, &tmp, matrix); -} -slim_hidden_def(cairo_matrix_scale); - -/** - * cairo_matrix_init_rotate: - * @matrix: a #cairo_matrix_t - * @radians: angle of rotation, in radians. The direction of rotation - * is defined such that positive angles rotate in the direction from - * the positive X axis toward the positive Y axis. With the default - * axis orientation of cairo, positive angles rotate in a clockwise - * direction. - * - * Initialized @matrix to a transformation that rotates by @radians. - **/ -void -cairo_matrix_init_rotate (cairo_matrix_t *matrix, - double radians) -{ - double s; - double c; - - s = sin (radians); - c = cos (radians); - - cairo_matrix_init (matrix, - c, s, - -s, c, - 0, 0); -} -slim_hidden_def(cairo_matrix_init_rotate); - -/** - * cairo_matrix_rotate: - * @matrix: a #cairo_matrix_t - * @radians: angle of rotation, in radians. The direction of rotation - * is defined such that positive angles rotate in the direction from - * the positive X axis toward the positive Y axis. With the default - * axis orientation of cairo, positive angles rotate in a clockwise - * direction. - * - * Applies rotation by @radians to the transformation in - * @matrix. The effect of the new transformation is to first rotate the - * coordinates by @radians, then apply the original transformation - * to the coordinates. - **/ -void -cairo_matrix_rotate (cairo_matrix_t *matrix, double radians) -{ - cairo_matrix_t tmp; - - cairo_matrix_init_rotate (&tmp, radians); - - cairo_matrix_multiply (matrix, &tmp, matrix); -} - -/** - * cairo_matrix_multiply: - * @result: a #cairo_matrix_t in which to store the result - * @a: a #cairo_matrix_t - * @b: a #cairo_matrix_t - * - * Multiplies the affine transformations in @a and @b together - * and stores the result in @result. The effect of the resulting - * transformation is to first apply the transformation in @a to the - * coordinates and then apply the transformation in @b to the - * coordinates. - * - * It is allowable for @result to be identical to either @a or @b. - **/ -/* - * XXX: The ordering of the arguments to this function corresponds - * to [row_vector]*A*B. If we want to use column vectors instead, - * then we need to switch the two arguments and fix up all - * uses. - */ -void -cairo_matrix_multiply (cairo_matrix_t *result, const cairo_matrix_t *a, const cairo_matrix_t *b) -{ - cairo_matrix_t r; - - r.xx = a->xx * b->xx + a->yx * b->xy; - r.yx = a->xx * b->yx + a->yx * b->yy; - - r.xy = a->xy * b->xx + a->yy * b->xy; - r.yy = a->xy * b->yx + a->yy * b->yy; - - r.x0 = a->x0 * b->xx + a->y0 * b->xy + b->x0; - r.y0 = a->x0 * b->yx + a->y0 * b->yy + b->y0; - - *result = r; -} -slim_hidden_def(cairo_matrix_multiply); - -/** - * cairo_matrix_transform_distance: - * @matrix: a #cairo_matrix_t - * @dx: X component of a distance vector. An in/out parameter - * @dy: Y component of a distance vector. An in/out parameter - * - * Transforms the distance vector (@dx,@dy) by @matrix. This is - * similar to cairo_matrix_transform_point() except that the translation - * components of the transformation are ignored. The calculation of - * the returned vector is as follows: - * - * - * dx2 = dx1 * a + dy1 * c; - * dy2 = dx1 * b + dy1 * d; - * - * - * Affine transformations are position invariant, so the same vector - * always transforms to the same vector. If (@x1,@y1) transforms - * to (@x2,@y2) then (@x1+@dx1,@y1+@dy1) will transform to - * (@x1+@dx2,@y1+@dy2) for all values of @x1 and @x2. - **/ -void -cairo_matrix_transform_distance (const cairo_matrix_t *matrix, double *dx, double *dy) -{ - double new_x, new_y; - - new_x = (matrix->xx * *dx + matrix->xy * *dy); - new_y = (matrix->yx * *dx + matrix->yy * *dy); - - *dx = new_x; - *dy = new_y; -} -slim_hidden_def(cairo_matrix_transform_distance); - -/** - * cairo_matrix_transform_point: - * @matrix: a #cairo_matrix_t - * @x: X position. An in/out parameter - * @y: Y position. An in/out parameter - * - * Transforms the point (@x, @y) by @matrix. - **/ -void -cairo_matrix_transform_point (const cairo_matrix_t *matrix, double *x, double *y) -{ - cairo_matrix_transform_distance (matrix, x, y); - - *x += matrix->x0; - *y += matrix->y0; -} -slim_hidden_def(cairo_matrix_transform_point); - -void -_cairo_matrix_transform_bounding_box (const cairo_matrix_t *matrix, - double *x1, double *y1, - double *x2, double *y2, - cairo_bool_t *is_tight) -{ - int i; - double quad_x[4], quad_y[4]; - double min_x, max_x; - double min_y, max_y; - - quad_x[0] = *x1; - quad_y[0] = *y1; - cairo_matrix_transform_point (matrix, &quad_x[0], &quad_y[0]); - - quad_x[1] = *x2; - quad_y[1] = *y1; - cairo_matrix_transform_point (matrix, &quad_x[1], &quad_y[1]); - - quad_x[2] = *x1; - quad_y[2] = *y2; - cairo_matrix_transform_point (matrix, &quad_x[2], &quad_y[2]); - - quad_x[3] = *x2; - quad_y[3] = *y2; - cairo_matrix_transform_point (matrix, &quad_x[3], &quad_y[3]); - - min_x = max_x = quad_x[0]; - min_y = max_y = quad_y[0]; - - for (i=1; i < 4; i++) { - if (quad_x[i] < min_x) - min_x = quad_x[i]; - if (quad_x[i] > max_x) - max_x = quad_x[i]; - - if (quad_y[i] < min_y) - min_y = quad_y[i]; - if (quad_y[i] > max_y) - max_y = quad_y[i]; - } - - *x1 = min_x; - *y1 = min_y; - *x2 = max_x; - *y2 = max_y; - - if (is_tight) { - /* it's tight if and only if the four corner points form an axis-aligned - rectangle. - And that's true if and only if we can derive corners 0 and 3 from - corners 1 and 2 in one of two straightforward ways... - We could use a tolerance here but for now we'll fall back to FALSE in the case - of floating point error. - */ - *is_tight = - (quad_x[1] == quad_x[0] && quad_y[1] == quad_y[3] && - quad_x[2] == quad_x[3] && quad_y[2] == quad_y[0]) || - (quad_x[1] == quad_x[3] && quad_y[1] == quad_y[0] && - quad_x[2] == quad_x[0] && quad_y[2] == quad_y[3]); - } -} - -cairo_private void -_cairo_matrix_transform_bounding_box_fixed (const cairo_matrix_t *matrix, - cairo_box_t *bbox, - cairo_bool_t *is_tight) -{ - double x1, y1, x2, y2; - - _cairo_box_to_doubles (bbox, &x1, &y1, &x2, &y2); - _cairo_matrix_transform_bounding_box (matrix, &x1, &y1, &x2, &y2, is_tight); - _cairo_box_from_doubles (bbox, &x1, &y1, &x2, &y2); -} - -static void -_cairo_matrix_scalar_multiply (cairo_matrix_t *matrix, double scalar) -{ - matrix->xx *= scalar; - matrix->yx *= scalar; - - matrix->xy *= scalar; - matrix->yy *= scalar; - - matrix->x0 *= scalar; - matrix->y0 *= scalar; -} - -/* This function isn't a correct adjoint in that the implicit 1 in the - homogeneous result should actually be ad-bc instead. But, since this - adjoint is only used in the computation of the inverse, which - divides by det (A)=ad-bc anyway, everything works out in the end. */ -static void -_cairo_matrix_compute_adjoint (cairo_matrix_t *matrix) -{ - /* adj (A) = transpose (C:cofactor (A,i,j)) */ - double a, b, c, d, tx, ty; - - _cairo_matrix_get_affine (matrix, - &a, &b, - &c, &d, - &tx, &ty); - - cairo_matrix_init (matrix, - d, -b, - -c, a, - c*ty - d*tx, b*tx - a*ty); -} - -/** - * cairo_matrix_invert: - * @matrix: a #cairo_matrix_t - * - * Changes @matrix to be the inverse of it's original value. Not - * all transformation matrices have inverses; if the matrix - * collapses points together (it is degenerate), - * then it has no inverse and this function will fail. - * - * Returns: If @matrix has an inverse, modifies @matrix to - * be the inverse matrix and returns %CAIRO_STATUS_SUCCESS. Otherwise, - * returns %CAIRO_STATUS_INVALID_MATRIX. - **/ -cairo_status_t -cairo_matrix_invert (cairo_matrix_t *matrix) -{ - /* inv (A) = 1/det (A) * adj (A) */ - double det; - - det = _cairo_matrix_compute_determinant (matrix); - - if (! ISFINITE (det)) - return _cairo_error (CAIRO_STATUS_INVALID_MATRIX); - - if (det == 0) - return _cairo_error (CAIRO_STATUS_INVALID_MATRIX); - - _cairo_matrix_compute_adjoint (matrix); - _cairo_matrix_scalar_multiply (matrix, 1 / det); - - return CAIRO_STATUS_SUCCESS; -} -slim_hidden_def(cairo_matrix_invert); - -cairo_bool_t -_cairo_matrix_is_invertible (const cairo_matrix_t *matrix) -{ - double det; - - det = _cairo_matrix_compute_determinant (matrix); - - return ISFINITE (det) && det != 0.; -} - -double -_cairo_matrix_compute_determinant (const cairo_matrix_t *matrix) -{ - double a, b, c, d; - - a = matrix->xx; b = matrix->yx; - c = matrix->xy; d = matrix->yy; - - return a*d - b*c; -} - -/** - * _cairo_matrix_compute_basis_scale_factors: - * @matrix: a matrix - * @basis_scale: the scale factor in the direction of basis - * @normal_scale: the scale factor in the direction normal to the basis - * @x_basis: basis to use. X basis if true, Y basis otherwise. - * - * Computes |Mv| and det(M)/|Mv| for v=[1,0] if x_basis is true, and v=[0,1] - * otherwise, and M is @matrix. - * - * Return value: the scale factor of @matrix on the height of the font, - * or 1.0 if @matrix is %NULL. - **/ -cairo_status_t -_cairo_matrix_compute_basis_scale_factors (const cairo_matrix_t *matrix, - double *basis_scale, double *normal_scale, - cairo_bool_t x_basis) -{ - double det; - - det = _cairo_matrix_compute_determinant (matrix); - - if (! ISFINITE (det)) - return _cairo_error (CAIRO_STATUS_INVALID_MATRIX); - - if (det == 0) - { - *basis_scale = *normal_scale = 0; - } - else - { - double x = x_basis != 0; - double y = x == 0; - double major, minor; - - cairo_matrix_transform_distance (matrix, &x, &y); - major = sqrt(x*x + y*y); - /* - * ignore mirroring - */ - if (det < 0) - det = -det; - if (major) - minor = det / major; - else - minor = 0.0; - if (x_basis) - { - *basis_scale = major; - *normal_scale = minor; - } - else - { - *basis_scale = minor; - *normal_scale = major; - } - } - - return CAIRO_STATUS_SUCCESS; -} - -cairo_bool_t -_cairo_matrix_is_identity (const cairo_matrix_t *matrix) -{ - return (matrix->xx == 1.0 && matrix->yx == 0.0 && - matrix->xy == 0.0 && matrix->yy == 1.0 && - matrix->x0 == 0.0 && matrix->y0 == 0.0); -} - -cairo_bool_t -_cairo_matrix_is_translation (const cairo_matrix_t *matrix) -{ - return (matrix->xx == 1.0 && matrix->yx == 0.0 && - matrix->xy == 0.0 && matrix->yy == 1.0); -} - -cairo_bool_t -_cairo_matrix_is_integer_translation (const cairo_matrix_t *matrix, - int *itx, int *ity) -{ - if (_cairo_matrix_is_translation (matrix)) - { - cairo_fixed_t x0_fixed = _cairo_fixed_from_double (matrix->x0); - cairo_fixed_t y0_fixed = _cairo_fixed_from_double (matrix->y0); - - if (_cairo_fixed_is_integer (x0_fixed) && - _cairo_fixed_is_integer (y0_fixed)) - { - if (itx) - *itx = _cairo_fixed_integer_part (x0_fixed); - if (ity) - *ity = _cairo_fixed_integer_part (y0_fixed); - - return TRUE; - } - } - - return FALSE; -} - -/* By pixel exact here, we mean a matrix that is composed only of - * 90 degree rotations, flips, and integer translations and produces a 1:1 - * mapping between source and destination pixels. If we transform an image - * with a pixel-exact matrix, filtering is not useful. - */ -cairo_private cairo_bool_t -_cairo_matrix_is_pixel_exact (const cairo_matrix_t *matrix) -{ - cairo_fixed_t x0_fixed, y0_fixed; - - 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; - - x0_fixed = _cairo_fixed_from_double (matrix->x0); - y0_fixed = _cairo_fixed_from_double (matrix->y0); - - return _cairo_fixed_is_integer (x0_fixed) && _cairo_fixed_is_integer (y0_fixed); -} - -/* - A circle in user space is transformed into an ellipse in device space. - - The following is a derivation of a formula to calculate the length of the - major axis for this ellipse; this is useful for error bounds calculations. - - Thanks to Walter Brisken for this derivation: - - 1. First some notation: - - All capital letters represent vectors in two dimensions. A prime ' - represents a transformed coordinate. Matrices are written in underlined - form, ie _R_. Lowercase letters represent scalar real values. - - 2. The question has been posed: What is the maximum expansion factor - achieved by the linear transformation - - X' = X _R_ - - where _R_ is a real-valued 2x2 matrix with entries: - - _R_ = [a b] - [c d] . - - In other words, what is the maximum radius, MAX[ |X'| ], reached for any - X on the unit circle ( |X| = 1 ) ? - - 3. Some useful formulae - - (A) through (C) below are standard double-angle formulae. (D) is a lesser - known result and is derived below: - - (A) sin²(θ) = (1 - cos(2*θ))/2 - (B) cos²(θ) = (1 + cos(2*θ))/2 - (C) sin(θ)*cos(θ) = sin(2*θ)/2 - (D) MAX[a*cos(θ) + b*sin(θ)] = sqrt(a² + b²) - - Proof of (D): - - find the maximum of the function by setting the derivative to zero: - - -a*sin(θ)+b*cos(θ) = 0 - - From this it follows that - - tan(θ) = b/a - - and hence - - sin(θ) = b/sqrt(a² + b²) - - and - - cos(θ) = a/sqrt(a² + b²) - - Thus the maximum value is - - MAX[a*cos(θ) + b*sin(θ)] = (a² + b²)/sqrt(a² + b²) - = sqrt(a² + b²) - - 4. Derivation of maximum expansion - - To find MAX[ |X'| ] we search brute force method using calculus. The unit - circle on which X is constrained is to be parameterized by t: - - X(θ) = (cos(θ), sin(θ)) - - Thus - - X'(θ) = X(θ) * _R_ = (cos(θ), sin(θ)) * [a b] - [c d] - = (a*cos(θ) + c*sin(θ), b*cos(θ) + d*sin(θ)). - - Define - - r(θ) = |X'(θ)| - - Thus - - r²(θ) = (a*cos(θ) + c*sin(θ))² + (b*cos(θ) + d*sin(θ))² - = (a² + b²)*cos²(θ) + (c² + d²)*sin²(θ) - + 2*(a*c + b*d)*cos(θ)*sin(θ) - - Now apply the double angle formulae (A) to (C) from above: - - r²(θ) = (a² + b² + c² + d²)/2 - + (a² + b² - c² - d²)*cos(2*θ)/2 - + (a*c + b*d)*sin(2*θ) - = f + g*cos(φ) + h*sin(φ) - - Where - - f = (a² + b² + c² + d²)/2 - g = (a² + b² - c² - d²)/2 - h = (a*c + d*d) - φ = 2*θ - - It is clear that MAX[ |X'| ] = sqrt(MAX[ r² ]). Here we determine MAX[ r² ] - using (D) from above: - - MAX[ r² ] = f + sqrt(g² + h²) - - And finally - - MAX[ |X'| ] = sqrt( f + sqrt(g² + h²) ) - - Which is the solution to this problem. - - Walter Brisken - 2004/10/08 - - (Note that the minor axis length is at the minimum of the above solution, - which is just sqrt ( f - sqrt(g² + h²) ) given the symmetry of (D)). - - - For another derivation of the same result, using Singular Value Decomposition, - see doc/tutorial/src/singular.c. -*/ - -/* determine the length of the major axis of a circle of the given radius - after applying the transformation matrix. */ -double -_cairo_matrix_transformed_circle_major_axis (cairo_matrix_t *matrix, double radius) -{ - double a, b, c, d, f, g, h, i, j; - - _cairo_matrix_get_affine (matrix, - &a, &b, - &c, &d, - NULL, NULL); - - i = a*a + b*b; - j = c*c + d*d; - - f = 0.5 * (i + j); - g = 0.5 * (i - j); - h = a*c + b*d; - - return radius * sqrt (f + sqrt (g*g+h*h)); - - /* - * we don't need the minor axis length, which is - * double min = radius * sqrt (f - sqrt (g*g+h*h)); - */ -} - -void -_cairo_matrix_to_pixman_matrix (const cairo_matrix_t *matrix, - pixman_transform_t *pixman_transform) -{ - static const pixman_transform_t pixman_identity_transform = {{ - {1 << 16, 0, 0}, - { 0, 1 << 16, 0}, - { 0, 0, 1 << 16} - }}; - - if (_cairo_matrix_is_identity (matrix)) { - *pixman_transform = pixman_identity_transform; - } - else { - cairo_matrix_t inv = *matrix; - double x = 0, y = 0; - pixman_vector_t vector; - - pixman_transform->matrix[0][0] = _cairo_fixed_16_16_from_double (matrix->xx); - pixman_transform->matrix[0][1] = _cairo_fixed_16_16_from_double (matrix->xy); - pixman_transform->matrix[0][2] = _cairo_fixed_16_16_from_double (matrix->x0); - - pixman_transform->matrix[1][0] = _cairo_fixed_16_16_from_double (matrix->yx); - pixman_transform->matrix[1][1] = _cairo_fixed_16_16_from_double (matrix->yy); - pixman_transform->matrix[1][2] = _cairo_fixed_16_16_from_double (matrix->y0); - - pixman_transform->matrix[2][0] = 0; - pixman_transform->matrix[2][1] = 0; - pixman_transform->matrix[2][2] = 1 << 16; - - /* The conversion above breaks cairo's translation invariance: - * a translation of (a, b) in device space translates to - * a translation of (xx * a + xy * b, yx * a + yy * b) - * for cairo, while pixman uses rounded versions of xx ... yy. - * This error increases as a and b get larger. - * - * To compensate for this, we fix the point (0, 0) in pattern - * space and adjust pixman's transform to agree with cairo's at - * that point. */ - - /* Note: If we can't invert the transformation, skip the adjustment. */ - if (cairo_matrix_invert (&inv) != CAIRO_STATUS_SUCCESS) - return; - - /* find the device space coordinate that maps to (0, 0) */ - cairo_matrix_transform_point (&inv, &x, &y); - - /* transform the resulting device space coordinate back - * to the pattern space, using pixman's transform */ - vector.vector[0] = _cairo_fixed_16_16_from_double (x); - vector.vector[1] = _cairo_fixed_16_16_from_double (y); - vector.vector[2] = 1 << 16; - - if (!pixman_transform_point_3d (pixman_transform, &vector)) - return; - - /* Ideally, the vector should now be (0, 0). We can now compensate - * for the resulting error */ - pixman_transform->matrix[0][2] -= vector.vector[0]; - pixman_transform->matrix[1][2] -= vector.vector[1]; - } -} diff --git a/uppdev/plugin/cairo/lib/cairo-meta-surface-private.h b/uppdev/plugin/cairo/lib/cairo-meta-surface-private.h deleted file mode 100644 index 9a1b169cf..000000000 --- a/uppdev/plugin/cairo/lib/cairo-meta-surface-private.h +++ /dev/null @@ -1,190 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Kristian Høgsberg - * Adrian Johnson - */ - -#ifndef CAIRO_META_SURFACE_H -#define CAIRO_META_SURFACE_H - -#include "cairoint.h" -#include "cairo-path-fixed-private.h" - -typedef enum { - /* The 5 basic drawing operations. */ - CAIRO_COMMAND_PAINT, - CAIRO_COMMAND_MASK, - CAIRO_COMMAND_STROKE, - CAIRO_COMMAND_FILL, - CAIRO_COMMAND_SHOW_TEXT_GLYPHS, - - /* Other junk. For most of these, we should be able to assert that - * they never get called except as part of fallbacks for the 5 - * basic drawing operations (which we implement already so the - * fallbacks should never get triggered). So the plan is to - * eliminate as many of these as possible. */ - - CAIRO_COMMAND_INTERSECT_CLIP_PATH - -} cairo_command_type_t; - -typedef enum { - CAIRO_META_REGION_ALL, - CAIRO_META_REGION_NATIVE, - CAIRO_META_REGION_IMAGE_FALLBACK -} cairo_meta_region_type_t; - -typedef struct _cairo_command_header { - cairo_command_type_t type; - cairo_meta_region_type_t region; -} cairo_command_header_t; - -typedef struct _cairo_command_paint { - cairo_command_header_t header; - cairo_operator_t op; - cairo_pattern_union_t source; -} cairo_command_paint_t; - -typedef struct _cairo_command_mask { - cairo_command_header_t header; - cairo_operator_t op; - cairo_pattern_union_t source; - cairo_pattern_union_t mask; -} cairo_command_mask_t; - -typedef struct _cairo_command_stroke { - cairo_command_header_t header; - cairo_operator_t op; - cairo_pattern_union_t source; - 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_command_stroke_t; - -typedef struct _cairo_command_fill { - cairo_command_header_t header; - cairo_operator_t op; - cairo_pattern_union_t source; - cairo_path_fixed_t path; - cairo_fill_rule_t fill_rule; - double tolerance; - cairo_antialias_t antialias; -} cairo_command_fill_t; - -typedef struct _cairo_command_show_text_glyphs { - cairo_command_header_t header; - cairo_operator_t op; - cairo_pattern_union_t source; - char *utf8; - int utf8_len; - cairo_glyph_t *glyphs; - unsigned int num_glyphs; - cairo_text_cluster_t *clusters; - int num_clusters; - cairo_text_cluster_flags_t cluster_flags; - cairo_scaled_font_t *scaled_font; -} cairo_command_show_text_glyphs_t; - -typedef struct _cairo_command_intersect_clip_path { - cairo_command_header_t header; - cairo_path_fixed_t *path_pointer; - cairo_path_fixed_t path; - cairo_fill_rule_t fill_rule; - double tolerance; - cairo_antialias_t antialias; -} cairo_command_intersect_clip_path_t; - -typedef union _cairo_command { - cairo_command_header_t header; - - /* The 5 basic drawing operations. */ - cairo_command_paint_t paint; - cairo_command_mask_t mask; - cairo_command_stroke_t stroke; - cairo_command_fill_t fill; - cairo_command_show_text_glyphs_t show_text_glyphs; - - /* The other junk. */ - cairo_command_intersect_clip_path_t intersect_clip_path; -} cairo_command_t; - -typedef struct _cairo_meta_surface { - cairo_surface_t base; - - cairo_content_t content; - - /* A meta-surface is logically unbounded, but when used as a - * source we need to render it to an image, so we need a size at - * which to create that image. */ - int width_pixels; - int height_pixels; - - cairo_array_t commands; - cairo_surface_t *commands_owner; - - cairo_bool_t is_clipped; - int replay_start_idx; -} cairo_meta_surface_t; - -cairo_private cairo_surface_t * -_cairo_meta_surface_create (cairo_content_t content, - int width_pixels, - int height_pixels); - -cairo_private cairo_int_status_t -_cairo_meta_surface_get_path (cairo_surface_t *surface, - cairo_path_fixed_t *path); - -cairo_private cairo_status_t -_cairo_meta_surface_replay (cairo_surface_t *surface, - cairo_surface_t *target); - -cairo_private cairo_status_t -_cairo_meta_surface_replay_analyze_meta_pattern (cairo_surface_t *surface, - cairo_surface_t *target); - -cairo_private cairo_status_t -_cairo_meta_surface_replay_and_create_regions (cairo_surface_t *surface, - cairo_surface_t *target); -cairo_private cairo_status_t -_cairo_meta_surface_replay_region (cairo_surface_t *surface, - cairo_surface_t *target, - cairo_meta_region_type_t region); - -cairo_private cairo_bool_t -_cairo_surface_is_meta (const cairo_surface_t *surface); - -#endif /* CAIRO_META_SURFACE_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-meta-surface.c b/uppdev/plugin/cairo/lib/cairo-meta-surface.c deleted file mode 100644 index b86cb5136..000000000 --- a/uppdev/plugin/cairo/lib/cairo-meta-surface.c +++ /dev/null @@ -1,1010 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2005 Red Hat, Inc - * Copyright © 2007 Adrian Johnson - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Kristian Høgsberg - * Carl Worth - * Adrian Johnson - */ - -/* A meta surface is a surface that records all drawing operations at - * the highest level of the surface backend interface, (that is, the - * level of paint, mask, stroke, fill, and show_text_glyphs). The meta - * surface can then be "replayed" against any target surface with: - * - * _cairo_meta_surface_replay (meta, target); - * - * after which the results in target will be identical to the results - * that would have been obtained if the original operations applied to - * the meta surface had instead been applied to the target surface. - * - * The recording phase of the meta surface is careful to snapshot all - * necessary objects (paths, patterns, etc.), in order to achieve - * accurate replay. The efficiency of the meta surface could be - * improved by improving the implementation of snapshot for the - * various objects. For example, it would be nice to have a - * copy-on-write implementation for _cairo_surface_snapshot. - */ - -#include "cairoint.h" -#include "cairo-meta-surface-private.h" -#include "cairo-clip-private.h" - -typedef enum { - CAIRO_META_REPLAY, - CAIRO_META_CREATE_REGIONS -} cairo_meta_replay_type_t; - -static const cairo_surface_backend_t cairo_meta_surface_backend; - -/* Currently all meta surfaces do have a size which should be passed - * in as the maximum size of any target surface against which the - * meta-surface will ever be replayed. - * - * XXX: The naming of "pixels" in the size here is a misnomer. It's - * actually a size in whatever device-space units are desired (again, - * according to the intended replay target). This should likely also - * be changed to use doubles not ints. - */ -cairo_surface_t * -_cairo_meta_surface_create (cairo_content_t content, - int width_pixels, - int height_pixels) -{ - cairo_meta_surface_t *meta; - - meta = malloc (sizeof (cairo_meta_surface_t)); - if (meta == NULL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - _cairo_surface_init (&meta->base, &cairo_meta_surface_backend, - content); - - meta->content = content; - meta->width_pixels = width_pixels; - meta->height_pixels = height_pixels; - - _cairo_array_init (&meta->commands, sizeof (cairo_command_t *)); - meta->commands_owner = NULL; - - meta->is_clipped = FALSE; - meta->replay_start_idx = 0; - - return &meta->base; -} - -static cairo_surface_t * -_cairo_meta_surface_create_similar (void *abstract_surface, - cairo_content_t content, - int width, - int height) -{ - return _cairo_meta_surface_create (content, width, height); -} - -static cairo_status_t -_cairo_meta_surface_finish (void *abstract_surface) -{ - cairo_meta_surface_t *meta = abstract_surface; - cairo_command_t *command; - cairo_command_t **elements; - int i, num_elements; - - if (meta->commands_owner) { - cairo_surface_destroy (meta->commands_owner); - return CAIRO_STATUS_SUCCESS; - } - - num_elements = meta->commands.num_elements; - elements = _cairo_array_index (&meta->commands, 0); - for (i = 0; i < num_elements; i++) { - command = elements[i]; - switch (command->header.type) { - - /* 5 basic drawing operations */ - - case CAIRO_COMMAND_PAINT: - _cairo_pattern_fini (&command->paint.source.base); - free (command); - break; - - case CAIRO_COMMAND_MASK: - _cairo_pattern_fini (&command->mask.source.base); - _cairo_pattern_fini (&command->mask.mask.base); - free (command); - break; - - case CAIRO_COMMAND_STROKE: - _cairo_pattern_fini (&command->stroke.source.base); - _cairo_path_fixed_fini (&command->stroke.path); - _cairo_stroke_style_fini (&command->stroke.style); - free (command); - break; - - case CAIRO_COMMAND_FILL: - _cairo_pattern_fini (&command->fill.source.base); - _cairo_path_fixed_fini (&command->fill.path); - free (command); - break; - - case CAIRO_COMMAND_SHOW_TEXT_GLYPHS: - _cairo_pattern_fini (&command->show_text_glyphs.source.base); - free (command->show_text_glyphs.utf8); - free (command->show_text_glyphs.glyphs); - free (command->show_text_glyphs.clusters); - cairo_scaled_font_destroy (command->show_text_glyphs.scaled_font); - free (command); - break; - - /* Other junk. */ - case CAIRO_COMMAND_INTERSECT_CLIP_PATH: - if (command->intersect_clip_path.path_pointer) - _cairo_path_fixed_fini (&command->intersect_clip_path.path); - free (command); - break; - - default: - ASSERT_NOT_REACHED; - } - } - - _cairo_array_fini (&meta->commands); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_meta_surface_acquire_source_image (void *abstract_surface, - cairo_image_surface_t **image_out, - void **image_extra) -{ - cairo_status_t status; - cairo_meta_surface_t *surface = abstract_surface; - cairo_surface_t *image; - - image = _cairo_image_surface_create_with_content (surface->content, - surface->width_pixels, - surface->height_pixels); - - status = _cairo_meta_surface_replay (&surface->base, image); - if (status) { - cairo_surface_destroy (image); - return status; - } - - *image_out = (cairo_image_surface_t *) image; - *image_extra = NULL; - - return status; -} - -static void -_cairo_meta_surface_release_source_image (void *abstract_surface, - cairo_image_surface_t *image, - void *image_extra) -{ - cairo_surface_destroy (&image->base); -} - -static cairo_int_status_t -_cairo_meta_surface_paint (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source) -{ - cairo_status_t status; - cairo_meta_surface_t *meta = abstract_surface; - cairo_command_paint_t *command; - - command = malloc (sizeof (cairo_command_paint_t)); - if (command == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - command->header.type = CAIRO_COMMAND_PAINT; - command->header.region = CAIRO_META_REGION_ALL; - command->op = op; - - status = _cairo_pattern_init_snapshot (&command->source.base, source); - if (status) - goto CLEANUP_COMMAND; - - status = _cairo_array_append (&meta->commands, &command); - if (status) - goto CLEANUP_SOURCE; - - /* An optimisation that takes care to not replay what was done - * before surface is cleared. We don't erase recorded commands - * since we may have earlier snapshots of this surface. */ - if (op == CAIRO_OPERATOR_CLEAR && !meta->is_clipped) - meta->replay_start_idx = meta->commands.num_elements; - - return CAIRO_STATUS_SUCCESS; - - CLEANUP_SOURCE: - _cairo_pattern_fini (&command->source.base); - CLEANUP_COMMAND: - free (command); - return status; -} - -static cairo_int_status_t -_cairo_meta_surface_mask (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_pattern_t *mask) -{ - cairo_status_t status; - cairo_meta_surface_t *meta = abstract_surface; - cairo_command_mask_t *command; - - command = malloc (sizeof (cairo_command_mask_t)); - if (command == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - command->header.type = CAIRO_COMMAND_MASK; - command->header.region = CAIRO_META_REGION_ALL; - command->op = op; - - status = _cairo_pattern_init_snapshot (&command->source.base, source); - if (status) - goto CLEANUP_COMMAND; - - status = _cairo_pattern_init_snapshot (&command->mask.base, mask); - if (status) - goto CLEANUP_SOURCE; - - status = _cairo_array_append (&meta->commands, &command); - if (status) - goto CLEANUP_MASK; - - return CAIRO_STATUS_SUCCESS; - - CLEANUP_MASK: - _cairo_pattern_fini (&command->mask.base); - CLEANUP_SOURCE: - _cairo_pattern_fini (&command->source.base); - CLEANUP_COMMAND: - free (command); - return status; -} - -static cairo_int_status_t -_cairo_meta_surface_stroke (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - 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_status_t status; - cairo_meta_surface_t *meta = abstract_surface; - cairo_command_stroke_t *command; - - command = malloc (sizeof (cairo_command_stroke_t)); - if (command == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - command->header.type = CAIRO_COMMAND_STROKE; - command->header.region = CAIRO_META_REGION_ALL; - command->op = op; - - status = _cairo_pattern_init_snapshot (&command->source.base, source); - if (status) - goto CLEANUP_COMMAND; - - status = _cairo_path_fixed_init_copy (&command->path, path); - if (status) - goto CLEANUP_SOURCE; - - status = _cairo_stroke_style_init_copy (&command->style, style); - if (status) - goto CLEANUP_PATH; - - command->ctm = *ctm; - command->ctm_inverse = *ctm_inverse; - command->tolerance = tolerance; - command->antialias = antialias; - - status = _cairo_array_append (&meta->commands, &command); - if (status) - goto CLEANUP_STYLE; - - return CAIRO_STATUS_SUCCESS; - - CLEANUP_STYLE: - _cairo_stroke_style_fini (&command->style); - CLEANUP_PATH: - _cairo_path_fixed_fini (&command->path); - CLEANUP_SOURCE: - _cairo_pattern_fini (&command->source.base); - CLEANUP_COMMAND: - free (command); - return status; -} - -static cairo_int_status_t -_cairo_meta_surface_fill (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_status_t status; - cairo_meta_surface_t *meta = abstract_surface; - cairo_command_fill_t *command; - - command = malloc (sizeof (cairo_command_fill_t)); - if (command == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - command->header.type = CAIRO_COMMAND_FILL; - command->header.region = CAIRO_META_REGION_ALL; - command->op = op; - - status = _cairo_pattern_init_snapshot (&command->source.base, source); - if (status) - goto CLEANUP_COMMAND; - - status = _cairo_path_fixed_init_copy (&command->path, path); - if (status) - goto CLEANUP_SOURCE; - - command->fill_rule = fill_rule; - command->tolerance = tolerance; - command->antialias = antialias; - - status = _cairo_array_append (&meta->commands, &command); - if (status) - goto CLEANUP_PATH; - - return CAIRO_STATUS_SUCCESS; - - CLEANUP_PATH: - _cairo_path_fixed_fini (&command->path); - CLEANUP_SOURCE: - _cairo_pattern_fini (&command->source.base); - CLEANUP_COMMAND: - free (command); - return status; -} - -static cairo_bool_t -_cairo_meta_surface_has_show_text_glyphs (void *abstract_surface) -{ - return TRUE; -} - -static cairo_int_status_t -_cairo_meta_surface_show_text_glyphs (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - const char *utf8, - int utf8_len, - cairo_glyph_t *glyphs, - int num_glyphs, - const cairo_text_cluster_t *clusters, - int num_clusters, - cairo_text_cluster_flags_t cluster_flags, - cairo_scaled_font_t *scaled_font) -{ - cairo_status_t status; - cairo_meta_surface_t *meta = abstract_surface; - cairo_command_show_text_glyphs_t *command; - - command = malloc (sizeof (cairo_command_show_text_glyphs_t)); - if (command == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - command->header.type = CAIRO_COMMAND_SHOW_TEXT_GLYPHS; - command->header.region = CAIRO_META_REGION_ALL; - command->op = op; - - status = _cairo_pattern_init_snapshot (&command->source.base, source); - if (status) - goto CLEANUP_COMMAND; - - command->utf8 = NULL; - command->utf8_len = utf8_len; - command->glyphs = NULL; - command->num_glyphs = num_glyphs; - command->clusters = NULL; - command->num_clusters = num_clusters; - - if (utf8_len) { - command->utf8 = malloc (utf8_len); - if (command->utf8 == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto CLEANUP_ARRAYS; - } - memcpy (command->utf8, utf8, utf8_len); - } - if (num_glyphs) { - command->glyphs = _cairo_malloc_ab (num_glyphs, sizeof (glyphs[0])); - if (command->glyphs == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto CLEANUP_ARRAYS; - } - memcpy (command->glyphs, glyphs, sizeof (glyphs[0]) * num_glyphs); - } - if (num_clusters) { - command->clusters = _cairo_malloc_ab (num_clusters, sizeof (clusters[0])); - if (command->clusters == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto CLEANUP_ARRAYS; - } - memcpy (command->clusters, clusters, sizeof (clusters[0]) * num_clusters); - } - - command->cluster_flags = cluster_flags; - - command->scaled_font = cairo_scaled_font_reference (scaled_font); - - status = _cairo_array_append (&meta->commands, &command); - if (status) - goto CLEANUP_SCALED_FONT; - - return CAIRO_STATUS_SUCCESS; - - CLEANUP_SCALED_FONT: - cairo_scaled_font_destroy (command->scaled_font); - CLEANUP_ARRAYS: - free (command->utf8); - free (command->glyphs); - free (command->clusters); - - _cairo_pattern_fini (&command->source.base); - CLEANUP_COMMAND: - free (command); - return status; -} - -/** - * _cairo_meta_surface_snapshot - * @surface: a #cairo_surface_t which must be a meta surface - * - * Make an immutable copy of @surface. It is an error to call a - * surface-modifying function on the result of this function. - * - * The caller owns the return value and should call - * cairo_surface_destroy() when finished with it. This function will not - * return %NULL, but will return a nil surface instead. - * - * Return value: The snapshot surface. - **/ -static cairo_surface_t * -_cairo_meta_surface_snapshot (void *abstract_other) -{ - cairo_meta_surface_t *other = abstract_other; - cairo_meta_surface_t *meta; - - meta = malloc (sizeof (cairo_meta_surface_t)); - if (meta == NULL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - _cairo_surface_init (&meta->base, &cairo_meta_surface_backend, - other->base.content); - meta->base.is_snapshot = TRUE; - - meta->width_pixels = other->width_pixels; - meta->height_pixels = other->height_pixels; - meta->replay_start_idx = other->replay_start_idx; - meta->content = other->content; - - _cairo_array_init_snapshot (&meta->commands, &other->commands); - meta->commands_owner = cairo_surface_reference (&other->base); - - return &meta->base; -} - -static cairo_int_status_t -_cairo_meta_surface_intersect_clip_path (void *dst, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_meta_surface_t *meta = dst; - cairo_command_intersect_clip_path_t *command; - cairo_status_t status; - - command = malloc (sizeof (cairo_command_intersect_clip_path_t)); - if (command == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - command->header.type = CAIRO_COMMAND_INTERSECT_CLIP_PATH; - command->header.region = CAIRO_META_REGION_ALL; - - if (path) { - status = _cairo_path_fixed_init_copy (&command->path, path); - if (status) { - free (command); - return status; - } - command->path_pointer = &command->path; - meta->is_clipped = TRUE; - } else { - command->path_pointer = NULL; - meta->is_clipped = FALSE; - } - command->fill_rule = fill_rule; - command->tolerance = tolerance; - command->antialias = antialias; - - status = _cairo_array_append (&meta->commands, &command); - if (status) { - if (path) - _cairo_path_fixed_fini (&command->path); - free (command); - return status; - } - - return CAIRO_STATUS_SUCCESS; -} - -/* Currently, we're using as the "size" of a meta surface the largest - * surface size against which the meta-surface is expected to be - * replayed, (as passed in to _cairo_meta_surface_create). - */ -static cairo_int_status_t -_cairo_meta_surface_get_extents (void *abstract_surface, - cairo_rectangle_int_t *rectangle) -{ - cairo_meta_surface_t *surface = abstract_surface; - - if (surface->width_pixels == -1 && surface->height_pixels == -1) - return CAIRO_INT_STATUS_UNSUPPORTED; - - rectangle->x = 0; - rectangle->y = 0; - rectangle->width = surface->width_pixels; - rectangle->height = surface->height_pixels; - - return CAIRO_STATUS_SUCCESS; -} - -/** - * _cairo_surface_is_meta: - * @surface: a #cairo_surface_t - * - * Checks if a surface is a #cairo_meta_surface_t - * - * Return value: %TRUE if the surface is a meta surface - **/ -cairo_bool_t -_cairo_surface_is_meta (const cairo_surface_t *surface) -{ - return surface->backend == &cairo_meta_surface_backend; -} - -static const cairo_surface_backend_t cairo_meta_surface_backend = { - CAIRO_INTERNAL_SURFACE_TYPE_META, - _cairo_meta_surface_create_similar, - _cairo_meta_surface_finish, - _cairo_meta_surface_acquire_source_image, - _cairo_meta_surface_release_source_image, - NULL, /* acquire_dest_image */ - NULL, /* release_dest_image */ - NULL, /* clone_similar */ - NULL, /* composite */ - NULL, /* fill_rectangles */ - NULL, /* composite_trapezoids */ - NULL, /* copy_page */ - NULL, /* show_page */ - NULL, /* set_clip_region */ - _cairo_meta_surface_intersect_clip_path, - _cairo_meta_surface_get_extents, - NULL, /* old_show_glyphs */ - NULL, /* get_font_options */ - NULL, /* flush */ - NULL, /* mark_dirty_rectangle */ - NULL, /* scaled_font_fini */ - NULL, /* scaled_glyph_fini */ - - /* Here are the 5 basic drawing operations, (which are in some - * sense the only things that cairo_meta_surface should need to - * implement). However, we implement the more generic show_text_glyphs - * instead of show_glyphs. One or the other is eough. */ - - _cairo_meta_surface_paint, - _cairo_meta_surface_mask, - _cairo_meta_surface_stroke, - _cairo_meta_surface_fill, - NULL, - - _cairo_meta_surface_snapshot, - - NULL, /* is_similar */ - NULL, /* reset */ - NULL, /* fill_stroke */ - NULL, /* create_solid_pattern_surface */ - - _cairo_meta_surface_has_show_text_glyphs, - _cairo_meta_surface_show_text_glyphs -}; - -static cairo_path_fixed_t * -_cairo_command_get_path (cairo_command_t *command) -{ - switch (command->header.type) { - case CAIRO_COMMAND_PAINT: - case CAIRO_COMMAND_MASK: - case CAIRO_COMMAND_SHOW_TEXT_GLYPHS: - return NULL; - case CAIRO_COMMAND_STROKE: - return &command->stroke.path; - case CAIRO_COMMAND_FILL: - return &command->fill.path; - case CAIRO_COMMAND_INTERSECT_CLIP_PATH: - return command->intersect_clip_path.path_pointer; - } - - ASSERT_NOT_REACHED; - return NULL; -} - -cairo_int_status_t -_cairo_meta_surface_get_path (cairo_surface_t *surface, - cairo_path_fixed_t *path) -{ - cairo_meta_surface_t *meta; - cairo_command_t *command, **elements; - int i, num_elements; - cairo_int_status_t status; - - if (surface->status) - return surface->status; - - meta = (cairo_meta_surface_t *) surface; - status = CAIRO_STATUS_SUCCESS; - - num_elements = meta->commands.num_elements; - elements = _cairo_array_index (&meta->commands, 0); - for (i = meta->replay_start_idx; i < num_elements; i++) { - command = elements[i]; - - switch (command->header.type) { - case CAIRO_COMMAND_PAINT: - case CAIRO_COMMAND_MASK: - case CAIRO_COMMAND_INTERSECT_CLIP_PATH: - status = CAIRO_INT_STATUS_UNSUPPORTED; - break; - - case CAIRO_COMMAND_STROKE: - { - cairo_traps_t traps; - - _cairo_traps_init (&traps); - - /* XXX call cairo_stroke_to_path() when that is implemented */ - status = _cairo_path_fixed_stroke_to_traps (&command->stroke.path, - &command->stroke.style, - &command->stroke.ctm, - &command->stroke.ctm_inverse, - command->stroke.tolerance, - &traps); - - if (status == CAIRO_STATUS_SUCCESS) - status = _cairo_traps_path (&traps, path); - - _cairo_traps_fini (&traps); - break; - } - case CAIRO_COMMAND_FILL: - { - status = _cairo_path_fixed_append (path, &command->fill.path, CAIRO_DIRECTION_FORWARD); - break; - } - case CAIRO_COMMAND_SHOW_TEXT_GLYPHS: - { - status = _cairo_scaled_font_glyph_path (command->show_text_glyphs.scaled_font, - command->show_text_glyphs.glyphs, - command->show_text_glyphs.num_glyphs, - path); - break; - } - - default: - ASSERT_NOT_REACHED; - } - - if (status) - break; - } - - return _cairo_surface_set_error (surface, status); -} - -static cairo_status_t -_cairo_meta_surface_replay_internal (cairo_surface_t *surface, - cairo_surface_t *target, - cairo_meta_replay_type_t type, - cairo_meta_region_type_t region) -{ - cairo_meta_surface_t *meta; - cairo_command_t *command, **elements; - int i, num_elements; - cairo_int_status_t status, status2; - cairo_clip_t clip, *old_clip; - cairo_bool_t has_device_transform = _cairo_surface_has_device_transform (target); - cairo_matrix_t *device_transform = &target->device_transform; - cairo_path_fixed_t path_copy, *dev_path; - - if (surface->status) - return surface->status; - - if (target->status) - return _cairo_surface_set_error (surface, target->status); - - meta = (cairo_meta_surface_t *) surface; - status = CAIRO_STATUS_SUCCESS; - - _cairo_clip_init (&clip, target); - old_clip = _cairo_surface_get_clip (target); - - num_elements = meta->commands.num_elements; - elements = _cairo_array_index (&meta->commands, 0); - for (i = meta->replay_start_idx; i < num_elements; i++) { - command = elements[i]; - - if (type == CAIRO_META_REPLAY && region != CAIRO_META_REGION_ALL) { - if (command->header.region != region) - continue; - } - - /* For all commands except intersect_clip_path, we have to - * ensure the current clip gets set on the surface. */ - if (command->header.type != CAIRO_COMMAND_INTERSECT_CLIP_PATH) { - status = _cairo_surface_set_clip (target, &clip); - if (status) - break; - } - - dev_path = _cairo_command_get_path (command); - if (dev_path && has_device_transform) { - status = _cairo_path_fixed_init_copy (&path_copy, dev_path); - if (status) - break; - _cairo_path_fixed_transform (&path_copy, device_transform); - dev_path = &path_copy; - } - - switch (command->header.type) { - case CAIRO_COMMAND_PAINT: - status = _cairo_surface_paint (target, - command->paint.op, - &command->paint.source.base); - break; - case CAIRO_COMMAND_MASK: - status = _cairo_surface_mask (target, - command->mask.op, - &command->mask.source.base, - &command->mask.mask.base); - break; - case CAIRO_COMMAND_STROKE: - { - cairo_matrix_t dev_ctm = command->stroke.ctm; - cairo_matrix_t dev_ctm_inverse = command->stroke.ctm_inverse; - - if (has_device_transform) { - cairo_matrix_multiply (&dev_ctm, &dev_ctm, device_transform); - cairo_matrix_multiply (&dev_ctm_inverse, - &target->device_transform_inverse, - &dev_ctm_inverse); - } - - status = _cairo_surface_stroke (target, - command->stroke.op, - &command->stroke.source.base, - dev_path, - &command->stroke.style, - &dev_ctm, - &dev_ctm_inverse, - command->stroke.tolerance, - command->stroke.antialias); - break; - } - case CAIRO_COMMAND_FILL: - { - cairo_command_t *stroke_command; - - if (type != CAIRO_META_CREATE_REGIONS) - stroke_command = (i < num_elements - 1) ? elements[i + 1] : NULL; - else - stroke_command = NULL; - - if (stroke_command != NULL && - type == CAIRO_META_REPLAY && region != CAIRO_META_REGION_ALL) - { - if (stroke_command->header.region != region) - stroke_command = NULL; - } - if (stroke_command != NULL && - stroke_command->header.type == CAIRO_COMMAND_STROKE && - _cairo_path_fixed_is_equal (dev_path, _cairo_command_get_path (stroke_command))) { - cairo_matrix_t dev_ctm; - cairo_matrix_t dev_ctm_inverse; - - dev_ctm = stroke_command->stroke.ctm; - dev_ctm_inverse = stroke_command->stroke.ctm_inverse; - - if (has_device_transform) { - cairo_matrix_multiply (&dev_ctm, &dev_ctm, device_transform); - cairo_matrix_multiply (&dev_ctm_inverse, - &surface->device_transform_inverse, - &dev_ctm_inverse); - } - - status = _cairo_surface_fill_stroke (target, - command->fill.op, - &command->fill.source.base, - command->fill.fill_rule, - command->fill.tolerance, - command->fill.antialias, - dev_path, - stroke_command->stroke.op, - &stroke_command->stroke.source.base, - &stroke_command->stroke.style, - &dev_ctm, - &dev_ctm_inverse, - stroke_command->stroke.tolerance, - stroke_command->stroke.antialias); - i++; - } else - status = _cairo_surface_fill (target, - command->fill.op, - &command->fill.source.base, - dev_path, - command->fill.fill_rule, - command->fill.tolerance, - command->fill.antialias); - break; - } - case CAIRO_COMMAND_SHOW_TEXT_GLYPHS: - { - cairo_glyph_t *glyphs = command->show_text_glyphs.glyphs; - cairo_glyph_t *dev_glyphs; - int i, num_glyphs = command->show_text_glyphs.num_glyphs; - - /* show_text_glyphs is special because _cairo_surface_show_text_glyphs is allowed - * to modify the glyph array that's passed in. We must always - * copy the array before handing it to the backend. - */ - dev_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t)); - if (dev_glyphs == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - break; - } - - if (has_device_transform) { - for (i = 0; i < num_glyphs; i++) { - dev_glyphs[i] = glyphs[i]; - cairo_matrix_transform_point (device_transform, - &dev_glyphs[i].x, - &dev_glyphs[i].y); - } - } else { - memcpy (dev_glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs); - } - - status = _cairo_surface_show_text_glyphs (target, - command->show_text_glyphs.op, - &command->show_text_glyphs.source.base, - command->show_text_glyphs.utf8, command->show_text_glyphs.utf8_len, - dev_glyphs, num_glyphs, - command->show_text_glyphs.clusters, command->show_text_glyphs.num_clusters, - command->show_text_glyphs.cluster_flags, - command->show_text_glyphs.scaled_font); - - free (dev_glyphs); - break; - } - case CAIRO_COMMAND_INTERSECT_CLIP_PATH: - /* XXX Meta surface clipping is broken and requires some - * cairo-gstate.c rewriting. Work around it for now. */ - if (dev_path == NULL) - _cairo_clip_reset (&clip); - else - status = _cairo_clip_clip (&clip, dev_path, - command->intersect_clip_path.fill_rule, - command->intersect_clip_path.tolerance, - command->intersect_clip_path.antialias, - target); - break; - default: - ASSERT_NOT_REACHED; - } - - if (dev_path == &path_copy) - _cairo_path_fixed_fini (&path_copy); - - if (type == CAIRO_META_CREATE_REGIONS) { - if (status == CAIRO_STATUS_SUCCESS) { - command->header.region = CAIRO_META_REGION_NATIVE; - } else if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK) { - command->header.region = CAIRO_META_REGION_IMAGE_FALLBACK; - status = CAIRO_STATUS_SUCCESS; - } - } - - if (status) - break; - } - - _cairo_clip_reset (&clip); - status2 = _cairo_surface_set_clip (target, old_clip); - if (status == CAIRO_STATUS_SUCCESS) - status = status2; - - return _cairo_surface_set_error (surface, status); -} - -cairo_status_t -_cairo_meta_surface_replay (cairo_surface_t *surface, - cairo_surface_t *target) -{ - return _cairo_meta_surface_replay_internal (surface, - target, - CAIRO_META_REPLAY, - CAIRO_META_REGION_ALL); -} - -/* Replay meta to surface. When the return status of each operation is - * one of %CAIRO_STATUS_SUCCESS, %CAIRO_INT_STATUS_UNSUPPORTED, or - * %CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY the status of each operation - * will be stored in the meta surface. Any other status will abort the - * replay and return the status. - */ -cairo_status_t -_cairo_meta_surface_replay_and_create_regions (cairo_surface_t *surface, - cairo_surface_t *target) -{ - return _cairo_meta_surface_replay_internal (surface, - target, - CAIRO_META_CREATE_REGIONS, - CAIRO_META_REGION_ALL); -} - -cairo_status_t -_cairo_meta_surface_replay_region (cairo_surface_t *surface, - cairo_surface_t *target, - cairo_meta_region_type_t region) -{ - return _cairo_meta_surface_replay_internal (surface, - target, - CAIRO_META_REPLAY, - region); -} diff --git a/uppdev/plugin/cairo/lib/cairo-misc.c b/uppdev/plugin/cairo/lib/cairo-misc.c deleted file mode 100644 index 27050a242..000000000 --- a/uppdev/plugin/cairo/lib/cairo-misc.c +++ /dev/null @@ -1,669 +0,0 @@ -/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * Copyright © 2005 Red Hat, Inc. - * Copyright © 2007 Adrian Johnson - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - * Adrian Johnson - */ - -#include "cairoint.h" - -COMPILE_TIME_ASSERT (CAIRO_STATUS_LAST_STATUS < CAIRO_INT_STATUS_UNSUPPORTED); -COMPILE_TIME_ASSERT (CAIRO_INT_STATUS_LAST_STATUS <= 127); - -/* Public stuff */ - -/** - * cairo_status_to_string: - * @status: a cairo status - * - * Provides a human-readable description of a #cairo_status_t. - * - * Returns: a string representation of the status - */ -const char * -cairo_status_to_string (cairo_status_t status) -{ - switch (status) { - case CAIRO_STATUS_SUCCESS: - return "success"; - case CAIRO_STATUS_NO_MEMORY: - return "out of memory"; - case CAIRO_STATUS_INVALID_RESTORE: - return "cairo_restore without matching cairo_save"; - case CAIRO_STATUS_INVALID_POP_GROUP: - return "cairo_pop_group without matching cairo_push_group"; - case CAIRO_STATUS_NO_CURRENT_POINT: - return "no current point defined"; - case CAIRO_STATUS_INVALID_MATRIX: - return "invalid matrix (not invertible)"; - case CAIRO_STATUS_INVALID_STATUS: - return "invalid value for an input cairo_status_t"; - case CAIRO_STATUS_NULL_POINTER: - return "NULL pointer"; - case CAIRO_STATUS_INVALID_STRING: - return "input string not valid UTF-8"; - case CAIRO_STATUS_INVALID_PATH_DATA: - return "input path data not valid"; - case CAIRO_STATUS_READ_ERROR: - return "error while reading from input stream"; - case CAIRO_STATUS_WRITE_ERROR: - return "error while writing to output stream"; - case CAIRO_STATUS_SURFACE_FINISHED: - return "the target surface has been finished"; - case CAIRO_STATUS_SURFACE_TYPE_MISMATCH: - return "the surface type is not appropriate for the operation"; - case CAIRO_STATUS_PATTERN_TYPE_MISMATCH: - return "the pattern type is not appropriate for the operation"; - case CAIRO_STATUS_INVALID_CONTENT: - return "invalid value for an input cairo_content_t"; - case CAIRO_STATUS_INVALID_FORMAT: - return "invalid value for an input cairo_format_t"; - case CAIRO_STATUS_INVALID_VISUAL: - return "invalid value for an input Visual*"; - case CAIRO_STATUS_FILE_NOT_FOUND: - return "file not found"; - case CAIRO_STATUS_INVALID_DASH: - return "invalid value for a dash setting"; - case CAIRO_STATUS_INVALID_DSC_COMMENT: - return "invalid value for a DSC comment"; - case CAIRO_STATUS_INVALID_INDEX: - return "invalid index passed to getter"; - case CAIRO_STATUS_CLIP_NOT_REPRESENTABLE: - return "clip region not representable in desired format"; - case CAIRO_STATUS_TEMP_FILE_ERROR: - return "error creating or writing to a temporary file"; - case CAIRO_STATUS_INVALID_STRIDE: - return "invalid value for stride"; - case CAIRO_STATUS_FONT_TYPE_MISMATCH: - return "the font type is not appropriate for the operation"; - case CAIRO_STATUS_USER_FONT_IMMUTABLE: - return "the user-font is immutable"; - case CAIRO_STATUS_USER_FONT_ERROR: - return "error occurred in a user-font callback function"; - case CAIRO_STATUS_NEGATIVE_COUNT: - return "negative number used where it is not allowed"; - case CAIRO_STATUS_INVALID_CLUSTERS: - return "input clusters do not represent the accompanying text and glyph arrays"; - case CAIRO_STATUS_INVALID_SLANT: - return "invalid value for an input #cairo_font_slant_t"; - case CAIRO_STATUS_INVALID_WEIGHT: - return "input value for an input #cairo_font_weight_t"; - } - - return ""; -} - - -/** - * cairo_glyph_allocate: - * @num_glyphs: number of glyphs to allocate - * - * Allocates an array of #cairo_glyph_t's. - * This function is only useful in implementations of - * #cairo_user_scaled_font_text_to_glyphs_func_t where the user - * needs to allocate an array of glyphs that cairo will free. - * For all other uses, user can use their own allocation method - * for glyphs. - * - * This function returns %NULL if @num_glyphs is not positive, - * or if out of memory. That means, the %NULL return value - * signals out-of-memory only if @num_glyphs was positive. - * - * Returns: the newly allocated array of glyphs that should be - * freed using cairo_glyph_free() - * - * Since: 1.8 - */ -cairo_glyph_t * -cairo_glyph_allocate (int num_glyphs) -{ - if (num_glyphs <= 0) - return NULL; - - return _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t)); -} -slim_hidden_def (cairo_glyph_allocate); - -/** - * cairo_glyph_free: - * @glyphs: array of glyphs to free, or %NULL - * - * Frees an array of #cairo_glyph_t's allocated using cairo_glyph_allocate(). - * This function is only useful to free glyph array returned - * by cairo_scaled_font_text_to_glyphs() where cairo returns - * an array of glyphs that the user will free. - * For all other uses, user can use their own allocation method - * for glyphs. - * - * Since: 1.8 - */ -void -cairo_glyph_free (cairo_glyph_t *glyphs) -{ - if (glyphs) - free (glyphs); -} -slim_hidden_def (cairo_glyph_free); - -/** - * cairo_text_cluster_allocate: - * @num_clusters: number of text_clusters to allocate - * - * Allocates an array of #cairo_text_cluster_t's. - * This function is only useful in implementations of - * #cairo_user_scaled_font_text_to_glyphs_func_t where the user - * needs to allocate an array of text clusters that cairo will free. - * For all other uses, user can use their own allocation method - * for text clusters. - * - * This function returns %NULL if @num_clusters is not positive, - * or if out of memory. That means, the %NULL return value - * signals out-of-memory only if @num_clusters was positive. - * - * Returns: the newly allocated array of text clusters that should be - * freed using cairo_text_cluster_free() - * - * Since: 1.8 - */ -cairo_text_cluster_t * -cairo_text_cluster_allocate (int num_clusters) -{ - if (num_clusters <= 0) - return NULL; - - return _cairo_malloc_ab (num_clusters, sizeof (cairo_text_cluster_t)); -} -slim_hidden_def (cairo_text_cluster_allocate); - -/** - * cairo_text_cluster_free: - * @clusters: array of text clusters to free, or %NULL - * - * Frees an array of #cairo_text_cluster's allocated using cairo_text_cluster_allocate(). - * This function is only useful to free text cluster array returned - * by cairo_scaled_font_text_to_glyphs() where cairo returns - * an array of text clusters that the user will free. - * For all other uses, user can use their own allocation method - * for text clusters. - * - * Since: 1.8 - */ -void -cairo_text_cluster_free (cairo_text_cluster_t *clusters) -{ - if (clusters) - free (clusters); -} -slim_hidden_def (cairo_text_cluster_free); - - -/* Private stuff */ - -/** - * _cairo_validate_text_clusters: - * @utf8: UTF-8 text - * @utf8_len: length of @utf8 in bytes - * @glyphs: array of glyphs - * @num_glyphs: number of glyphs - * @clusters: array of cluster mapping information - * @num_clusters: number of clusters in the mapping - * @cluster_flags: cluster flags - * - * Check that clusters cover the entire glyphs and utf8 arrays, - * and that cluster boundaries are UTF-8 boundaries. - * - * Return value: %CAIRO_STATUS_SUCCESS upon success, or - * %CAIRO_STATUS_INVALID_CLUSTERS on error. - * The error is either invalid UTF-8 input, - * or bad cluster mapping. - */ -cairo_status_t -_cairo_validate_text_clusters (const char *utf8, - int utf8_len, - const cairo_glyph_t *glyphs, - int num_glyphs, - const cairo_text_cluster_t *clusters, - int num_clusters, - cairo_text_cluster_flags_t cluster_flags) -{ - cairo_status_t status; - unsigned int n_bytes = 0; - unsigned int n_glyphs = 0; - int i; - - for (i = 0; i < num_clusters; i++) { - int cluster_bytes = clusters[i].num_bytes; - int cluster_glyphs = clusters[i].num_glyphs; - - if (cluster_bytes < 0 || cluster_glyphs < 0) - goto BAD; - - /* A cluster should cover at least one character or glyph. - * I can't see any use for a 0,0 cluster. - * I can't see an immediate use for a zero-text cluster - * right now either, but they don't harm. - * Zero-glyph clusters on the other hand are useful for - * things like U+200C ZERO WIDTH NON-JOINER */ - if (cluster_bytes == 0 && cluster_glyphs == 0) - goto BAD; - - /* Since n_bytes and n_glyphs are unsigned, but the rest of - * values involved are signed, we can detect overflow easily */ - if (n_bytes+cluster_bytes > (unsigned int)utf8_len || n_glyphs+cluster_glyphs > (unsigned int)num_glyphs) - goto BAD; - - /* Make sure we've got valid UTF-8 for the cluster */ - status = _cairo_utf8_to_ucs4 (utf8+n_bytes, cluster_bytes, NULL, NULL); - if (status) - return CAIRO_STATUS_INVALID_CLUSTERS; - - n_bytes += cluster_bytes ; - n_glyphs += cluster_glyphs; - } - - if (n_bytes != (unsigned int) utf8_len || n_glyphs != (unsigned int) num_glyphs) { - BAD: - return CAIRO_STATUS_INVALID_CLUSTERS; - } - - return CAIRO_STATUS_SUCCESS; -} - -/** - * _cairo_operator_bounded_by_mask: - * @op: a #cairo_operator_t - * - * A bounded operator is one where mask pixel - * of zero results in no effect on the destination image. - * - * Unbounded operators often require special handling; if you, for - * example, draw trapezoids with an unbounded operator, the effect - * extends past the bounding box of the trapezoids. - * - * Return value: %TRUE if the operator is bounded by the mask operand - **/ -cairo_bool_t -_cairo_operator_bounded_by_mask (cairo_operator_t op) -{ - switch (op) { - case CAIRO_OPERATOR_CLEAR: - case CAIRO_OPERATOR_SOURCE: - case CAIRO_OPERATOR_OVER: - case CAIRO_OPERATOR_ATOP: - case CAIRO_OPERATOR_DEST: - case CAIRO_OPERATOR_DEST_OVER: - case CAIRO_OPERATOR_DEST_OUT: - case CAIRO_OPERATOR_XOR: - case CAIRO_OPERATOR_ADD: - case CAIRO_OPERATOR_SATURATE: - return TRUE; - case CAIRO_OPERATOR_OUT: - case CAIRO_OPERATOR_IN: - case CAIRO_OPERATOR_DEST_IN: - case CAIRO_OPERATOR_DEST_ATOP: - return FALSE; - } - - ASSERT_NOT_REACHED; - return FALSE; -} - -/** - * _cairo_operator_bounded_by_source: - * @op: a #cairo_operator_t - * - * A bounded operator is one where source pixels of zero - * (in all four components, r, g, b and a) effect no change - * in the resulting destination image. - * - * Unbounded operators often require special handling; if you, for - * example, copy a surface with the SOURCE operator, the effect - * extends past the bounding box of the source surface. - * - * Return value: %TRUE if the operator is bounded by the source operand - **/ -cairo_bool_t -_cairo_operator_bounded_by_source (cairo_operator_t op) -{ - switch (op) { - case CAIRO_OPERATOR_OVER: - case CAIRO_OPERATOR_ATOP: - case CAIRO_OPERATOR_DEST: - case CAIRO_OPERATOR_DEST_OVER: - case CAIRO_OPERATOR_DEST_OUT: - case CAIRO_OPERATOR_XOR: - case CAIRO_OPERATOR_ADD: - case CAIRO_OPERATOR_SATURATE: - return TRUE; - case CAIRO_OPERATOR_CLEAR: - case CAIRO_OPERATOR_SOURCE: - case CAIRO_OPERATOR_OUT: - case CAIRO_OPERATOR_IN: - case CAIRO_OPERATOR_DEST_IN: - case CAIRO_OPERATOR_DEST_ATOP: - return FALSE; - } - - ASSERT_NOT_REACHED; - return FALSE; -} - - -void -_cairo_restrict_value (double *value, double min, double max) -{ - if (*value < min) - *value = min; - else if (*value > max) - *value = max; -} - -/* This function is identical to the C99 function lround(), except that it - * performs arithmetic rounding (instead of away-from-zero rounding) and - * has a valid input range of (INT_MIN, INT_MAX] instead of - * [INT_MIN, INT_MAX]. It is much faster on both x86 and FPU-less systems - * than other commonly used methods for rounding (lround, round, rint, lrint - * or float (d + 0.5)). - * - * The reason why this function is much faster on x86 than other - * methods is due to the fact that it avoids the fldcw instruction. - * This instruction incurs a large performance penalty on modern Intel - * processors due to how it prevents efficient instruction pipelining. - * - * The reason why this function is much faster on FPU-less systems is for - * an entirely different reason. All common rounding methods involve multiple - * floating-point operations. Each one of these operations has to be - * emulated in software, which adds up to be a large performance penalty. - * This function doesn't perform any floating-point calculations, and thus - * avoids this penalty. - */ -int -_cairo_lround (double d) -{ - uint32_t top, shift_amount, output; - union { - double d; - uint64_t ui64; - uint32_t ui32[2]; - } u; - - u.d = d; - - /* If the integer word order doesn't match the float word order, we swap - * the words of the input double. This is needed because we will be - * treating the whole double as a 64-bit unsigned integer. Notice that we - * use WORDS_BIGENDIAN to detect the integer word order, which isn't - * exactly correct because WORDS_BIGENDIAN refers to byte order, not word - * order. Thus, we are making the assumption that the byte order is the - * same as the integer word order which, on the modern machines that we - * care about, is OK. - */ -#if ( defined(FLOAT_WORDS_BIGENDIAN) && !defined(WORDS_BIGENDIAN)) || \ - (!defined(FLOAT_WORDS_BIGENDIAN) && defined(WORDS_BIGENDIAN)) - { - uint32_t temp = u.ui32[0]; - u.ui32[0] = u.ui32[1]; - u.ui32[1] = temp; - } -#endif - -#ifdef WORDS_BIGENDIAN - #define MSW (0) /* Most Significant Word */ - #define LSW (1) /* Least Significant Word */ -#else - #define MSW (1) - #define LSW (0) -#endif - - /* By shifting the most significant word of the input double to the - * right 20 places, we get the very "top" of the double where the exponent - * and sign bit lie. - */ - top = u.ui32[MSW] >> 20; - - /* Here, we calculate how much we have to shift the mantissa to normalize - * it to an integer value. We extract the exponent "top" by masking out the - * sign bit, then we calculate the shift amount by subtracting the exponent - * from the bias. Notice that the correct bias for 64-bit doubles is - * actually 1075, but we use 1053 instead for two reasons: - * - * 1) To perform rounding later on, we will first need the target - * value in a 31.1 fixed-point format. Thus, the bias needs to be one - * less: (1075 - 1: 1074). - * - * 2) To avoid shifting the mantissa as a full 64-bit integer (which is - * costly on certain architectures), we break the shift into two parts. - * First, the upper and lower parts of the mantissa are shifted - * individually by a constant amount that all valid inputs will require - * at the very least. This amount is chosen to be 21, because this will - * allow the two parts of the mantissa to later be combined into a - * single 32-bit representation, on which the remainder of the shift - * will be performed. Thus, we decrease the bias by an additional 21: - * (1074 - 21: 1053). - */ - shift_amount = 1053 - (top & 0x7FF); - - /* We are done with the exponent portion in "top", so here we shift it off - * the end. - */ - top >>= 11; - - /* Before we perform any operations on the mantissa, we need to OR in - * the implicit 1 at the top (see the IEEE-754 spec). We needn't mask - * off the sign bit nor the exponent bits because these higher bits won't - * make a bit of difference in the rest of our calculations. - */ - u.ui32[MSW] |= 0x100000; - - /* If the input double is negative, we have to decrease the mantissa - * by a hair. This is an important part of performing arithmetic rounding, - * as negative numbers must round towards positive infinity in the - * halfwase case of -x.5. Since "top" contains only the sign bit at this - * point, we can just decrease the mantissa by the value of "top". - */ - u.ui64 -= top; - - /* By decrementing "top", we create a bitmask with a value of either - * 0x0 (if the input was negative) or 0xFFFFFFFF (if the input was positive - * and thus the unsigned subtraction underflowed) that we'll use later. - */ - top--; - - /* Here, we shift the mantissa by the constant value as described above. - * We can emulate a 64-bit shift right by 21 through shifting the top 32 - * bits left 11 places and ORing in the bottom 32 bits shifted 21 places - * to the right. Both parts of the mantissa are now packed into a single - * 32-bit integer. Although we severely truncate the lower part in the - * process, we still have enough significant bits to perform the conversion - * without error (for all valid inputs). - */ - output = (u.ui32[MSW] << 11) | (u.ui32[LSW] >> 21); - - /* Next, we perform the shift that converts the X.Y fixed-point number - * currently found in "output" to the desired 31.1 fixed-point format - * needed for the following rounding step. It is important to consider - * all possible values for "shift_amount" at this point: - * - * - {shift_amount < 0} Since shift_amount is an unsigned integer, it - * really can't have a value less than zero. But, if the shift_amount - * calculation above caused underflow (which would happen with - * input > INT_MAX or input <= INT_MIN) then shift_amount will now be - * a very large number, and so this shift will result in complete - * garbage. But that's OK, as the input was out of our range, so our - * output is undefined. - * - * - {shift_amount > 31} If the magnitude of the input was very small - * (i.e. |input| << 1.0), shift_amount will have a value greater than - * 31. Thus, this shift will also result in garbage. After performing - * the shift, we will zero-out "output" if this is the case. - * - * - {0 <= shift_amount < 32} In this case, the shift will properly convert - * the mantissa into a 31.1 fixed-point number. - */ - output >>= shift_amount; - - /* This is where we perform rounding with the 31.1 fixed-point number. - * Since what we're after is arithmetic rounding, we simply add the single - * fractional bit into the integer part of "output", and just keep the - * integer part. - */ - output = (output >> 1) + (output & 1); - - /* Here, we zero-out the result if the magnitude if the input was very small - * (as explained in the section above). Notice that all input out of the - * valid range is also caught by this condition, which means we produce 0 - * for all invalid input, which is a nice side effect. - * - * The most straightforward way to do this would be: - * - * if (shift_amount > 31) - * output = 0; - * - * But we can use a little trick to avoid the potential branch. The - * expression (shift_amount > 31) will be either 1 or 0, which when - * decremented will be either 0x0 or 0xFFFFFFFF (unsigned underflow), - * which can be used to conditionally mask away all the bits in "output" - * (in the 0x0 case), effectively zeroing it out. Certain, compilers would - * have done this for us automatically. - */ - output &= ((shift_amount > 31) - 1); - - /* If the input double was a negative number, then we have to negate our - * output. The most straightforward way to do this would be: - * - * if (!top) - * output = -output; - * - * as "top" at this point is either 0x0 (if the input was negative) or - * 0xFFFFFFFF (if the input was positive). But, we can use a trick to - * avoid the branch. Observe that the following snippet of code has the - * same effect as the reference snippet above: - * - * if (!top) - * output = 0 - output; - * else - * output = output - 0; - * - * Armed with the bitmask found in "top", we can condense the two statements - * into the following: - * - * output = (output & top) - (output & ~top); - * - * where, in the case that the input double was negative, "top" will be 0, - * and the statement will be equivalent to: - * - * output = (0) - (output); - * - * and if the input double was positive, "top" will be 0xFFFFFFFF, and the - * statement will be equivalent to: - * - * output = (output) - (0); - * - * Which, as pointed out earlier, is equivalent to the original reference - * snippet. - */ - output = (output & top) - (output & ~top); - - return output; -#undef MSW -#undef LSW -} - - -#ifdef _WIN32 - -#define WIN32_LEAN_AND_MEAN -/* We require Windows 2000 features such as ETO_PDY */ -#if !defined(WINVER) || (WINVER < 0x0500) -# define WINVER 0x0500 -#endif -#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500) -# define _WIN32_WINNT 0x0500 -#endif - -#include -#include - -/* tmpfile() replacment for Windows. - * - * On Windows tmpfile() creates the file in the root directory. This - * may fail due to unsufficient privileges. - */ -FILE * -_cairo_win32_tmpfile (void) -{ - DWORD path_len; - WCHAR path_name[MAX_PATH + 1]; - WCHAR file_name[MAX_PATH + 1]; - HANDLE handle; - int fd; - FILE *fp; - - path_len = GetTempPathW (MAX_PATH, path_name); - if (path_len <= 0 || path_len >= MAX_PATH) - return NULL; - - if (GetTempFileNameW (path_name, L"ps_", 0, file_name) == 0) - return NULL; - - handle = CreateFileW (file_name, - GENERIC_READ | GENERIC_WRITE, - 0, - NULL, - CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, - NULL); - if (handle == INVALID_HANDLE_VALUE) { - DeleteFileW (file_name); - return NULL; - } - - fd = _open_osfhandle((intptr_t) handle, 0); - if (fd < 0) { - CloseHandle (handle); - return NULL; - } - - fp = fdopen(fd, "w+b"); - if (fp == NULL) { - _close(fd); - return NULL; - } - - return fp; -} - -#endif /* _WIN32 */ diff --git a/uppdev/plugin/cairo/lib/cairo-mutex-impl-private.h b/uppdev/plugin/cairo/lib/cairo-mutex-impl-private.h deleted file mode 100644 index 239dbbb09..000000000 --- a/uppdev/plugin/cairo/lib/cairo-mutex-impl-private.h +++ /dev/null @@ -1,239 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * Copyright © 2005,2007 Red Hat, Inc. - * Copyright © 2007 Mathias Hasselmann - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - * Mathias Hasselmann - * Behdad Esfahbod - */ - -#ifndef CAIRO_MUTEX_IMPL_PRIVATE_H -#define CAIRO_MUTEX_IMPL_PRIVATE_H - -#include "cairo.h" - -#if HAVE_CONFIG_H -#include "config.h" -#endif - -#if HAVE_LOCKDEP -#include -#endif - -/* A fully qualified no-operation statement */ -#define CAIRO_MUTEX_IMPL_NOOP do {/*no-op*/} while (0) -/* And one that evaluates it's argument once */ -#define CAIRO_MUTEX_IMPL_NOOP1(expr) do { if (expr) ; } while (0) - - -/* Cairo mutex implementation: - * - * Any new mutex implementation needs to do the following: - * - * - Condition on the right header or feature. Headers are - * preferred as eg. you still can use win32 mutex implementation - * on a win32 system even if you do not compile the win32 - * surface/backend. - * - * - typedef #cairo_mutex_impl_t to the proper mutex type on your target - * system. Note that you may or may not need to use a pointer, - * depending on what kinds of initialization your mutex - * implementation supports. No trailing semicolon needed. - * You should be able to compile the following snippet (don't try - * running it): - * - * - * cairo_mutex_impl_t _cairo_some_mutex; - * - * - * - #define %CAIRO_MUTEX_IMPL_ 1 with suitable name for your platform. You - * can later use this symbol in cairo-system.c. - * - * - #define CAIRO_MUTEX_IMPL_LOCK(mutex) and CAIRO_MUTEX_IMPL_UNLOCK(mutex) to - * proper statement to lock/unlock the mutex object passed in. - * You can (and should) assume that the mutex is already - * initialized, and is-not-already-locked/is-locked, - * respectively. Use the "do { ... } while (0)" idiom if necessary. - * No trailing semicolons are needed (in any macro you define here). - * You should be able to compile the following snippet: - * - * - * cairo_mutex_impl_t _cairo_some_mutex; - * - * if (1) - * CAIRO_MUTEX_IMPL_LOCK (_cairo_some_mutex); - * else - * CAIRO_MUTEX_IMPL_UNLOCK (_cairo_some_mutex); - * - * - * - #define %CAIRO_MUTEX_IMPL_NIL_INITIALIZER to something that can - * initialize the #cairo_mutex_impl_t type you defined. Most of the - * time one of 0, %NULL, or {} works. At this point - * you should be able to compile the following snippet: - * - * - * cairo_mutex_impl_t _cairo_some_mutex = CAIRO_MUTEX_IMPL_NIL_INITIALIZER; - * - * if (1) - * CAIRO_MUTEX_IMPL_LOCK (_cairo_some_mutex); - * else - * CAIRO_MUTEX_IMPL_UNLOCK (_cairo_some_mutex); - * - * - * - If the above code is not enough to initialize a mutex on - * your platform, #define CAIRO_MUTEX_IMPL_INIT(mutex) to statement - * to initialize the mutex (allocate resources, etc). Such that - * you should be able to compile AND RUN the following snippet: - * - * - * cairo_mutex_impl_t _cairo_some_mutex = CAIRO_MUTEX_IMPL_NIL_INITIALIZER; - * - * CAIRO_MUTEX_IMPL_INIT (_cairo_some_mutex); - * - * if (1) - * CAIRO_MUTEX_IMPL_LOCK (_cairo_some_mutex); - * else - * CAIRO_MUTEX_IMPL_UNLOCK (_cairo_some_mutex); - * - * - * - If you define CAIRO_MUTEX_IMPL_INIT(mutex), cairo will use it to - * initialize all static mutex'es. If for any reason that should - * not happen (eg. %CAIRO_MUTEX_IMPL_INIT is just a faster way than - * what cairo does using %CAIRO_MUTEX_IMPL_NIL_INITIALIZER), then - * - * #define CAIRO_MUTEX_IMPL_INITIALIZE() CAIRO_MUTEX_IMPL_NOOP - * - * - * - If your system supports freeing a mutex object (deallocating - * resources, etc), then #define CAIRO_MUTEX_IMPL_FINI(mutex) to do - * that. - * - * - If you define CAIRO_MUTEX_IMPL_FINI(mutex), cairo will use it to - * define a finalizer function to finalize all static mutex'es. - * However, it's up to you to call CAIRO_MUTEX_IMPL_FINALIZE() at - * proper places, eg. when the system is unloading the cairo library. - * So, if for any reason finalizing static mutex'es is not needed - * (eg. you never call CAIRO_MUTEX_IMPL_FINALIZE()), then - * - * #define CAIRO_MUTEX_IMPL_FINALIZE() CAIRO_MUTEX_IMPL_NOOP - * - * - * - That is all. If for any reason you think the above API is - * not enough to implement #cairo_mutex_impl_t on your system, please - * stop and write to the cairo mailing list about it. DO NOT - * poke around cairo-mutex-private.h for possible solutions. - */ - -#if CAIRO_NO_MUTEX - -/* No mutexes */ - - typedef int cairo_mutex_impl_t; - -# define CAIRO_MUTEX_IMPL_NO 1 -# define CAIRO_MUTEX_IMPL_INITIALIZE() CAIRO_MUTEX_IMPL_NOOP -# define CAIRO_MUTEX_IMPL_LOCK(mutex) CAIRO_MUTEX_IMPL_NOOP1(mutex) -# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) CAIRO_MUTEX_IMPL_NOOP1(mutex) -# define CAIRO_MUTEX_IMPL_NIL_INITIALIZER 0 - -#elif HAVE_PTHREAD_H /*******************************************************/ - -# include - - typedef pthread_mutex_t cairo_mutex_impl_t; - -# define CAIRO_MUTEX_IMPL_PTHREAD 1 -#if HAVE_LOCKDEP -/* expose all mutexes to the validator */ -# define CAIRO_MUTEX_IMPL_INIT(mutex) pthread_mutex_init (&(mutex), NULL) -#endif -# define CAIRO_MUTEX_IMPL_LOCK(mutex) pthread_mutex_lock (&(mutex)) -# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) pthread_mutex_unlock (&(mutex)) -#if HAVE_LOCKDEP -# define CAIRO_MUTEX_IS_LOCKED(mutex) LOCKDEP_IS_LOCKED (&(mutex)) -# define CAIRO_MUTEX_IS_UNLOCKED(mutex) LOCKDEP_IS_UNLOCKED (&(mutex)) -#endif -# define CAIRO_MUTEX_IMPL_FINI(mutex) pthread_mutex_destroy (&(mutex)) -#if ! HAVE_LOCKDEP -# define CAIRO_MUTEX_IMPL_FINALIZE() CAIRO_MUTEX_IMPL_NOOP -#endif -# define CAIRO_MUTEX_IMPL_NIL_INITIALIZER PTHREAD_MUTEX_INITIALIZER - -#elif defined(HAVE_WINDOWS_H) || defined(_MSC_VER) /*************************/ - -# include - - typedef CRITICAL_SECTION cairo_mutex_impl_t; - -# define CAIRO_MUTEX_IMPL_WIN32 1 -# define CAIRO_MUTEX_IMPL_LOCK(mutex) EnterCriticalSection (&(mutex)) -# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) LeaveCriticalSection (&(mutex)) -# define CAIRO_MUTEX_IMPL_INIT(mutex) InitializeCriticalSection (&(mutex)) -# define CAIRO_MUTEX_IMPL_FINI(mutex) DeleteCriticalSection (&(mutex)) -# define CAIRO_MUTEX_IMPL_NIL_INITIALIZER { NULL, 0, 0, NULL, NULL, 0 } - -#elif defined __OS2__ /******************************************************/ - -# define INCL_BASE -# define INCL_PM -# include - - typedef HMTX cairo_mutex_impl_t; - -# define CAIRO_MUTEX_IMPL_OS2 1 -# define CAIRO_MUTEX_IMPL_LOCK(mutex) DosRequestMutexSem(mutex, SEM_INDEFINITE_WAIT) -# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) DosReleaseMutexSem(mutex) -# define CAIRO_MUTEX_IMPL_INIT(mutex) DosCreateMutexSem (NULL, &(mutex), 0L, FALSE) -# define CAIRO_MUTEX_IMPL_FINI(mutex) DosCloseMutexSem (mutex) -# define CAIRO_MUTEX_IMPL_NIL_INITIALIZER 0 - -#elif CAIRO_HAS_BEOS_SURFACE /***********************************************/ - - typedef BLocker* cairo_mutex_impl_t; - -# define CAIRO_MUTEX_IMPL_BEOS 1 -# define CAIRO_MUTEX_IMPL_LOCK(mutex) (mutex)->Lock() -# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) (mutex)->Unlock() -# define CAIRO_MUTEX_IMPL_INIT(mutex) (mutex) = new BLocker() -# define CAIRO_MUTEX_IMPL_FINI(mutex) delete (mutex) -# define CAIRO_MUTEX_IMPL_NIL_INITIALIZER NULL - -#else /**********************************************************************/ - -# error "XXX: No mutex implementation found. Cairo will not work with multiple threads. Define CAIRO_NO_MUTEX to 1 to acknowledge and accept this limitation and compile cairo without thread-safety support." - - -#endif - -#endif diff --git a/uppdev/plugin/cairo/lib/cairo-mutex-list-private.h b/uppdev/plugin/cairo/lib/cairo-mutex-list-private.h deleted file mode 100644 index 6fdb389a2..000000000 --- a/uppdev/plugin/cairo/lib/cairo-mutex-list-private.h +++ /dev/null @@ -1,59 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2007 Mathias Hasselmann - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * Contributor(s): - * Mathias Hasselmann - */ - -#ifndef CAIRO_FEATURES_H -/* This block is to just make this header file standalone */ -#define CAIRO_MUTEX_DECLARE(mutex) -#endif - -CAIRO_MUTEX_DECLARE (_cairo_pattern_solid_pattern_cache_lock) -CAIRO_MUTEX_DECLARE (_cairo_pattern_solid_surface_cache_lock) - -CAIRO_MUTEX_DECLARE (_cairo_font_face_mutex) -CAIRO_MUTEX_DECLARE (_cairo_scaled_font_map_mutex) -CAIRO_MUTEX_DECLARE (_cairo_scaled_font_error_mutex) - -#if CAIRO_HAS_FT_FONT -CAIRO_MUTEX_DECLARE (_cairo_ft_unscaled_font_map_mutex) -#endif - -#if CAIRO_HAS_XLIB_SURFACE -CAIRO_MUTEX_DECLARE (_cairo_xlib_display_mutex) -#endif - -#if !defined (HAS_ATOMIC_OPS) || defined (ATOMIC_OP_NEEDS_MEMORY_BARRIER) -CAIRO_MUTEX_DECLARE (_cairo_atomic_mutex) -#endif - -/* Undefine, to err on unintended inclusion */ -#undef CAIRO_MUTEX_DECLARE diff --git a/uppdev/plugin/cairo/lib/cairo-mutex-private.h b/uppdev/plugin/cairo/lib/cairo-mutex-private.h deleted file mode 100644 index a3a7271f2..000000000 --- a/uppdev/plugin/cairo/lib/cairo-mutex-private.h +++ /dev/null @@ -1,67 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * Copyright © 2005,2007 Red Hat, Inc. - * Copyright © 2007 Mathias Hasselmann - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - * Mathias Hasselmann - * Behdad Esfahbod - */ - -#ifndef CAIRO_MUTEX_PRIVATE_H -#define CAIRO_MUTEX_PRIVATE_H - -#include "cairo-mutex-type-private.h" - -CAIRO_BEGIN_DECLS - -#if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER -cairo_private void _cairo_mutex_initialize (void); -#endif -#if _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER -cairo_private void _cairo_mutex_finalize (void); -#endif -/* only if using static initializer and/or finalizer define the boolean */ -#if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER || _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER - cairo_private extern cairo_bool_t _cairo_mutex_initialized; -#endif - -/* Finally, extern the static mutexes and undef */ - -#define CAIRO_MUTEX_DECLARE(mutex) cairo_private extern cairo_mutex_t mutex; -#include "cairo-mutex-list-private.h" -#undef CAIRO_MUTEX_DECLARE - -CAIRO_END_DECLS - -#endif diff --git a/uppdev/plugin/cairo/lib/cairo-mutex-type-private.h b/uppdev/plugin/cairo/lib/cairo-mutex-type-private.h deleted file mode 100644 index adf17bbed..000000000 --- a/uppdev/plugin/cairo/lib/cairo-mutex-type-private.h +++ /dev/null @@ -1,187 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * Copyright © 2005,2007 Red Hat, Inc. - * Copyright © 2007 Mathias Hasselmann - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - * Mathias Hasselmann - * Behdad Esfahbod - */ - -#ifndef CAIRO_MUTEX_TYPE_PRIVATE_H -#define CAIRO_MUTEX_TYPE_PRIVATE_H - -#include "cairo-compiler-private.h" -#include "cairo-mutex-impl-private.h" - -/* Only the following three are mandatory at this point */ -#ifndef CAIRO_MUTEX_IMPL_LOCK -# error "CAIRO_MUTEX_IMPL_LOCK not defined. Check cairo-mutex-impl-private.h." -#endif -#ifndef CAIRO_MUTEX_IMPL_UNLOCK -# error "CAIRO_MUTEX_IMPL_UNLOCK not defined. Check cairo-mutex-impl-private.h." -#endif -#ifndef CAIRO_MUTEX_IMPL_NIL_INITIALIZER -# error "CAIRO_MUTEX_IMPL_NIL_INITIALIZER not defined. Check cairo-mutex-impl-private.h." -#endif - - -/* make sure implementations don't fool us: we decide these ourself */ -#undef _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER -#undef _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER - - -#ifdef CAIRO_MUTEX_IMPL_INIT - -/* If %CAIRO_MUTEX_IMPL_INIT is defined, we may need to initialize all - * static mutex'es. */ -# ifndef CAIRO_MUTEX_IMPL_INITIALIZE -# define CAIRO_MUTEX_IMPL_INITIALIZE() do { \ - if (!_cairo_mutex_initialized) \ - _cairo_mutex_initialize (); \ - } while(0) - -/* and make sure we implement the above */ -# define _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER 1 -# endif /* CAIRO_MUTEX_IMPL_INITIALIZE */ - -#else /* no CAIRO_MUTEX_IMPL_INIT */ - -/* Otherwise we probably don't need to initialize static mutex'es, */ -# ifndef CAIRO_MUTEX_IMPL_INITIALIZE -# define CAIRO_MUTEX_IMPL_INITIALIZE() CAIRO_MUTEX_IMPL_NOOP -# endif /* CAIRO_MUTEX_IMPL_INITIALIZE */ - -/* and dynamic ones can be initialized using the static initializer. */ -# define CAIRO_MUTEX_IMPL_INIT(mutex) do { \ - cairo_mutex_t _tmp_mutex = CAIRO_MUTEX_IMPL_NIL_INITIALIZER; \ - memcpy (&(mutex), &_tmp_mutex, sizeof (_tmp_mutex)); \ - } while (0) - -#endif /* CAIRO_MUTEX_IMPL_INIT */ - -#ifdef CAIRO_MUTEX_IMPL_FINI - -/* If %CAIRO_MUTEX_IMPL_FINI is defined, we may need to finalize all - * static mutex'es. */ -# ifndef CAIRO_MUTEX_IMPL_FINALIZE -# define CAIRO_MUTEX_IMPL_FINALIZE() do { \ - if (_cairo_mutex_initialized) \ - _cairo_mutex_finalize (); \ - } while(0) - -/* and make sure we implement the above */ -# define _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER 1 -# endif /* CAIRO_MUTEX_IMPL_FINALIZE */ - -#else /* no CAIRO_MUTEX_IMPL_FINI */ - -/* Otherwise we probably don't need to finalize static mutex'es, */ -# ifndef CAIRO_MUTEX_IMPL_FINALIZE -# define CAIRO_MUTEX_IMPL_FINALIZE() CAIRO_MUTEX_IMPL_NOOP -# endif /* CAIRO_MUTEX_IMPL_FINALIZE */ - -/* neither do the dynamic ones. */ -# define CAIRO_MUTEX_IMPL_FINI(mutex) CAIRO_MUTEX_IMPL_NOOP1(mutex) - -#endif /* CAIRO_MUTEX_IMPL_FINI */ - - -#ifndef _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER -#define _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER 0 -#endif -#ifndef _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER -#define _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER 0 -#endif - - -/* Make sure everything we want is defined */ -#ifndef CAIRO_MUTEX_IMPL_INITIALIZE -# error "CAIRO_MUTEX_IMPL_INITIALIZE not defined" -#endif -#ifndef CAIRO_MUTEX_IMPL_FINALIZE -# error "CAIRO_MUTEX_IMPL_FINALIZE not defined" -#endif -#ifndef CAIRO_MUTEX_IMPL_LOCK -# error "CAIRO_MUTEX_IMPL_LOCK not defined" -#endif -#ifndef CAIRO_MUTEX_IMPL_UNLOCK -# error "CAIRO_MUTEX_IMPL_UNLOCK not defined" -#endif -#ifndef CAIRO_MUTEX_IMPL_INIT -# error "CAIRO_MUTEX_IMPL_INIT not defined" -#endif -#ifndef CAIRO_MUTEX_IMPL_FINI -# error "CAIRO_MUTEX_IMPL_FINI not defined" -#endif -#ifndef CAIRO_MUTEX_IMPL_NIL_INITIALIZER -# error "CAIRO_MUTEX_IMPL_NIL_INITIALIZER not defined" -#endif - - -/* Public interface. */ - -/* By default it simply uses the implementation provided. - * But we can provide for debugging features by overriding them */ - -#ifndef CAIRO_MUTEX_DEBUG -typedef cairo_mutex_impl_t cairo_mutex_t; -#else -# define cairo_mutex_t cairo_mutex_impl_t -#endif - -#define CAIRO_MUTEX_INITIALIZE CAIRO_MUTEX_IMPL_INITIALIZE -#define CAIRO_MUTEX_FINALIZE CAIRO_MUTEX_IMPL_FINALIZE -#define CAIRO_MUTEX_LOCK CAIRO_MUTEX_IMPL_LOCK -#define CAIRO_MUTEX_UNLOCK CAIRO_MUTEX_IMPL_UNLOCK -#define CAIRO_MUTEX_INIT CAIRO_MUTEX_IMPL_INIT -#define CAIRO_MUTEX_FINI CAIRO_MUTEX_IMPL_FINI -#define CAIRO_MUTEX_NIL_INITIALIZER CAIRO_MUTEX_IMPL_NIL_INITIALIZER - -#ifndef CAIRO_MUTEX_IS_LOCKED -# define CAIRO_MUTEX_IS_LOCKED(name) 1 -#endif -#ifndef CAIRO_MUTEX_IS_UNLOCKED -# define CAIRO_MUTEX_IS_UNLOCKED(name) 1 -#endif - - -/* Debugging support */ - -#ifdef CAIRO_MUTEX_DEBUG - -/* TODO add mutex debugging facilities here (eg deadlock detection) */ - -#endif /* CAIRO_MUTEX_DEBUG */ - -#endif diff --git a/uppdev/plugin/cairo/lib/cairo-mutex.c b/uppdev/plugin/cairo/lib/cairo-mutex.c deleted file mode 100644 index 5b6a6e150..000000000 --- a/uppdev/plugin/cairo/lib/cairo-mutex.c +++ /dev/null @@ -1,82 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2007 Mathias Hasselmann - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * Contributor(s): - * Mathias Hasselmann - */ - -#include "cairoint.h" - -#include "cairo-mutex-private.h" - -#define CAIRO_MUTEX_DECLARE(mutex) cairo_mutex_t mutex = CAIRO_MUTEX_NIL_INITIALIZER; -#include "cairo-mutex-list-private.h" -#undef CAIRO_MUTEX_DECLARE - -#if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER || _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER - -# if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER -# define _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VALUE FALSE -# else -# define _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VALUE TRUE -# endif - -cairo_bool_t _cairo_mutex_initialized = _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VALUE; - -# undef _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VALUE - -#endif - -#if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER -void _cairo_mutex_initialize (void) -{ - if (_cairo_mutex_initialized) - return; - - _cairo_mutex_initialized = TRUE; - -#define CAIRO_MUTEX_DECLARE(mutex) CAIRO_MUTEX_INIT (mutex); -#include "cairo-mutex-list-private.h" -#undef CAIRO_MUTEX_DECLARE -} -#endif - -#if _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER -void _cairo_mutex_finalize (void) -{ - if (!_cairo_mutex_initialized) - return; - - _cairo_mutex_initialized = FALSE; - -#define CAIRO_MUTEX_DECLARE(mutex) CAIRO_MUTEX_FINI (mutex); -#include "cairo-mutex-list-private.h" -#undef CAIRO_MUTEX_DECLARE -} -#endif diff --git a/uppdev/plugin/cairo/lib/cairo-os2-private.h b/uppdev/plugin/cairo/lib/cairo-os2-private.h deleted file mode 100644 index 5fa282951..000000000 --- a/uppdev/plugin/cairo/lib/cairo-os2-private.h +++ /dev/null @@ -1,77 +0,0 @@ -/* vim: set sw=4 sts=4 et cin: */ -/* cairo - a vector graphics library with display and print output - * - * Copyright (c) 2005-2006 netlabs.org - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is - * Doodle - * - * Contributor(s): - * Peter Weilbacher - */ - -#ifndef CAIRO_OS2_PRIVATE_H -#define CAIRO_OS2_PRIVATE_H - -#include "cairo-os2.h" -#include "cairoint.h" - -#define INCL_DOS -#define INCL_DOSSEMAPHORES -#define INCL_DOSERRORS -#define INCL_WIN -#define INCL_GPI -#ifdef __WATCOMC__ -# include -#else -# include -#endif - -typedef struct _cairo_os2_surface -{ - cairo_surface_t base; - - /* Mutex semaphore to protect private fields from concurrent access */ - HMTX hmtx_use_private_fields; - /* Private fields: */ - HPS hps_client_window; - HWND hwnd_client_window; - BITMAPINFO2 bitmap_info; - unsigned char *pixels; - cairo_image_surface_t *image_surface; - int pixel_array_lend_count; - HEV hev_pixel_array_came_back; - - RECTL rcl_dirty_area; - cairo_bool_t dirty_area_present; - - /* General flags: */ - cairo_bool_t blit_as_changes; -} cairo_os2_surface_t; - -#endif /* CAIRO_OS2_PRIVATE_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-os2-surface.c b/uppdev/plugin/cairo/lib/cairo-os2-surface.c deleted file mode 100644 index bff649ae8..000000000 --- a/uppdev/plugin/cairo/lib/cairo-os2-surface.c +++ /dev/null @@ -1,1351 +0,0 @@ -/* vim: set sw=4 sts=4 et cin: */ -/* cairo - a vector graphics library with display and print output - * - * Copyright (c) 2005-2006 netlabs.org - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is - * Doodle - * - * Contributor(s): - * Peter Weilbacher - */ - -#include "cairoint.h" - -#include "cairo-os2-private.h" - -#include - -#include -#ifdef BUILD_CAIRO_DLL -# define INCL_WIN -# define INCL_GPI -# define INCL_DOS -# define INCL_DOSERRORS -# include -# include "cairo-os2.h" -# ifndef __WATCOMC__ -# include -# endif -#endif - -/* - * Here comes the extra API for the OS/2 platform. Currently it consists - * of two extra functions, the cairo_os2_init() and the - * cairo_os2_fini(). Both of them are called automatically if - * Cairo is compiled to be a DLL file, but you have to call them before - * using the Cairo API if you link to Cairo statically! - * - * You'll also find the code in here which deals with DLL initialization - * and termination, if the code is built to be a DLL. - * (if BUILD_CAIRO_DLL is defined) - */ - -/* Initialization counter: */ -static int cairo_os2_initialization_count = 0; - -static void inline -DisableFPUException (void) -{ - unsigned short usCW; - - /* Some OS/2 PM API calls modify the FPU Control Word, - * but forget to restore it. - * - * This can result in XCPT_FLOAT_INVALID_OPCODE exceptions, - * so to be sure, we disable Invalid Opcode FPU exception - * before using FPU stuffs. - */ - usCW = _control87 (0, 0); - usCW = usCW | EM_INVALID | 0x80; - _control87 (usCW, MCW_EM | 0x80); -} - -/** - * cairo_os2_init: - * - * Initializes the Cairo library. This function is automatically called if - * Cairo was compiled to be a DLL (however it's not a problem if it's called - * multiple times). But if you link to Cairo statically, you have to call it - * once to set up Cairo's internal structures and mutexes. - * - * Since: 1.4 - **/ -cairo_public void -cairo_os2_init (void) -{ - /* This may initialize some stuffs, like create mutex semaphores etc.. */ - - cairo_os2_initialization_count++; - if (cairo_os2_initialization_count > 1) return; - - DisableFPUException (); - -#if CAIRO_HAS_FT_FONT - /* Initialize FontConfig */ - FcInit (); -#endif - - CAIRO_MUTEX_INITIALIZE (); -} - -/** - * cairo_os2_fini: - * - * Uninitializes the Cairo library. This function is automatically called if - * Cairo was compiled to be a DLL (however it's not a problem if it's called - * multiple times). But if you link to Cairo statically, you have to call it - * once to shut down Cairo, to let it free all the resources it has allocated. - * - * Since: 1.4 - **/ -cairo_public void -cairo_os2_fini (void) -{ - /* This has to uninitialize some stuffs, like destroy mutex semaphores etc.. */ - - if (cairo_os2_initialization_count <= 0) return; - cairo_os2_initialization_count--; - if (cairo_os2_initialization_count > 0) return; - - DisableFPUException (); - - /* Free allocated memories! */ - /* (Check cairo_debug_reset_static_data () for an example of this!) */ - _cairo_font_face_reset_static_data (); -#if CAIRO_HAS_FT_FONT - _cairo_ft_font_reset_static_data (); -#endif - - CAIRO_MUTEX_FINALIZE (); - -#if CAIRO_HAS_FT_FONT -# if HAVE_FCFINI - /* Uninitialize FontConfig */ - FcFini (); -# endif -#endif - -#ifdef __WATCOMC__ - /* It can happen that the libraries we use have memory leaks, - * so there are still memory chunks allocated at this point. - * In these cases, Watcom might still have a bigger memory chunk, - * called "the heap" allocated from the OS. - * As we want to minimize the memory we lose from the point of - * view of the OS, we call this function to shrink that heap - * as much as possible. - */ - _heapshrink (); -#else - /* GCC has a heapmin function that approximately corresponds to - * what the Watcom function does - */ - _heapmin (); -#endif -} - -/* - * This function calls the allocation function depending on which - * method was compiled into the library: it can be native allocation - * (DosAllocMem/DosFreeMem) or C-Library based allocation (malloc/free). - * Actually, for pixel buffers that we use this function for, cairo - * uses _cairo_malloc_abc, so we use that here, too. And use the - * change to check the size argument - */ -void *_buffer_alloc (size_t a, size_t b, const unsigned int size) -{ - /* check length like in the _cairo_malloc_abc macro, but we can leave - * away the unsigned casts as our arguments are unsigned already - */ - size_t nbytes = b && - a >= INT32_MAX / b ? 0 : size && - a*b >= INT32_MAX / size ? 0 : a * b * size; - void *buffer = NULL; -#ifdef OS2_USE_PLATFORM_ALLOC - APIRET rc = NO_ERROR; - - rc = DosAllocMem ((PPVOID)&buffer, - nbytes, -#ifdef OS2_HIGH_MEMORY /* only if compiled with high-memory support, */ - OBJ_ANY | /* we can allocate anywhere! */ -#endif - PAG_READ | PAG_WRITE | PAG_COMMIT); - if (rc != NO_ERROR) { - /* should there for some reason be another error, let's return - * a null surface and free the buffer again, because that's - * how a malloc failure would look like - */ - if (rc != ERROR_NOT_ENOUGH_MEMORY && buffer) { - DosFreeMem (buffer); - } - return NULL; - } -#else - buffer = malloc (nbytes); -#endif - - /* This does not seem to be needed, malloc'd space is usually - * already zero'd out! - */ - /* - * memset (buffer, 0x00, nbytes); - */ - - return buffer; -} - -/* - * This function selects the free function depending on which - * allocation method was compiled into the library - */ -void _buffer_free (void *buffer) -{ -#ifdef OS2_USE_PLATFORM_ALLOC - DosFreeMem (buffer); -#else - free (buffer); -#endif -} - -/* XXX - * The cairo_os2_ini() and cairo_os2_fini() functions should be removed and - * the LibMain code moved to cairo-system.c. It should also call - * cairo_debug_reset_static_data() instead of duplicating its logic... - */ - -#ifdef BUILD_CAIRO_DLL -/* The main DLL entry for DLL initialization and uninitialization */ -/* Only include this code if we're about to build a DLL. */ - -#ifdef __WATCOMC__ -unsigned _System -LibMain (unsigned hmod, - unsigned termination) -#else -unsigned long _System -_DLL_InitTerm (unsigned long hModule, - unsigned long termination) -#endif -{ - if (termination) { - /* Unloading the DLL */ - cairo_os2_fini (); - -#ifndef __WATCOMC__ - /* Uninitialize RTL of GCC */ - __ctordtorTerm (); - _CRT_term (); -#endif - return 1; - } else { - /* Loading the DLL */ -#ifndef __WATCOMC__ - /* Initialize RTL of GCC */ - if (_CRT_init () != 0) - return 0; - __ctordtorInit (); -#endif - - cairo_os2_init (); - return 1; - } -} - -#endif /* BUILD_CAIRO_DLL */ - -/* - * The following part of the source file contains the code which might - * be called the "core" of the OS/2 backend support. This contains the - * OS/2 surface support functions and structures. - */ - -/* Forward declaration */ -static const cairo_surface_backend_t cairo_os2_surface_backend; - -/* Unpublished API: - * GpiEnableYInversion = PMGPI.723 - * GpiQueryYInversion = PMGPI.726 - * BOOL APIENTRY GpiEnableYInversion (HPS hps, LONG lHeight); - * LONG APIENTRY GpiQueryYInversion (HPS hps); - */ -BOOL APIENTRY GpiEnableYInversion (HPS hps, LONG lHeight); -LONG APIENTRY GpiQueryYInversion (HPS hps); - -#ifdef __WATCOMC__ -/* Function declaration for GpiDrawBits () (missing from OpenWatcom headers) */ -LONG APIENTRY GpiDrawBits (HPS hps, - PVOID pBits, - PBITMAPINFO2 pbmiInfoTable, - LONG lCount, - PPOINTL aptlPoints, - LONG lRop, - ULONG flOptions); -#endif - -static void -_cairo_os2_surface_blit_pixels (cairo_os2_surface_t *surface, - HPS hps_begin_paint, - PRECTL prcl_begin_paint_rect) -{ - POINTL aptlPoints[4]; - LONG lOldYInversion, rc = GPI_OK; - - /* Enable Y Inversion for the HPS, so the - * GpiDrawBits will work with upside-top image, not with upside-down image! - */ - lOldYInversion = GpiQueryYInversion (hps_begin_paint); - GpiEnableYInversion (hps_begin_paint, surface->bitmap_info.cy-1); - - /* Target coordinates (Noninclusive) */ - aptlPoints[0].x = prcl_begin_paint_rect->xLeft; - aptlPoints[0].y = prcl_begin_paint_rect->yBottom; - - aptlPoints[1].x = prcl_begin_paint_rect->xRight-1; - aptlPoints[1].y = prcl_begin_paint_rect->yTop-1; - - /* Source coordinates (Inclusive) */ - aptlPoints[2].x = prcl_begin_paint_rect->xLeft; - aptlPoints[2].y = prcl_begin_paint_rect->yBottom; - - aptlPoints[3].x = prcl_begin_paint_rect->xRight; - aptlPoints[3].y = (prcl_begin_paint_rect->yTop); - - /* Some extra checking for limits - * (Dunno if really needed, but had some crashes sometimes without it, - * while developing the code...) - */ - { - int i; - for (i = 0; i < 4; i++) { - if (aptlPoints[i].x < 0) - aptlPoints[i].x = 0; - if (aptlPoints[i].y < 0) - aptlPoints[i].y = 0; - if (aptlPoints[i].x > (LONG) surface->bitmap_info.cx) - aptlPoints[i].x = (LONG) surface->bitmap_info.cx; - if (aptlPoints[i].y > (LONG) surface->bitmap_info.cy) - aptlPoints[i].y = (LONG) surface->bitmap_info.cy; - } - } - - /* Debug code to draw rectangle limits */ -#if 0 - { - int x, y; - unsigned char *pixels; - - pixels = surface->pixels; - for (x = 0; x < surface->bitmap_info.cx; x++) { - for (y = 0; y < surface->bitmap_info.cy; y++) { - if ((x == 0) || - (y == 0) || - (x == y) || - (x >= surface->bitmap_info.cx-1) || - (y >= surface->bitmap_info.cy-1)) - { - pixels[y*surface->bitmap_info.cx*4+x*4] = 255; - } - } - } - } -#endif - rc = GpiDrawBits (hps_begin_paint, - surface->pixels, - &(surface->bitmap_info), - 4, - aptlPoints, - ROP_SRCCOPY, - BBO_IGNORE); - - if (rc != GPI_OK) { - /* if GpiDrawBits () failed then this is most likely because the - * display driver could not handle a 32bit bitmap. So we need to - * - create a buffer that only contains 3 bytes per pixel - * - change the bitmap info header to contain 24bit - * - pass the new buffer to GpiDrawBits () again - * - clean up the new buffer - */ - BITMAPINFOHEADER2 bmpheader; - unsigned char *pchPixBuf, *pchPixSource; - void *pBufStart; - ULONG ulPixels; - - /* allocate temporary pixel buffer */ - pchPixBuf = (unsigned char *) _buffer_alloc (surface->bitmap_info.cy, - surface->bitmap_info.cx, - 3); - pchPixSource = surface->pixels; /* start at beginning of pixel buffer */ - pBufStart = pchPixBuf; /* remember beginning of the new pixel buffer */ - - /* copy the first three bytes for each pixel but skip over the fourth */ - for (ulPixels = 0; ulPixels < surface->bitmap_info.cx * surface->bitmap_info.cy; ulPixels++) - { - /* copy BGR from source buffer */ - *pchPixBuf++ = *pchPixSource++; - *pchPixBuf++ = *pchPixSource++; - *pchPixBuf++ = *pchPixSource++; - pchPixSource++; /* jump over alpha channel in source buffer */ - } - - /* jump back to start of the buffer for display and cleanup */ - pchPixBuf = pBufStart; - - /* set up the bitmap header, but this time with 24bit depth only */ - memset (&bmpheader, 0, sizeof (bmpheader)); - bmpheader.cbFix = sizeof (BITMAPINFOHEADER2); - bmpheader.cx = surface->bitmap_info.cx; - bmpheader.cy = surface->bitmap_info.cy; - bmpheader.cPlanes = surface->bitmap_info.cPlanes; - bmpheader.cBitCount = 24; - rc = GpiDrawBits (hps_begin_paint, - pchPixBuf, - (PBITMAPINFO2)&bmpheader, - 4, - aptlPoints, - ROP_SRCCOPY, - BBO_IGNORE); - - _buffer_free (pchPixBuf); - } - - /* Restore Y inversion */ - GpiEnableYInversion (hps_begin_paint, lOldYInversion); -} - -static void -_cairo_os2_surface_get_pixels_from_screen (cairo_os2_surface_t *surface, - HPS hps_begin_paint, - PRECTL prcl_begin_paint_rect) -{ - HPS hps; - HDC hdc; - HAB hab; - SIZEL sizlTemp; - HBITMAP hbmpTemp; - BITMAPINFO2 bmi2Temp; - POINTL aptlPoints[4]; - int y; - unsigned char *pchTemp; - - /* To copy pixels from screen to our buffer, we do the following steps: - * - * - Blit pixels from screen to a HBITMAP: - * -- Create Memory Device Context - * -- Create a PS into it - * -- Create a HBITMAP - * -- Select HBITMAP into memory PS - * -- Blit dirty pixels from screen to HBITMAP - * - Copy HBITMAP lines (pixels) into our buffer - * - Free resources - * - * These steps will require an Anchor Block (HAB). However, - * WinQUeryAnchorBlock () documentation says that HAB is not - * used in current OS/2 implementations, OS/2 deduces all information - * it needs from the TID. Anyway, we'd be in trouble if we'd have to - * get a HAB where we only know a HPS... - * So, we'll simply use a fake HAB. - */ - - hab = (HAB) 1; /* OS/2 doesn't really use HAB... */ - - /* Create a memory device context */ - hdc = DevOpenDC (hab, OD_MEMORY,"*",0L, NULL, NULLHANDLE); - if (!hdc) { - return; - } - - /* Create a memory PS */ - sizlTemp.cx = prcl_begin_paint_rect->xRight - prcl_begin_paint_rect->xLeft; - sizlTemp.cy = prcl_begin_paint_rect->yTop - prcl_begin_paint_rect->yBottom; - hps = GpiCreatePS (hab, - hdc, - &sizlTemp, - PU_PELS | GPIT_NORMAL | GPIA_ASSOC); - if (!hps) { - DevCloseDC (hdc); - return; - } - - /* Create an uninitialized bitmap. */ - /* Prepare BITMAPINFO2 structure for our buffer */ - memset (&bmi2Temp, 0, sizeof (bmi2Temp)); - bmi2Temp.cbFix = sizeof (BITMAPINFOHEADER2); - bmi2Temp.cx = sizlTemp.cx; - bmi2Temp.cy = sizlTemp.cy; - bmi2Temp.cPlanes = 1; - bmi2Temp.cBitCount = 32; - - hbmpTemp = GpiCreateBitmap (hps, - (PBITMAPINFOHEADER2) &bmi2Temp, - 0, - NULL, - NULL); - - if (!hbmpTemp) { - GpiDestroyPS (hps); - DevCloseDC (hdc); - return; - } - - /* Select the bitmap into the memory device context. */ - GpiSetBitmap (hps, hbmpTemp); - - /* Target coordinates (Noninclusive) */ - aptlPoints[0].x = 0; - aptlPoints[0].y = 0; - - aptlPoints[1].x = sizlTemp.cx; - aptlPoints[1].y = sizlTemp.cy; - - /* Source coordinates (Inclusive) */ - aptlPoints[2].x = prcl_begin_paint_rect->xLeft; - aptlPoints[2].y = surface->bitmap_info.cy - prcl_begin_paint_rect->yBottom; - - aptlPoints[3].x = prcl_begin_paint_rect->xRight; - aptlPoints[3].y = surface->bitmap_info.cy - prcl_begin_paint_rect->yTop; - - /* Blit pixels from screen to bitmap */ - GpiBitBlt (hps, - hps_begin_paint, - 4, - aptlPoints, - ROP_SRCCOPY, - BBO_IGNORE); - - /* Now we have to extract the pixels from the bitmap. */ - pchTemp = - surface->pixels + - (prcl_begin_paint_rect->yBottom)*surface->bitmap_info.cx*4 + - prcl_begin_paint_rect->xLeft*4; - for (y = 0; y < sizlTemp.cy; y++) { - /* Get one line of pixels */ - GpiQueryBitmapBits (hps, - sizlTemp.cy - y - 1, /* lScanStart */ - 1, /* lScans */ - pchTemp, - &bmi2Temp); - - /* Go for next line */ - pchTemp += surface->bitmap_info.cx*4; - } - - /* Clean up resources */ - GpiSetBitmap (hps, (HBITMAP) NULL); - GpiDeleteBitmap (hbmpTemp); - GpiDestroyPS (hps); - DevCloseDC (hdc); -} - -static cairo_status_t -_cairo_os2_surface_acquire_source_image (void *abstract_surface, - cairo_image_surface_t **image_out, - void **image_extra) -{ - cairo_os2_surface_t *local_os2_surface; - - local_os2_surface = (cairo_os2_surface_t *) abstract_surface; - if ((!local_os2_surface) || - (local_os2_surface->base.backend != &cairo_os2_surface_backend)) - { - /* Invalid parameter (wrong surface)! */ - return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - } - - DosRequestMutexSem (local_os2_surface->hmtx_use_private_fields, SEM_INDEFINITE_WAIT); - - /* Increase lend counter */ - local_os2_surface->pixel_array_lend_count++; - - *image_out = local_os2_surface->image_surface; - *image_extra = NULL; - - DosReleaseMutexSem (local_os2_surface->hmtx_use_private_fields); - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_os2_surface_release_source_image (void *abstract_surface, - cairo_image_surface_t *image, - void *image_extra) -{ - cairo_os2_surface_t *local_os2_surface; - - local_os2_surface = (cairo_os2_surface_t *) abstract_surface; - if ((!local_os2_surface) || - (local_os2_surface->base.backend != &cairo_os2_surface_backend)) - { - /* Invalid parameter (wrong surface)! */ - return; - } - - /* Decrease Lend counter! */ - DosRequestMutexSem (local_os2_surface->hmtx_use_private_fields, SEM_INDEFINITE_WAIT); - - if (local_os2_surface->pixel_array_lend_count > 0) - local_os2_surface->pixel_array_lend_count--; - DosPostEventSem (local_os2_surface->hev_pixel_array_came_back); - - DosReleaseMutexSem (local_os2_surface->hmtx_use_private_fields); - return; -} - -static cairo_status_t -_cairo_os2_surface_acquire_dest_image (void *abstract_surface, - cairo_rectangle_int_t *interest_rect, - cairo_image_surface_t **image_out, - cairo_rectangle_int_t *image_rect, - void **image_extra) -{ - cairo_os2_surface_t *local_os2_surface; - - local_os2_surface = (cairo_os2_surface_t *) abstract_surface; - if ((!local_os2_surface) || - (local_os2_surface->base.backend != &cairo_os2_surface_backend)) - { - /* Invalid parameter (wrong surface)! */ - return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - } - - DosRequestMutexSem (local_os2_surface->hmtx_use_private_fields, SEM_INDEFINITE_WAIT); - - /* Increase lend counter */ - local_os2_surface->pixel_array_lend_count++; - - *image_out = local_os2_surface->image_surface; - *image_extra = NULL; - - image_rect->x = 0; - image_rect->y = 0; - image_rect->width = local_os2_surface->bitmap_info.cx; - image_rect->height = local_os2_surface->bitmap_info.cy; - - DosReleaseMutexSem (local_os2_surface->hmtx_use_private_fields); - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_os2_surface_release_dest_image (void *abstract_surface, - cairo_rectangle_int_t *interest_rect, - cairo_image_surface_t *image, - cairo_rectangle_int_t *image_rect, - void *image_extra) -{ - cairo_os2_surface_t *local_os2_surface; - RECTL rclToBlit; - - local_os2_surface = (cairo_os2_surface_t *) abstract_surface; - if ((!local_os2_surface) || - (local_os2_surface->base.backend != &cairo_os2_surface_backend)) - { - /* Invalid parameter (wrong surface)! */ - return; - } - - /* So, we got back the image, and if all goes well, then - * something has been changed inside the interest_rect. - * So, we blit it to the screen! - */ - - if (local_os2_surface->blit_as_changes) { - /* Get mutex, we'll work with the pixel array! */ - if (DosRequestMutexSem (local_os2_surface->hmtx_use_private_fields, SEM_INDEFINITE_WAIT)!=NO_ERROR) { - /* Could not get mutex! */ - return; - } - - if (local_os2_surface->hwnd_client_window) { - /* We know the HWND, so let's invalidate the window region, - * so the application will redraw itself, using the - * cairo_os2_surface_refresh_window () API from its own PM thread. - * - * This is the safe method, which should be preferred every time. - */ - rclToBlit.xLeft = interest_rect->x; - rclToBlit.xRight = interest_rect->x+interest_rect->width; /* Noninclusive */ - rclToBlit.yTop = local_os2_surface->bitmap_info.cy - (interest_rect->y); - rclToBlit.yBottom = local_os2_surface->bitmap_info.cy - (interest_rect->y+interest_rect->height); /* Noninclusive */ - - WinInvalidateRect (local_os2_surface->hwnd_client_window, - &rclToBlit, - FALSE); - } else { - /* We don't know the HWND, so try to blit the pixels from here! - * Please note that it can be problematic if this is not the PM thread! - * - * It can cause internal PM stuffs to be scewed up, for some reason. - * Please always tell the HWND to the surface using the - * cairo_os2_surface_set_hwnd () API, and call cairo_os2_surface_refresh_window () - * from your WM_PAINT, if it's possible! - */ - rclToBlit.xLeft = interest_rect->x; - rclToBlit.xRight = interest_rect->x+interest_rect->width; /* Noninclusive */ - rclToBlit.yBottom = interest_rect->y; - rclToBlit.yTop = interest_rect->y+interest_rect->height; /* Noninclusive */ - /* Now blit there the stuffs! */ - _cairo_os2_surface_blit_pixels (local_os2_surface, - local_os2_surface->hps_client_window, - &rclToBlit); - } - - DosReleaseMutexSem (local_os2_surface->hmtx_use_private_fields); - } - /* Also decrease Lend counter! */ - DosRequestMutexSem (local_os2_surface->hmtx_use_private_fields, SEM_INDEFINITE_WAIT); - - if (local_os2_surface->pixel_array_lend_count > 0) - local_os2_surface->pixel_array_lend_count--; - DosPostEventSem (local_os2_surface->hev_pixel_array_came_back); - - DosReleaseMutexSem (local_os2_surface->hmtx_use_private_fields); -} - -static cairo_int_status_t -_cairo_os2_surface_get_extents (void *abstract_surface, - cairo_rectangle_int_t *rectangle) -{ - cairo_os2_surface_t *local_os2_surface; - - local_os2_surface = (cairo_os2_surface_t *) abstract_surface; - if ((!local_os2_surface) || - (local_os2_surface->base.backend != &cairo_os2_surface_backend)) - { - /* Invalid parameter (wrong surface)! */ - return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - } - - rectangle->x = 0; - rectangle->y = 0; - rectangle->width = local_os2_surface->bitmap_info.cx; - rectangle->height = local_os2_surface->bitmap_info.cy; - - return CAIRO_STATUS_SUCCESS; -} - -/** - * cairo_os2_surface_create: - * @hps_client_window: the presentation handle to bind the surface to - * @width: the width of the surface - * @height: the height of the surface - * - * Create a Cairo surface which is bound to a given presentation space (HPS). - * The surface will be created to have the given size. - * By default every change to the surface will be made visible immediately by - * blitting it into the window. This can be changed with - * cairo_os2_surface_set_manual_window_refresh(). - * Note that the surface will contain garbage when created, so the pixels have - * to be initialized by hand first. You can use the Cairo functions to fill it - * with black, or use cairo_surface_mark_dirty() to fill the surface with pixels - * from the window/HPS. - * - * Return value: the newly created surface - * - * Since: 1.4 - **/ -cairo_surface_t * -cairo_os2_surface_create (HPS hps_client_window, - int width, - int height) -{ - cairo_os2_surface_t *local_os2_surface; - cairo_status_t status; - int rc; - - /* Check the size of the window */ - if ((width <= 0) || - (height <= 0)) - { - /* Invalid window size! */ - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - } - - local_os2_surface = (cairo_os2_surface_t *) malloc (sizeof (cairo_os2_surface_t)); - if (!local_os2_surface) { - /* Not enough memory! */ - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - } - - /* Initialize the OS/2 specific parts of the surface! */ - - /* Create mutex semaphore */ - rc = DosCreateMutexSem (NULL, - &(local_os2_surface->hmtx_use_private_fields), - 0, - FALSE); - if (rc != NO_ERROR) { - /* Could not create mutex semaphore! */ - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - } - - /* Save PS handle */ - local_os2_surface->hps_client_window = hps_client_window; - - /* Defaults */ - local_os2_surface->hwnd_client_window = NULLHANDLE; - local_os2_surface->blit_as_changes = TRUE; - local_os2_surface->pixel_array_lend_count = 0; - rc = DosCreateEventSem (NULL, - &(local_os2_surface->hev_pixel_array_came_back), - 0, - FALSE); - - if (rc != NO_ERROR) { - /* Could not create event semaphore! */ - DosCloseMutexSem (local_os2_surface->hmtx_use_private_fields); - free (local_os2_surface); - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - } - - /* Prepare BITMAPINFO2 structure for our buffer */ - memset (&(local_os2_surface->bitmap_info), 0, sizeof (local_os2_surface->bitmap_info)); - local_os2_surface->bitmap_info.cbFix = sizeof (BITMAPINFOHEADER2); - local_os2_surface->bitmap_info.cx = width; - local_os2_surface->bitmap_info.cy = height; - local_os2_surface->bitmap_info.cPlanes = 1; - local_os2_surface->bitmap_info.cBitCount = 32; - - /* Allocate memory for pixels */ - local_os2_surface->pixels = (unsigned char *) _buffer_alloc (height, width, 4); - if (!(local_os2_surface->pixels)) { - /* Not enough memory for the pixels! */ - DosCloseEventSem (local_os2_surface->hev_pixel_array_came_back); - DosCloseMutexSem (local_os2_surface->hmtx_use_private_fields); - free (local_os2_surface); - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - } - - /* Create image surface from pixel array */ - local_os2_surface->image_surface = (cairo_image_surface_t *) - cairo_image_surface_create_for_data (local_os2_surface->pixels, - CAIRO_FORMAT_ARGB32, - width, /* Width */ - height, /* Height */ - width * 4); /* Rowstride */ - - status = local_os2_surface->image_surface->base.status; - if (status) { - /* Could not create image surface! */ - _buffer_free (local_os2_surface->pixels); - DosCloseEventSem (local_os2_surface->hev_pixel_array_came_back); - DosCloseMutexSem (local_os2_surface->hmtx_use_private_fields); - free (local_os2_surface); - return _cairo_surface_create_in_error (status); - } - - /* Initialize base surface */ - _cairo_surface_init (&local_os2_surface->base, - &cairo_os2_surface_backend, - _cairo_content_from_format (CAIRO_FORMAT_ARGB32)); - - return (cairo_surface_t *)local_os2_surface; -} - -/** - * cairo_os2_surface_set_size: - * @surface: the cairo surface to resize - * @new_width: the new width of the surface - * @new_height: the new height of the surface - * @timeout: timeout value in milliseconds - * - * When the client window is resized, call this API to set the new size in the - * underlying surface accordingly. This function will reallocate everything, - * so you'll have to redraw everything in the surface after this call. - * The surface will contain garbage after the resizing. So the notes of - * cairo_os2_surface_create() apply here, too. - * - * The timeout value specifies how long the function should wait on other parts - * of the program to release the buffers. It is necessary, because it can happen - * that Cairo is just drawing something into the surface while we want to - * destroy and recreate it. - * - * Return value: %CAIRO_STATUS_SUCCESS if the surface could be resized, - * %CAIRO_STATUS_SURFACE_TYPE_MISMATCH if the surface is not an OS/2 surface, - * %CAIRO_STATUS_NO_MEMORY if the new size could not be allocated, for invalid - * sizes, or if the timeout happened before all the buffers were released - * - * Since: 1.4 - **/ -int -cairo_os2_surface_set_size (cairo_surface_t *surface, - int new_width, - int new_height, - int timeout) -{ - cairo_os2_surface_t *local_os2_surface; - unsigned char *pchNewPixels; - int rc; - cairo_image_surface_t *pNewImageSurface; - - local_os2_surface = (cairo_os2_surface_t *) surface; - if ((!local_os2_surface) || - (local_os2_surface->base.backend != &cairo_os2_surface_backend)) - { - /* Invalid parameter (wrong surface)! */ - return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - } - - if ((new_width <= 0) || - (new_height <= 0)) - { - /* Invalid size! */ - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - /* Allocate memory for new stuffs */ - pchNewPixels = (unsigned char *) _buffer_alloc (new_height, new_width, 4); - if (!pchNewPixels) { - /* Not enough memory for the pixels! - * Everything remains the same! - */ - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - /* Create image surface from new pixel array */ - pNewImageSurface = (cairo_image_surface_t *) - cairo_image_surface_create_for_data (pchNewPixels, - CAIRO_FORMAT_ARGB32, - new_width, /* Width */ - new_height, /* Height */ - new_width * 4); /* Rowstride */ - - if (pNewImageSurface->base.status) { - /* Could not create image surface! - * Everything remains the same! - */ - _buffer_free (pchNewPixels); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - /* Okay, new memory allocated, so it's time to swap old buffers - * to new ones! - */ - if (DosRequestMutexSem (local_os2_surface->hmtx_use_private_fields, SEM_INDEFINITE_WAIT)!=NO_ERROR) { - /* Could not get mutex! - * Everything remains the same! - */ - cairo_surface_destroy ((cairo_surface_t *) pNewImageSurface); - _buffer_free (pchNewPixels); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - /* We have to make sure that we won't destroy a surface which - * is lent to some other code (Cairo is drawing into it)! - */ - while (local_os2_surface->pixel_array_lend_count > 0) { - ULONG ulPostCount; - DosResetEventSem (local_os2_surface->hev_pixel_array_came_back, &ulPostCount); - DosReleaseMutexSem (local_os2_surface->hmtx_use_private_fields); - /* Wait for somebody to return the pixels! */ - rc = DosWaitEventSem (local_os2_surface->hev_pixel_array_came_back, timeout); - if (rc != NO_ERROR) { - /* Either timeout or something wrong... Exit. */ - cairo_surface_destroy ((cairo_surface_t *) pNewImageSurface); - _buffer_free (pchNewPixels); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - /* Okay, grab mutex and check counter again! */ - if (DosRequestMutexSem (local_os2_surface->hmtx_use_private_fields, SEM_INDEFINITE_WAIT) - != NO_ERROR) - { - /* Could not get mutex! - * Everything remains the same! - */ - cairo_surface_destroy ((cairo_surface_t *) pNewImageSurface); - _buffer_free (pchNewPixels); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - } - - /* Destroy old image surface */ - cairo_surface_destroy ((cairo_surface_t *) (local_os2_surface->image_surface)); - /* Destroy old pixel buffer */ - _buffer_free (local_os2_surface->pixels); - /* Set new image surface */ - local_os2_surface->image_surface = pNewImageSurface; - /* Set new pixel buffer */ - local_os2_surface->pixels = pchNewPixels; - /* Change bitmap2 structure */ - local_os2_surface->bitmap_info.cx = new_width; - local_os2_surface->bitmap_info.cy = new_height; - - DosReleaseMutexSem (local_os2_surface->hmtx_use_private_fields); - return CAIRO_STATUS_SUCCESS; -} - -/** - * cairo_os2_surface_refresh_window: - * @surface: the cairo surface to refresh - * @hps_begin_paint: the presentation handle of the window to refresh - * @prcl_begin_paint_rect: the rectangle to redraw - * - * This function can be used to force a repaint of a given area of the client - * window. It should usually be called from the WM_PAINT processing of the - * window procedure. However, it can be called any time a given part of the - * window has to be updated. - * - * The HPS and RECTL to be passed can be taken from the usual WinBeginPaint call - * of the window procedure, but you can also get the HPS using WinGetPS, and you - * can assemble your own update rectangle by hand. - * If hps_begin_paint is %NULL, the function will use the HPS passed into - * cairo_os2_surface_create(). If @prcl_begin_paint_rect is %NULL, the function - * will query the current window size and repaint the whole window. - * - * Cairo assumes that if you set the HWND to the surface using - * cairo_os2_surface_set_hwnd(), this function will be called by the application - * every time it gets a WM_PAINT for that HWND. If the HWND is set in the - * surface, Cairo uses this function to handle dirty areas too. - * - * Since: 1.4 - **/ -void -cairo_os2_surface_refresh_window (cairo_surface_t *surface, - HPS hps_begin_paint, - PRECTL prcl_begin_paint_rect) -{ - cairo_os2_surface_t *local_os2_surface; - RECTL rclTemp; - - local_os2_surface = (cairo_os2_surface_t *) surface; - if ((!local_os2_surface) || - (local_os2_surface->base.backend != &cairo_os2_surface_backend)) - { - /* Invalid parameter (wrong surface)! */ - return; - } - - /* Manage defaults (NULLs) */ - if (!hps_begin_paint) - hps_begin_paint = local_os2_surface->hps_client_window; - - if (prcl_begin_paint_rect == NULL) { - /* Update the whole window! */ - rclTemp.xLeft = 0; - rclTemp.xRight = local_os2_surface->bitmap_info.cx; - rclTemp.yTop = local_os2_surface->bitmap_info.cy; - rclTemp.yBottom = 0; - } else { - /* Use the rectangle we got passed as parameter! */ - rclTemp.xLeft = prcl_begin_paint_rect->xLeft; - rclTemp.xRight = prcl_begin_paint_rect->xRight; - rclTemp.yTop = local_os2_surface->bitmap_info.cy - prcl_begin_paint_rect->yBottom; - rclTemp.yBottom = local_os2_surface->bitmap_info.cy - prcl_begin_paint_rect->yTop ; - } - - /* Get mutex, we'll work with the pixel array! */ - if (DosRequestMutexSem (local_os2_surface->hmtx_use_private_fields, SEM_INDEFINITE_WAIT) - != NO_ERROR) - { - /* Could not get mutex! */ - return; - } - - if ((local_os2_surface->dirty_area_present) && - (local_os2_surface->rcl_dirty_area.xLeft == rclTemp.xLeft) && - (local_os2_surface->rcl_dirty_area.xRight == rclTemp.xRight) && - (local_os2_surface->rcl_dirty_area.yTop == rclTemp.yTop) && - (local_os2_surface->rcl_dirty_area.yBottom == rclTemp.yBottom)) - { - /* Aha, this call was because of a dirty area, so in this case we - * have to blit the pixels from the screen to the surface! - */ - local_os2_surface->dirty_area_present = FALSE; - _cairo_os2_surface_get_pixels_from_screen (local_os2_surface, - hps_begin_paint, - &rclTemp); - } else { - /* Okay, we have the surface, have the HPS - * (might be from WinBeginPaint () or from WinGetPS () ) - * Now blit there the stuffs! - */ - _cairo_os2_surface_blit_pixels (local_os2_surface, - hps_begin_paint, - &rclTemp); - } - - DosReleaseMutexSem (local_os2_surface->hmtx_use_private_fields); -} - -static cairo_status_t -_cairo_os2_surface_finish (void *abstract_surface) -{ - cairo_os2_surface_t *local_os2_surface; - - local_os2_surface = (cairo_os2_surface_t *) abstract_surface; - if ((!local_os2_surface) || - (local_os2_surface->base.backend != &cairo_os2_surface_backend)) - { - /* Invalid parameter (wrong surface)! */ - return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - } - - DosRequestMutexSem (local_os2_surface->hmtx_use_private_fields, SEM_INDEFINITE_WAIT); - - /* Destroy old image surface */ - cairo_surface_destroy ((cairo_surface_t *) (local_os2_surface->image_surface)); - /* Destroy old pixel buffer */ - _buffer_free (local_os2_surface->pixels); - DosCloseMutexSem (local_os2_surface->hmtx_use_private_fields); - DosCloseEventSem (local_os2_surface->hev_pixel_array_came_back); - - /* The memory itself will be free'd by the cairo_surface_destroy () - * who called us. - */ - - return CAIRO_STATUS_SUCCESS; -} - -/** - * cairo_os2_surface_set_hwnd: - * @surface: the cairo surface to associate with the window handle - * @hwnd_client_window: the window handle of the client window - * - * Sets window handle for surface. If Cairo wants to blit into the window - * because it is set to blit as the surface changes (see - * cairo_os2_surface_set_manual_window_refresh()), then there are two ways it - * can choose: - * If it knows the HWND of the surface, then it invalidates that area, so the - * application will get a WM_PAINT message and it can call - * cairo_os2_surface_refresh_window() to redraw that area. Otherwise cairo itself - * will use the HPS it got at surface creation time, and blit the pixels itself. - * It's also a solution, but experience shows that if this happens from a non-PM - * thread, then it can screw up PM internals. - * - * So, best solution is to set the HWND for the surface after the surface - * creation, so every blit will be done from application's message processing - * loop, which is the safest way to do. - * - * Since: 1.4 - **/ -void -cairo_os2_surface_set_hwnd (cairo_surface_t *surface, - HWND hwnd_client_window) -{ - cairo_os2_surface_t *local_os2_surface; - - local_os2_surface = (cairo_os2_surface_t *) surface; - if ((!local_os2_surface) || - (local_os2_surface->base.backend != &cairo_os2_surface_backend)) - { - /* Invalid parameter (wrong surface)! */ - return; - } - - if (DosRequestMutexSem (local_os2_surface->hmtx_use_private_fields, SEM_INDEFINITE_WAIT) - != NO_ERROR) - { - /* Could not get mutex! */ - return; - } - - local_os2_surface->hwnd_client_window = hwnd_client_window; - - DosReleaseMutexSem (local_os2_surface->hmtx_use_private_fields); -} - -/** - * cairo_os2_surface_set_manual_window_refresh: - * @surface: the cairo surface to set the refresh mode for - * @manual_refresh: the switch for manual surface refresh - * - * This API can tell Cairo if it should show every change to this surface - * immediately in the window or if it should be cached and will only be visible - * once the user calls cairo_os2_surface_refresh_window() explicitly. If the - * HWND was not set in the cairo surface, then the HPS will be used to blit the - * graphics. Otherwise it will invalidate the given window region so the user - * will get the WM_PAINT message to redraw that area of the window. - * - * So, if you're only interested in displaying the final result after several - * drawing operations, you might get better performance if you put the surface - * into manual refresh mode by passing a true value to this function. Then call - * cairo_os2_surface_refresh() whenever desired. - * - * Since: 1.4 - **/ -void -cairo_os2_surface_set_manual_window_refresh (cairo_surface_t *surface, - cairo_bool_t manual_refresh) -{ - cairo_os2_surface_t *local_os2_surface; - - local_os2_surface = (cairo_os2_surface_t *) surface; - if ((!local_os2_surface) || - (local_os2_surface->base.backend != &cairo_os2_surface_backend)) - { - /* Invalid parameter (wrong surface)! */ - return; - } - - local_os2_surface->blit_as_changes = !manual_refresh; -} - -/** - * cairo_os2_surface_get_manual_window_refresh: - * @surface: the cairo surface to query the refresh mode from - * - * This space left intentionally blank. - * - * Return value: current refresh mode of the surface (true by default) - * - * Since: 1.4 - **/ -cairo_bool_t -cairo_os2_surface_get_manual_window_refresh (cairo_surface_t *surface) -{ - cairo_os2_surface_t *local_os2_surface; - - local_os2_surface = (cairo_os2_surface_t *) surface; - if ((!local_os2_surface) || - (local_os2_surface->base.backend != &cairo_os2_surface_backend)) - { - /* Invalid parameter (wrong surface)! */ - return FALSE; - } - - return !(local_os2_surface->blit_as_changes); -} - -static cairo_status_t -_cairo_os2_surface_mark_dirty_rectangle (void *surface, - int x, - int y, - int width, - int height) -{ - cairo_os2_surface_t *local_os2_surface; - RECTL rclToBlit; - - local_os2_surface = (cairo_os2_surface_t *) surface; - if ((!local_os2_surface) || - (local_os2_surface->base.backend != &cairo_os2_surface_backend)) - { - /* Invalid parameter (wrong surface)! */ - return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - } - - /* Get mutex, we'll work with the pixel array! */ - if (DosRequestMutexSem (local_os2_surface->hmtx_use_private_fields, SEM_INDEFINITE_WAIT) - != NO_ERROR) - { - /* Could not get mutex! */ - return CAIRO_STATUS_NO_MEMORY; - } - - /* Check for defaults */ - if (width < 0) - width = local_os2_surface->bitmap_info.cx; - if (height < 0) - height = local_os2_surface->bitmap_info.cy; - - if (local_os2_surface->hwnd_client_window) { - /* We know the HWND, so let's invalidate the window region, - * so the application will redraw itself, using the - * cairo_os2_surface_refresh_window () API from its own PM thread. - * From that function we'll note that it's not a redraw but a - * dirty-rectangle deal stuff, so we'll handle the things from - * there. - * - * This is the safe method, which should be preferred every time. - */ - rclToBlit.xLeft = x; - rclToBlit.xRight = x + width; /* Noninclusive */ - rclToBlit.yTop = local_os2_surface->bitmap_info.cy - (y); - rclToBlit.yBottom = local_os2_surface->bitmap_info.cy - (y + height); /* Noninclusive */ - -#if 0 - if (local_os2_surface->dirty_area_present) { - /* Yikes, there is already a dirty area which should be - * cleaned up, but we'll overwrite it. Sorry. - * TODO: Something clever should be done here. - */ - } -#endif - - /* Set up dirty area reminder stuff */ - memcpy (&(local_os2_surface->rcl_dirty_area), &rclToBlit, sizeof (RECTL)); - local_os2_surface->dirty_area_present = TRUE; - - /* Invalidate window area */ - WinInvalidateRect (local_os2_surface->hwnd_client_window, - &rclToBlit, - FALSE); - } else { - /* We don't know the HWND, so try to blit the pixels from here! - * Please note that it can be problematic if this is not the PM thread! - * - * It can cause internal PM stuffs to be scewed up, for some reason. - * Please always tell the HWND to the surface using the - * cairo_os2_surface_set_hwnd () API, and call cairo_os2_surface_refresh_window () - * from your WM_PAINT, if it's possible! - */ - - rclToBlit.xLeft = x; - rclToBlit.xRight = x + width; /* Noninclusive */ - rclToBlit.yBottom = y; - rclToBlit.yTop = y + height; /* Noninclusive */ - /* Now get the pixels from the screen! */ - _cairo_os2_surface_get_pixels_from_screen (local_os2_surface, - local_os2_surface->hps_client_window, - &rclToBlit); - } - - DosReleaseMutexSem (local_os2_surface->hmtx_use_private_fields); - - return CAIRO_STATUS_SUCCESS; -} - -static const cairo_surface_backend_t cairo_os2_surface_backend = { - CAIRO_SURFACE_TYPE_OS2, - NULL, /* create_similar */ - _cairo_os2_surface_finish, - _cairo_os2_surface_acquire_source_image, - _cairo_os2_surface_release_source_image, - _cairo_os2_surface_acquire_dest_image, - _cairo_os2_surface_release_dest_image, - NULL, /* clone_similar */ - NULL, /* composite */ - NULL, /* fill_rectangles */ - NULL, /* composite_trapezoids */ - NULL, /* copy_page */ - NULL, /* show_page */ - NULL, /* set_clip_region */ - NULL, /* intersect_clip_path */ - _cairo_os2_surface_get_extents, - NULL, /* old_show_glyphs */ - NULL, /* get_font_options */ - NULL, /* flush */ - _cairo_os2_surface_mark_dirty_rectangle, - NULL, /* scaled_font_fini */ - NULL, /* scaled_glyph_fini */ - NULL, /* paint */ - NULL, /* mask */ - NULL, /* stroke */ - NULL, /* fill */ - NULL, /* show_glyphs */ - NULL /* snapshot */ -}; diff --git a/uppdev/plugin/cairo/lib/cairo-os2.h b/uppdev/plugin/cairo/lib/cairo-os2.h deleted file mode 100644 index d0a13e47f..000000000 --- a/uppdev/plugin/cairo/lib/cairo-os2.h +++ /dev/null @@ -1,88 +0,0 @@ -/* vim: set sw=4 sts=4 et cin: */ -/* cairo - a vector graphics library with display and print output - * - * Copyright (c) 2005-2006 netlabs.org - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is - * Doodle - * - * Contributor(s): - * Peter Weilbacher - */ - -#ifndef _CAIRO_OS2_H_ -#define _CAIRO_OS2_H_ - -#include "cairo.h" - -CAIRO_BEGIN_DECLS - -/* The OS/2 Specific Cairo API */ - -cairo_public void -cairo_os2_init (void); - -cairo_public void -cairo_os2_fini (void); - -#if CAIRO_HAS_OS2_SURFACE - -cairo_public cairo_surface_t * -cairo_os2_surface_create (HPS hps_client_window, - int width, - int height); - -cairo_public void -cairo_os2_surface_set_hwnd (cairo_surface_t *surface, - HWND hwnd_client_window); - -cairo_public int -cairo_os2_surface_set_size (cairo_surface_t *surface, - int new_width, - int new_height, - int timeout); - -cairo_public void -cairo_os2_surface_refresh_window (cairo_surface_t *surface, - HPS hps_begin_paint, - PRECTL prcl_begin_paint_rect); - -cairo_public void -cairo_os2_surface_set_manual_window_refresh (cairo_surface_t *surface, - cairo_bool_t manual_refresh); - -cairo_public cairo_bool_t -cairo_os2_surface_get_manual_window_refresh (cairo_surface_t *surface); - -#else /* CAIRO_HAS_OS2_SURFACE */ -# error Cairo was not compiled with support for the OS/2 backend -#endif /* CAIRO_HAS_OS2_SURFACE */ - -CAIRO_END_DECLS - -#endif /* _CAIRO_OS2_H_ */ diff --git a/uppdev/plugin/cairo/lib/cairo-output-stream-private.h b/uppdev/plugin/cairo/lib/cairo-output-stream-private.h deleted file mode 100644 index 787d06161..000000000 --- a/uppdev/plugin/cairo/lib/cairo-output-stream-private.h +++ /dev/null @@ -1,176 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2006 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Author(s): - * Kristian Høgsberg - */ - -#ifndef CAIRO_OUTPUT_STREAM_PRIVATE_H -#define CAIRO_OUTPUT_STREAM_PRIVATE_H - -#include "cairo-compiler-private.h" -#include "cairo-types-private.h" - -#include -#include -#include - -typedef cairo_status_t (*cairo_output_stream_write_func_t) (cairo_output_stream_t *output_stream, - const unsigned char *data, - unsigned int length); - -typedef cairo_status_t (*cairo_output_stream_close_func_t) (cairo_output_stream_t *output_stream); - -struct _cairo_output_stream { - cairo_output_stream_write_func_t write_func; - cairo_output_stream_close_func_t close_func; - unsigned long position; - cairo_status_t status; - cairo_bool_t closed; -}; - -extern const cairo_private cairo_output_stream_t _cairo_output_stream_nil; - -cairo_private void -_cairo_output_stream_init (cairo_output_stream_t *stream, - cairo_output_stream_write_func_t write_func, - cairo_output_stream_close_func_t close_func); - -cairo_private cairo_status_t -_cairo_output_stream_fini (cairo_output_stream_t *stream); - - -/* We already have the following declared in cairo.h: - -typedef cairo_status_t (*cairo_write_func_t) (void *closure, - const unsigned char *data, - unsigned int length); -*/ -typedef cairo_status_t (*cairo_close_func_t) (void *closure); - - -/* This function never returns %NULL. If an error occurs (NO_MEMORY) - * while trying to create the output stream this function returns a - * valid pointer to a nil output stream. - * - * Note that even with a nil surface, the close_func callback will be - * called by a call to _cairo_output_stream_close or - * _cairo_output_stream_destroy. - */ -cairo_private cairo_output_stream_t * -_cairo_output_stream_create (cairo_write_func_t write_func, - cairo_close_func_t close_func, - void *closure); - -cairo_private cairo_output_stream_t * -_cairo_output_stream_create_in_error (cairo_status_t status); - -/* Returns the final status value associated with this object, just - * before its last gasp. This final status value will capture any - * status failure returned by the stream's close_func as well. */ -cairo_private cairo_status_t -_cairo_output_stream_close (cairo_output_stream_t *stream); - -/* Returns the final status value associated with this object, just - * before its last gasp. This final status value will capture any - * status failure returned by the stream's close_func as well. */ -cairo_private cairo_status_t -_cairo_output_stream_destroy (cairo_output_stream_t *stream); - -cairo_private void -_cairo_output_stream_write (cairo_output_stream_t *stream, - const void *data, size_t length); - -cairo_private void -_cairo_output_stream_write_hex_string (cairo_output_stream_t *stream, - const unsigned char *data, - size_t length); - -cairo_private void -_cairo_output_stream_vprintf (cairo_output_stream_t *stream, - const char *fmt, - va_list ap) CAIRO_PRINTF_FORMAT ( 2, 0); - -cairo_private void -_cairo_output_stream_printf (cairo_output_stream_t *stream, - const char *fmt, - ...) CAIRO_PRINTF_FORMAT (2, 3); - -cairo_private long -_cairo_output_stream_get_position (cairo_output_stream_t *stream); - -cairo_private cairo_status_t -_cairo_output_stream_get_status (cairo_output_stream_t *stream); - -/* This function never returns %NULL. If an error occurs (NO_MEMORY or - * WRITE_ERROR) while trying to create the output stream this function - * returns a valid pointer to a nil output stream. - * - * Note: Even if a nil surface is returned, the caller should still - * call _cairo_output_stream_destroy (or _cairo_output_stream_close at - * least) in order to ensure that everything is properly cleaned up. - */ -cairo_private cairo_output_stream_t * -_cairo_output_stream_create_for_filename (const char *filename); - -/* This function never returns %NULL. If an error occurs (NO_MEMORY or - * WRITE_ERROR) while trying to create the output stream this function - * returns a valid pointer to a nil output stream. - * - * The caller still "owns" file and is responsible for calling fclose - * on it when finished. The stream will not do this itself. - */ -cairo_private cairo_output_stream_t * -_cairo_output_stream_create_for_file (FILE *file); - -cairo_private cairo_output_stream_t * -_cairo_memory_stream_create (void); - -cairo_private void -_cairo_memory_stream_copy (cairo_output_stream_t *base, - cairo_output_stream_t *dest); - -cairo_private int -_cairo_memory_stream_length (cairo_output_stream_t *stream); - -cairo_private cairo_output_stream_t * -_cairo_null_stream_create (void); - -/* cairo-base85-stream.c */ -cairo_private cairo_output_stream_t * -_cairo_base85_stream_create (cairo_output_stream_t *output); - -/* cairo-deflate-stream.c */ -cairo_private cairo_output_stream_t * -_cairo_deflate_stream_create (cairo_output_stream_t *output); - - -#endif /* CAIRO_OUTPUT_STREAM_PRIVATE_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-output-stream.c b/uppdev/plugin/cairo/lib/cairo-output-stream.c deleted file mode 100644 index bae6ac4fe..000000000 --- a/uppdev/plugin/cairo/lib/cairo-output-stream.c +++ /dev/null @@ -1,707 +0,0 @@ -/* cairo-output-stream.c: Output stream abstraction - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Author(s): - * Kristian Høgsberg - */ - -#define _BSD_SOURCE /* for snprintf() */ -#include "cairoint.h" - -#include "cairo-output-stream-private.h" -#include "cairo-compiler-private.h" - -#include -#include -#include -#include - -/* Numbers printed with %f are printed with this number of significant - * digits after the decimal. - */ -#define SIGNIFICANT_DIGITS_AFTER_DECIMAL 6 - -/* Numbers printed with %g are assumed to only have %CAIRO_FIXED_FRAC_BITS - * bits of precision available after the decimal point. - * - * FIXED_POINT_DECIMAL_DIGITS specifies the minimum number of decimal - * digits after the decimal point required to preserve the available - * precision. - * - * The conversion is: - * - * - * FIXED_POINT_DECIMAL_DIGITS = ceil( CAIRO_FIXED_FRAC_BITS * ln(2)/ln(10) ) - * - * - * We can replace ceil(x) with (int)(x+1) since x will never be an - * integer for any likely value of %CAIRO_FIXED_FRAC_BITS. - */ -#define FIXED_POINT_DECIMAL_DIGITS ((int)(CAIRO_FIXED_FRAC_BITS*0.301029996 + 1)) - -void -_cairo_output_stream_init (cairo_output_stream_t *stream, - cairo_output_stream_write_func_t write_func, - cairo_output_stream_close_func_t close_func) -{ - stream->write_func = write_func; - stream->close_func = close_func; - stream->position = 0; - stream->status = CAIRO_STATUS_SUCCESS; - stream->closed = FALSE; -} - -cairo_status_t -_cairo_output_stream_fini (cairo_output_stream_t *stream) -{ - return _cairo_output_stream_close (stream); -} - -const cairo_output_stream_t _cairo_output_stream_nil = { - NULL, /* write_func */ - NULL, /* close_func */ - 0, /* position */ - CAIRO_STATUS_NO_MEMORY, - FALSE /* closed */ -}; - -static const cairo_output_stream_t _cairo_output_stream_nil_write_error = { - NULL, /* write_func */ - NULL, /* close_func */ - 0, /* position */ - CAIRO_STATUS_WRITE_ERROR, - FALSE /* closed */ -}; - -typedef struct _cairo_output_stream_with_closure { - cairo_output_stream_t base; - cairo_write_func_t write_func; - cairo_close_func_t close_func; - void *closure; -} cairo_output_stream_with_closure_t; - - -static cairo_status_t -closure_write (cairo_output_stream_t *stream, - const unsigned char *data, unsigned int length) -{ - cairo_output_stream_with_closure_t *stream_with_closure = - (cairo_output_stream_with_closure_t *) stream; - - if (stream_with_closure->write_func == NULL) - return CAIRO_STATUS_SUCCESS; - - return stream_with_closure->write_func (stream_with_closure->closure, - data, length); -} - -static cairo_status_t -closure_close (cairo_output_stream_t *stream) -{ - cairo_output_stream_with_closure_t *stream_with_closure = - (cairo_output_stream_with_closure_t *) stream; - - if (stream_with_closure->close_func != NULL) - return stream_with_closure->close_func (stream_with_closure->closure); - else - return CAIRO_STATUS_SUCCESS; -} - -cairo_output_stream_t * -_cairo_output_stream_create (cairo_write_func_t write_func, - cairo_close_func_t close_func, - void *closure) -{ - cairo_output_stream_with_closure_t *stream; - - stream = malloc (sizeof (cairo_output_stream_with_closure_t)); - if (stream == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_output_stream_t *) &_cairo_output_stream_nil; - } - - _cairo_output_stream_init (&stream->base, closure_write, closure_close); - stream->write_func = write_func; - stream->close_func = close_func; - stream->closure = closure; - - return &stream->base; -} - -cairo_output_stream_t * -_cairo_output_stream_create_in_error (cairo_status_t status) -{ - cairo_output_stream_t *stream; - - /* check for the common ones */ - if (status == CAIRO_STATUS_NO_MEMORY) - return (cairo_output_stream_t *) &_cairo_output_stream_nil; - if (status == CAIRO_STATUS_WRITE_ERROR) - return (cairo_output_stream_t *) &_cairo_output_stream_nil_write_error; - - stream = malloc (sizeof (cairo_output_stream_t)); - if (stream == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_output_stream_t *) &_cairo_output_stream_nil; - } - - _cairo_output_stream_init (stream, NULL, NULL); - stream->status = status; - - return stream; -} - -cairo_status_t -_cairo_output_stream_close (cairo_output_stream_t *stream) -{ - cairo_status_t status; - - if (stream->closed) - return stream->status; - - if (stream == &_cairo_output_stream_nil || - stream == &_cairo_output_stream_nil_write_error) - { - return stream->status; - } - - if (stream->close_func) { - status = stream->close_func (stream); - /* Don't overwrite a pre-existing status failure. */ - if (stream->status == CAIRO_STATUS_SUCCESS) - stream->status = status; - } - - stream->closed = TRUE; - - return stream->status; -} - -cairo_status_t -_cairo_output_stream_destroy (cairo_output_stream_t *stream) -{ - cairo_status_t status; - - assert (stream != NULL); - - if (stream == &_cairo_output_stream_nil || - stream == &_cairo_output_stream_nil_write_error) - { - return stream->status; - } - - status = _cairo_output_stream_fini (stream); - free (stream); - - return status; -} - -void -_cairo_output_stream_write (cairo_output_stream_t *stream, - const void *data, size_t length) -{ - if (length == 0) - return; - - if (stream->status) - return; - - stream->status = stream->write_func (stream, data, length); - stream->position += length; -} - -void -_cairo_output_stream_write_hex_string (cairo_output_stream_t *stream, - const unsigned char *data, - size_t length) -{ - const char hex_chars[] = "0123456789abcdef"; - char buffer[2]; - unsigned int i, column; - - if (stream->status) - return; - - for (i = 0, column = 0; i < length; i++, column++) { - if (column == 38) { - _cairo_output_stream_write (stream, "\n", 1); - column = 0; - } - buffer[0] = hex_chars[(data[i] >> 4) & 0x0f]; - buffer[1] = hex_chars[data[i] & 0x0f]; - _cairo_output_stream_write (stream, buffer, 2); - } -} - -/* Format a double in a locale independent way and trim trailing - * zeros. Based on code from Alex Larson . - * http://mail.gnome.org/archives/gtk-devel-list/2001-October/msg00087.html - * - * The code in the patch is copyright Red Hat, Inc under the LGPL, but - * has been relicensed under the LGPL/MPL dual license for inclusion - * into cairo (see COPYING). -- Kristian Høgsberg - */ -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; - int decimal_len; - int num_zeros, decimal_digits; - - /* Omit the minus sign from negative zero. */ - if (d == 0.0) - d = 0.0; - - locale_data = localeconv (); - decimal_point = locale_data->decimal_point; - decimal_point_len = strlen (decimal_point); - - assert (decimal_point_len != 0); - - if (limited_precision) { - snprintf (buffer, size, "%.*f", FIXED_POINT_DECIMAL_DIGITS, d); - } else { - /* Using "%f" to print numbers less than 0.1 will result in - * reduced precision due to the default 6 digits after the - * decimal point. - * - * For numbers is < 0.1, we print with maximum precision and count - * the number of zeros between the decimal point and the first - * significant digit. We then print the number again with the - * number of decimal places that gives us the required number of - * significant digits. This ensures the number is correctly - * rounded. - */ - if (fabs (d) >= 0.1) { - snprintf (buffer, size, "%f", d); - } else { - snprintf (buffer, size, "%.18f", d); - p = buffer; - - if (*p == '+' || *p == '-') - p++; - - while (isdigit (*p)) - p++; - - if (strncmp (p, decimal_point, decimal_point_len) == 0) - p += decimal_point_len; - - num_zeros = 0; - while (*p++ == '0') - num_zeros++; - - decimal_digits = num_zeros + SIGNIFICANT_DIGITS_AFTER_DECIMAL; - - if (decimal_digits < 18) - snprintf (buffer, size, "%.*f", decimal_digits, d); - } - } - p = buffer; - - if (*p == '+' || *p == '-') - p++; - - while (isdigit (*p)) - p++; - - if (strncmp (p, decimal_point, decimal_point_len) == 0) { - *p = '.'; - decimal_len = strlen (p + decimal_point_len); - memmove (p + 1, p + decimal_point_len, decimal_len); - p[1 + decimal_len] = 0; - - /* Remove trailing zeros and decimal point if possible. */ - for (p = p + decimal_len; *p == '0'; p--) - *p = 0; - - if (*p == '.') { - *p = 0; - p--; - } - } -} - -enum { - LENGTH_MODIFIER_LONG = 0x100 -}; - -/* Here's a limited reimplementation of printf. The reason for doing - * this is primarily to special case handling of doubles. We want - * locale independent formatting of doubles and we want to trim - * trailing zeros. This is handled by dtostr() above, and the code - * below handles everything else by calling snprintf() to do the - * formatting. This functionality is only for internal use and we - * only implement the formats we actually use. - */ -void -_cairo_output_stream_vprintf (cairo_output_stream_t *stream, - const char *fmt, va_list ap) -{ -#define SINGLE_FMT_BUFFER_SIZE 32 - char buffer[512], single_fmt[SINGLE_FMT_BUFFER_SIZE]; - int single_fmt_length; - char *p; - const char *f, *start; - int length_modifier, width; - cairo_bool_t var_width; - - if (stream->status) - return; - - f = fmt; - p = buffer; - while (*f != '\0') { - if (p == buffer + sizeof (buffer)) { - _cairo_output_stream_write (stream, buffer, sizeof (buffer)); - p = buffer; - } - - if (*f != '%') { - *p++ = *f++; - continue; - } - - start = f; - f++; - - if (*f == '0') - f++; - - var_width = FALSE; - if (*f == '*') { - var_width = TRUE; - f++; - } - - while (isdigit (*f)) - f++; - - length_modifier = 0; - if (*f == 'l') { - length_modifier = LENGTH_MODIFIER_LONG; - f++; - } - - /* The only format strings exist in the cairo implementation - * itself. So there's an internal consistency problem if any - * of them is larger than our format buffer size. */ - single_fmt_length = f - start + 1; - assert (single_fmt_length + 1 <= SINGLE_FMT_BUFFER_SIZE); - - /* Reuse the format string for this conversion. */ - memcpy (single_fmt, start, single_fmt_length); - single_fmt[single_fmt_length] = '\0'; - - /* Flush contents of buffer before snprintf()'ing into it. */ - _cairo_output_stream_write (stream, buffer, p - buffer); - - /* We group signed and unsigned together in this switch, the - * only thing that matters here is the size of the arguments, - * since we're just passing the data through to sprintf(). */ - switch (*f | length_modifier) { - case '%': - buffer[0] = *f; - buffer[1] = 0; - break; - case 'd': - case 'u': - case 'o': - case 'x': - case 'X': - if (var_width) { - width = va_arg (ap, int); - snprintf (buffer, sizeof buffer, - single_fmt, width, va_arg (ap, int)); - } else { - snprintf (buffer, sizeof buffer, single_fmt, va_arg (ap, int)); - } - break; - case 'd' | LENGTH_MODIFIER_LONG: - case 'u' | LENGTH_MODIFIER_LONG: - case 'o' | LENGTH_MODIFIER_LONG: - case 'x' | LENGTH_MODIFIER_LONG: - case 'X' | LENGTH_MODIFIER_LONG: - if (var_width) { - width = va_arg (ap, int); - snprintf (buffer, sizeof buffer, - single_fmt, width, va_arg (ap, long int)); - } else { - snprintf (buffer, sizeof buffer, - single_fmt, va_arg (ap, long int)); - } - break; - case 's': - snprintf (buffer, sizeof buffer, - single_fmt, va_arg (ap, const char *)); - break; - case 'f': - _cairo_dtostr (buffer, sizeof buffer, va_arg (ap, double), FALSE); - break; - case 'g': - _cairo_dtostr (buffer, sizeof buffer, va_arg (ap, double), TRUE); - break; - case 'c': - buffer[0] = va_arg (ap, int); - buffer[1] = 0; - break; - default: - ASSERT_NOT_REACHED; - } - p = buffer + strlen (buffer); - f++; - } - - _cairo_output_stream_write (stream, buffer, p - buffer); -} - -void -_cairo_output_stream_printf (cairo_output_stream_t *stream, - const char *fmt, ...) -{ - va_list ap; - - va_start (ap, fmt); - - _cairo_output_stream_vprintf (stream, fmt, ap); - - va_end (ap); -} - -long -_cairo_output_stream_get_position (cairo_output_stream_t *stream) -{ - return stream->position; -} - -cairo_status_t -_cairo_output_stream_get_status (cairo_output_stream_t *stream) -{ - return stream->status; -} - -/* Maybe this should be a configure time option, so embedded targets - * don't have to pull in stdio. */ - - -typedef struct _stdio_stream { - cairo_output_stream_t base; - FILE *file; -} stdio_stream_t; - -static cairo_status_t -stdio_write (cairo_output_stream_t *base, - const unsigned char *data, unsigned int length) -{ - stdio_stream_t *stream = (stdio_stream_t *) base; - - if (fwrite (data, 1, length, stream->file) != length) - return _cairo_error (CAIRO_STATUS_WRITE_ERROR); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -stdio_flush (cairo_output_stream_t *base) -{ - stdio_stream_t *stream = (stdio_stream_t *) base; - - fflush (stream->file); - - if (ferror (stream->file)) - return _cairo_error (CAIRO_STATUS_WRITE_ERROR); - else - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -stdio_close (cairo_output_stream_t *base) -{ - cairo_status_t status; - stdio_stream_t *stream = (stdio_stream_t *) base; - - status = stdio_flush (base); - - fclose (stream->file); - - return status; -} - -cairo_output_stream_t * -_cairo_output_stream_create_for_file (FILE *file) -{ - stdio_stream_t *stream; - - if (file == NULL) { - _cairo_error_throw (CAIRO_STATUS_WRITE_ERROR); - return (cairo_output_stream_t *) &_cairo_output_stream_nil_write_error; - } - - stream = malloc (sizeof *stream); - if (stream == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_output_stream_t *) &_cairo_output_stream_nil; - } - - _cairo_output_stream_init (&stream->base, stdio_write, stdio_flush); - stream->file = file; - - return &stream->base; -} - -cairo_output_stream_t * -_cairo_output_stream_create_for_filename (const char *filename) -{ - stdio_stream_t *stream; - FILE *file; - - if (filename == NULL) - return _cairo_null_stream_create (); - - file = fopen (filename, "wb"); - if (file == NULL) { - switch (errno) { - case ENOMEM: - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_output_stream_t *) &_cairo_output_stream_nil; - default: - _cairo_error_throw (CAIRO_STATUS_WRITE_ERROR); - return (cairo_output_stream_t *) &_cairo_output_stream_nil_write_error; - } - } - - stream = malloc (sizeof *stream); - if (stream == NULL) { - fclose (file); - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_output_stream_t *) &_cairo_output_stream_nil; - } - - _cairo_output_stream_init (&stream->base, stdio_write, stdio_close); - stream->file = file; - - return &stream->base; -} - - -typedef struct _memory_stream { - cairo_output_stream_t base; - cairo_array_t array; -} memory_stream_t; - -static cairo_status_t -memory_write (cairo_output_stream_t *base, - const unsigned char *data, unsigned int length) -{ - memory_stream_t *stream = (memory_stream_t *) base; - - return _cairo_array_append_multiple (&stream->array, data, length); -} - -static cairo_status_t -memory_close (cairo_output_stream_t *base) -{ - memory_stream_t *stream = (memory_stream_t *) base; - - _cairo_array_fini (&stream->array); - - return CAIRO_STATUS_SUCCESS; -} - -cairo_output_stream_t * -_cairo_memory_stream_create (void) -{ - memory_stream_t *stream; - - stream = malloc (sizeof *stream); - if (stream == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_output_stream_t *) &_cairo_output_stream_nil; - } - - _cairo_output_stream_init (&stream->base, memory_write, memory_close); - _cairo_array_init (&stream->array, 1); - - return &stream->base; -} - -void -_cairo_memory_stream_copy (cairo_output_stream_t *base, - cairo_output_stream_t *dest) -{ - memory_stream_t *stream = (memory_stream_t *) base; - - if (dest->status) - return; - - if (base->status) { - dest->status = base->status; - return; - } - - _cairo_output_stream_write (dest, - _cairo_array_index (&stream->array, 0), - _cairo_array_num_elements (&stream->array)); -} - -int -_cairo_memory_stream_length (cairo_output_stream_t *base) -{ - memory_stream_t *stream = (memory_stream_t *) base; - - return _cairo_array_num_elements (&stream->array); -} - -static cairo_status_t -null_write (cairo_output_stream_t *base, - const unsigned char *data, unsigned int length) -{ - return CAIRO_STATUS_SUCCESS; -} - -cairo_output_stream_t * -_cairo_null_stream_create (void) -{ - cairo_output_stream_t *stream; - - stream = malloc (sizeof *stream); - if (stream == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_output_stream_t *) &_cairo_output_stream_nil; - } - - _cairo_output_stream_init (stream, null_write, NULL); - - return stream; -} diff --git a/uppdev/plugin/cairo/lib/cairo-paginated-private.h b/uppdev/plugin/cairo/lib/cairo-paginated-private.h deleted file mode 100644 index 5cb2e48b6..000000000 --- a/uppdev/plugin/cairo/lib/cairo-paginated-private.h +++ /dev/null @@ -1,167 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Carl Worth - */ - -#ifndef CAIRO_PAGINATED_H -#define CAIRO_PAGINATED_H - -#include "cairoint.h" - -struct _cairo_paginated_surface_backend { - /* Optional. Will be called once for each page. - * - * Note: With respect to the order of drawing operations as seen - * by the target, this call will occur before any drawing - * operations for the relevant page. However, with respect to the - * function calls as made by the user, this call will be *after* - * any drawing operations for the page, (that is, it will occur - * during the user's call to cairo_show_page or cairo_copy_page). - */ - cairo_warn cairo_int_status_t - (*start_page) (void *surface); - - /* Required. Will be called twice for each page, once with an - * argument of CAIRO_PAGINATED_MODE_ANALYZE and once with - * CAIRO_PAGINATED_MODE_RENDER. See more details in the - * documentation for _cairo_paginated_surface_create below. - */ - void - (*set_paginated_mode) (void *surface, - cairo_paginated_mode_t mode); - - /* Optional. Specifies the smallest box that encloses all objects - * on the page. Will be called at the end of the ANALYZE phase but - * before the mode is changed to RENDER. - */ - cairo_warn cairo_int_status_t - (*set_bounding_box) (void *surface, - cairo_box_t *bbox); - - /* Optional. Indicates whether the page requires fallback images. - * Will be called at the end of the ANALYZE phase but before the - * mode is changed to RENDER. - */ - cairo_warn cairo_int_status_t - (*set_fallback_images_required) (void *surface, - cairo_bool_t fallbacks_required); - - cairo_bool_t - (*supports_fine_grained_fallbacks) (void *surface); -}; - -/* A #cairo_paginated_surface_t provides a very convenient wrapper that - * is well-suited for doing the analysis common to most surfaces that - * have paginated output, (that is, things directed at printers, or - * for saving content in files such as PostScript or PDF files). - * - * To use the paginated surface, you'll first need to create your - * 'real' surface using _cairo_surface_init() and the standard - * #cairo_surface_backend_t. Then you also call - * _cairo_paginated_surface_create which takes its own, much simpler, - * #cairo_paginated_surface_backend_t. You are free to return the result - * of _cairo_paginated_surface_create() from your public - * cairo__surface_create(). The paginated backend will be careful - * to not let the user see that they really got a "wrapped" - * surface. See test-paginated-surface.c for a fairly minimal example - * of a paginated-using surface. That should be a reasonable example - * to follow. - * - * What the paginated surface does is first save all drawing - * operations for a page into a meta-surface. Then when the user calls - * cairo_show_page(), the paginated surface performs the following - * sequence of operations (using the backend functions passed to - * cairo_paginated_surface_create()): - * - * 1. Calls start_page() (if not %NULL). At this point, it is appropriate - * for the target to emit any page-specific header information into - * its output. - * - * 2. Calls set_paginated_mode() with an argument of %CAIRO_PAGINATED_MODE_ANALYZE - * - * 3. Replays the meta-surface to the target surface, (with an - * analysis surface inserted between which watches the return value - * from each operation). This analysis stage is used to decide which - * operations will require fallbacks. - * - * 4. Calls set_bounding_box() to provide the target surface with the - * tight bounding box of the page. - * - * 5. Calls set_paginated_mode() with an argument of %CAIRO_PAGINATED_MODE_RENDER - * - * 6. Replays a subset of the meta-surface operations to the target surface - * - * 7. Calls set_paginated_mode() with an argument of %CAIRO_PAGINATED_MODE_FALLBACK - * - * 8. Replays the remaining operations to an image surface, sets an - * appropriate clip on the target, then paints the resulting image - * surface to the target. - * - * So, the target will see drawing operations during three separate - * stages, (ANALYZE, RENDER and FALLBACK). During the ANALYZE phase - * the target should not actually perform any rendering, (for example, - * if performing output to a file, no output should be generated - * during this stage). Instead the drawing functions simply need to - * return %CAIRO_STATUS_SUCCESS or %CAIRO_INT_STATUS_UNSUPPORTED to - * indicate whether rendering would be supported. And it should do - * this as quickly as possible. The FALLBACK phase allows the surface - * to distinguish fallback images from native rendering in case they - * need to be handled as a special case. - * - * Note: The paginated surface layer assumes that the target surface - * is "blank" by default at the beginning of each page, without any - * need for an explicit erase operation, (as opposed to an image - * surface, for example, which might have uninitialized content - * originally). As such, it optimizes away CLEAR operations that - * happen at the beginning of each page---the target surface will not - * even see these operations. - */ -cairo_private cairo_surface_t * -_cairo_paginated_surface_create (cairo_surface_t *target, - cairo_content_t content, - int width, - int height, - const cairo_paginated_surface_backend_t *backend); - -cairo_private cairo_surface_t * -_cairo_paginated_surface_get_target (cairo_surface_t *surface); - -cairo_private cairo_bool_t -_cairo_surface_is_paginated (cairo_surface_t *surface); - -cairo_private cairo_status_t -_cairo_paginated_surface_set_size (cairo_surface_t *surface, - int width, - int height); - -#endif /* CAIRO_PAGINATED_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-paginated-surface-private.h b/uppdev/plugin/cairo/lib/cairo-paginated-surface-private.h deleted file mode 100644 index b406cac15..000000000 --- a/uppdev/plugin/cairo/lib/cairo-paginated-surface-private.h +++ /dev/null @@ -1,72 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Carl Worth - */ - -#ifndef CAIRO_PAGINATED_SURFACE_H -#define CAIRO_PAGINATED_SURFACE_H - -#include "cairo.h" - -#include "cairo-surface-private.h" - -typedef struct _cairo_paginated_surface { - cairo_surface_t base; - - /* The target surface to hold the final result. */ - cairo_surface_t *target; - - cairo_content_t content; - - /* XXX: These shouldn't actually exist. We inherit this ugliness - * from _cairo_meta_surface_create. The width/height parameters - * from that function also should not exist. The fix that will - * allow us to remove all of these is to fix acquire_source_image - * to pass an interest rectangle. */ - int width; - int height; - - /* Paginated-surface specific functions for the target */ - const cairo_paginated_surface_backend_t *backend; - - /* A cairo_meta_surface to record all operations. To be replayed - * against target, and also against image surface as necessary for - * fallbacks. */ - cairo_surface_t *meta; - - int page_num; - cairo_bool_t page_is_blank; - -} cairo_paginated_surface_t; - -#endif /* CAIRO_PAGINATED_SURFACE_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-paginated-surface.c b/uppdev/plugin/cairo/lib/cairo-paginated-surface.c deleted file mode 100644 index a94ca80a0..000000000 --- a/uppdev/plugin/cairo/lib/cairo-paginated-surface.c +++ /dev/null @@ -1,693 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2005 Red Hat, Inc - * Copyright © 2007 Adrian Johnson - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Carl Worth - * Keith Packard - * Adrian Johnson - */ - -/* The paginated surface layer exists to provide as much code sharing - * as possible for the various paginated surface backends in cairo - * (PostScript, PDF, etc.). See cairo-paginated-private.h for - * more details on how it works and how to use it. - */ - -#include "cairoint.h" - -#include "cairo-paginated-private.h" -#include "cairo-paginated-surface-private.h" -#include "cairo-meta-surface-private.h" -#include "cairo-analysis-surface-private.h" - -static const cairo_surface_backend_t cairo_paginated_surface_backend; - -static cairo_int_status_t -_cairo_paginated_surface_show_page (void *abstract_surface); - -static cairo_surface_t * -_cairo_paginated_surface_create_similar (void *abstract_surface, - cairo_content_t content, - int width, - int height) -{ - cairo_paginated_surface_t *surface = abstract_surface; - return cairo_surface_create_similar (surface->target, content, - width, height); -} - -/* XXX The integer width,height here should be doubles and all uses updated */ -cairo_surface_t * -_cairo_paginated_surface_create (cairo_surface_t *target, - cairo_content_t content, - int width, - int height, - const cairo_paginated_surface_backend_t *backend) -{ - cairo_paginated_surface_t *surface; - cairo_status_t status; - - surface = malloc (sizeof (cairo_paginated_surface_t)); - if (surface == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto FAIL; - } - - _cairo_surface_init (&surface->base, &cairo_paginated_surface_backend, - content); - - /* Override surface->base.type with target's type so we don't leak - * evidence of the paginated wrapper out to the user. */ - surface->base.type = cairo_surface_get_type (target); - - surface->target = cairo_surface_reference (target); - - surface->content = content; - surface->width = width; - surface->height = height; - - surface->backend = backend; - - surface->meta = _cairo_meta_surface_create (content, width, height); - status = cairo_surface_status (surface->meta); - if (status) - goto FAIL_CLEANUP_SURFACE; - - surface->page_num = 1; - surface->page_is_blank = TRUE; - - return &surface->base; - - FAIL_CLEANUP_SURFACE: - cairo_surface_destroy (target); - free (surface); - FAIL: - return _cairo_surface_create_in_error (status); -} - -cairo_bool_t -_cairo_surface_is_paginated (cairo_surface_t *surface) -{ - return surface->backend == &cairo_paginated_surface_backend; -} - -cairo_surface_t * -_cairo_paginated_surface_get_target (cairo_surface_t *surface) -{ - cairo_paginated_surface_t *paginated_surface; - - assert (_cairo_surface_is_paginated (surface)); - - paginated_surface = (cairo_paginated_surface_t *) surface; - - return paginated_surface->target; -} - -cairo_status_t -_cairo_paginated_surface_set_size (cairo_surface_t *surface, - int width, - int height) -{ - cairo_paginated_surface_t *paginated_surface; - cairo_status_t status; - - assert (_cairo_surface_is_paginated (surface)); - - paginated_surface = (cairo_paginated_surface_t *) surface; - - paginated_surface->width = width; - paginated_surface->height = height; - - cairo_surface_destroy (paginated_surface->meta); - paginated_surface->meta = _cairo_meta_surface_create (paginated_surface->content, - width, height); - status = cairo_surface_status (paginated_surface->meta); - if (status) - return _cairo_surface_set_error (surface, status); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_paginated_surface_finish (void *abstract_surface) -{ - cairo_paginated_surface_t *surface = abstract_surface; - cairo_status_t status = CAIRO_STATUS_SUCCESS; - - if (surface->page_is_blank == FALSE || surface->page_num == 1) { - cairo_surface_show_page (abstract_surface); - status = cairo_surface_status (abstract_surface); - } - - if (status == CAIRO_STATUS_SUCCESS) { - cairo_surface_finish (surface->target); - status = cairo_surface_status (surface->target); - } - - if (status == CAIRO_STATUS_SUCCESS) { - cairo_surface_finish (surface->meta); - status = cairo_surface_status (surface->meta); - } - - cairo_surface_destroy (surface->target); - - cairo_surface_destroy (surface->meta); - - return status; -} - -static cairo_surface_t * -_cairo_paginated_surface_create_image_surface (void *abstract_surface, - int width, - int height) -{ - cairo_paginated_surface_t *surface = abstract_surface; - cairo_surface_t *image; - cairo_font_options_t options; - - image = _cairo_image_surface_create_with_content (surface->content, - width, - height); - - cairo_surface_get_font_options (&surface->base, &options); - _cairo_surface_set_font_options (image, &options); - - return image; -} - -static cairo_status_t -_cairo_paginated_surface_acquire_source_image (void *abstract_surface, - cairo_image_surface_t **image_out, - void **image_extra) -{ - cairo_paginated_surface_t *surface = abstract_surface; - cairo_surface_t *image; - cairo_status_t status; - cairo_rectangle_int_t extents; - - status = _cairo_surface_get_extents (surface->target, &extents); - if (status) - return status; - - image = _cairo_paginated_surface_create_image_surface (surface, - extents.width, - extents.height); - - status = _cairo_meta_surface_replay (surface->meta, image); - if (status) { - cairo_surface_destroy (image); - return status; - } - - *image_out = (cairo_image_surface_t*) image; - *image_extra = NULL; - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_paginated_surface_release_source_image (void *abstract_surface, - cairo_image_surface_t *image, - void *image_extra) -{ - cairo_surface_destroy (&image->base); -} - -static cairo_int_status_t -_paint_fallback_image (cairo_paginated_surface_t *surface, - cairo_box_int_t *box) -{ - double x_scale = surface->base.x_fallback_resolution / surface->target->x_resolution; - double y_scale = surface->base.y_fallback_resolution / surface->target->y_resolution; - cairo_matrix_t matrix; - int x, y, width, height; - cairo_status_t status; - cairo_surface_t *image; - cairo_pattern_t *pattern; - - x = box->p1.x; - y = box->p1.y; - width = box->p2.x - x; - height = box->p2.y - y; - 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); - /* 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); - - status = _cairo_meta_surface_replay (surface->meta, image); - if (status) - goto CLEANUP_IMAGE; - - pattern = cairo_pattern_create_for_surface (image); - cairo_matrix_init (&matrix, x_scale, 0, 0, y_scale, -x*x_scale, -y*y_scale); - cairo_pattern_set_matrix (pattern, &matrix); - - status = _cairo_surface_paint (surface->target, - CAIRO_OPERATOR_SOURCE, - pattern); - - cairo_pattern_destroy (pattern); -CLEANUP_IMAGE: - cairo_surface_destroy (image); - - return status; -} - -static cairo_int_status_t -_paint_page (cairo_paginated_surface_t *surface) -{ - cairo_surface_t *analysis; - cairo_status_t status; - cairo_bool_t has_supported, has_page_fallback, has_finegrained_fallback; - - if (surface->target->status) - return surface->target->status; - - analysis = _cairo_analysis_surface_create (surface->target, - surface->width, surface->height); - if (analysis->status) - return _cairo_surface_set_error (surface->target, analysis->status); - - surface->backend->set_paginated_mode (surface->target, - CAIRO_PAGINATED_MODE_ANALYZE); - status = _cairo_meta_surface_replay_and_create_regions (surface->meta, - analysis); - if (status || analysis->status) { - if (status == CAIRO_STATUS_SUCCESS) - status = analysis->status; - goto FAIL; - } - - if (surface->backend->set_bounding_box) { - cairo_box_t bbox; - - _cairo_analysis_surface_get_bounding_box (analysis, &bbox); - status = surface->backend->set_bounding_box (surface->target, &bbox); - if (status) - goto FAIL; - } - - if (surface->backend->set_fallback_images_required) { - cairo_bool_t has_fallbacks = _cairo_analysis_surface_has_unsupported (analysis); - - status = surface->backend->set_fallback_images_required (surface->target, - has_fallbacks); - if (status) - goto FAIL; - } - - /* Finer grained fallbacks are currently only supported for some - * surface types */ - if (surface->backend->supports_fine_grained_fallbacks != NULL && - surface->backend->supports_fine_grained_fallbacks (surface->target)) - { - has_supported = _cairo_analysis_surface_has_supported (analysis); - has_page_fallback = FALSE; - has_finegrained_fallback = _cairo_analysis_surface_has_unsupported (analysis); - } - else - { - if (_cairo_analysis_surface_has_unsupported (analysis)) { - has_supported = FALSE; - has_page_fallback = TRUE; - } else { - has_supported = TRUE; - has_page_fallback = FALSE; - } - has_finegrained_fallback = FALSE; - } - - if (has_supported) { - surface->backend->set_paginated_mode (surface->target, - CAIRO_PAGINATED_MODE_RENDER); - - status = _cairo_meta_surface_replay_region (surface->meta, - surface->target, - CAIRO_META_REGION_NATIVE); - assert (status != CAIRO_INT_STATUS_UNSUPPORTED); - if (status) - goto FAIL; - } - - if (has_page_fallback) { - cairo_box_int_t box; - - surface->backend->set_paginated_mode (surface->target, - CAIRO_PAGINATED_MODE_FALLBACK); - - box.p1.x = 0; - box.p1.y = 0; - box.p2.x = surface->width; - box.p2.y = surface->height; - status = _paint_fallback_image (surface, &box); - if (status) - goto FAIL; - } - - if (has_finegrained_fallback) { - cairo_region_t *region; - cairo_box_int_t *boxes; - int num_boxes, i; - - surface->backend->set_paginated_mode (surface->target, - CAIRO_PAGINATED_MODE_FALLBACK); - - /* Reset clip region before drawing the fall back images */ - status = _cairo_surface_intersect_clip_path (surface->target, - NULL, - CAIRO_FILL_RULE_WINDING, - CAIRO_GSTATE_TOLERANCE_DEFAULT, - CAIRO_ANTIALIAS_DEFAULT); - if (status) - goto FAIL; - - region = _cairo_analysis_surface_get_unsupported (analysis); - status = _cairo_region_get_boxes (region, &num_boxes, &boxes); - if (status) - goto FAIL; - for (i = 0; i < num_boxes; i++) { - status = _paint_fallback_image (surface, &boxes[i]); - if (status) { - _cairo_region_boxes_fini (region, boxes); - goto FAIL; - } - } - _cairo_region_boxes_fini (region, boxes); - } - - FAIL: - cairo_surface_destroy (analysis); - - return _cairo_surface_set_error (surface->target, status); -} - -static cairo_status_t -_start_page (cairo_paginated_surface_t *surface) -{ - if (surface->target->status) - return surface->target->status; - - if (! surface->backend->start_page) - return CAIRO_STATUS_SUCCESS; - - return _cairo_surface_set_error (surface->target, - surface->backend->start_page (surface->target)); -} - -static cairo_int_status_t -_cairo_paginated_surface_copy_page (void *abstract_surface) -{ - cairo_status_t status; - cairo_paginated_surface_t *surface = abstract_surface; - - status = _start_page (surface); - if (status) - return status; - - status = _paint_page (surface); - if (status) - return status; - - surface->page_num++; - - /* XXX: It might make sense to add some suport here for calling - * cairo_surface_copy_page on the target surface. It would be an - * optimization for the output, but the interaction with image - * fallbacks gets tricky. For now, we just let the target see a - * show_page and we implement the copying by simply not destroying - * the meta-surface. */ - - cairo_surface_show_page (surface->target); - return cairo_surface_status (surface->target); -} - -static cairo_int_status_t -_cairo_paginated_surface_show_page (void *abstract_surface) -{ - cairo_status_t status; - cairo_paginated_surface_t *surface = abstract_surface; - - status = _start_page (surface); - if (status) - return status; - - status = _paint_page (surface); - if (status) - return status; - - cairo_surface_show_page (surface->target); - status = cairo_surface_status (surface->target); - if (status) - return status; - - status = cairo_surface_status (surface->meta); - if (status) - return status; - - cairo_surface_destroy (surface->meta); - - surface->meta = _cairo_meta_surface_create (surface->content, - surface->width, - surface->height); - status = cairo_surface_status (surface->meta); - if (status) - return status; - - surface->page_num++; - surface->page_is_blank = TRUE; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_paginated_surface_intersect_clip_path (void *abstract_surface, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_paginated_surface_t *surface = abstract_surface; - - return _cairo_surface_intersect_clip_path (surface->meta, - path, fill_rule, - tolerance, antialias); -} - -static cairo_int_status_t -_cairo_paginated_surface_get_extents (void *abstract_surface, - cairo_rectangle_int_t *rectangle) -{ - cairo_paginated_surface_t *surface = abstract_surface; - - return _cairo_surface_get_extents (surface->target, rectangle); -} - -static void -_cairo_paginated_surface_get_font_options (void *abstract_surface, - cairo_font_options_t *options) -{ - cairo_paginated_surface_t *surface = abstract_surface; - - cairo_surface_get_font_options (surface->target, options); -} - -static cairo_int_status_t -_cairo_paginated_surface_paint (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source) -{ - cairo_paginated_surface_t *surface = abstract_surface; - - /* Optimize away erasing of nothing. */ - if (surface->page_is_blank && op == CAIRO_OPERATOR_CLEAR) - return CAIRO_STATUS_SUCCESS; - - surface->page_is_blank = FALSE; - - return _cairo_surface_paint (surface->meta, op, source); -} - -static cairo_int_status_t -_cairo_paginated_surface_mask (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_pattern_t *mask) -{ - cairo_paginated_surface_t *surface = abstract_surface; - - return _cairo_surface_mask (surface->meta, op, source, mask); -} - -static cairo_int_status_t -_cairo_paginated_surface_stroke (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - 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_paginated_surface_t *surface = abstract_surface; - - /* Optimize away erasing of nothing. */ - if (surface->page_is_blank && op == CAIRO_OPERATOR_CLEAR) - return CAIRO_STATUS_SUCCESS; - - surface->page_is_blank = FALSE; - - return _cairo_surface_stroke (surface->meta, op, source, - path, style, - ctm, ctm_inverse, - tolerance, antialias); -} - -static cairo_int_status_t -_cairo_paginated_surface_fill (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_paginated_surface_t *surface = abstract_surface; - - /* Optimize away erasing of nothing. */ - if (surface->page_is_blank && op == CAIRO_OPERATOR_CLEAR) - return CAIRO_STATUS_SUCCESS; - - surface->page_is_blank = FALSE; - - return _cairo_surface_fill (surface->meta, op, source, - path, fill_rule, - tolerance, antialias); -} - -static cairo_bool_t -_cairo_paginated_surface_has_show_text_glyphs (void *abstract_surface) -{ - cairo_paginated_surface_t *surface = abstract_surface; - - return cairo_surface_has_show_text_glyphs (surface->target); -} - -static cairo_int_status_t -_cairo_paginated_surface_show_text_glyphs (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - const char *utf8, - int utf8_len, - cairo_glyph_t *glyphs, - int num_glyphs, - const cairo_text_cluster_t *clusters, - int num_clusters, - cairo_text_cluster_flags_t cluster_flags, - cairo_scaled_font_t *scaled_font) -{ - cairo_paginated_surface_t *surface = abstract_surface; - cairo_int_status_t status; - - /* Optimize away erasing of nothing. */ - if (surface->page_is_blank && op == CAIRO_OPERATOR_CLEAR) - return CAIRO_STATUS_SUCCESS; - - surface->page_is_blank = FALSE; - - /* Since this is a "wrapping" surface, we're calling back into - * _cairo_surface_show_text_glyphs from within a call to the same. - * Since _cairo_surface_show_text_glyphs acquires a mutex, we release - * and re-acquire the mutex around this nested call. - * - * Yes, this is ugly, but we consider it pragmatic as compared to - * adding locking code to all 18 surface-backend-specific - * show_glyphs functions, (which would get less testing and likely - * lead to bugs). - */ - status = _cairo_surface_show_text_glyphs (surface->meta, op, source, - utf8, utf8_len, - glyphs, num_glyphs, - clusters, num_clusters, - cluster_flags, - scaled_font); - - return status; -} - -static cairo_surface_t * -_cairo_paginated_surface_snapshot (void *abstract_other) -{ - cairo_paginated_surface_t *other = abstract_other; - - return _cairo_surface_snapshot (other->meta); -} - -static const cairo_surface_backend_t cairo_paginated_surface_backend = { - CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED, - _cairo_paginated_surface_create_similar, - _cairo_paginated_surface_finish, - _cairo_paginated_surface_acquire_source_image, - _cairo_paginated_surface_release_source_image, - NULL, /* acquire_dest_image */ - NULL, /* release_dest_image */ - NULL, /* clone_similar */ - NULL, /* composite */ - NULL, /* fill_rectangles */ - NULL, /* composite_trapezoids */ - _cairo_paginated_surface_copy_page, - _cairo_paginated_surface_show_page, - NULL, /* set_clip_region */ - _cairo_paginated_surface_intersect_clip_path, - _cairo_paginated_surface_get_extents, - NULL, /* old_show_glyphs */ - _cairo_paginated_surface_get_font_options, - NULL, /* flush */ - NULL, /* mark_dirty_rectangle */ - NULL, /* scaled_font_fini */ - NULL, /* scaled_glyph_fini */ - _cairo_paginated_surface_paint, - _cairo_paginated_surface_mask, - _cairo_paginated_surface_stroke, - _cairo_paginated_surface_fill, - NULL, /* show_glyphs */ - _cairo_paginated_surface_snapshot, - NULL, /* is_similar */ - NULL, /* reset */ - NULL, /* fill_stroke */ - NULL, /* create_solid_pattern_surface */ - _cairo_paginated_surface_has_show_text_glyphs, - _cairo_paginated_surface_show_text_glyphs -}; diff --git a/uppdev/plugin/cairo/lib/cairo-path-bounds.c b/uppdev/plugin/cairo/lib/cairo-path-bounds.c deleted file mode 100644 index 70867e31c..000000000 --- a/uppdev/plugin/cairo/lib/cairo-path-bounds.c +++ /dev/null @@ -1,174 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2003 University of Southern California - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - */ - -#include "cairoint.h" - -typedef struct cairo_path_bounder { - cairo_point_t move_to_point; - cairo_bool_t has_move_to_point; - cairo_bool_t has_point; - - cairo_fixed_t min_x; - cairo_fixed_t min_y; - cairo_fixed_t max_x; - cairo_fixed_t max_y; -} cairo_path_bounder_t; - -static void -_cairo_path_bounder_init (cairo_path_bounder_t *bounder); - -static void -_cairo_path_bounder_fini (cairo_path_bounder_t *bounder); - -static void -_cairo_path_bounder_add_point (cairo_path_bounder_t *bounder, cairo_point_t *point); - -static cairo_status_t -_cairo_path_bounder_move_to (void *closure, cairo_point_t *point); - -static cairo_status_t -_cairo_path_bounder_line_to (void *closure, cairo_point_t *point); - -static cairo_status_t -_cairo_path_bounder_close_path (void *closure); - -static void -_cairo_path_bounder_init (cairo_path_bounder_t *bounder) -{ - bounder->has_move_to_point = FALSE; - bounder->has_point = FALSE; -} - -static void -_cairo_path_bounder_fini (cairo_path_bounder_t *bounder) -{ - bounder->has_move_to_point = FALSE; - bounder->has_point = FALSE; -} - -static void -_cairo_path_bounder_add_point (cairo_path_bounder_t *bounder, cairo_point_t *point) -{ - if (bounder->has_point) { - if (point->x < bounder->min_x) - bounder->min_x = point->x; - - if (point->y < bounder->min_y) - bounder->min_y = point->y; - - if (point->x > bounder->max_x) - bounder->max_x = point->x; - - if (point->y > bounder->max_y) - bounder->max_y = point->y; - } else { - bounder->min_x = point->x; - bounder->min_y = point->y; - bounder->max_x = point->x; - bounder->max_y = point->y; - - bounder->has_point = TRUE; - } -} - -static cairo_status_t -_cairo_path_bounder_move_to (void *closure, cairo_point_t *point) -{ - cairo_path_bounder_t *bounder = closure; - - bounder->move_to_point = *point; - bounder->has_move_to_point = TRUE; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_path_bounder_line_to (void *closure, cairo_point_t *point) -{ - cairo_path_bounder_t *bounder = closure; - - if (bounder->has_move_to_point) { - _cairo_path_bounder_add_point (bounder, - &bounder->move_to_point); - bounder->has_move_to_point = FALSE; - } - - _cairo_path_bounder_add_point (bounder, point); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_path_bounder_close_path (void *closure) -{ - return CAIRO_STATUS_SUCCESS; -} - -/* XXX: Perhaps this should compute a PixRegion rather than 4 doubles */ -cairo_status_t -_cairo_path_fixed_bounds (cairo_path_fixed_t *path, - double *x1, double *y1, - double *x2, double *y2, - double tolerance) -{ - cairo_path_bounder_t bounder; - cairo_status_t status; - - _cairo_path_bounder_init (&bounder); - - status = _cairo_path_fixed_interpret_flat (path, CAIRO_DIRECTION_FORWARD, - _cairo_path_bounder_move_to, - _cairo_path_bounder_line_to, - _cairo_path_bounder_close_path, - &bounder, - tolerance); - - if (status == CAIRO_STATUS_SUCCESS && bounder.has_point) { - *x1 = _cairo_fixed_to_double (bounder.min_x); - *y1 = _cairo_fixed_to_double (bounder.min_y); - *x2 = _cairo_fixed_to_double (bounder.max_x); - *y2 = _cairo_fixed_to_double (bounder.max_y); - } else { - *x1 = 0.0; - *y1 = 0.0; - *x2 = 0.0; - *y2 = 0.0; - } - - _cairo_path_bounder_fini (&bounder); - - return status; -} diff --git a/uppdev/plugin/cairo/lib/cairo-path-fill.c b/uppdev/plugin/cairo/lib/cairo-path-fill.c deleted file mode 100644 index 1cef20e4a..000000000 --- a/uppdev/plugin/cairo/lib/cairo-path-fill.c +++ /dev/null @@ -1,239 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - */ - -#include "cairoint.h" -#include "cairo-path-fixed-private.h" - -typedef struct cairo_filler { - double tolerance; - cairo_traps_t *traps; - - cairo_point_t current_point; - - cairo_polygon_t polygon; -} cairo_filler_t; - -static void -_cairo_filler_init (cairo_filler_t *filler, double tolerance, cairo_traps_t *traps); - -static void -_cairo_filler_fini (cairo_filler_t *filler); - -static cairo_status_t -_cairo_filler_move_to (void *closure, cairo_point_t *point); - -static cairo_status_t -_cairo_filler_line_to (void *closure, cairo_point_t *point); - -static cairo_status_t -_cairo_filler_curve_to (void *closure, - cairo_point_t *b, - cairo_point_t *c, - cairo_point_t *d); - -static cairo_status_t -_cairo_filler_close_path (void *closure); - -static void -_cairo_filler_init (cairo_filler_t *filler, double tolerance, cairo_traps_t *traps) -{ - filler->tolerance = tolerance; - filler->traps = traps; - - filler->current_point.x = 0; - filler->current_point.y = 0; - - _cairo_polygon_init (&filler->polygon); -} - -static void -_cairo_filler_fini (cairo_filler_t *filler) -{ - _cairo_polygon_fini (&filler->polygon); -} - -static cairo_status_t -_cairo_filler_move_to (void *closure, cairo_point_t *point) -{ - cairo_filler_t *filler = closure; - cairo_polygon_t *polygon = &filler->polygon; - - _cairo_polygon_close (polygon); - _cairo_polygon_move_to (polygon, point); - - filler->current_point = *point; - - return _cairo_polygon_status (&filler->polygon); -} - -static cairo_status_t -_cairo_filler_line_to (void *closure, cairo_point_t *point) -{ - cairo_filler_t *filler = closure; - cairo_polygon_t *polygon = &filler->polygon; - - _cairo_polygon_line_to (polygon, point); - - filler->current_point = *point; - - return _cairo_polygon_status (&filler->polygon); -} - -static cairo_status_t -_cairo_filler_curve_to (void *closure, - cairo_point_t *b, - cairo_point_t *c, - cairo_point_t *d) -{ - int i; - cairo_status_t status = CAIRO_STATUS_SUCCESS; - cairo_filler_t *filler = closure; - cairo_polygon_t *polygon = &filler->polygon; - cairo_spline_t spline; - - status = _cairo_spline_init (&spline, &filler->current_point, b, c, d); - - if (status == CAIRO_INT_STATUS_DEGENERATE) - return CAIRO_STATUS_SUCCESS; - - status = _cairo_spline_decompose (&spline, filler->tolerance); - if (status) - goto CLEANUP_SPLINE; - - for (i = 1; i < spline.num_points; i++) - _cairo_polygon_line_to (polygon, &spline.points[i]); - - CLEANUP_SPLINE: - _cairo_spline_fini (&spline); - - filler->current_point = *d; - - return status; -} - -static cairo_status_t -_cairo_filler_close_path (void *closure) -{ - cairo_filler_t *filler = closure; - cairo_polygon_t *polygon = &filler->polygon; - - _cairo_polygon_close (polygon); - - return _cairo_polygon_status (polygon); -} - -static cairo_int_status_t -_cairo_path_fixed_fill_rectangle (cairo_path_fixed_t *path, - cairo_traps_t *traps); - -cairo_status_t -_cairo_path_fixed_fill_to_traps (cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_traps_t *traps) -{ - cairo_status_t status = CAIRO_STATUS_SUCCESS; - cairo_filler_t filler; - - /* Before we do anything else, we use a special-case filler for - * a device-axis aligned rectangle if possible. */ - status = _cairo_path_fixed_fill_rectangle (path, traps); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - - _cairo_filler_init (&filler, tolerance, traps); - - status = _cairo_path_fixed_interpret (path, - CAIRO_DIRECTION_FORWARD, - _cairo_filler_move_to, - _cairo_filler_line_to, - _cairo_filler_curve_to, - _cairo_filler_close_path, - &filler); - if (status) - goto BAIL; - - _cairo_polygon_close (&filler.polygon); - status = _cairo_polygon_status (&filler.polygon); - if (status) - goto BAIL; - - status = _cairo_bentley_ottmann_tessellate_polygon (filler.traps, - &filler.polygon, - fill_rule); - if (status) - goto BAIL; - -BAIL: - _cairo_filler_fini (&filler); - - return status; -} - -/* This special-case filler supports only a path that describes a - * device-axis aligned rectangle. It exists to avoid the overhead of - * the general tessellator when drawing very common rectangles. - * - * If the path described anything but a device-axis aligned rectangle, - * this function will return %CAIRO_INT_STATUS_UNSUPPORTED. - */ -static cairo_int_status_t -_cairo_path_fixed_fill_rectangle (cairo_path_fixed_t *path, - cairo_traps_t *traps) -{ - if (_cairo_path_fixed_is_box (path, NULL)) { - cairo_point_t *p = path->buf_head.base.points; - cairo_point_t *top_left, *bot_right; - - top_left = &p[0]; - bot_right = &p[2]; - if (top_left->x > bot_right->x || top_left->y > bot_right->y) { - int n; - - /* not a simple cairo_rectangle() */ - for (n = 0; n < 4; n++) { - if (p[n].x <= top_left->x && p[n].y <= top_left->y) - top_left = &p[n]; - if (p[n].x >= bot_right->x && p[n].y >= bot_right->y) - bot_right = &p[n]; - } - } - - return _cairo_traps_tessellate_rectangle (traps, top_left, bot_right); - } - - return CAIRO_INT_STATUS_UNSUPPORTED; -} diff --git a/uppdev/plugin/cairo/lib/cairo-path-fixed-private.h b/uppdev/plugin/cairo/lib/cairo-path-fixed-private.h deleted file mode 100644 index 4a5990d48..000000000 --- a/uppdev/plugin/cairo/lib/cairo-path-fixed-private.h +++ /dev/null @@ -1,80 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Carl D. Worth - */ - -#ifndef CAIRO_PATH_FIXED_PRIVATE_H -#define CAIRO_PATH_FIXED_PRIVATE_H - -#include "cairo-types-private.h" - -enum cairo_path_op { - CAIRO_PATH_OP_MOVE_TO = 0, - CAIRO_PATH_OP_LINE_TO = 1, - CAIRO_PATH_OP_CURVE_TO = 2, - CAIRO_PATH_OP_CLOSE_PATH = 3 -}; -/* we want to make sure a single byte is used for thie enum */ -typedef char cairo_path_op_t; - -/* make _cairo_path_fixed fit a 512 bytes. about 50 items */ -#define CAIRO_PATH_BUF_SIZE ((512 - 4 * sizeof (void*) - sizeof (cairo_path_buf_t)) \ - / (2 * sizeof (cairo_point_t) + sizeof (cairo_path_op_t))) - -typedef struct _cairo_path_buf { - struct _cairo_path_buf *next, *prev; - int buf_size; - int num_ops; - int num_points; - - cairo_path_op_t *op; - cairo_point_t *points; -} cairo_path_buf_t; -typedef struct _cairo_path_buf_fixed { - cairo_path_buf_t base; - - cairo_path_op_t op[CAIRO_PATH_BUF_SIZE]; - cairo_point_t points[2 * CAIRO_PATH_BUF_SIZE]; -} cairo_path_buf_fixed_t; - -struct _cairo_path_fixed { - cairo_point_t last_move_point; - cairo_point_t current_point; - unsigned int has_current_point : 1; - unsigned int has_curve_to : 1; - - cairo_path_buf_t *buf_tail; - cairo_path_buf_fixed_t buf_head; -}; - -#endif /* CAIRO_PATH_FIXED_PRIVATE_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-path-fixed.c b/uppdev/plugin/cairo/lib/cairo-path-fixed.c deleted file mode 100644 index 90861198b..000000000 --- a/uppdev/plugin/cairo/lib/cairo-path-fixed.c +++ /dev/null @@ -1,896 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - */ - -#include "cairoint.h" - -#include "cairo-path-fixed-private.h" - -/* private functions */ -static cairo_status_t -_cairo_path_fixed_add (cairo_path_fixed_t *path, - cairo_path_op_t op, - cairo_point_t *points, - int num_points); - -static void -_cairo_path_fixed_add_buf (cairo_path_fixed_t *path, - cairo_path_buf_t *buf); - -static cairo_path_buf_t * -_cairo_path_buf_create (int buf_size); - -static void -_cairo_path_buf_destroy (cairo_path_buf_t *buf); - -static void -_cairo_path_buf_add_op (cairo_path_buf_t *buf, - cairo_path_op_t op); - -static void -_cairo_path_buf_add_points (cairo_path_buf_t *buf, - cairo_point_t *points, - int num_points); - -void -_cairo_path_fixed_init (cairo_path_fixed_t *path) -{ - path->buf_head.base.next = NULL; - path->buf_head.base.prev = NULL; - path->buf_tail = &path->buf_head.base; - - path->buf_head.base.num_ops = 0; - path->buf_head.base.num_points = 0; - path->buf_head.base.buf_size = CAIRO_PATH_BUF_SIZE; - path->buf_head.base.op = path->buf_head.op; - path->buf_head.base.points = path->buf_head.points; - - path->current_point.x = 0; - path->current_point.y = 0; - path->has_current_point = FALSE; - path->has_curve_to = FALSE; - path->last_move_point = path->current_point; -} - -cairo_status_t -_cairo_path_fixed_init_copy (cairo_path_fixed_t *path, - cairo_path_fixed_t *other) -{ - cairo_path_buf_t *buf, *other_buf; - unsigned int num_points, num_ops, buf_size; - - _cairo_path_fixed_init (path); - - path->current_point = other->current_point; - path->has_current_point = other->has_current_point; - path->has_curve_to = other->has_curve_to; - path->last_move_point = other->last_move_point; - - path->buf_head.base.num_ops = other->buf_head.base.num_ops; - path->buf_head.base.num_points = other->buf_head.base.num_points; - path->buf_head.base.buf_size = other->buf_head.base.buf_size; - memcpy (path->buf_head.op, other->buf_head.base.op, - other->buf_head.base.num_ops * sizeof (other->buf_head.op[0])); - memcpy (path->buf_head.points, other->buf_head.points, - other->buf_head.base.num_points * sizeof (other->buf_head.points[0])); - - num_points = num_ops = 0; - for (other_buf = other->buf_head.base.next; - other_buf != NULL; - other_buf = other_buf->next) - { - num_ops += other_buf->num_ops; - num_points += other_buf->num_points; - } - - buf_size = MAX (num_ops, (num_points + 1) / 2); - if (buf_size) { - buf = _cairo_path_buf_create (buf_size); - if (buf == NULL) { - _cairo_path_fixed_fini (path); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - for (other_buf = other->buf_head.base.next; - other_buf != NULL; - other_buf = other_buf->next) - { - memcpy (buf->op + buf->num_ops, other_buf->op, - other_buf->num_ops * sizeof (buf->op[0])); - buf->num_ops += other_buf->num_ops; - - memcpy (buf->points + buf->num_points, other_buf->points, - other_buf->num_points * sizeof (buf->points[0])); - buf->num_points += other_buf->num_points; - } - - _cairo_path_fixed_add_buf (path, buf); - } - - return CAIRO_STATUS_SUCCESS; -} - -cairo_path_fixed_t * -_cairo_path_fixed_create (void) -{ - cairo_path_fixed_t *path; - - path = malloc (sizeof (cairo_path_fixed_t)); - if (!path) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return NULL; - } - - _cairo_path_fixed_init (path); - return path; -} - -void -_cairo_path_fixed_fini (cairo_path_fixed_t *path) -{ - cairo_path_buf_t *buf; - - buf = path->buf_head.base.next; - while (buf) { - cairo_path_buf_t *this = buf; - buf = buf->next; - _cairo_path_buf_destroy (this); - } - path->buf_head.base.next = NULL; - path->buf_head.base.prev = NULL; - path->buf_tail = &path->buf_head.base; - path->buf_head.base.num_ops = 0; - path->buf_head.base.num_points = 0; - - path->has_current_point = FALSE; - path->has_curve_to = FALSE; -} - -void -_cairo_path_fixed_destroy (cairo_path_fixed_t *path) -{ - _cairo_path_fixed_fini (path); - free (path); -} - -cairo_status_t -_cairo_path_fixed_move_to (cairo_path_fixed_t *path, - cairo_fixed_t x, - cairo_fixed_t y) -{ - cairo_status_t status; - cairo_point_t point; - - point.x = x; - point.y = y; - - /* If the previous op was also a MOVE_TO, then just change its - * point rather than adding a new op. */ - if (path->buf_tail && path->buf_tail->num_ops && - path->buf_tail->op[path->buf_tail->num_ops - 1] == CAIRO_PATH_OP_MOVE_TO) - { - cairo_point_t *last_move_to_point; - last_move_to_point = &path->buf_tail->points[path->buf_tail->num_points - 1]; - *last_move_to_point = point; - } else { - status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_MOVE_TO, &point, 1); - if (status) - return status; - } - - path->current_point = point; - path->has_current_point = TRUE; - path->last_move_point = path->current_point; - - return CAIRO_STATUS_SUCCESS; -} - -void -_cairo_path_fixed_new_sub_path (cairo_path_fixed_t *path) -{ - path->has_current_point = FALSE; -} - -cairo_status_t -_cairo_path_fixed_rel_move_to (cairo_path_fixed_t *path, - cairo_fixed_t dx, - cairo_fixed_t dy) -{ - cairo_fixed_t x, y; - - if (! path->has_current_point) - return _cairo_error (CAIRO_STATUS_NO_CURRENT_POINT); - - x = path->current_point.x + dx; - y = path->current_point.y + dy; - - return _cairo_path_fixed_move_to (path, x, y); -} - -cairo_status_t -_cairo_path_fixed_line_to (cairo_path_fixed_t *path, - cairo_fixed_t x, - cairo_fixed_t y) -{ - cairo_status_t status; - cairo_point_t point; - - point.x = x; - point.y = y; - - /* When there is not yet a current point, the line_to operation - * becomes a move_to instead. Note: We have to do this by - * explicitly calling into _cairo_path_fixed_line_to to ensure - * that the last_move_point state is updated properly. - */ - if (! path->has_current_point) - status = _cairo_path_fixed_move_to (path, point.x, point.y); - else - status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_LINE_TO, &point, 1); - - if (status) - return status; - - path->current_point = point; - path->has_current_point = TRUE; - - return CAIRO_STATUS_SUCCESS; -} - -cairo_status_t -_cairo_path_fixed_rel_line_to (cairo_path_fixed_t *path, - cairo_fixed_t dx, - cairo_fixed_t dy) -{ - cairo_fixed_t x, y; - - if (! path->has_current_point) - return _cairo_error (CAIRO_STATUS_NO_CURRENT_POINT); - - x = path->current_point.x + dx; - y = path->current_point.y + dy; - - return _cairo_path_fixed_line_to (path, x, y); -} - -cairo_status_t -_cairo_path_fixed_curve_to (cairo_path_fixed_t *path, - cairo_fixed_t x0, cairo_fixed_t y0, - cairo_fixed_t x1, cairo_fixed_t y1, - cairo_fixed_t x2, cairo_fixed_t y2) -{ - cairo_status_t status; - cairo_point_t point[3]; - - point[0].x = x0; point[0].y = y0; - point[1].x = x1; point[1].y = y1; - point[2].x = x2; point[2].y = y2; - - if (! path->has_current_point) { - status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_MOVE_TO, - &point[0], 1); - if (status) - return status; - } - - status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_CURVE_TO, point, 3); - if (status) - return status; - - path->current_point = point[2]; - path->has_current_point = TRUE; - path->has_curve_to = TRUE; - - return CAIRO_STATUS_SUCCESS; -} - -cairo_status_t -_cairo_path_fixed_rel_curve_to (cairo_path_fixed_t *path, - cairo_fixed_t dx0, cairo_fixed_t dy0, - cairo_fixed_t dx1, cairo_fixed_t dy1, - cairo_fixed_t dx2, cairo_fixed_t dy2) -{ - cairo_fixed_t x0, y0; - cairo_fixed_t x1, y1; - cairo_fixed_t x2, y2; - - if (! path->has_current_point) - return _cairo_error (CAIRO_STATUS_NO_CURRENT_POINT); - - x0 = path->current_point.x + dx0; - y0 = path->current_point.y + dy0; - - x1 = path->current_point.x + dx1; - y1 = path->current_point.y + dy1; - - x2 = path->current_point.x + dx2; - y2 = path->current_point.y + dy2; - - return _cairo_path_fixed_curve_to (path, - x0, y0, - x1, y1, - x2, y2); -} - -cairo_status_t -_cairo_path_fixed_close_path (cairo_path_fixed_t *path) -{ - cairo_status_t status; - - if (! path->has_current_point) - return CAIRO_STATUS_SUCCESS; - - status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_CLOSE_PATH, NULL, 0); - if (status) - return status; - - status = _cairo_path_fixed_move_to (path, - path->last_move_point.x, - path->last_move_point.y); - if (status) - return status; - - return CAIRO_STATUS_SUCCESS; -} - -cairo_bool_t -_cairo_path_fixed_get_current_point (cairo_path_fixed_t *path, - cairo_fixed_t *x, - cairo_fixed_t *y) -{ - if (! path->has_current_point) - return FALSE; - - *x = path->current_point.x; - *y = path->current_point.y; - - return TRUE; -} - -static cairo_status_t -_cairo_path_fixed_add (cairo_path_fixed_t *path, - cairo_path_op_t op, - cairo_point_t *points, - int num_points) -{ - cairo_path_buf_t *buf = path->buf_tail; - - if (buf->num_ops + 1 > buf->buf_size || - buf->num_points + num_points > 2 * buf->buf_size) - { - buf = _cairo_path_buf_create (buf->buf_size * 2); - if (buf == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - _cairo_path_fixed_add_buf (path, buf); - } - - _cairo_path_buf_add_op (buf, op); - _cairo_path_buf_add_points (buf, points, num_points); - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_path_fixed_add_buf (cairo_path_fixed_t *path, - cairo_path_buf_t *buf) -{ - buf->next = NULL; - buf->prev = path->buf_tail; - - path->buf_tail->next = buf; - path->buf_tail = buf; -} - -static cairo_path_buf_t * -_cairo_path_buf_create (int buf_size) -{ - cairo_path_buf_t *buf; - - /* adjust buf_size to ensure that buf->points is naturally aligned */ - buf_size += sizeof (double) - - ((buf_size + sizeof (cairo_path_buf_t)) & (sizeof (double)-1)); - buf = _cairo_malloc_ab_plus_c (buf_size, - sizeof (cairo_path_op_t) + - 2 * sizeof (cairo_point_t), - sizeof (cairo_path_buf_t)); - if (buf) { - buf->next = NULL; - buf->prev = NULL; - buf->num_ops = 0; - buf->num_points = 0; - buf->buf_size = buf_size; - - buf->op = (cairo_path_op_t *) (buf + 1); - buf->points = (cairo_point_t *) (buf->op + buf_size); - } - - return buf; -} - -static void -_cairo_path_buf_destroy (cairo_path_buf_t *buf) -{ - free (buf); -} - -static void -_cairo_path_buf_add_op (cairo_path_buf_t *buf, - cairo_path_op_t op) -{ - buf->op[buf->num_ops++] = op; -} - -static void -_cairo_path_buf_add_points (cairo_path_buf_t *buf, - cairo_point_t *points, - int num_points) -{ - int i; - - for (i=0; i < num_points; i++) { - buf->points[buf->num_points++] = points[i]; - } -} - -static int const num_args[] = -{ - 1, /* cairo_path_move_to */ - 1, /* cairo_path_op_line_to */ - 3, /* cairo_path_op_curve_to */ - 0, /* cairo_path_op_close_path */ -}; - -cairo_status_t -_cairo_path_fixed_interpret (const cairo_path_fixed_t *path, - cairo_direction_t dir, - 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 status; - const cairo_path_buf_t *buf; - cairo_path_op_t op; - cairo_bool_t forward = (dir == CAIRO_DIRECTION_FORWARD); - int step = forward ? 1 : -1; - - for (buf = forward ? &path->buf_head.base : path->buf_tail; - buf; - buf = forward ? buf->next : buf->prev) - { - cairo_point_t *points; - int start, stop, i; - if (forward) { - start = 0; - stop = buf->num_ops; - points = buf->points; - } else { - start = buf->num_ops - 1; - stop = -1; - points = buf->points + buf->num_points; - } - - for (i=start; i != stop; i += step) { - op = buf->op[i]; - - if (! forward) { - points -= num_args[(int) op]; - } - - switch (op) { - case CAIRO_PATH_OP_MOVE_TO: - status = (*move_to) (closure, &points[0]); - break; - case CAIRO_PATH_OP_LINE_TO: - status = (*line_to) (closure, &points[0]); - break; - case CAIRO_PATH_OP_CURVE_TO: - status = (*curve_to) (closure, &points[0], &points[1], &points[2]); - break; - case CAIRO_PATH_OP_CLOSE_PATH: - default: - status = (*close_path) (closure); - break; - } - if (status) - return status; - - if (forward) { - points += num_args[(int) op]; - } - - } - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_append_move_to (void *closure, - cairo_point_t *point) -{ - cairo_path_fixed_t *path = (cairo_path_fixed_t *) closure; - return _cairo_path_fixed_move_to (path, point->x, point->y); -} - -static cairo_status_t -_append_line_to (void *closure, - cairo_point_t *point) -{ - cairo_path_fixed_t *path = (cairo_path_fixed_t *) closure; - return _cairo_path_fixed_line_to (path, point->x, point->y); -} - -static cairo_status_t -_append_curve_to (void *closure, - cairo_point_t *p0, - cairo_point_t *p1, - cairo_point_t *p2) -{ - cairo_path_fixed_t *path = (cairo_path_fixed_t *) closure; - return _cairo_path_fixed_curve_to (path, p0->x, p0->y, p1->x, p1->y, p2->x, p2->y); -} - -static cairo_status_t -_append_close_path (void *closure) -{ - cairo_path_fixed_t *path = (cairo_path_fixed_t *) closure; - return _cairo_path_fixed_close_path (path); -} - -cairo_private cairo_status_t -_cairo_path_fixed_append (cairo_path_fixed_t *path, - const cairo_path_fixed_t *other, - cairo_direction_t dir) -{ - return _cairo_path_fixed_interpret (other, dir, - _append_move_to, - _append_line_to, - _append_curve_to, - _append_close_path, - path); -} - -static void -_cairo_path_fixed_offset_and_scale (cairo_path_fixed_t *path, - cairo_fixed_t offx, - cairo_fixed_t offy, - cairo_fixed_t scalex, - cairo_fixed_t scaley) -{ - cairo_path_buf_t *buf = &path->buf_head.base; - int i; - - while (buf) { - for (i = 0; i < buf->num_points; i++) { - if (scalex != CAIRO_FIXED_ONE) - buf->points[i].x = _cairo_fixed_mul (buf->points[i].x, scalex); - buf->points[i].x += offx; - - if (scaley != CAIRO_FIXED_ONE) - buf->points[i].y = _cairo_fixed_mul (buf->points[i].y, scaley); - buf->points[i].y += offy; - } - - buf = buf->next; - } -} - -/** - * _cairo_path_fixed_transform: - * @path: a #cairo_path_fixed_t to be transformed - * @matrix: a #cairo_matrix_t - * - * Transform the fixed-point path according to the given matrix. - * There is a fast path for the case where @matrix has no rotation - * or shear. - **/ -void -_cairo_path_fixed_transform (cairo_path_fixed_t *path, - cairo_matrix_t *matrix) -{ - cairo_path_buf_t *buf; - int i; - double dx, dy; - - if (matrix->yx == 0.0 && matrix->xy == 0.0) { - /* Fast path for the common case of scale+transform */ - _cairo_path_fixed_offset_and_scale (path, - _cairo_fixed_from_double (matrix->x0), - _cairo_fixed_from_double (matrix->y0), - _cairo_fixed_from_double (matrix->xx), - _cairo_fixed_from_double (matrix->yy)); - return; - } - - buf = &path->buf_head.base; - while (buf) { - for (i = 0; i < buf->num_points; i++) { - dx = _cairo_fixed_to_double (buf->points[i].x); - dy = _cairo_fixed_to_double (buf->points[i].y); - - cairo_matrix_transform_point (matrix, &dx, &dy); - - buf->points[i].x = _cairo_fixed_from_double (dx); - buf->points[i].y = _cairo_fixed_from_double (dy); - } - - buf = buf->next; - } -} - -cairo_bool_t -_cairo_path_fixed_is_equal (cairo_path_fixed_t *path, - cairo_path_fixed_t *other) -{ - cairo_path_buf_t *path_buf, *other_buf; - - if (path->current_point.x != other->current_point.x || - path->current_point.y != other->current_point.y || - path->has_current_point != other->has_current_point || - path->has_curve_to != other->has_curve_to || - path->last_move_point.x != other->last_move_point.x || - path->last_move_point.y != other->last_move_point.y) - return FALSE; - - other_buf = &other->buf_head.base; - for (path_buf = &path->buf_head.base; - path_buf != NULL; - path_buf = path_buf->next) - { - if (other_buf == NULL || - path_buf->num_ops != other_buf->num_ops || - path_buf->num_points != other_buf->num_points || - memcmp (path_buf->op, other_buf->op, - sizeof (cairo_path_op_t) * path_buf->num_ops) != 0 || - memcmp (path_buf->points, other_buf->points, - sizeof (cairo_point_t) * path_buf->num_points) != 0) - { - return FALSE; - } - other_buf = other_buf->next; - } - return TRUE; -} - -/* Closure for path flattening */ -typedef struct cairo_path_flattener { - double tolerance; - cairo_point_t current_point; - cairo_path_fixed_move_to_func_t *move_to; - cairo_path_fixed_line_to_func_t *line_to; - cairo_path_fixed_close_path_func_t *close_path; - void *closure; -} cpf_t; - -static cairo_status_t -_cpf_move_to (void *closure, cairo_point_t *point) -{ - cpf_t *cpf = closure; - - cpf->current_point = *point; - - return cpf->move_to (cpf->closure, point); -} - -static cairo_status_t -_cpf_line_to (void *closure, cairo_point_t *point) -{ - cpf_t *cpf = closure; - - cpf->current_point = *point; - - return cpf->line_to (cpf->closure, point); -} - -static cairo_status_t -_cpf_curve_to (void *closure, - cairo_point_t *p1, - cairo_point_t *p2, - cairo_point_t *p3) -{ - cpf_t *cpf = closure; - cairo_status_t status; - cairo_spline_t spline; - int i; - - cairo_point_t *p0 = &cpf->current_point; - - status = _cairo_spline_init (&spline, p0, p1, p2, p3); - if (status == CAIRO_INT_STATUS_DEGENERATE) - return CAIRO_STATUS_SUCCESS; - - status = _cairo_spline_decompose (&spline, cpf->tolerance); - if (status) - goto out; - - for (i=1; i < spline.num_points; i++) { - status = cpf->line_to (cpf->closure, &spline.points[i]); - if (status) - goto out; - } - - cpf->current_point = *p3; - - status = CAIRO_STATUS_SUCCESS; - - out: - _cairo_spline_fini (&spline); - return status; -} - -static cairo_status_t -_cpf_close_path (void *closure) -{ - cpf_t *cpf = closure; - - return cpf->close_path (cpf->closure); -} - - -cairo_status_t -_cairo_path_fixed_interpret_flat (const cairo_path_fixed_t *path, - cairo_direction_t dir, - cairo_path_fixed_move_to_func_t *move_to, - cairo_path_fixed_line_to_func_t *line_to, - cairo_path_fixed_close_path_func_t *close_path, - void *closure, - double tolerance) -{ - cpf_t flattener; - - flattener.tolerance = tolerance; - flattener.move_to = move_to; - flattener.line_to = line_to; - flattener.close_path = close_path; - flattener.closure = closure; - return _cairo_path_fixed_interpret (path, dir, - _cpf_move_to, - _cpf_line_to, - _cpf_curve_to, - _cpf_close_path, - &flattener); -} - -cairo_bool_t -_cairo_path_fixed_is_empty (cairo_path_fixed_t *path) -{ - if (path->buf_head.base.num_ops == 0) - return TRUE; - - return FALSE; -} - -/** - * Check whether the given path contains a single rectangle. - */ -cairo_bool_t -_cairo_path_fixed_is_box (cairo_path_fixed_t *path, - cairo_box_t *box) -{ - cairo_path_buf_t *buf = &path->buf_head.base; - - /* We can't have more than one buf for this check */ - if (buf->next != NULL) - return FALSE; - - /* Do we have the right number of ops? */ - if (buf->num_ops != 5 && buf->num_ops != 6) - return FALSE; - - /* Check whether the ops are those that would be used for a rectangle */ - if (buf->op[0] != CAIRO_PATH_OP_MOVE_TO || - buf->op[1] != CAIRO_PATH_OP_LINE_TO || - buf->op[2] != CAIRO_PATH_OP_LINE_TO || - buf->op[3] != CAIRO_PATH_OP_LINE_TO) - { - return FALSE; - } - - /* Now, there are choices. The rectangle might end with a LINE_TO - * (to the original point), but this isn't required. If it - * doesn't, then it must end with a CLOSE_PATH. */ - if (buf->op[4] == CAIRO_PATH_OP_LINE_TO) { - if (buf->points[4].x != buf->points[0].x || - buf->points[4].y != buf->points[0].y) - return FALSE; - } else if (buf->op[4] != CAIRO_PATH_OP_CLOSE_PATH) { - return FALSE; - } - - if (buf->num_ops == 6) { - /* A trailing CLOSE_PATH or MOVE_TO is ok */ - if (buf->op[5] != CAIRO_PATH_OP_MOVE_TO && - buf->op[5] != CAIRO_PATH_OP_CLOSE_PATH) - return FALSE; - } - - /* Ok, we may have a box, if the points line up */ - if (buf->points[0].y == buf->points[1].y && - buf->points[1].x == buf->points[2].x && - buf->points[2].y == buf->points[3].y && - buf->points[3].x == buf->points[0].x) - { - if (box) { - box->p1 = buf->points[0]; - box->p2 = buf->points[2]; - } - return TRUE; - } - - if (buf->points[0].x == buf->points[1].x && - buf->points[1].y == buf->points[2].y && - buf->points[2].x == buf->points[3].x && - buf->points[3].y == buf->points[0].y) - { - if (box) { - box->p1 = buf->points[0]; - box->p2 = buf->points[2]; - } - return TRUE; - } - - return FALSE; -} - -/* - * Check whether the given path contains a single rectangle - * that is logically equivalent to: - * - * cairo_move_to (cr, x, y); - * cairo_rel_line_to (cr, width, 0); - * cairo_rel_line_to (cr, 0, height); - * cairo_rel_line_to (cr, -width, 0); - * cairo_close_path (cr); - * - */ -cairo_bool_t -_cairo_path_fixed_is_rectangle (cairo_path_fixed_t *path, - cairo_box_t *box) -{ - cairo_path_buf_t *buf = &path->buf_head.base; - - if (!_cairo_path_fixed_is_box (path, box)) - return FALSE; - - if (buf->points[0].y == buf->points[1].y) - return TRUE; - - return FALSE; -} diff --git a/uppdev/plugin/cairo/lib/cairo-path-private.h b/uppdev/plugin/cairo/lib/cairo-path-private.h deleted file mode 100644 index a24eaa492..000000000 --- a/uppdev/plugin/cairo/lib/cairo-path-private.h +++ /dev/null @@ -1,57 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2005 Red Hat, Inc. - * Copyright © 2006 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Carl D. Worth - */ - -#ifndef CAIRO_PATH_PRIVATE_H -#define CAIRO_PATH_PRIVATE_H - -#include "cairoint.h" - -cairo_private cairo_path_t * -_cairo_path_create (cairo_path_fixed_t *path, - cairo_gstate_t *gstate); - -cairo_private cairo_path_t * -_cairo_path_create_flat (cairo_path_fixed_t *path, - cairo_gstate_t *gstate); - -cairo_private cairo_path_t * -_cairo_path_create_in_error (cairo_status_t status); - -cairo_private cairo_status_t -_cairo_path_append_to_context (const cairo_path_t *path, - cairo_t *cr); - -#endif /* CAIRO_PATH_DATA_PRIVATE_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-path-stroke.c b/uppdev/plugin/cairo/lib/cairo-path-stroke.c deleted file mode 100644 index efccbcfea..000000000 --- a/uppdev/plugin/cairo/lib/cairo-path-stroke.c +++ /dev/null @@ -1,1522 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - */ - -#include "cairoint.h" -#include "cairo-path-fixed-private.h" - -typedef struct cairo_stroker { - cairo_stroke_style_t *style; - - cairo_matrix_t *ctm; - cairo_matrix_t *ctm_inverse; - double tolerance; - double ctm_determinant; - cairo_bool_t ctm_det_positive; - - cairo_traps_t *traps; - - cairo_pen_t pen; - - cairo_point_t current_point; - cairo_point_t first_point; - - cairo_bool_t has_initial_sub_path; - - cairo_bool_t has_current_face; - cairo_stroke_face_t current_face; - - cairo_bool_t has_first_face; - cairo_stroke_face_t first_face; - - cairo_bool_t dashed; - unsigned int dash_index; - cairo_bool_t dash_on; - cairo_bool_t dash_starts_on; - double dash_remain; - - cairo_bool_t has_bounds; - cairo_box_t bounds; -} cairo_stroker_t; - -/* private functions */ -static cairo_status_t -_cairo_stroker_init (cairo_stroker_t *stroker, - cairo_stroke_style_t *stroke_style, - cairo_matrix_t *ctm, - cairo_matrix_t *ctm_inverse, - double tolerance, - cairo_traps_t *traps); - -static void -_cairo_stroker_fini (cairo_stroker_t *stroker); - -static cairo_status_t -_cairo_stroker_move_to (void *closure, cairo_point_t *point); - -static cairo_status_t -_cairo_stroker_line_to (void *closure, cairo_point_t *point); - -static cairo_status_t -_cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point); - -static cairo_status_t -_cairo_stroker_curve_to (void *closure, - cairo_point_t *b, - cairo_point_t *c, - cairo_point_t *d); - -static cairo_status_t -_cairo_stroker_curve_to_dashed (void *closure, - cairo_point_t *b, - cairo_point_t *c, - cairo_point_t *d); - -static cairo_status_t -_cairo_stroker_close_path (void *closure); - -static void -_translate_point (cairo_point_t *point, cairo_point_t *offset); - -static int -_cairo_stroker_face_clockwise (cairo_stroke_face_t *in, cairo_stroke_face_t *out); - -static cairo_status_t -_cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_stroke_face_t *out); - -static void -_cairo_stroker_start_dash (cairo_stroker_t *stroker) -{ - double offset; - cairo_bool_t on = TRUE; - unsigned int i = 0; - - offset = stroker->style->dash_offset; - - /* We stop searching for a starting point as soon as the - offset reaches zero. Otherwise when an initial dash - segment shrinks to zero it will be skipped over. */ - while (offset > 0.0 && offset >= stroker->style->dash[i]) { - offset -= stroker->style->dash[i]; - on = !on; - if (++i == stroker->style->num_dashes) - i = 0; - } - stroker->dashed = TRUE; - stroker->dash_index = i; - stroker->dash_on = stroker->dash_starts_on = on; - stroker->dash_remain = stroker->style->dash[i] - offset; -} - -static void -_cairo_stroker_step_dash (cairo_stroker_t *stroker, double step) -{ - stroker->dash_remain -= step; - if (stroker->dash_remain <= 0) { - stroker->dash_index++; - if (stroker->dash_index == stroker->style->num_dashes) - stroker->dash_index = 0; - stroker->dash_on = !stroker->dash_on; - stroker->dash_remain = stroker->style->dash[stroker->dash_index]; - } -} - -static cairo_status_t -_cairo_stroker_init (cairo_stroker_t *stroker, - cairo_stroke_style_t *stroke_style, - cairo_matrix_t *ctm, - cairo_matrix_t *ctm_inverse, - double tolerance, - cairo_traps_t *traps) -{ - cairo_status_t status; - stroker->style = stroke_style; - stroker->ctm = ctm; - stroker->ctm_inverse = ctm_inverse; - stroker->tolerance = tolerance; - stroker->traps = traps; - - stroker->ctm_determinant = _cairo_matrix_compute_determinant (stroker->ctm); - stroker->ctm_det_positive = stroker->ctm_determinant >= 0.0; - - status = _cairo_pen_init (&stroker->pen, - stroke_style->line_width / 2.0, - tolerance, ctm); - if (status) - return status; - - stroker->has_current_face = FALSE; - stroker->has_first_face = FALSE; - stroker->has_initial_sub_path = FALSE; - - if (stroker->style->dash) - _cairo_stroker_start_dash (stroker); - else - stroker->dashed = FALSE; - - stroker->has_bounds = _cairo_traps_get_limit (traps, &stroker->bounds); - if (stroker->has_bounds) { - /* Extend the bounds in each direction to account for the maximum area - * we might generate trapezoids, to capture line segments that are outside - * of the bounds but which might generate rendering that's within bounds. - */ - double dx, dy; - cairo_fixed_t fdx, fdy; - - _cairo_stroke_style_max_distance_from_path (stroker->style, stroker->ctm, &dx, &dy); - - fdx = _cairo_fixed_from_double (dx); - fdy = _cairo_fixed_from_double (dy); - - stroker->bounds.p1.x -= fdx; - stroker->bounds.p2.x += fdx; - - stroker->bounds.p1.y -= fdy; - stroker->bounds.p2.y += fdy; - } - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_stroker_fini (cairo_stroker_t *stroker) -{ - _cairo_pen_fini (&stroker->pen); -} - -static void -_translate_point (cairo_point_t *point, cairo_point_t *offset) -{ - point->x += offset->x; - point->y += offset->y; -} - -static int -_cairo_stroker_face_clockwise (cairo_stroke_face_t *in, cairo_stroke_face_t *out) -{ - cairo_slope_t in_slope, out_slope; - - _cairo_slope_init (&in_slope, &in->point, &in->cw); - _cairo_slope_init (&out_slope, &out->point, &out->cw); - - return _cairo_slope_compare (&in_slope, &out_slope) < 0; -} - -/** - * _cairo_slope_compare_sgn - * - * Return -1, 0 or 1 depending on the relative slopes of - * two lines. - */ -static int -_cairo_slope_compare_sgn (double dx1, double dy1, double dx2, double dy2) -{ - double c = (dx1 * dy2 - dx2 * dy1); - - if (c > 0) return 1; - if (c < 0) return -1; - return 0; -} - -static cairo_status_t -_cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_stroke_face_t *out) -{ - int clockwise = _cairo_stroker_face_clockwise (out, in); - cairo_point_t *inpt, *outpt; - cairo_status_t status; - - if (in->cw.x == out->cw.x - && in->cw.y == out->cw.y - && in->ccw.x == out->ccw.x - && in->ccw.y == out->ccw.y) - { - return CAIRO_STATUS_SUCCESS; - } - - if (clockwise) { - inpt = &in->ccw; - outpt = &out->ccw; - } else { - inpt = &in->cw; - outpt = &out->cw; - } - - switch (stroker->style->line_join) { - case CAIRO_LINE_JOIN_ROUND: { - int i; - int start, step, stop; - cairo_point_t tri[3]; - cairo_pen_t *pen = &stroker->pen; - - tri[0] = in->point; - if (clockwise) { - _cairo_pen_find_active_ccw_vertex_index (pen, &in->dev_vector, &start); - step = -1; - _cairo_pen_find_active_ccw_vertex_index (pen, &out->dev_vector, &stop); - } else { - _cairo_pen_find_active_cw_vertex_index (pen, &in->dev_vector, &start); - step = +1; - _cairo_pen_find_active_cw_vertex_index (pen, &out->dev_vector, &stop); - } - - i = start; - tri[1] = *inpt; - while (i != stop) { - tri[2] = in->point; - _translate_point (&tri[2], &pen->vertices[i].point); - status = _cairo_traps_tessellate_triangle (stroker->traps, tri); - if (status) - return status; - tri[1] = tri[2]; - i += step; - if (i < 0) - i = pen->num_vertices - 1; - if (i >= pen->num_vertices) - i = 0; - } - - tri[2] = *outpt; - - return _cairo_traps_tessellate_triangle (stroker->traps, tri); - } - case CAIRO_LINE_JOIN_MITER: - default: { - /* dot product of incoming slope vector with outgoing slope vector */ - double in_dot_out = ((-in->usr_vector.x * out->usr_vector.x)+ - (-in->usr_vector.y * out->usr_vector.y)); - double ml = stroker->style->miter_limit; - - /* Check the miter limit -- lines meeting at an acute angle - * can generate long miters, the limit converts them to bevel - * - * Consider the miter join formed when two line segments - * meet at an angle psi: - * - * /.\ - * /. .\ - * /./ \.\ - * /./psi\.\ - * - * We can zoom in on the right half of that to see: - * - * |\ - * | \ psi/2 - * | \ - * | \ - * | \ - * | \ - * miter \ - * length \ - * | \ - * | .\ - * | . \ - * |. line \ - * \ width \ - * \ \ - * - * - * The right triangle in that figure, (the line-width side is - * shown faintly with three '.' characters), gives us the - * following expression relating miter length, angle and line - * width: - * - * 1 /sin (psi/2) = miter_length / line_width - * - * The right-hand side of this relationship is the same ratio - * in which the miter limit (ml) is expressed. We want to know - * when the miter length is within the miter limit. That is - * when the following condition holds: - * - * 1/sin(psi/2) <= ml - * 1 <= ml sin(psi/2) - * 1 <= ml² sin²(psi/2) - * 2 <= ml² 2 sin²(psi/2) - * 2·sin²(psi/2) = 1-cos(psi) - * 2 <= ml² (1-cos(psi)) - * - * in · out = |in| |out| cos (psi) - * - * in and out are both unit vectors, so: - * - * in · out = cos (psi) - * - * 2 <= ml² (1 - in · out) - * - */ - if (2 <= ml * ml * (1 - in_dot_out)) - { - double x1, y1, x2, y2; - double mx, my; - double dx1, dx2, dy1, dy2; - cairo_point_t outer; - cairo_point_t quad[4]; - double ix, iy; - double fdx1, fdy1, fdx2, fdy2; - double mdx, mdy; - - /* - * we've got the points already transformed to device - * space, but need to do some computation with them and - * also need to transform the slope from user space to - * device space - */ - /* outer point of incoming line face */ - x1 = _cairo_fixed_to_double (inpt->x); - y1 = _cairo_fixed_to_double (inpt->y); - dx1 = in->usr_vector.x; - dy1 = in->usr_vector.y; - cairo_matrix_transform_distance (stroker->ctm, &dx1, &dy1); - - /* outer point of outgoing line face */ - x2 = _cairo_fixed_to_double (outpt->x); - y2 = _cairo_fixed_to_double (outpt->y); - dx2 = out->usr_vector.x; - dy2 = out->usr_vector.y; - cairo_matrix_transform_distance (stroker->ctm, &dx2, &dy2); - - /* - * Compute the location of the outer corner of the miter. - * That's pretty easy -- just the intersection of the two - * outer edges. We've got slopes and points on each - * of those edges. Compute my directly, then compute - * mx by using the edge with the larger dy; that avoids - * dividing by values close to zero. - */ - my = (((x2 - x1) * dy1 * dy2 - y2 * dx2 * dy1 + y1 * dx1 * dy2) / - (dx1 * dy2 - dx2 * dy1)); - if (fabs (dy1) >= fabs (dy2)) - mx = (my - y1) * dx1 / dy1 + x1; - else - mx = (my - y2) * dx2 / dy2 + x2; - - /* - * When the two outer edges are nearly parallel, slight - * perturbations in the position of the outer points of the lines - * caused by representing them in fixed point form can cause the - * intersection point of the miter to move a large amount. If - * that moves the miter intersection from between the two faces, - * then draw a bevel instead. - */ - - ix = _cairo_fixed_to_double (in->point.x); - iy = _cairo_fixed_to_double (in->point.y); - - /* slope of one face */ - fdx1 = x1 - ix; fdy1 = y1 - iy; - - /* slope of the other face */ - fdx2 = x2 - ix; fdy2 = y2 - iy; - - /* slope from the intersection to the miter point */ - mdx = mx - ix; mdy = my - iy; - - /* - * Make sure the miter point line lies between the two - * faces by comparing the slopes - */ - if (_cairo_slope_compare_sgn (fdx1, fdy1, mdx, mdy) != - _cairo_slope_compare_sgn (fdx2, fdy2, mdx, mdy)) - { - /* - * Draw the quadrilateral - */ - outer.x = _cairo_fixed_from_double (mx); - outer.y = _cairo_fixed_from_double (my); - - quad[0] = in->point; - quad[1] = *inpt; - quad[2] = outer; - quad[3] = *outpt; - - return _cairo_traps_tessellate_convex_quad (stroker->traps, quad); - } - } - /* fall through ... */ - } - case CAIRO_LINE_JOIN_BEVEL: { - cairo_point_t tri[3]; - tri[0] = in->point; - tri[1] = *inpt; - tri[2] = *outpt; - - return _cairo_traps_tessellate_triangle (stroker->traps, tri); - } - } -} - -static cairo_status_t -_cairo_stroker_add_cap (cairo_stroker_t *stroker, cairo_stroke_face_t *f) -{ - cairo_status_t status; - - if (stroker->style->line_cap == CAIRO_LINE_CAP_BUTT) - return CAIRO_STATUS_SUCCESS; - - switch (stroker->style->line_cap) { - case CAIRO_LINE_CAP_ROUND: { - int i; - int start, stop; - cairo_slope_t slope; - cairo_point_t tri[3]; - cairo_pen_t *pen = &stroker->pen; - - slope = f->dev_vector; - _cairo_pen_find_active_cw_vertex_index (pen, &slope, &start); - slope.dx = -slope.dx; - slope.dy = -slope.dy; - _cairo_pen_find_active_cw_vertex_index (pen, &slope, &stop); - - tri[0] = f->point; - tri[1] = f->cw; - for (i=start; i != stop; i = (i+1) % pen->num_vertices) { - tri[2] = f->point; - _translate_point (&tri[2], &pen->vertices[i].point); - status = _cairo_traps_tessellate_triangle (stroker->traps, tri); - if (status) - return status; - tri[1] = tri[2]; - } - tri[2] = f->ccw; - - return _cairo_traps_tessellate_triangle (stroker->traps, tri); - } - case CAIRO_LINE_CAP_SQUARE: { - double dx, dy; - cairo_slope_t fvector; - cairo_point_t occw, ocw; - cairo_polygon_t polygon; - - dx = f->usr_vector.x; - dy = f->usr_vector.y; - dx *= stroker->style->line_width / 2.0; - dy *= stroker->style->line_width / 2.0; - cairo_matrix_transform_distance (stroker->ctm, &dx, &dy); - fvector.dx = _cairo_fixed_from_double (dx); - fvector.dy = _cairo_fixed_from_double (dy); - occw.x = f->ccw.x + fvector.dx; - occw.y = f->ccw.y + fvector.dy; - ocw.x = f->cw.x + fvector.dx; - ocw.y = f->cw.y + fvector.dy; - - _cairo_polygon_init (&polygon); - _cairo_polygon_move_to (&polygon, &f->cw); - _cairo_polygon_line_to (&polygon, &ocw); - _cairo_polygon_line_to (&polygon, &occw); - _cairo_polygon_line_to (&polygon, &f->ccw); - _cairo_polygon_close (&polygon); - status = _cairo_polygon_status (&polygon); - - if (status == CAIRO_STATUS_SUCCESS) { - status = _cairo_bentley_ottmann_tessellate_polygon (stroker->traps, - &polygon, - CAIRO_FILL_RULE_WINDING); - } - - _cairo_polygon_fini (&polygon); - - return status; - } - case CAIRO_LINE_CAP_BUTT: - default: - return CAIRO_STATUS_SUCCESS; - } -} - -static cairo_status_t -_cairo_stroker_add_leading_cap (cairo_stroker_t *stroker, - cairo_stroke_face_t *face) -{ - cairo_stroke_face_t reversed; - cairo_point_t t; - - reversed = *face; - - /* The initial cap needs an outward facing vector. Reverse everything */ - reversed.usr_vector.x = -reversed.usr_vector.x; - reversed.usr_vector.y = -reversed.usr_vector.y; - reversed.dev_vector.dx = -reversed.dev_vector.dx; - reversed.dev_vector.dy = -reversed.dev_vector.dy; - t = reversed.cw; - reversed.cw = reversed.ccw; - reversed.ccw = t; - - return _cairo_stroker_add_cap (stroker, &reversed); -} - -static cairo_status_t -_cairo_stroker_add_trailing_cap (cairo_stroker_t *stroker, - cairo_stroke_face_t *face) -{ - return _cairo_stroker_add_cap (stroker, face); -} - -static inline cairo_bool_t -_compute_normalized_device_slope (double *dx, double *dy, cairo_matrix_t *ctm_inverse, double *mag_out) -{ - double dx0 = *dx, dy0 = *dy; - double mag; - - cairo_matrix_transform_distance (ctm_inverse, &dx0, &dy0); - - if (dx0 == 0.0 && dy0 == 0.0) { - if (mag_out) - *mag_out = 0.0; - return FALSE; - } - - if (dx0 == 0.0) { - *dx = 0.0; - if (dy0 > 0.0) { - mag = dy0; - *dy = 1.0; - } else { - mag = -dy0; - *dy = -1.0; - } - } else if (dy0 == 0.0) { - *dy = 0.0; - if (dx0 > 0.0) { - mag = dx0; - *dx = 1.0; - } else { - mag = -dx0; - *dx = -1.0; - } - } else { - mag = sqrt (dx0 * dx0 + dy0 * dy0); - *dx = dx0 / mag; - *dy = dy0 / mag; - } - - if (mag_out) - *mag_out = mag; - - return TRUE; -} - -static void -_compute_face (cairo_point_t *point, cairo_slope_t *dev_slope, - double slope_dx, double slope_dy, - cairo_stroker_t *stroker, cairo_stroke_face_t *face); - -static cairo_status_t -_cairo_stroker_add_caps (cairo_stroker_t *stroker) -{ - cairo_status_t status; - /* check for a degenerative sub_path */ - if (stroker->has_initial_sub_path - && !stroker->has_first_face - && !stroker->has_current_face - && stroker->style->line_cap == CAIRO_LINE_JOIN_ROUND) - { - /* pick an arbitrary slope to use */ - double dx = 1.0, dy = 0.0; - cairo_slope_t slope = { CAIRO_FIXED_ONE, 0 }; - cairo_stroke_face_t face; - - _compute_normalized_device_slope (&dx, &dy, stroker->ctm_inverse, NULL); - - /* arbitrarily choose first_point - * first_point and current_point should be the same */ - _compute_face (&stroker->first_point, &slope, dx, dy, stroker, &face); - - status = _cairo_stroker_add_leading_cap (stroker, &face); - if (status) - return status; - status = _cairo_stroker_add_trailing_cap (stroker, &face); - if (status) - return status; - } - - if (stroker->has_first_face) { - status = _cairo_stroker_add_leading_cap (stroker, &stroker->first_face); - if (status) - return status; - } - - if (stroker->has_current_face) { - status = _cairo_stroker_add_trailing_cap (stroker, &stroker->current_face); - if (status) - return status; - } - - return CAIRO_STATUS_SUCCESS; -} - -static void -_compute_face (cairo_point_t *point, cairo_slope_t *dev_slope, - double slope_dx, double slope_dy, - cairo_stroker_t *stroker, cairo_stroke_face_t *face) -{ - double face_dx, face_dy; - cairo_point_t offset_ccw, offset_cw; - - /* - * rotate to get a line_width/2 vector along the face, note that - * the vector must be rotated the right direction in device space, - * but by 90° in user space. So, the rotation depends on - * whether the ctm reflects or not, and that can be determined - * by looking at the determinant of the matrix. - */ - if (stroker->ctm_det_positive) - { - face_dx = - slope_dy * (stroker->style->line_width / 2.0); - face_dy = slope_dx * (stroker->style->line_width / 2.0); - } - else - { - face_dx = slope_dy * (stroker->style->line_width / 2.0); - face_dy = - slope_dx * (stroker->style->line_width / 2.0); - } - - /* back to device space */ - cairo_matrix_transform_distance (stroker->ctm, &face_dx, &face_dy); - - offset_ccw.x = _cairo_fixed_from_double (face_dx); - offset_ccw.y = _cairo_fixed_from_double (face_dy); - offset_cw.x = -offset_ccw.x; - offset_cw.y = -offset_ccw.y; - - face->ccw = *point; - _translate_point (&face->ccw, &offset_ccw); - - face->point = *point; - - face->cw = *point; - _translate_point (&face->cw, &offset_cw); - - face->usr_vector.x = slope_dx; - face->usr_vector.y = slope_dy; - - face->dev_vector = *dev_slope; -} - -static cairo_status_t -_cairo_stroker_add_sub_edge (cairo_stroker_t *stroker, cairo_point_t *p1, cairo_point_t *p2, - cairo_slope_t *dev_slope, double slope_dx, double slope_dy, - cairo_stroke_face_t *start, cairo_stroke_face_t *end) -{ - cairo_point_t rectangle[4]; - - _compute_face (p1, dev_slope, slope_dx, slope_dy, stroker, start); - - /* XXX: This could be optimized slightly by not calling - _compute_face again but rather translating the relevant - fields from start. */ - _compute_face (p2, dev_slope, slope_dx, slope_dy, stroker, end); - - if (p1->x == p2->x && p1->y == p2->y) - return CAIRO_STATUS_SUCCESS; - - rectangle[0] = start->cw; - rectangle[1] = start->ccw; - rectangle[2] = end->ccw; - rectangle[3] = end->cw; - - return _cairo_traps_tessellate_convex_quad (stroker->traps, rectangle); -} - -static cairo_status_t -_cairo_stroker_move_to (void *closure, cairo_point_t *point) -{ - cairo_status_t status; - cairo_stroker_t *stroker = closure; - - /* Cap the start and end of the previous sub path as needed */ - status = _cairo_stroker_add_caps (stroker); - if (status) - return status; - - stroker->first_point = *point; - stroker->current_point = *point; - - stroker->has_first_face = FALSE; - stroker->has_current_face = FALSE; - stroker->has_initial_sub_path = FALSE; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_stroker_move_to_dashed (void *closure, cairo_point_t *point) -{ - /* reset the dash pattern for new sub paths */ - cairo_stroker_t *stroker = closure; - _cairo_stroker_start_dash (stroker); - - return _cairo_stroker_move_to (closure, point); -} - -static cairo_status_t -_cairo_stroker_line_to (void *closure, cairo_point_t *point) -{ - cairo_status_t status; - cairo_stroker_t *stroker = closure; - cairo_stroke_face_t start, end; - cairo_point_t *p1 = &stroker->current_point; - cairo_point_t *p2 = point; - cairo_slope_t dev_slope; - double slope_dx, slope_dy; - - stroker->has_initial_sub_path = TRUE; - - if (p1->x == p2->x && p1->y == p2->y) - return CAIRO_STATUS_SUCCESS; - - _cairo_slope_init (&dev_slope, p1, p2); - slope_dx = _cairo_fixed_to_double (p2->x - p1->x); - slope_dy = _cairo_fixed_to_double (p2->y - p1->y); - _compute_normalized_device_slope (&slope_dx, &slope_dy, stroker->ctm_inverse, NULL); - - status = _cairo_stroker_add_sub_edge (stroker, p1, p2, &dev_slope, slope_dx, slope_dy, &start, &end); - if (status) - return status; - - if (stroker->has_current_face) { - /* Join with final face from previous segment */ - status = _cairo_stroker_join (stroker, &stroker->current_face, &start); - if (status) - return status; - } else if (!stroker->has_first_face) { - /* Save sub path's first face in case needed for closing join */ - stroker->first_face = start; - stroker->has_first_face = TRUE; - } - stroker->current_face = end; - stroker->has_current_face = TRUE; - - stroker->current_point = *point; - - return CAIRO_STATUS_SUCCESS; -} - -/* - * Dashed lines. Cap each dash end, join around turns when on - */ -static cairo_status_t -_cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point) -{ - cairo_stroker_t *stroker = closure; - double mag, remain, step_length = 0; - double slope_dx, slope_dy; - double dx2, dy2; - cairo_stroke_face_t sub_start, sub_end; - cairo_point_t *p1 = &stroker->current_point; - cairo_point_t *p2 = point; - cairo_slope_t dev_slope; - cairo_line_t segment; - cairo_bool_t fully_in_bounds; - cairo_status_t status; - - stroker->has_initial_sub_path = stroker->dash_starts_on; - - if (p1->x == p2->x && p1->y == p2->y) - return CAIRO_STATUS_SUCCESS; - - fully_in_bounds = TRUE; - if (stroker->has_bounds && - (! _cairo_box_contains_point (&stroker->bounds, p1) || - ! _cairo_box_contains_point (&stroker->bounds, p2))) - { - fully_in_bounds = FALSE; - } - - _cairo_slope_init (&dev_slope, p1, p2); - - slope_dx = _cairo_fixed_to_double (p2->x - p1->x); - slope_dy = _cairo_fixed_to_double (p2->y - p1->y); - - if (! _compute_normalized_device_slope (&slope_dx, &slope_dy, - stroker->ctm_inverse, &mag)) - { - return CAIRO_STATUS_SUCCESS; - } - - remain = mag; - segment.p1 = *p1; - while (remain) { - step_length = MIN (stroker->dash_remain, remain); - remain -= step_length; - dx2 = slope_dx * (mag - remain); - dy2 = slope_dy * (mag - remain); - cairo_matrix_transform_distance (stroker->ctm, &dx2, &dy2); - segment.p2.x = _cairo_fixed_from_double (dx2) + p1->x; - segment.p2.y = _cairo_fixed_from_double (dy2) + p1->y; - - if (stroker->dash_on && - (fully_in_bounds || - (! stroker->has_first_face && stroker->dash_starts_on) || - _cairo_box_intersects_line_segment (&stroker->bounds, &segment))) - { - status = _cairo_stroker_add_sub_edge (stroker, - &segment.p1, &segment.p2, - &dev_slope, - slope_dx, slope_dy, - &sub_start, &sub_end); - if (status) - return status; - - if (stroker->has_current_face) { - /* Join with final face from previous segment */ - status = _cairo_stroker_join (stroker, - &stroker->current_face, - &sub_start); - if (status) - return status; - - stroker->has_current_face = FALSE; - } else if (! stroker->has_first_face && stroker->dash_starts_on) { - /* Save sub path's first face in case needed for closing join */ - stroker->first_face = sub_start; - stroker->has_first_face = TRUE; - } else { - /* Cap dash start if not connecting to a previous segment */ - status = _cairo_stroker_add_leading_cap (stroker, &sub_start); - if (status) - return status; - } - - if (remain) { - /* Cap dash end if not at end of segment */ - status = _cairo_stroker_add_trailing_cap (stroker, &sub_end); - if (status) - return status; - } else { - stroker->current_face = sub_end; - stroker->has_current_face = TRUE; - } - } else { - if (stroker->has_current_face) { - /* Cap final face from previous segment */ - status = _cairo_stroker_add_trailing_cap (stroker, - &stroker->current_face); - if (status) - return status; - - stroker->has_current_face = FALSE; - } - } - - _cairo_stroker_step_dash (stroker, step_length); - segment.p1 = segment.p2; - } - - if (stroker->dash_on && ! stroker->has_current_face) { - /* This segment ends on a transition to dash_on, compute a new face - * and add cap for the beginning of the next dash_on step. - * - * Note: this will create a degenerate cap if this is not the last line - * in the path. Whether this behaviour is desirable or not is debatable. - * On one side these degenerate caps can not be reproduced with regular - * path stroking. - * On the other hand, Acroread 7 also produces the degenerate caps. - */ - _compute_face (point, &dev_slope, - slope_dx, slope_dy, - stroker, - &stroker->current_face); - - status = _cairo_stroker_add_leading_cap (stroker, - &stroker->current_face); - if (status) - return status; - - stroker->has_current_face = TRUE; - } - - stroker->current_point = *point; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_stroker_curve_to (void *closure, - cairo_point_t *b, - cairo_point_t *c, - cairo_point_t *d) -{ - cairo_status_t status = CAIRO_STATUS_SUCCESS; - cairo_stroker_t *stroker = closure; - cairo_spline_t spline; - cairo_pen_t pen; - cairo_stroke_face_t start, end; - cairo_point_t extra_points[4]; - cairo_point_t *a = &stroker->current_point; - double initial_slope_dx, initial_slope_dy; - double final_slope_dx, final_slope_dy; - - status = _cairo_spline_init (&spline, a, b, c, d); - if (status == CAIRO_INT_STATUS_DEGENERATE) - return _cairo_stroker_line_to (closure, d); - - status = _cairo_pen_init_copy (&pen, &stroker->pen); - if (status) - goto CLEANUP_SPLINE; - - initial_slope_dx = _cairo_fixed_to_double (spline.initial_slope.dx); - initial_slope_dy = _cairo_fixed_to_double (spline.initial_slope.dy); - final_slope_dx = _cairo_fixed_to_double (spline.final_slope.dx); - final_slope_dy = _cairo_fixed_to_double (spline.final_slope.dy); - - if (_compute_normalized_device_slope (&initial_slope_dx, &initial_slope_dy, stroker->ctm_inverse, NULL)) - _compute_face (a, &spline.initial_slope, initial_slope_dx, initial_slope_dy, stroker, &start); - - if (_compute_normalized_device_slope (&final_slope_dx, &final_slope_dy, stroker->ctm_inverse, NULL)) - _compute_face (d, &spline.final_slope, final_slope_dx, final_slope_dy, stroker, &end); - - if (stroker->has_current_face) { - status = _cairo_stroker_join (stroker, &stroker->current_face, &start); - if (status) - goto CLEANUP_PEN; - } else if (!stroker->has_first_face) { - stroker->first_face = start; - stroker->has_first_face = TRUE; - } - stroker->current_face = end; - stroker->has_current_face = TRUE; - - extra_points[0] = start.cw; - extra_points[0].x -= start.point.x; - extra_points[0].y -= start.point.y; - extra_points[1] = start.ccw; - extra_points[1].x -= start.point.x; - extra_points[1].y -= start.point.y; - extra_points[2] = end.cw; - extra_points[2].x -= end.point.x; - extra_points[2].y -= end.point.y; - extra_points[3] = end.ccw; - extra_points[3].x -= end.point.x; - extra_points[3].y -= end.point.y; - - status = _cairo_pen_add_points (&pen, extra_points, 4); - if (status) - goto CLEANUP_PEN; - - status = _cairo_pen_stroke_spline (&pen, &spline, stroker->tolerance, stroker->traps); - if (status) - goto CLEANUP_PEN; - - CLEANUP_PEN: - _cairo_pen_fini (&pen); - CLEANUP_SPLINE: - _cairo_spline_fini (&spline); - - stroker->current_point = *d; - - return status; -} - -/* We're using two different algorithms here for dashed and un-dashed - * splines. The dashed algorithm uses the existing line dashing - * code. It's linear in path length, but gets subtly wrong results for - * self-intersecting paths (an outstanding but for self-intersecting - * non-curved paths as well). The non-dashed algorithm tessellates a - * single polygon for the whole curve. It handles the - * self-intersecting problem, but it's (unsurprisingly) not O(n) and - * more significantly, it doesn't yet handle dashes. - * - * The only reason we're doing split algorithms here is to - * minimize the impact of fixing the splines-aren't-dashed bug for - * 1.0.2. Long-term the right answer is to rewrite the whole pile - * of stroking code so that the entire result is computed as a - * single polygon that is tessellated, (that is, stroking can be - * built on top of filling). That will solve the self-intersecting - * problem. It will also increase the importance of implementing - * an efficient and more robust tessellator. - */ -static cairo_status_t -_cairo_stroker_curve_to_dashed (void *closure, - cairo_point_t *b, - cairo_point_t *c, - cairo_point_t *d) -{ - cairo_status_t status = CAIRO_STATUS_SUCCESS; - cairo_stroker_t *stroker = closure; - cairo_spline_t spline; - cairo_point_t *a = &stroker->current_point; - cairo_line_join_t line_join_save; - int i; - - status = _cairo_spline_init (&spline, a, b, c, d); - if (status == CAIRO_INT_STATUS_DEGENERATE) - return _cairo_stroker_line_to_dashed (closure, d); - - /* If the line width is so small that the pen is reduced to a - single point, then we have nothing to do. */ - if (stroker->pen.num_vertices <= 1) - goto CLEANUP_SPLINE; - - /* Temporarily modify the stroker to use round joins to guarantee - * smooth stroked curves. */ - line_join_save = stroker->style->line_join; - stroker->style->line_join = CAIRO_LINE_JOIN_ROUND; - - status = _cairo_spline_decompose (&spline, stroker->tolerance); - if (status) - goto CLEANUP_GSTATE; - - for (i = 1; i < spline.num_points; i++) { - if (stroker->dashed) - status = _cairo_stroker_line_to_dashed (stroker, &spline.points[i]); - else - status = _cairo_stroker_line_to (stroker, &spline.points[i]); - if (status) - break; - } - - CLEANUP_GSTATE: - stroker->style->line_join = line_join_save; - - CLEANUP_SPLINE: - _cairo_spline_fini (&spline); - - return status; -} - -static cairo_status_t -_cairo_stroker_close_path (void *closure) -{ - cairo_status_t status; - cairo_stroker_t *stroker = closure; - - if (stroker->dashed) - status = _cairo_stroker_line_to_dashed (stroker, &stroker->first_point); - else - status = _cairo_stroker_line_to (stroker, &stroker->first_point); - if (status) - return status; - - if (stroker->has_first_face && stroker->has_current_face) { - /* Join first and final faces of sub path */ - status = _cairo_stroker_join (stroker, &stroker->current_face, &stroker->first_face); - if (status) - return status; - } else { - /* Cap the start and end of the sub path as needed */ - status = _cairo_stroker_add_caps (stroker); - if (status) - return status; - } - - stroker->has_initial_sub_path = FALSE; - stroker->has_first_face = FALSE; - stroker->has_current_face = FALSE; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_path_fixed_stroke_rectilinear (cairo_path_fixed_t *path, - cairo_stroke_style_t *stroke_style, - cairo_matrix_t *ctm, - cairo_traps_t *traps); - -cairo_status_t -_cairo_path_fixed_stroke_to_traps (cairo_path_fixed_t *path, - cairo_stroke_style_t *stroke_style, - cairo_matrix_t *ctm, - cairo_matrix_t *ctm_inverse, - double tolerance, - cairo_traps_t *traps) -{ - cairo_status_t status; - cairo_stroker_t stroker; - - /* Before we do anything else, we attempt the rectilinear - * stroker. It's careful to generate trapezoids that align to - * device-pixel boundaries when possible. Many backends can render - * those much faster than non-aligned trapezoids, (by using clip - * regions, etc.) */ - status = _cairo_path_fixed_stroke_rectilinear (path, - stroke_style, - ctm, - traps); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - - status = _cairo_stroker_init (&stroker, stroke_style, - ctm, ctm_inverse, tolerance, - traps); - if (status) - return status; - - if (stroker.style->dash) - status = _cairo_path_fixed_interpret (path, - CAIRO_DIRECTION_FORWARD, - _cairo_stroker_move_to_dashed, - _cairo_stroker_line_to_dashed, - _cairo_stroker_curve_to_dashed, - _cairo_stroker_close_path, - &stroker); - else - status = _cairo_path_fixed_interpret (path, - CAIRO_DIRECTION_FORWARD, - _cairo_stroker_move_to, - _cairo_stroker_line_to, - _cairo_stroker_curve_to, - _cairo_stroker_close_path, - &stroker); - if (status) - goto BAIL; - - /* Cap the start and end of the final sub path as needed */ - status = _cairo_stroker_add_caps (&stroker); - -BAIL: - _cairo_stroker_fini (&stroker); - - return status; -} - -typedef struct _cairo_rectilinear_stroker -{ - cairo_stroke_style_t *stroke_style; - cairo_fixed_t half_line_width; - cairo_traps_t *traps; - cairo_point_t current_point; - cairo_point_t first_point; - cairo_bool_t open_sub_path; - int num_segments; - int segments_size; - cairo_line_t *segments; - cairo_line_t segments_embedded[8]; /* common case is a single rectangle */ -} cairo_rectilinear_stroker_t; - -static void -_cairo_rectilinear_stroker_init (cairo_rectilinear_stroker_t *stroker, - cairo_stroke_style_t *stroke_style, - cairo_traps_t *traps) -{ - stroker->stroke_style = stroke_style; - stroker->half_line_width = - _cairo_fixed_from_double (stroke_style->line_width / 2.0); - stroker->traps = traps; - stroker->open_sub_path = FALSE; - stroker->segments = stroker->segments_embedded; - stroker->segments_size = ARRAY_LENGTH (stroker->segments_embedded); - stroker->num_segments = 0; -} - -static void -_cairo_rectilinear_stroker_fini (cairo_rectilinear_stroker_t *stroker) -{ - if (stroker->segments != stroker->segments_embedded) - free (stroker->segments); -} - -static cairo_status_t -_cairo_rectilinear_stroker_add_segment (cairo_rectilinear_stroker_t *stroker, - cairo_point_t *p1, - cairo_point_t *p2) -{ - - if (stroker->num_segments == stroker->segments_size) { - int new_size = stroker->segments_size * 2; - cairo_line_t *new_segments; - - if (stroker->segments == stroker->segments_embedded) { - new_segments = _cairo_malloc_ab (new_size, sizeof (cairo_line_t)); - if (new_segments == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - memcpy (new_segments, stroker->segments, - stroker->num_segments * sizeof (cairo_line_t)); - } else { - new_segments = _cairo_realloc_ab (stroker->segments, - new_size, sizeof (cairo_line_t)); - if (new_segments == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - stroker->segments_size = new_size; - stroker->segments = new_segments; - } - - stroker->segments[stroker->num_segments].p1 = *p1; - stroker->segments[stroker->num_segments].p2 = *p2; - stroker->num_segments++; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_rectilinear_stroker_emit_segments (cairo_rectilinear_stroker_t *stroker) -{ - cairo_status_t status; - cairo_line_cap_t line_cap = stroker->stroke_style->line_cap; - cairo_fixed_t half_line_width = stroker->half_line_width; - int i; - - for (i = 0; i < stroker->num_segments; i++) { - cairo_point_t *a, *b; - cairo_bool_t lengthen_initial, shorten_final, lengthen_final; - - a = &stroker->segments[i].p1; - b = &stroker->segments[i].p2; - - /* For each segment we generate a single rectangular - * trapezoid. This rectangle is based on a perpendicular - * extension (by half the line width) of the segment endpoints - * after some adjustments of the endpoints to account for caps - * and joins. - */ - - /* We adjust the initial point of the segment to extend the - * rectangle to include the previous cap or join, (this - * adjustment applies to all segments except for the first - * segment of open, butt-capped paths). - */ - lengthen_initial = TRUE; - if (i == 0 && stroker->open_sub_path && line_cap == CAIRO_LINE_CAP_BUTT) - lengthen_initial = FALSE; - - /* The adjustment of the final point is trickier. For all but - * the last segment we shorten the segment at the final - * endpoint to not overlap with the subsequent join. For the - * last segment we do the same shortening if the path is - * closed. If the path is open and butt-capped we do no - * adjustment, while if it's open and square-capped we do a - * lengthening adjustment instead to include the cap. - */ - shorten_final = TRUE; - lengthen_final = FALSE; - if (i == stroker->num_segments - 1 && stroker->open_sub_path) { - shorten_final = FALSE; - if (line_cap == CAIRO_LINE_CAP_SQUARE) - lengthen_final = TRUE; - } - - /* Perform the adjustments of the endpoints. */ - if (a->y == b->y) { - if (a->x < b->x) { - if (lengthen_initial) - a->x -= half_line_width; - if (shorten_final) - b->x -= half_line_width; - else if (lengthen_final) - b->x += half_line_width; - } else { - if (lengthen_initial) - a->x += half_line_width; - if (shorten_final) - b->x += half_line_width; - else if (lengthen_final) - b->x -= half_line_width; - } - - if (a->x > b->x) { - cairo_point_t *t; - - t = a; - a = b; - b = t; - } - } else { - if (a->y < b->y) { - if (lengthen_initial) - a->y -= half_line_width; - if (shorten_final) - b->y -= half_line_width; - else if (lengthen_final) - b->y += half_line_width; - } else { - if (lengthen_initial) - a->y += half_line_width; - if (shorten_final) - b->y += half_line_width; - else if (lengthen_final) - b->y -= half_line_width; - } - - if (a->y > b->y) { - cairo_point_t *t; - - t = a; - a = b; - b = t; - } - } - - /* Form the rectangle by expanding by half the line width in - * either perpendicular direction. */ - if (a->y == b->y) { - a->y -= half_line_width; - b->y += half_line_width; - } else { - a->x -= half_line_width; - b->x += half_line_width; - } - - status = _cairo_traps_tessellate_rectangle (stroker->traps, a, b); - if (status) - return status; - } - - stroker->num_segments = 0; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_rectilinear_stroker_move_to (void *closure, - cairo_point_t *point) -{ - cairo_rectilinear_stroker_t *stroker = closure; - cairo_status_t status; - - status = _cairo_rectilinear_stroker_emit_segments (stroker); - if (status) - return status; - - stroker->current_point = *point; - stroker->first_point = *point; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_rectilinear_stroker_line_to (void *closure, - cairo_point_t *point) -{ - cairo_rectilinear_stroker_t *stroker = closure; - cairo_point_t *a = &stroker->current_point; - cairo_point_t *b = point; - cairo_status_t status; - - /* We only support horizontal or vertical elements. */ - if (! (a->x == b->x || a->y == b->y)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - /* We don't draw anything for degenerate paths. */ - if (a->x == b->x && a->y == b->y) - return CAIRO_STATUS_SUCCESS; - - status = _cairo_rectilinear_stroker_add_segment (stroker, a, b); - - stroker->current_point = *point; - stroker->open_sub_path = TRUE; - - return status; -} - -static cairo_status_t -_cairo_rectilinear_stroker_close_path (void *closure) -{ - cairo_rectilinear_stroker_t *stroker = closure; - cairo_status_t status; - - /* We don't draw anything for degenerate paths. */ - if (! stroker->open_sub_path) - return CAIRO_STATUS_SUCCESS; - - status = _cairo_rectilinear_stroker_line_to (stroker, - &stroker->first_point); - if (status) - return status; - - stroker->open_sub_path = FALSE; - - status = _cairo_rectilinear_stroker_emit_segments (stroker); - if (status) - return status; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_path_fixed_stroke_rectilinear (cairo_path_fixed_t *path, - cairo_stroke_style_t *stroke_style, - cairo_matrix_t *ctm, - cairo_traps_t *traps) -{ - cairo_rectilinear_stroker_t rectilinear_stroker; - cairo_int_status_t status; - - /* This special-case rectilinear stroker only supports - * miter-joined lines (not curves) and no dashing and a - * translation-only matrix (though it could probably be extended - * to support a matrix with uniform, integer scaling). - * - * It also only supports horizontal and vertical line_to - * elements. But we don't catch that here, but instead return - * UNSUPPORTED from _cairo_rectilinear_stroker_line_to if any - * non-rectilinear line_to is encountered. - */ - if (path->has_curve_to) - return CAIRO_INT_STATUS_UNSUPPORTED; - if (stroke_style->line_join != CAIRO_LINE_JOIN_MITER) - return CAIRO_INT_STATUS_UNSUPPORTED; - /* If the miter limit turns right angles into bevels, then we - * can't use this optimization. Remember, the ratio is - * 1/sin(ɸ/2). So the cutoff is 1/sin(Ï€/4.0) or ⎷2, - * which we round for safety. */ - if (stroke_style->miter_limit < M_SQRT2) - return CAIRO_INT_STATUS_UNSUPPORTED; - if (stroke_style->dash) - return CAIRO_INT_STATUS_UNSUPPORTED; - if (! (stroke_style->line_cap == CAIRO_LINE_CAP_BUTT || - stroke_style->line_cap == CAIRO_LINE_CAP_SQUARE)) - { - return CAIRO_INT_STATUS_UNSUPPORTED; - } - if (! (_cairo_matrix_is_identity (ctm) || - _cairo_matrix_is_translation (ctm))) - { - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - _cairo_rectilinear_stroker_init (&rectilinear_stroker, stroke_style, traps); - - status = _cairo_path_fixed_interpret (path, - CAIRO_DIRECTION_FORWARD, - _cairo_rectilinear_stroker_move_to, - _cairo_rectilinear_stroker_line_to, - NULL, - _cairo_rectilinear_stroker_close_path, - &rectilinear_stroker); - if (status) - goto BAIL; - - status = _cairo_rectilinear_stroker_emit_segments (&rectilinear_stroker); - -BAIL: - _cairo_rectilinear_stroker_fini (&rectilinear_stroker); - - if (status) - _cairo_traps_clear (traps); - - return status; -} diff --git a/uppdev/plugin/cairo/lib/cairo-path.c b/uppdev/plugin/cairo/lib/cairo-path.c deleted file mode 100644 index c6639f3f4..000000000 --- a/uppdev/plugin/cairo/lib/cairo-path.c +++ /dev/null @@ -1,482 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2005 Red Hat, Inc. - * Copyright © 2006 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Carl D. Worth - */ - -#include "cairoint.h" - -#include "cairo-path-private.h" -#include "cairo-path-fixed-private.h" - -static const cairo_path_t _cairo_path_nil = { CAIRO_STATUS_NO_MEMORY, NULL, 0 }; - -/* Closure for path interpretation. */ -typedef struct cairo_path_count { - int count; - cairo_point_t current_point; -} cpc_t; - -static cairo_status_t -_cpc_move_to (void *closure, cairo_point_t *point) -{ - cpc_t *cpc = closure; - - cpc->count += 2; - - cpc->current_point = *point; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cpc_line_to (void *closure, cairo_point_t *point) -{ - cpc_t *cpc = closure; - - cpc->count += 2; - - cpc->current_point = *point; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cpc_curve_to (void *closure, - cairo_point_t *p1, - cairo_point_t *p2, - cairo_point_t *p3) -{ - cpc_t *cpc = closure; - - cpc->count += 4; - - cpc->current_point = *p3; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cpc_close_path (void *closure) -{ - cpc_t *cpc = closure; - - cpc->count += 1; - - return CAIRO_STATUS_SUCCESS; -} - -static int -_cairo_path_count (cairo_path_t *path, - cairo_path_fixed_t *path_fixed, - double tolerance, - cairo_bool_t flatten) -{ - cairo_status_t status; - cpc_t cpc; - - cpc.count = 0; - cpc.current_point.x = 0; - cpc.current_point.y = 0; - - if (flatten) { - status = _cairo_path_fixed_interpret_flat (path_fixed, - CAIRO_DIRECTION_FORWARD, - _cpc_move_to, - _cpc_line_to, - _cpc_close_path, - &cpc, - tolerance); - } else { - status = _cairo_path_fixed_interpret (path_fixed, - CAIRO_DIRECTION_FORWARD, - _cpc_move_to, - _cpc_line_to, - _cpc_curve_to, - _cpc_close_path, - &cpc); - } - - if (status) - return -1; - - return cpc.count; -} - -/* Closure for path interpretation. */ -typedef struct cairo_path_populate { - cairo_path_data_t *data; - cairo_gstate_t *gstate; - cairo_point_t current_point; -} cpp_t; - -static cairo_status_t -_cpp_move_to (void *closure, cairo_point_t *point) -{ - cpp_t *cpp = closure; - cairo_path_data_t *data = cpp->data; - double x, y; - - x = _cairo_fixed_to_double (point->x); - y = _cairo_fixed_to_double (point->y); - - _cairo_gstate_backend_to_user (cpp->gstate, &x, &y); - - data->header.type = CAIRO_PATH_MOVE_TO; - data->header.length = 2; - - /* We index from 1 to leave room for data->header */ - data[1].point.x = x; - data[1].point.y = y; - - cpp->data += data->header.length; - - cpp->current_point = *point; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cpp_line_to (void *closure, cairo_point_t *point) -{ - cpp_t *cpp = closure; - cairo_path_data_t *data = cpp->data; - double x, y; - - x = _cairo_fixed_to_double (point->x); - y = _cairo_fixed_to_double (point->y); - - _cairo_gstate_backend_to_user (cpp->gstate, &x, &y); - - data->header.type = CAIRO_PATH_LINE_TO; - data->header.length = 2; - - /* We index from 1 to leave room for data->header */ - data[1].point.x = x; - data[1].point.y = y; - - cpp->data += data->header.length; - - cpp->current_point = *point; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cpp_curve_to (void *closure, - cairo_point_t *p1, - cairo_point_t *p2, - cairo_point_t *p3) -{ - cpp_t *cpp = closure; - cairo_path_data_t *data = cpp->data; - double x1, y1; - double x2, y2; - double x3, y3; - - x1 = _cairo_fixed_to_double (p1->x); - y1 = _cairo_fixed_to_double (p1->y); - _cairo_gstate_backend_to_user (cpp->gstate, &x1, &y1); - - x2 = _cairo_fixed_to_double (p2->x); - y2 = _cairo_fixed_to_double (p2->y); - _cairo_gstate_backend_to_user (cpp->gstate, &x2, &y2); - - x3 = _cairo_fixed_to_double (p3->x); - y3 = _cairo_fixed_to_double (p3->y); - _cairo_gstate_backend_to_user (cpp->gstate, &x3, &y3); - - data->header.type = CAIRO_PATH_CURVE_TO; - data->header.length = 4; - - /* We index from 1 to leave room for data->header */ - data[1].point.x = x1; - data[1].point.y = y1; - - data[2].point.x = x2; - data[2].point.y = y2; - - data[3].point.x = x3; - data[3].point.y = y3; - - cpp->data += data->header.length; - - cpp->current_point = *p3; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cpp_close_path (void *closure) -{ - cpp_t *cpp = closure; - cairo_path_data_t *data = cpp->data; - - data->header.type = CAIRO_PATH_CLOSE_PATH; - data->header.length = 1; - - cpp->data += data->header.length; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_path_populate (cairo_path_t *path, - cairo_path_fixed_t *path_fixed, - cairo_gstate_t *gstate, - cairo_bool_t flatten) -{ - cairo_status_t status; - cpp_t cpp; - - cpp.data = path->data; - cpp.gstate = gstate; - cpp.current_point.x = 0; - cpp.current_point.y = 0; - - if (flatten) { - double tolerance = _cairo_gstate_get_tolerance (gstate); - status = _cairo_path_fixed_interpret_flat (path_fixed, - CAIRO_DIRECTION_FORWARD, - _cpp_move_to, - _cpp_line_to, - _cpp_close_path, - &cpp, - tolerance); - } else { - status = _cairo_path_fixed_interpret (path_fixed, - CAIRO_DIRECTION_FORWARD, - _cpp_move_to, - _cpp_line_to, - _cpp_curve_to, - _cpp_close_path, - &cpp); - } - - if (status) - return status; - - /* Sanity check the count */ - assert (cpp.data - path->data == path->num_data); - - return CAIRO_STATUS_SUCCESS; -} - -cairo_path_t * -_cairo_path_create_in_error (cairo_status_t status) -{ - cairo_path_t *path; - - /* special case NO_MEMORY so as to avoid allocations */ - if (status == CAIRO_STATUS_NO_MEMORY) - return (cairo_path_t*) &_cairo_path_nil; - - path = malloc (sizeof (cairo_path_t)); - if (path == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_path_t*) &_cairo_path_nil; - } - - path->num_data = 0; - path->data = NULL; - path->status = status; - - return path; -} - -static cairo_path_t * -_cairo_path_create_internal (cairo_path_fixed_t *path_fixed, - cairo_gstate_t *gstate, - cairo_bool_t flatten) -{ - cairo_path_t *path; - - path = malloc (sizeof (cairo_path_t)); - if (path == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_path_t*) &_cairo_path_nil; - } - - path->num_data = _cairo_path_count (path, path_fixed, - _cairo_gstate_get_tolerance (gstate), - flatten); - if (path->num_data < 0) { - free (path); - return (cairo_path_t*) &_cairo_path_nil; - } - - if (path->num_data) { - path->data = _cairo_malloc_ab (path->num_data, - sizeof (cairo_path_data_t)); - if (path->data == NULL) { - free (path); - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_path_t*) &_cairo_path_nil; - } - - path->status = _cairo_path_populate (path, path_fixed, - gstate, flatten); - } else { - path->data = NULL; - path->status = CAIRO_STATUS_SUCCESS; - } - - return path; -} - -/** - * cairo_path_destroy: - * @path: a path previously returned by either cairo_copy_path() or - * cairo_copy_path_flat(). - * - * Immediately releases all memory associated with @path. After a call - * to cairo_path_destroy() the @path pointer is no longer valid and - * should not be used further. - * - * Note: cairo_path_destroy() should only be called with a - * pointer to a #cairo_path_t returned by a cairo function. Any path - * that is created manually (ie. outside of cairo) should be destroyed - * manually as well. - **/ -void -cairo_path_destroy (cairo_path_t *path) -{ - if (path == NULL || path == &_cairo_path_nil) - return; - - if (path->data) - free (path->data); - - free (path); -} - -/** - * _cairo_path_create: - * @path: a fixed-point, device-space path to be converted and copied - * @gstate: the current graphics state - * - * Creates a user-space #cairo_path_t copy of the given device-space - * @path. The @gstate parameter provides the inverse CTM for the - * conversion. - * - * Return value: the new copy of the path. If there is insufficient - * memory a pointer to a special static nil #cairo_path_t will be - * returned instead with status==%CAIRO_STATUS_NO_MEMORY and - * data==%NULL. - **/ -cairo_path_t * -_cairo_path_create (cairo_path_fixed_t *path, - cairo_gstate_t *gstate) -{ - return _cairo_path_create_internal (path, gstate, FALSE); -} - -/** - * _cairo_path_create_flat: - * @path: a fixed-point, device-space path to be flattened, converted and copied - * @gstate: the current graphics state - * - * Creates a flattened, user-space #cairo_path_t copy of the given - * device-space @path. The @gstate parameter provide the inverse CTM - * for the conversion, as well as the tolerance value to control the - * accuracy of the flattening. - * - * Return value: the flattened copy of the path. If there is insufficient - * memory a pointer to a special static nil #cairo_path_t will be - * returned instead with status==%CAIRO_STATUS_NO_MEMORY and - * data==%NULL. - **/ -cairo_path_t * -_cairo_path_create_flat (cairo_path_fixed_t *path, - cairo_gstate_t *gstate) -{ - return _cairo_path_create_internal (path, gstate, TRUE); -} - -/** - * _cairo_path_append_to_context: - * @path: the path data to be appended - * @cr: a cairo context - * - * Append @path to the current path within @cr. - * - * Return value: %CAIRO_STATUS_INVALID_PATH_DATA if the data in @path - * is invalid, and %CAIRO_STATUS_SUCCESS otherwise. - **/ -cairo_status_t -_cairo_path_append_to_context (const cairo_path_t *path, - cairo_t *cr) -{ - int i; - cairo_path_data_t *p; - cairo_status_t status; - - for (i=0; i < path->num_data; i += path->data[i].header.length) { - p = &path->data[i]; - switch (p->header.type) { - case CAIRO_PATH_MOVE_TO: - if (p->header.length < 2) - return _cairo_error (CAIRO_STATUS_INVALID_PATH_DATA); - cairo_move_to (cr, - p[1].point.x, p[1].point.y); - break; - case CAIRO_PATH_LINE_TO: - if (p->header.length < 2) - return _cairo_error (CAIRO_STATUS_INVALID_PATH_DATA); - cairo_line_to (cr, - p[1].point.x, p[1].point.y); - break; - case CAIRO_PATH_CURVE_TO: - if (p->header.length < 4) - return _cairo_error (CAIRO_STATUS_INVALID_PATH_DATA); - cairo_curve_to (cr, - p[1].point.x, p[1].point.y, - p[2].point.x, p[2].point.y, - p[3].point.x, p[3].point.y); - break; - case CAIRO_PATH_CLOSE_PATH: - if (p->header.length < 1) - return _cairo_error (CAIRO_STATUS_INVALID_PATH_DATA); - cairo_close_path (cr); - break; - default: - return _cairo_error (CAIRO_STATUS_INVALID_PATH_DATA); - } - - status = cairo_status (cr); - if (status) - return status; - } - - return CAIRO_STATUS_SUCCESS; -} diff --git a/uppdev/plugin/cairo/lib/cairo-pattern.c b/uppdev/plugin/cairo/lib/cairo-pattern.c deleted file mode 100644 index 81fa62ad5..000000000 --- a/uppdev/plugin/cairo/lib/cairo-pattern.c +++ /dev/null @@ -1,2528 +0,0 @@ -/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2004 David Reveman - * Copyright © 2005 Red Hat, Inc. - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without - * fee, provided that the above copyright notice appear in all copies - * and that both that copyright notice and this permission notice - * appear in supporting documentation, and that the name of David - * Reveman not be used in advertising or publicity pertaining to - * distribution of the software without specific, written prior - * permission. David Reveman makes no representations about the - * suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL DAVID REVEMAN 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. - * - * Authors: David Reveman - * Keith Packard - * Carl Worth - */ - -#include "cairoint.h" - -const cairo_solid_pattern_t _cairo_pattern_nil = { - { CAIRO_PATTERN_TYPE_SOLID, /* type */ - CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */ - CAIRO_STATUS_NO_MEMORY, /* status */ - { 0, 0, 0, NULL }, /* user_data */ - { 1., 0., 0., 1., 0., 0., }, /* matrix */ - CAIRO_FILTER_DEFAULT, /* filter */ - CAIRO_EXTEND_GRADIENT_DEFAULT }, /* extend */ -}; - -static const cairo_solid_pattern_t _cairo_pattern_nil_null_pointer = { - { CAIRO_PATTERN_TYPE_SOLID, /* type */ - CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */ - CAIRO_STATUS_NULL_POINTER, /* status */ - { 0, 0, 0, NULL }, /* user_data */ - { 1., 0., 0., 1., 0., 0., }, /* matrix */ - CAIRO_FILTER_DEFAULT, /* filter */ - CAIRO_EXTEND_GRADIENT_DEFAULT }, /* extend */ -}; - -const cairo_solid_pattern_t _cairo_pattern_none = { - { CAIRO_PATTERN_TYPE_SOLID, /* type */ - CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */ - CAIRO_STATUS_SUCCESS, /* status */ - { 0, 0, 0, NULL }, /* user_data */ - { 1., 0., 0., 1., 0., 0., }, /* matrix */ - CAIRO_FILTER_DEFAULT, /* filter */ - CAIRO_EXTEND_GRADIENT_DEFAULT }, /* extend */ -}; - -/** - * _cairo_pattern_set_error: - * @pattern: a pattern - * @status: a status value indicating an error - * - * Atomically sets pattern->status to @status and calls _cairo_error; - * Does nothing if status is %CAIRO_STATUS_SUCCESS. - * - * All assignments of an error status to pattern->status should happen - * through _cairo_pattern_set_error(). Note that due to the nature of - * the atomic operation, it is not safe to call this function on the nil - * objects. - * - * The purpose of this function is to allow the user to set a - * breakpoint in _cairo_error() to generate a stack trace for when the - * user causes cairo to detect an error. - **/ -static cairo_status_t -_cairo_pattern_set_error (cairo_pattern_t *pattern, - cairo_status_t status) -{ - if (status == CAIRO_STATUS_SUCCESS) - return status; - - /* Don't overwrite an existing error. This preserves the first - * error, which is the most significant. */ - _cairo_status_set_error (&pattern->status, status); - - return _cairo_error (status); -} - -static void -_cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type) -{ - pattern->type = type; - pattern->status = CAIRO_STATUS_SUCCESS; - - /* Set the reference count to zero for on-stack patterns. - * Callers needs to explicitly increment the count for heap allocations. */ - CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 0); - - _cairo_user_data_array_init (&pattern->user_data); - - if (type == CAIRO_PATTERN_TYPE_SURFACE) - pattern->extend = CAIRO_EXTEND_SURFACE_DEFAULT; - else - pattern->extend = CAIRO_EXTEND_GRADIENT_DEFAULT; - - pattern->filter = CAIRO_FILTER_DEFAULT; - - cairo_matrix_init_identity (&pattern->matrix); -} - -static cairo_status_t -_cairo_gradient_pattern_init_copy (cairo_gradient_pattern_t *pattern, - const cairo_gradient_pattern_t *other) -{ - if (other->base.type == CAIRO_PATTERN_TYPE_LINEAR) - { - cairo_linear_pattern_t *dst = (cairo_linear_pattern_t *) pattern; - cairo_linear_pattern_t *src = (cairo_linear_pattern_t *) other; - - *dst = *src; - } - else - { - cairo_radial_pattern_t *dst = (cairo_radial_pattern_t *) pattern; - cairo_radial_pattern_t *src = (cairo_radial_pattern_t *) other; - - *dst = *src; - } - - if (other->stops == other->stops_embedded) - pattern->stops = pattern->stops_embedded; - else if (other->stops) - { - pattern->stops = _cairo_malloc_ab (other->stops_size, - sizeof (cairo_gradient_stop_t)); - if (pattern->stops == NULL) { - pattern->stops_size = 0; - pattern->n_stops = 0; - return _cairo_pattern_set_error (&pattern->base, CAIRO_STATUS_NO_MEMORY); - } - - memcpy (pattern->stops, other->stops, - other->n_stops * sizeof (cairo_gradient_stop_t)); - } - - return CAIRO_STATUS_SUCCESS; -} - -cairo_status_t -_cairo_pattern_init_copy (cairo_pattern_t *pattern, - const cairo_pattern_t *other) -{ - if (other->status) - return _cairo_pattern_set_error (pattern, other->status); - - switch (other->type) { - case CAIRO_PATTERN_TYPE_SOLID: { - cairo_solid_pattern_t *dst = (cairo_solid_pattern_t *) pattern; - cairo_solid_pattern_t *src = (cairo_solid_pattern_t *) other; - - *dst = *src; - } break; - case CAIRO_PATTERN_TYPE_SURFACE: { - cairo_surface_pattern_t *dst = (cairo_surface_pattern_t *) pattern; - cairo_surface_pattern_t *src = (cairo_surface_pattern_t *) other; - - *dst = *src; - cairo_surface_reference (dst->surface); - } break; - case CAIRO_PATTERN_TYPE_LINEAR: - case CAIRO_PATTERN_TYPE_RADIAL: { - cairo_gradient_pattern_t *dst = (cairo_gradient_pattern_t *) pattern; - cairo_gradient_pattern_t *src = (cairo_gradient_pattern_t *) other; - cairo_status_t status; - - status = _cairo_gradient_pattern_init_copy (dst, src); - if (status) - return status; - - } break; - } - - /* The reference count and user_data array are unique to the copy. */ - CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 0); - _cairo_user_data_array_init (&pattern->user_data); - - return CAIRO_STATUS_SUCCESS; -} - -cairo_status_t -_cairo_pattern_init_snapshot (cairo_pattern_t *pattern, - const cairo_pattern_t *other) -{ - cairo_status_t status; - - /* We don't bother doing any fancy copy-on-write implementation - * for the pattern's data. It's generally quite tiny. */ - status = _cairo_pattern_init_copy (pattern, other); - if (status) - return status; - - /* But we do let the surface snapshot stuff be as fancy as it - * would like to be. */ - if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) { - cairo_surface_pattern_t *surface_pattern = - (cairo_surface_pattern_t *) pattern; - cairo_surface_t *surface = surface_pattern->surface; - - surface_pattern->surface = _cairo_surface_snapshot (surface); - - cairo_surface_destroy (surface); - - if (surface_pattern->surface->status) - return surface_pattern->surface->status; - } - - return CAIRO_STATUS_SUCCESS; -} - -void -_cairo_pattern_fini (cairo_pattern_t *pattern) -{ - _cairo_user_data_array_fini (&pattern->user_data); - - switch (pattern->type) { - case CAIRO_PATTERN_TYPE_SOLID: - break; - case CAIRO_PATTERN_TYPE_SURFACE: { - cairo_surface_pattern_t *surface_pattern = - (cairo_surface_pattern_t *) pattern; - - cairo_surface_destroy (surface_pattern->surface); - } break; - case CAIRO_PATTERN_TYPE_LINEAR: - case CAIRO_PATTERN_TYPE_RADIAL: { - cairo_gradient_pattern_t *gradient = - (cairo_gradient_pattern_t *) pattern; - - if (gradient->stops && gradient->stops != gradient->stops_embedded) - free (gradient->stops); - } break; - } -} - -cairo_status_t -_cairo_pattern_create_copy (cairo_pattern_t **pattern, - const cairo_pattern_t *other) -{ - cairo_status_t status; - - if (other->status) - return other->status; - - switch (other->type) { - case CAIRO_PATTERN_TYPE_SOLID: - *pattern = malloc (sizeof (cairo_solid_pattern_t)); - break; - case CAIRO_PATTERN_TYPE_SURFACE: - *pattern = malloc (sizeof (cairo_surface_pattern_t)); - break; - case CAIRO_PATTERN_TYPE_LINEAR: - *pattern = malloc (sizeof (cairo_linear_pattern_t)); - break; - case CAIRO_PATTERN_TYPE_RADIAL: - *pattern = malloc (sizeof (cairo_radial_pattern_t)); - break; - } - if (*pattern == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - status = _cairo_pattern_init_copy (*pattern, other); - if (status) { - free (*pattern); - return status; - } - - CAIRO_REFERENCE_COUNT_INIT (&(*pattern)->ref_count, 1); - - return CAIRO_STATUS_SUCCESS; -} - - -void -_cairo_pattern_init_solid (cairo_solid_pattern_t *pattern, - const cairo_color_t *color, - cairo_content_t content) -{ - if (content == CAIRO_CONTENT_COLOR_ALPHA && CAIRO_COLOR_IS_OPAQUE (color)) - content = CAIRO_CONTENT_COLOR; - - _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SOLID); - pattern->color = *color; - pattern->content = content; -} - -void -_cairo_pattern_init_for_surface (cairo_surface_pattern_t *pattern, - cairo_surface_t *surface) -{ - if (surface->status) { - /* Force to solid to simplify the pattern_fini process. */ - _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SOLID); - _cairo_pattern_set_error (&pattern->base, surface->status); - return; - } - - _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SURFACE); - - pattern->surface = cairo_surface_reference (surface); -} - -static void -_cairo_pattern_init_gradient (cairo_gradient_pattern_t *pattern, - cairo_pattern_type_t type) -{ - _cairo_pattern_init (&pattern->base, type); - - pattern->n_stops = 0; - pattern->stops_size = 0; - pattern->stops = NULL; -} - -void -_cairo_pattern_init_linear (cairo_linear_pattern_t *pattern, - double x0, double y0, double x1, double y1) -{ - _cairo_pattern_init_gradient (&pattern->base, CAIRO_PATTERN_TYPE_LINEAR); - - pattern->p1.x = _cairo_fixed_from_double (x0); - pattern->p1.y = _cairo_fixed_from_double (y0); - pattern->p2.x = _cairo_fixed_from_double (x1); - pattern->p2.y = _cairo_fixed_from_double (y1); -} - -void -_cairo_pattern_init_radial (cairo_radial_pattern_t *pattern, - double cx0, double cy0, double radius0, - double cx1, double cy1, double radius1) -{ - _cairo_pattern_init_gradient (&pattern->base, CAIRO_PATTERN_TYPE_RADIAL); - - pattern->c1.x = _cairo_fixed_from_double (cx0); - pattern->c1.y = _cairo_fixed_from_double (cy0); - pattern->r1 = _cairo_fixed_from_double (fabs (radius0)); - pattern->c2.x = _cairo_fixed_from_double (cx1); - pattern->c2.y = _cairo_fixed_from_double (cy1); - pattern->r2 = _cairo_fixed_from_double (fabs (radius1)); -} - -/* We use a small freed pattern cache here, because we don't want to - * constantly reallocate simple colors. */ -#define MAX_PATTERN_CACHE_SIZE 4 -static struct { - cairo_solid_pattern_t *patterns[MAX_PATTERN_CACHE_SIZE]; - int size; -} solid_pattern_cache; - -cairo_pattern_t * -_cairo_pattern_create_solid (const cairo_color_t *color, - cairo_content_t content) -{ - cairo_solid_pattern_t *pattern = NULL; - - CAIRO_MUTEX_LOCK (_cairo_pattern_solid_pattern_cache_lock); - - if (solid_pattern_cache.size) { - int i = --solid_pattern_cache.size % - ARRAY_LENGTH (solid_pattern_cache.patterns); - pattern = solid_pattern_cache.patterns[i]; - solid_pattern_cache.patterns[i] = NULL; - } - - CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_pattern_cache_lock); - - if (pattern == NULL) { - /* None cached, need to create a new pattern. */ - pattern = malloc (sizeof (cairo_solid_pattern_t)); - } - - if (pattern == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - pattern = (cairo_solid_pattern_t *) &_cairo_pattern_nil; - } else { - _cairo_pattern_init_solid (pattern, color, content); - CAIRO_REFERENCE_COUNT_INIT (&pattern->base.ref_count, 1); - } - - return &pattern->base; -} - -static void -_cairo_pattern_reset_solid_pattern_cache (void) -{ - int i; - - CAIRO_MUTEX_LOCK (_cairo_pattern_solid_pattern_cache_lock); - - for (i = 0; i < MIN (ARRAY_LENGTH (solid_pattern_cache.patterns), solid_pattern_cache.size); i++) { - if (solid_pattern_cache.patterns[i]) - free (solid_pattern_cache.patterns[i]); - solid_pattern_cache.patterns[i] = NULL; - } - solid_pattern_cache.size = 0; - - CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_pattern_cache_lock); -} - -static const cairo_pattern_t * -_cairo_pattern_create_in_error (cairo_status_t status) -{ - cairo_pattern_t *pattern; - - if (status == CAIRO_STATUS_NO_MEMORY) - return (cairo_pattern_t *)&_cairo_pattern_nil.base; - - CAIRO_MUTEX_INITIALIZE (); - - pattern = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK, CAIRO_CONTENT_COLOR); - if (pattern->status == CAIRO_STATUS_SUCCESS) - status = _cairo_pattern_set_error (pattern, status); - - return pattern; -} - -/** - * cairo_pattern_create_rgb: - * @red: red component of the color - * @green: green component of the color - * @blue: blue component of the color - * - * Creates a new #cairo_pattern_t corresponding to an opaque color. The - * color components are floating point numbers in the range 0 to 1. - * If the values passed in are outside that range, they will be - * clamped. - * - * Return value: the newly created #cairo_pattern_t if successful, or - * an error pattern in case of no memory. The caller owns the - * returned object and should call cairo_pattern_destroy() when - * finished with it. - * - * This function will always return a valid pointer, but if an error - * occurred the pattern status will be set to an error. To inspect - * the status of a pattern use cairo_pattern_status(). - **/ -cairo_pattern_t * -cairo_pattern_create_rgb (double red, double green, double blue) -{ - cairo_color_t color; - - _cairo_restrict_value (&red, 0.0, 1.0); - _cairo_restrict_value (&green, 0.0, 1.0); - _cairo_restrict_value (&blue, 0.0, 1.0); - - _cairo_color_init_rgb (&color, red, green, blue); - - CAIRO_MUTEX_INITIALIZE (); - - return _cairo_pattern_create_solid (&color, CAIRO_CONTENT_COLOR); -} -slim_hidden_def (cairo_pattern_create_rgb); - -/** - * cairo_pattern_create_rgba: - * @red: red component of the color - * @green: green component of the color - * @blue: blue component of the color - * @alpha: alpha component of the color - * - * Creates a new #cairo_pattern_t corresponding to a translucent color. - * The color components are floating point numbers in the range 0 to - * 1. If the values passed in are outside that range, they will be - * clamped. - * - * Return value: the newly created #cairo_pattern_t if successful, or - * an error pattern in case of no memory. The caller owns the - * returned object and should call cairo_pattern_destroy() when - * finished with it. - * - * This function will always return a valid pointer, but if an error - * occurred the pattern status will be set to an error. To inspect - * the status of a pattern use cairo_pattern_status(). - **/ -cairo_pattern_t * -cairo_pattern_create_rgba (double red, double green, double blue, - double alpha) -{ - cairo_color_t color; - - _cairo_restrict_value (&red, 0.0, 1.0); - _cairo_restrict_value (&green, 0.0, 1.0); - _cairo_restrict_value (&blue, 0.0, 1.0); - _cairo_restrict_value (&alpha, 0.0, 1.0); - - _cairo_color_init_rgba (&color, red, green, blue, alpha); - - CAIRO_MUTEX_INITIALIZE (); - - return _cairo_pattern_create_solid (&color, CAIRO_CONTENT_COLOR_ALPHA); -} -slim_hidden_def (cairo_pattern_create_rgba); - -/** - * cairo_pattern_create_for_surface: - * @surface: the surface - * - * Create a new #cairo_pattern_t for the given surface. - * - * Return value: the newly created #cairo_pattern_t if successful, or - * an error pattern in case of no memory. The caller owns the - * returned object and should call cairo_pattern_destroy() when - * finished with it. - * - * This function will always return a valid pointer, but if an error - * occurred the pattern status will be set to an error. To inspect - * the status of a pattern use cairo_pattern_status(). - **/ -cairo_pattern_t * -cairo_pattern_create_for_surface (cairo_surface_t *surface) -{ - cairo_surface_pattern_t *pattern; - - if (surface == NULL) { - _cairo_error_throw (CAIRO_STATUS_NULL_POINTER); - return (cairo_pattern_t*) &_cairo_pattern_nil_null_pointer; - } - - if (surface->status) - return (cairo_pattern_t*) _cairo_pattern_create_in_error (surface->status); - - pattern = malloc (sizeof (cairo_surface_pattern_t)); - if (pattern == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_pattern_t *)&_cairo_pattern_nil.base; - } - - CAIRO_MUTEX_INITIALIZE (); - - _cairo_pattern_init_for_surface (pattern, surface); - CAIRO_REFERENCE_COUNT_INIT (&pattern->base.ref_count, 1); - - return &pattern->base; -} -slim_hidden_def (cairo_pattern_create_for_surface); - -/** - * cairo_pattern_create_linear: - * @x0: x coordinate of the start point - * @y0: y coordinate of the start point - * @x1: x coordinate of the end point - * @y1: y coordinate of the end point - * - * Create a new linear gradient #cairo_pattern_t along the line defined - * by (x0, y0) and (x1, y1). Before using the gradient pattern, a - * number of color stops should be defined using - * cairo_pattern_add_color_stop_rgb() or - * cairo_pattern_add_color_stop_rgba(). - * - * Note: The coordinates here are in pattern space. For a new pattern, - * pattern space is identical to user space, but the relationship - * between the spaces can be changed with cairo_pattern_set_matrix(). - * - * Return value: the newly created #cairo_pattern_t if successful, or - * an error pattern in case of no memory. The caller owns the - * returned object and should call cairo_pattern_destroy() when - * finished with it. - * - * This function will always return a valid pointer, but if an error - * occurred the pattern status will be set to an error. To inspect - * the status of a pattern use cairo_pattern_status(). - **/ -cairo_pattern_t * -cairo_pattern_create_linear (double x0, double y0, double x1, double y1) -{ - cairo_linear_pattern_t *pattern; - - pattern = malloc (sizeof (cairo_linear_pattern_t)); - if (pattern == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_pattern_t *) &_cairo_pattern_nil.base; - } - - CAIRO_MUTEX_INITIALIZE (); - - _cairo_pattern_init_linear (pattern, x0, y0, x1, y1); - CAIRO_REFERENCE_COUNT_INIT (&pattern->base.base.ref_count, 1); - - return &pattern->base.base; -} - -/** - * cairo_pattern_create_radial: - * @cx0: x coordinate for the center of the start circle - * @cy0: y coordinate for the center of the start circle - * @radius0: radius of the start circle - * @cx1: x coordinate for the center of the end circle - * @cy1: y coordinate for the center of the end circle - * @radius1: radius of the end circle - * - * Creates a new radial gradient #cairo_pattern_t between the two - * circles defined by (cx0, cy0, radius0) and (cx1, cy1, radius1). Before using the - * gradient pattern, a number of color stops should be defined using - * cairo_pattern_add_color_stop_rgb() or - * cairo_pattern_add_color_stop_rgba(). - * - * Note: The coordinates here are in pattern space. For a new pattern, - * pattern space is identical to user space, but the relationship - * between the spaces can be changed with cairo_pattern_set_matrix(). - * - * Return value: the newly created #cairo_pattern_t if successful, or - * an error pattern in case of no memory. The caller owns the - * returned object and should call cairo_pattern_destroy() when - * finished with it. - * - * This function will always return a valid pointer, but if an error - * occurred the pattern status will be set to an error. To inspect - * the status of a pattern use cairo_pattern_status(). - **/ -cairo_pattern_t * -cairo_pattern_create_radial (double cx0, double cy0, double radius0, - double cx1, double cy1, double radius1) -{ - cairo_radial_pattern_t *pattern; - - pattern = malloc (sizeof (cairo_radial_pattern_t)); - if (pattern == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_pattern_t *) &_cairo_pattern_nil.base; - } - - CAIRO_MUTEX_INITIALIZE (); - - _cairo_pattern_init_radial (pattern, cx0, cy0, radius0, cx1, cy1, radius1); - CAIRO_REFERENCE_COUNT_INIT (&pattern->base.base.ref_count, 1); - - return &pattern->base.base; -} - -/** - * cairo_pattern_reference: - * @pattern: a #cairo_pattern_t - * - * Increases the reference count on @pattern by one. This prevents - * @pattern from being destroyed until a matching call to - * cairo_pattern_destroy() is made. - * - * The number of references to a #cairo_pattern_t can be get using - * cairo_pattern_get_reference_count(). - * - * Return value: the referenced #cairo_pattern_t. - **/ -cairo_pattern_t * -cairo_pattern_reference (cairo_pattern_t *pattern) -{ - if (pattern == NULL || - CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count)) - return pattern; - - assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&pattern->ref_count)); - - _cairo_reference_count_inc (&pattern->ref_count); - - return pattern; -} -slim_hidden_def (cairo_pattern_reference); - -/** - * cairo_pattern_get_type: - * @pattern: a #cairo_pattern_t - * - * This function returns the type a pattern. - * See #cairo_pattern_type_t for available types. - * - * Return value: The type of @pattern. - * - * Since: 1.2 - **/ -cairo_pattern_type_t -cairo_pattern_get_type (cairo_pattern_t *pattern) -{ - return pattern->type; -} -slim_hidden_def (cairo_pattern_get_type); - -/** - * cairo_pattern_status: - * @pattern: a #cairo_pattern_t - * - * Checks whether an error has previously occurred for this - * pattern. - * - * Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_STATUS_NO_MEMORY, or - * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. - **/ -cairo_status_t -cairo_pattern_status (cairo_pattern_t *pattern) -{ - return pattern->status; -} -slim_hidden_def (cairo_pattern_status); - -/** - * cairo_pattern_destroy: - * @pattern: a #cairo_pattern_t - * - * Decreases the reference count on @pattern by one. If the result is - * zero, then @pattern and all associated resources are freed. See - * cairo_pattern_reference(). - **/ -void -cairo_pattern_destroy (cairo_pattern_t *pattern) -{ - if (pattern == NULL || - CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count)) - return; - - assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&pattern->ref_count)); - - if (! _cairo_reference_count_dec_and_test (&pattern->ref_count)) - return; - - _cairo_pattern_fini (pattern); - - /* maintain a small cache of freed patterns */ - if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) { - int i; - - CAIRO_MUTEX_LOCK (_cairo_pattern_solid_pattern_cache_lock); - - i = solid_pattern_cache.size++ % - ARRAY_LENGTH (solid_pattern_cache.patterns); - /* swap an old pattern for this 'cache-hot' pattern */ - if (solid_pattern_cache.patterns[i]) - free (solid_pattern_cache.patterns[i]); - - solid_pattern_cache.patterns[i] = (cairo_solid_pattern_t *) pattern; - - CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_pattern_cache_lock); - } else { - free (pattern); - } -} -slim_hidden_def (cairo_pattern_destroy); - -/** - * cairo_pattern_get_reference_count: - * @pattern: a #cairo_pattern_t - * - * Returns the current reference count of @pattern. - * - * Return value: the current reference count of @pattern. If the - * object is a nil object, 0 will be returned. - * - * Since: 1.4 - **/ -unsigned int -cairo_pattern_get_reference_count (cairo_pattern_t *pattern) -{ - if (pattern == NULL || - CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count)) - return 0; - - return CAIRO_REFERENCE_COUNT_GET_VALUE (&pattern->ref_count); -} - -/** - * cairo_pattern_get_user_data: - * @pattern: a #cairo_pattern_t - * @key: the address of the #cairo_user_data_key_t the user data was - * attached to - * - * Return user data previously attached to @pattern using the - * specified key. If no user data has been attached with the given - * key this function returns %NULL. - * - * Return value: the user data previously attached or %NULL. - * - * Since: 1.4 - **/ -void * -cairo_pattern_get_user_data (cairo_pattern_t *pattern, - const cairo_user_data_key_t *key) -{ - return _cairo_user_data_array_get_data (&pattern->user_data, - key); -} - -/** - * cairo_pattern_set_user_data: - * @pattern: a #cairo_pattern_t - * @key: the address of a #cairo_user_data_key_t to attach the user data to - * @user_data: the user data to attach to the #cairo_pattern_t - * @destroy: a #cairo_destroy_func_t which will be called when the - * #cairo_t is destroyed or when new user data is attached using the - * same key. - * - * Attach user data to @pattern. To remove user data from a surface, - * call this function with the key that was used to set it and %NULL - * for @data. - * - * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a - * slot could not be allocated for the user data. - * - * Since: 1.4 - **/ -cairo_status_t -cairo_pattern_set_user_data (cairo_pattern_t *pattern, - const cairo_user_data_key_t *key, - void *user_data, - cairo_destroy_func_t destroy) -{ - if (CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count)) - return pattern->status; - - return _cairo_user_data_array_set_data (&pattern->user_data, - key, user_data, destroy); -} - -/* make room for at least one more color stop */ -static cairo_status_t -_cairo_pattern_gradient_grow (cairo_gradient_pattern_t *pattern) -{ - cairo_gradient_stop_t *new_stops; - int old_size = pattern->stops_size; - int embedded_size = ARRAY_LENGTH (pattern->stops_embedded); - int new_size = 2 * MAX (old_size, 4); - - /* we have a local buffer at pattern->stops_embedded. try to fulfill the request - * from there. */ - if (old_size < embedded_size) { - pattern->stops = pattern->stops_embedded; - pattern->stops_size = embedded_size; - return CAIRO_STATUS_SUCCESS; - } - - assert (pattern->n_stops <= pattern->stops_size); - - if (pattern->stops == pattern->stops_embedded) { - new_stops = _cairo_malloc_ab (new_size, sizeof (cairo_gradient_stop_t)); - if (new_stops) - memcpy (new_stops, pattern->stops, old_size * sizeof (cairo_gradient_stop_t)); - } else { - new_stops = _cairo_realloc_ab (pattern->stops, - new_size, - sizeof (cairo_gradient_stop_t)); - } - - if (new_stops == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - pattern->stops = new_stops; - pattern->stops_size = new_size; - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern, - double offset, - double red, - double green, - double blue, - double alpha) -{ - cairo_gradient_stop_t *stops; - unsigned int i; - - if (pattern->n_stops >= pattern->stops_size) { - cairo_status_t status = _cairo_pattern_gradient_grow (pattern); - if (status) { - status = _cairo_pattern_set_error (&pattern->base, status); - return; - } - } - - stops = pattern->stops; - - for (i = 0; i < pattern->n_stops; i++) - { - if (offset < stops[i].offset) - { - memmove (&stops[i + 1], &stops[i], - sizeof (cairo_gradient_stop_t) * (pattern->n_stops - i)); - - break; - } - } - - stops[i].offset = offset; - - stops[i].color.red = red; - stops[i].color.green = green; - stops[i].color.blue = blue; - stops[i].color.alpha = alpha; - - stops[i].color.red_short = _cairo_color_double_to_short (red); - stops[i].color.green_short = _cairo_color_double_to_short (green); - stops[i].color.blue_short = _cairo_color_double_to_short (blue); - stops[i].color.alpha_short = _cairo_color_double_to_short (alpha); - - pattern->n_stops++; -} - -/** - * cairo_pattern_add_color_stop_rgb: - * @pattern: a #cairo_pattern_t - * @offset: an offset in the range [0.0 .. 1.0] - * @red: red component of color - * @green: green component of color - * @blue: blue component of color - * - * Adds an opaque color stop to a gradient pattern. The offset - * specifies the location along the gradient's control vector. For - * example, a linear gradient's control vector is from (x0,y0) to - * (x1,y1) while a radial gradient's control vector is from any point - * on the start circle to the corresponding point on the end circle. - * - * The color is specified in the same way as in cairo_set_source_rgb(). - * - * If two (or more) stops are specified with identical offset values, - * they will be sorted according to the order in which the stops are - * added, (stops added earlier will compare less than stops added - * later). This can be useful for reliably making sharp color - * transitions instead of the typical blend. - * - * - * Note: If the pattern is not a gradient pattern, (eg. a linear or - * radial pattern), then the pattern will be put into an error status - * with a status of %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. - **/ -void -cairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern, - double offset, - double red, - double green, - double blue) -{ - if (pattern->status) - return; - - if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR && - pattern->type != CAIRO_PATTERN_TYPE_RADIAL) - { - _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH); - return; - } - - _cairo_restrict_value (&offset, 0.0, 1.0); - _cairo_restrict_value (&red, 0.0, 1.0); - _cairo_restrict_value (&green, 0.0, 1.0); - _cairo_restrict_value (&blue, 0.0, 1.0); - - _cairo_pattern_add_color_stop ((cairo_gradient_pattern_t *) pattern, - offset, red, green, blue, 1.0); -} - -/** - * cairo_pattern_add_color_stop_rgba: - * @pattern: a #cairo_pattern_t - * @offset: an offset in the range [0.0 .. 1.0] - * @red: red component of color - * @green: green component of color - * @blue: blue component of color - * @alpha: alpha component of color - * - * Adds a translucent color stop to a gradient pattern. The offset - * specifies the location along the gradient's control vector. For - * example, a linear gradient's control vector is from (x0,y0) to - * (x1,y1) while a radial gradient's control vector is from any point - * on the start circle to the corresponding point on the end circle. - * - * The color is specified in the same way as in cairo_set_source_rgba(). - * - * If two (or more) stops are specified with identical offset values, - * they will be sorted according to the order in which the stops are - * added, (stops added earlier will compare less than stops added - * later). This can be useful for reliably making sharp color - * transitions instead of the typical blend. - * - * Note: If the pattern is not a gradient pattern, (eg. a linear or - * radial pattern), then the pattern will be put into an error status - * with a status of %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. - */ -void -cairo_pattern_add_color_stop_rgba (cairo_pattern_t *pattern, - double offset, - double red, - double green, - double blue, - double alpha) -{ - if (pattern->status) - return; - - if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR && - pattern->type != CAIRO_PATTERN_TYPE_RADIAL) - { - _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH); - return; - } - - _cairo_restrict_value (&offset, 0.0, 1.0); - _cairo_restrict_value (&red, 0.0, 1.0); - _cairo_restrict_value (&green, 0.0, 1.0); - _cairo_restrict_value (&blue, 0.0, 1.0); - _cairo_restrict_value (&alpha, 0.0, 1.0); - - _cairo_pattern_add_color_stop ((cairo_gradient_pattern_t *) pattern, - offset, red, green, blue, alpha); -} - -/** - * cairo_pattern_set_matrix: - * @pattern: a #cairo_pattern_t - * @matrix: a #cairo_matrix_t - * - * Sets the pattern's transformation matrix to @matrix. This matrix is - * a transformation from user space to pattern space. - * - * When a pattern is first created it always has the identity matrix - * for its transformation matrix, which means that pattern space is - * initially identical to user space. - * - * Important: Please note that the direction of this transformation - * matrix is from user space to pattern space. This means that if you - * imagine the flow from a pattern to user space (and on to device - * space), then coordinates in that flow will be transformed by the - * inverse of the pattern matrix. - * - * For example, if you want to make a pattern appear twice as large as - * it does by default the correct code to use is: - * - * - * cairo_matrix_init_scale (&matrix, 0.5, 0.5); - * cairo_pattern_set_matrix (pattern, &matrix); - * - * - * Meanwhile, using values of 2.0 rather than 0.5 in the code above - * would cause the pattern to appear at half of its default size. - * - * Also, please note the discussion of the user-space locking - * semantics of cairo_set_source(). - **/ -void -cairo_pattern_set_matrix (cairo_pattern_t *pattern, - const cairo_matrix_t *matrix) -{ - cairo_matrix_t inverse; - cairo_status_t status; - - if (pattern->status) - return; - - pattern->matrix = *matrix; - - inverse = *matrix; - status = cairo_matrix_invert (&inverse); - if (status) - status = _cairo_pattern_set_error (pattern, status); -} -slim_hidden_def (cairo_pattern_set_matrix); - -/** - * cairo_pattern_get_matrix: - * @pattern: a #cairo_pattern_t - * @matrix: return value for the matrix - * - * Stores the pattern's transformation matrix into @matrix. - **/ -void -cairo_pattern_get_matrix (cairo_pattern_t *pattern, cairo_matrix_t *matrix) -{ - *matrix = pattern->matrix; -} - -/** - * cairo_pattern_set_filter: - * @pattern: a #cairo_pattern_t - * @filter: a #cairo_filter_t describing the filter to use for resizing - * the pattern - * - * Sets the filter to be used for resizing when using this pattern. - * See #cairo_filter_t for details on each filter. - * - * * Note that you might want to control filtering even when you do not - * have an explicit #cairo_pattern_t object, (for example when using - * cairo_set_source_surface()). In these cases, it is convenient to - * use cairo_get_source() to get access to the pattern that cairo - * creates implicitly. For example: - * - * - * cairo_set_source_surface (cr, image, x, y); - * cairo_pattern_set_filter (cairo_get_source (cr), %CAIRO_FILTER_NEAREST); - * - **/ -void -cairo_pattern_set_filter (cairo_pattern_t *pattern, cairo_filter_t filter) -{ - if (pattern->status) - return; - - pattern->filter = filter; -} - -/** - * cairo_pattern_get_filter: - * @pattern: a #cairo_pattern_t - * - * Gets the current filter for a pattern. See #cairo_filter_t - * for details on each filter. - * - * Return value: the current filter used for resizing the pattern. - **/ -cairo_filter_t -cairo_pattern_get_filter (cairo_pattern_t *pattern) -{ - return pattern->filter; -} - -/** - * cairo_pattern_set_extend: - * @pattern: a #cairo_pattern_t - * @extend: a #cairo_extend_t describing how the area outside of the - * pattern will be drawn - * - * Sets the mode to be used for drawing outside the area of a pattern. - * See #cairo_extend_t for details on the semantics of each extend - * strategy. - * - * The default extend mode is %CAIRO_EXTEND_NONE for surface patterns - * and %CAIRO_EXTEND_PAD for gradient patterns. - **/ -void -cairo_pattern_set_extend (cairo_pattern_t *pattern, cairo_extend_t extend) -{ - if (pattern->status) - return; - - pattern->extend = extend; -} - -/** - * cairo_pattern_get_extend: - * @pattern: a #cairo_pattern_t - * - * Gets the current extend mode for a pattern. See #cairo_extend_t - * for details on the semantics of each extend strategy. - * - * Return value: the current extend strategy used for drawing the - * pattern. - **/ -cairo_extend_t -cairo_pattern_get_extend (cairo_pattern_t *pattern) -{ - return pattern->extend; -} -slim_hidden_def (cairo_pattern_get_extend); - -void -_cairo_pattern_transform (cairo_pattern_t *pattern, - const cairo_matrix_t *ctm_inverse) -{ - if (pattern->status) - return; - - cairo_matrix_multiply (&pattern->matrix, ctm_inverse, &pattern->matrix); -} - -static void -_cairo_linear_pattern_classify (cairo_linear_pattern_t *pattern, - double offset_x, - double offset_y, - int width, - int height, - cairo_bool_t *is_horizontal, - cairo_bool_t *is_vertical) -{ - cairo_point_double_t point0, point1; - double a, b, c, d, tx, ty; - double scale, start, dx, dy; - cairo_fixed_t factors[3]; - int i; - - /* To classify a pattern as horizontal or vertical, we first - * compute the (fixed point) factors at the corners of the - * pattern. We actually only need 3/4 corners, so we skip the - * fourth. - */ - point0.x = _cairo_fixed_to_double (pattern->p1.x); - point0.y = _cairo_fixed_to_double (pattern->p1.y); - point1.x = _cairo_fixed_to_double (pattern->p2.x); - point1.y = _cairo_fixed_to_double (pattern->p2.y); - - _cairo_matrix_get_affine (&pattern->base.base.matrix, - &a, &b, &c, &d, &tx, &ty); - - dx = point1.x - point0.x; - dy = point1.y - point0.y; - scale = dx * dx + dy * dy; - scale = (scale) ? 1.0 / scale : 1.0; - - start = dx * point0.x + dy * point0.y; - - for (i = 0; i < 3; i++) { - double qx_device = (i % 2) * (width - 1) + offset_x; - double qy_device = (i / 2) * (height - 1) + offset_y; - - /* transform fragment into pattern space */ - double qx = a * qx_device + c * qy_device + tx; - double qy = b * qx_device + d * qy_device + ty; - - factors[i] = _cairo_fixed_from_double (((dx * qx + dy * qy) - start) * scale); - } - - /* We consider a pattern to be vertical if the fixed point factor - * at the two upper corners is the same. We could accept a small - * change, but determining what change is acceptable would require - * sorting the stops in the pattern and looking at the differences. - * - * Horizontal works the same way with the two left corners. - */ - - *is_vertical = factors[1] == factors[0]; - *is_horizontal = factors[2] == factors[0]; -} - -static cairo_int_status_t -_cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern, - cairo_surface_t *dst, - int x, - int y, - unsigned int width, - unsigned int height, - cairo_surface_t **out, - cairo_surface_attributes_t *attr) -{ - cairo_image_surface_t *image; - pixman_image_t *pixman_image; - pixman_transform_t pixman_transform; - cairo_status_t status; - cairo_bool_t repeat = FALSE; - - pixman_gradient_stop_t pixman_stops_static[2]; - pixman_gradient_stop_t *pixman_stops = pixman_stops_static; - unsigned int i; - int clone_offset_x, clone_offset_y; - cairo_matrix_t matrix = pattern->base.matrix; - - if (pattern->n_stops > ARRAY_LENGTH(pixman_stops_static)) { - pixman_stops = _cairo_malloc_ab (pattern->n_stops, sizeof(pixman_gradient_stop_t)); - if (pixman_stops == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - for (i = 0; i < pattern->n_stops; i++) { - pixman_stops[i].x = _cairo_fixed_16_16_from_double (pattern->stops[i].offset); - pixman_stops[i].color.red = pattern->stops[i].color.red_short; - pixman_stops[i].color.green = pattern->stops[i].color.green_short; - pixman_stops[i].color.blue = pattern->stops[i].color.blue_short; - pixman_stops[i].color.alpha = pattern->stops[i].color.alpha_short; - } - - if (pattern->base.type == CAIRO_PATTERN_TYPE_LINEAR) - { - cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) pattern; - pixman_point_fixed_t p1, p2; - cairo_fixed_t xdim, ydim; - - xdim = linear->p2.x - linear->p1.x; - ydim = linear->p2.y - linear->p1.y; - - /* - * Transform the matrix to avoid overflow when converting between - * cairo_fixed_t and pixman_fixed_t (without incurring performance - * loss when the transformation is unnecessary). - * - * XXX: Consider converting out-of-range co-ordinates and transforms. - * Having a function to compute the required transformation to - * "normalize" a given bounding box would be generally useful - - * cf linear patterns, gradient patterns, surface patterns... - */ -#define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */ - if (_cairo_fixed_integer_ceil (xdim) > PIXMAN_MAX_INT || - _cairo_fixed_integer_ceil (ydim) > PIXMAN_MAX_INT) - { - double sf; - - if (xdim > ydim) - sf = PIXMAN_MAX_INT / _cairo_fixed_to_double (xdim); - else - sf = PIXMAN_MAX_INT / _cairo_fixed_to_double (ydim); - - p1.x = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p1.x) * sf); - p1.y = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p1.y) * sf); - p2.x = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p2.x) * sf); - p2.y = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p2.y) * sf); - - cairo_matrix_scale (&matrix, sf, sf); - } - else - { - p1.x = _cairo_fixed_to_16_16 (linear->p1.x); - p1.y = _cairo_fixed_to_16_16 (linear->p1.y); - p2.x = _cairo_fixed_to_16_16 (linear->p2.x); - p2.y = _cairo_fixed_to_16_16 (linear->p2.y); - } - - pixman_image = pixman_image_create_linear_gradient (&p1, &p2, - pixman_stops, - pattern->n_stops); - } - else - { - cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) pattern; - pixman_point_fixed_t c1, c2; - pixman_fixed_t r1, r2; - - c1.x = _cairo_fixed_to_16_16 (radial->c1.x); - c1.y = _cairo_fixed_to_16_16 (radial->c1.y); - r1 = _cairo_fixed_to_16_16 (radial->r1); - - c2.x = _cairo_fixed_to_16_16 (radial->c2.x); - c2.y = _cairo_fixed_to_16_16 (radial->c2.y); - r2 = _cairo_fixed_to_16_16 (radial->r2); - - pixman_image = pixman_image_create_radial_gradient (&c1, &c2, - r1, r2, - pixman_stops, - pattern->n_stops); - } - - if (pixman_stops != pixman_stops_static) - free (pixman_stops); - - if (pixman_image == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - if (_cairo_surface_is_image (dst)) - { - image = (cairo_image_surface_t *) - _cairo_image_surface_create_for_pixman_image (pixman_image, - PIXMAN_a8r8g8b8); - if (image->base.status) - { - pixman_image_unref (pixman_image); - return image->base.status; - } - - attr->x_offset = attr->y_offset = 0; - attr->matrix = matrix; - attr->extend = pattern->base.extend; - attr->filter = CAIRO_FILTER_NEAREST; - attr->acquired = FALSE; - - *out = &image->base; - - return CAIRO_STATUS_SUCCESS; - } - - if (pattern->base.type == CAIRO_PATTERN_TYPE_LINEAR) { - cairo_bool_t is_horizontal; - cairo_bool_t is_vertical; - - _cairo_linear_pattern_classify ((cairo_linear_pattern_t *)pattern, - x, y, width, height, - &is_horizontal, &is_vertical); - if (is_horizontal) { - height = 1; - repeat = TRUE; - } - /* width-1 repeating patterns are quite slow with scan-line based - * compositing code, so we use a wider strip and spend some extra - * expense in computing the gradient. It's possible that for narrow - * gradients we'd be better off using a 2 or 4 pixel strip; the - * wider the gradient, the more it's worth spending extra time - * computing a sample. - */ - if (is_vertical && width > 8) { - width = 8; - repeat = TRUE; - } - } - - if (! pixman_image_set_filter (pixman_image, PIXMAN_FILTER_BILINEAR, - NULL, 0)) - { - pixman_image_unref (pixman_image); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - image = (cairo_image_surface_t *) - cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); - if (image->base.status) { - pixman_image_unref (pixman_image); - return image->base.status; - } - - _cairo_matrix_to_pixman_matrix (&matrix, &pixman_transform); - if (!pixman_image_set_transform (pixman_image, &pixman_transform)) { - cairo_surface_destroy (&image->base); - pixman_image_unref (pixman_image); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - switch (pattern->base.extend) { - case CAIRO_EXTEND_NONE: - pixman_image_set_repeat (pixman_image, PIXMAN_REPEAT_NONE); - break; - case CAIRO_EXTEND_REPEAT: - pixman_image_set_repeat (pixman_image, PIXMAN_REPEAT_NORMAL); - break; - case CAIRO_EXTEND_REFLECT: - pixman_image_set_repeat (pixman_image, PIXMAN_REPEAT_REFLECT); - break; - case CAIRO_EXTEND_PAD: - pixman_image_set_repeat (pixman_image, PIXMAN_REPEAT_PAD); - break; - } - - pixman_image_composite (PIXMAN_OP_SRC, - pixman_image, - NULL, - image->pixman_image, - x, y, - 0, 0, - 0, 0, - width, height); - - pixman_image_unref (pixman_image); - - status = _cairo_surface_clone_similar (dst, &image->base, - 0, 0, width, height, - &clone_offset_x, - &clone_offset_y, - out); - - cairo_surface_destroy (&image->base); - - attr->x_offset = -x; - attr->y_offset = -y; - cairo_matrix_init_identity (&attr->matrix); - attr->extend = repeat ? CAIRO_EXTEND_REPEAT : CAIRO_EXTEND_NONE; - attr->filter = CAIRO_FILTER_NEAREST; - attr->acquired = FALSE; - - return status; -} - -/* We maintain a small cache here, because we don't want to constantly - * recreate surfaces for simple solid colors. */ -#define MAX_SURFACE_CACHE_SIZE 16 -static struct { - struct _cairo_pattern_solid_surface_cache{ - cairo_content_t content; - cairo_color_t color; - cairo_surface_t *surface; - } cache[MAX_SURFACE_CACHE_SIZE]; - int size; -} solid_surface_cache; - -static cairo_bool_t -_cairo_pattern_solid_surface_matches ( - const struct _cairo_pattern_solid_surface_cache *cache, - const cairo_solid_pattern_t *pattern, - cairo_surface_t *dst) -{ - if (cache->content != pattern->content) - return FALSE; - - if (CAIRO_REFERENCE_COUNT_GET_VALUE (&cache->surface->ref_count) != 1) - return FALSE; - - if (! _cairo_surface_is_similar (cache->surface, dst, pattern->content)) - return FALSE; - - return TRUE; -} - -static cairo_bool_t -_cairo_pattern_solid_surface_matches_color ( - const struct _cairo_pattern_solid_surface_cache *cache, - const cairo_solid_pattern_t *pattern, - cairo_surface_t *dst) -{ - if (! _cairo_color_equal (&cache->color, &pattern->color)) - return FALSE; - - return _cairo_pattern_solid_surface_matches (cache, pattern, dst); -} - -static cairo_int_status_t -_cairo_pattern_acquire_surface_for_solid (cairo_solid_pattern_t *pattern, - cairo_surface_t *dst, - int x, - int y, - unsigned int width, - unsigned int height, - cairo_surface_t **out, - cairo_surface_attributes_t *attribs) -{ - static int i; - - cairo_surface_t *surface, *to_destroy = NULL; - cairo_status_t status; - - CAIRO_MUTEX_LOCK (_cairo_pattern_solid_surface_cache_lock); - - /* Check cache first */ - if (i < solid_surface_cache.size && - _cairo_pattern_solid_surface_matches_color (&solid_surface_cache.cache[i], - pattern, - dst)) - { - status = _cairo_surface_reset (solid_surface_cache.cache[i].surface); - if (status) - goto UNLOCK; - - goto DONE; - } - - for (i = 0 ; i < solid_surface_cache.size; i++) { - if (_cairo_pattern_solid_surface_matches_color (&solid_surface_cache.cache[i], - pattern, - dst)) - { - status = _cairo_surface_reset (solid_surface_cache.cache[i].surface); - if (status) - goto UNLOCK; - - goto DONE; - } - } - - /* Choose a surface to repaint/evict */ - surface = NULL; - if (solid_surface_cache.size == MAX_SURFACE_CACHE_SIZE) { - i = rand () % MAX_SURFACE_CACHE_SIZE; - surface = solid_surface_cache.cache[i].surface; - - if (_cairo_pattern_solid_surface_matches (&solid_surface_cache.cache[i], - pattern, - dst)) - { - /* Reuse the surface instead of evicting */ - - status = _cairo_surface_reset (surface); - if (status) - goto EVICT; - - status = _cairo_surface_repaint_solid_pattern_surface (dst, surface, pattern); - if (status) - goto EVICT; - - cairo_surface_reference (surface); - } - else - { - EVICT: - surface = NULL; - } - } - - if (surface == NULL) { - /* Not cached, need to create new */ - surface = _cairo_surface_create_solid_pattern_surface (dst, pattern); - if (surface->status) { - status = surface->status; - goto UNLOCK; - } - - if (! _cairo_surface_is_similar (surface, dst, pattern->content)) { - /* in the rare event of a substitute surface being returned (e.g. - * malloc failure) don't cache the fallback surface */ - *out = surface; - goto NOCACHE; - } - } - - if (i == solid_surface_cache.size) - solid_surface_cache.size++; - - to_destroy = solid_surface_cache.cache[i].surface; - solid_surface_cache.cache[i].surface = surface; - solid_surface_cache.cache[i].color = pattern->color; - solid_surface_cache.cache[i].content = pattern->content; - -DONE: - *out = cairo_surface_reference (solid_surface_cache.cache[i].surface); - -NOCACHE: - attribs->x_offset = attribs->y_offset = 0; - cairo_matrix_init_identity (&attribs->matrix); - attribs->extend = CAIRO_EXTEND_REPEAT; - attribs->filter = CAIRO_FILTER_NEAREST; - attribs->acquired = FALSE; - - status = CAIRO_STATUS_SUCCESS; - -UNLOCK: - CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_surface_cache_lock); - - if (to_destroy) - cairo_surface_destroy (to_destroy); - - return status; -} - -static void -_cairo_pattern_reset_solid_surface_cache (void) -{ - CAIRO_MUTEX_LOCK (_cairo_pattern_solid_surface_cache_lock); - - /* remove surfaces starting from the end so that solid_surface_cache.cache - * is always in a consistent state when we release the mutex. */ - while (solid_surface_cache.size) { - cairo_surface_t *surface; - - solid_surface_cache.size--; - surface = solid_surface_cache.cache[solid_surface_cache.size].surface; - solid_surface_cache.cache[solid_surface_cache.size].surface = NULL; - - /* release the lock to avoid the possibility of a recursive - * deadlock when the scaled font destroy closure gets called */ - CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_surface_cache_lock); - cairo_surface_destroy (surface); - CAIRO_MUTEX_LOCK (_cairo_pattern_solid_surface_cache_lock); - } - - CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_surface_cache_lock); -} - -/** - * _cairo_pattern_is_opaque_solid - * - * Convenience function to determine whether a pattern is an opaque - * (alpha==1.0) solid color pattern. This is done by testing whether - * the pattern's alpha value when converted to a byte is 255, so if a - * backend actually supported deep alpha channels this function might - * not do the right thing. - * - * Return value: %TRUE if the pattern is an opaque, solid color. - **/ -cairo_bool_t -_cairo_pattern_is_opaque_solid (const cairo_pattern_t *pattern) -{ - cairo_solid_pattern_t *solid; - - if (pattern->type != CAIRO_PATTERN_TYPE_SOLID) - return FALSE; - - solid = (cairo_solid_pattern_t *) pattern; - - return CAIRO_COLOR_IS_OPAQUE (&solid->color); -} - -static cairo_bool_t -_gradient_is_opaque (const cairo_gradient_pattern_t *gradient) -{ - unsigned int i; - - for (i = 0; i < gradient->n_stops; i++) - if (! CAIRO_COLOR_IS_OPAQUE (&gradient->stops[i].color)) - return FALSE; - - return TRUE; -} - -/** - * _cairo_pattern_is_opaque - * - * Convenience function to determine whether a pattern is an opaque - * pattern (of any type). The same caveats that apply to - * _cairo_pattern_is_opaque_solid apply here as well. - * - * Return value: %TRUE if the pattern is a opaque. - **/ -cairo_bool_t -_cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern) -{ - const cairo_pattern_union_t *pattern; - - pattern = (cairo_pattern_union_t *) abstract_pattern; - switch (pattern->base.type) { - case CAIRO_PATTERN_TYPE_SOLID: - return _cairo_pattern_is_opaque_solid (abstract_pattern); - case CAIRO_PATTERN_TYPE_SURFACE: - return cairo_surface_get_content (pattern->surface.surface) == CAIRO_CONTENT_COLOR; - case CAIRO_PATTERN_TYPE_LINEAR: - case CAIRO_PATTERN_TYPE_RADIAL: - return _gradient_is_opaque (&pattern->gradient.base); - } - - ASSERT_NOT_REACHED; - 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) - */ -static cairo_filter_t -_cairo_pattern_analyze_filter (cairo_surface_pattern_t *pattern, - double *pad_out) -{ - double pad; - cairo_filter_t optimized_filter; - - switch (pattern->base.filter) { - case CAIRO_FILTER_GOOD: - case CAIRO_FILTER_BEST: - case CAIRO_FILTER_BILINEAR: - /* 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->base.matrix)) { - pad = 0.; - optimized_filter = 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... - */ - pad = 0.5; - optimized_filter = pattern->base.filter; - } - break; - - case CAIRO_FILTER_FAST: - case CAIRO_FILTER_NEAREST: - case CAIRO_FILTER_GAUSSIAN: - default: - pad = 0.; - optimized_filter = pattern->base.filter; - break; - } - - if (pad_out) - *pad_out = pad; - - return optimized_filter; -} - - -static double -_pixman_nearest_sample (double d) -{ - return ceil (d - .5); -} - -static cairo_int_status_t -_cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern, - cairo_surface_t *dst, - int x, - int y, - unsigned int width, - unsigned int height, - cairo_surface_t **out, - cairo_surface_attributes_t *attr) -{ - cairo_int_status_t status; - int tx, ty; - double pad; - - attr->acquired = FALSE; - - attr->extend = pattern->base.extend; - attr->filter = _cairo_pattern_analyze_filter (pattern, &pad); - - if (_cairo_matrix_is_integer_translation (&pattern->base.matrix, - &tx, &ty)) - { - cairo_matrix_init_identity (&attr->matrix); - attr->x_offset = tx; - attr->y_offset = ty; - } - else if (attr->filter == CAIRO_FILTER_NEAREST) - { - /* - * For NEAREST, we can remove the fractional translation component - * from the transformation - this ensures that the pattern will always - * hit fast-paths in the backends for simple transformations that - * become (almost) identity, without loss of quality. - */ - attr->matrix = pattern->base.matrix; - attr->matrix.x0 = 0; - attr->matrix.y0 = 0; - if (_cairo_matrix_is_pixel_exact (&attr->matrix)) { - /* The rounding here is rather peculiar as it needs to match the - * rounding performed on the sample coordinate used by pixman. - */ - attr->matrix.x0 = _pixman_nearest_sample (pattern->base.matrix.x0); - attr->matrix.y0 = _pixman_nearest_sample (pattern->base.matrix.y0); - } else { - attr->matrix.x0 = pattern->base.matrix.x0; - attr->matrix.y0 = pattern->base.matrix.y0; - } - - attr->x_offset = attr->y_offset = 0; - tx = ty = 0; - } - else - { - attr->matrix = pattern->base.matrix; - attr->x_offset = attr->y_offset = 0; - tx = 0; - ty = 0; - } - - /* XXX: Hack: - * - * The way we currently support CAIRO_EXTEND_REFLECT is to create - * an image twice bigger on each side, and create a pattern of four - * images such that the new image, when repeated, has the same effect - * of reflecting the original pattern. - * - * This is because the reflect support in pixman is broken and we - * pass repeat instead of reflect to pixman. See - * _cairo_image_surface_set_attributes() for that. - */ - if (attr->extend == CAIRO_EXTEND_REFLECT) { - cairo_t *cr; - int w,h; - - cairo_rectangle_int_t extents; - status = _cairo_surface_get_extents (pattern->surface, &extents); - if (status) - return status; - - attr->extend = CAIRO_EXTEND_REPEAT; - - /* TODO: Instead of rendering pattern->surface four times to - * out, we should first copy pattern->surface to surface similar - * to dst and then copy that four times to out. This may cause - * an extra copy in the case of image destination, but for X servers, - * this will send pattern->surface just once over the wire instead - * of current four. - */ - x = extents.x; - y = extents.y; - w = 2 * extents.width; - h = 2 * extents.height; - - *out = cairo_surface_create_similar (dst, dst->content, w, h); - status = cairo_surface_status (*out); - if (status) { - cairo_surface_destroy (*out); - *out = NULL; - return status; - } - - (*out)->device_transform = pattern->surface->device_transform; - (*out)->device_transform_inverse = pattern->surface->device_transform_inverse; - - cr = cairo_create (*out); - - cairo_set_source_surface (cr, pattern->surface, -x, -y); - cairo_paint (cr); - - cairo_scale (cr, -1, +1); - cairo_set_source_surface (cr, pattern->surface, x-w, -y); - cairo_paint (cr); - - cairo_scale (cr, +1, -1); - cairo_set_source_surface (cr, pattern->surface, x-w, y-h); - cairo_paint (cr); - - cairo_scale (cr, -1, +1); - cairo_set_source_surface (cr, pattern->surface, -x, y-h); - cairo_paint (cr); - - status = cairo_status (cr); - cairo_destroy (cr); - - if (status) { - cairo_surface_destroy (*out); - *out = NULL; - } - - return status; - } - - if (_cairo_surface_is_image (dst)) { - cairo_image_surface_t *image; - - status = _cairo_surface_acquire_source_image (pattern->surface, - &image, - &attr->extra); - if (status) - return status; - - *out = &image->base; - attr->acquired = TRUE; - } else { - cairo_rectangle_int_t extents; - cairo_bool_t is_empty; - - status = _cairo_surface_get_extents (pattern->surface, &extents); - if (status) - return status; - - /* If we're repeating, we just play it safe and clone the - * entire surface - i.e. we use the existing extents. - */ - if (attr->extend != CAIRO_EXTEND_REPEAT) { - cairo_rectangle_int_t sampled_area; - - /* Otherwise, we first transform the rectangle to the - * coordinate space of the source surface so that we can - * clone only that portion of the surface that will be - * read. - */ - if (_cairo_matrix_is_identity (&attr->matrix)) { - sampled_area.x = x; - sampled_area.y = y; - sampled_area.width = width; - sampled_area.height = height; - } else { - double x1 = x; - double y1 = y; - double x2 = x + (int) width; - double y2 = y + (int) height; - - _cairo_matrix_transform_bounding_box (&attr->matrix, - &x1, &y1, &x2, &y2, - NULL); - - sampled_area.x = floor (x1 - pad); - sampled_area.y = floor (y1 - pad); - sampled_area.width = ceil (x2 + pad) - sampled_area.x; - sampled_area.height = ceil (y2 + pad) - sampled_area.y; - - } - - sampled_area.x += tx; - sampled_area.y += ty; - - /* Never acquire a larger area than the source itself */ - is_empty = _cairo_rectangle_intersect (&extents, &sampled_area); - } - - /* XXX can we use is_empty? */ - - status = _cairo_surface_clone_similar (dst, pattern->surface, - extents.x, extents.y, - extents.width, extents.height, - &x, &y, out); - if (status == CAIRO_STATUS_SUCCESS && (x != 0 || y != 0)) { - if (_cairo_matrix_is_identity (&attr->matrix)) { - attr->x_offset -= x; - attr->y_offset -= y; - } else { - cairo_matrix_t m; - - x -= attr->x_offset; - y -= attr->y_offset; - attr->x_offset = 0; - attr->y_offset = 0; - - cairo_matrix_init_translate (&m, -x, -y); - cairo_matrix_multiply (&attr->matrix, &attr->matrix, &m); - } - } - } - - return status; -} - -/** - * _cairo_pattern_acquire_surface: - * @pattern: a #cairo_pattern_t - * @dst: destination surface - * @x: X coordinate in source corresponding to left side of destination area - * @y: Y coordinate in source corresponding to top side of destination area - * @width: width of destination area - * @height: height of destination area - * @surface_out: location to store a pointer to a surface - * @attributes: surface attributes that destination backend should apply to - * the returned surface - * - * A convenience function to obtain a surface to use as the source for - * drawing on @dst. - * - * Note that this function is only suitable for use when the destination - * surface is pixel based and 1 device unit maps to one pixel. - * - * Return value: %CAIRO_STATUS_SUCCESS if a surface was stored in @surface_out. - **/ -cairo_int_status_t -_cairo_pattern_acquire_surface (cairo_pattern_t *pattern, - cairo_surface_t *dst, - int x, - int y, - unsigned int width, - unsigned int height, - cairo_surface_t **surface_out, - cairo_surface_attributes_t *attributes) -{ - cairo_status_t status; - - if (pattern->status) { - *surface_out = NULL; - attributes->acquired = FALSE; - return pattern->status; - } - - switch (pattern->type) { - case CAIRO_PATTERN_TYPE_SOLID: { - cairo_solid_pattern_t *src = (cairo_solid_pattern_t *) pattern; - - status = _cairo_pattern_acquire_surface_for_solid (src, dst, - x, y, width, height, - surface_out, - attributes); - } break; - case CAIRO_PATTERN_TYPE_LINEAR: - case CAIRO_PATTERN_TYPE_RADIAL: { - cairo_gradient_pattern_t *src = (cairo_gradient_pattern_t *) pattern; - - /* fast path for gradients with less than 2 color stops */ - if (src->n_stops < 2) - { - cairo_solid_pattern_t solid; - - if (src->n_stops) - { - cairo_color_t color; - - _cairo_color_init_rgba (&color, - src->stops->color.red, - src->stops->color.green, - src->stops->color.blue, - src->stops->color.alpha); - - _cairo_pattern_init_solid (&solid, &color, CAIRO_CONTENT_COLOR_ALPHA); - } - else - { - _cairo_pattern_init_solid (&solid, CAIRO_COLOR_TRANSPARENT, CAIRO_CONTENT_ALPHA); - } - - status = _cairo_pattern_acquire_surface_for_solid (&solid, dst, - x, y, - width, height, - surface_out, - attributes); - } - else - { - status = _cairo_pattern_acquire_surface_for_gradient (src, dst, - x, y, - width, height, - surface_out, - attributes); - } - } break; - case CAIRO_PATTERN_TYPE_SURFACE: { - cairo_surface_pattern_t *src = (cairo_surface_pattern_t *) pattern; - - status = _cairo_pattern_acquire_surface_for_surface (src, dst, - x, y, width, height, - surface_out, - attributes); - } break; - default: - ASSERT_NOT_REACHED; - status = _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH); - } - - return status; -} - -/** - * _cairo_pattern_release_surface: - * @pattern: a #cairo_pattern_t - * @surface: a surface obtained by _cairo_pattern_acquire_surface - * @attributes: attributes obtained by _cairo_pattern_acquire_surface - * - * Releases resources obtained by _cairo_pattern_acquire_surface. - **/ -void -_cairo_pattern_release_surface (cairo_pattern_t *pattern, - cairo_surface_t *surface, - cairo_surface_attributes_t *attributes) -{ - if (attributes->acquired) - { - cairo_surface_pattern_t *surface_pattern; - - assert (pattern->type == CAIRO_PATTERN_TYPE_SURFACE); - surface_pattern = (cairo_surface_pattern_t *) pattern; - - _cairo_surface_release_source_image (surface_pattern->surface, - (cairo_image_surface_t *) surface, - attributes->extra); - } - else - { - cairo_surface_destroy (surface); - } -} - -cairo_int_status_t -_cairo_pattern_acquire_surfaces (cairo_pattern_t *src, - cairo_pattern_t *mask, - cairo_surface_t *dst, - int src_x, - int src_y, - int mask_x, - int mask_y, - unsigned int width, - unsigned int height, - cairo_surface_t **src_out, - cairo_surface_t **mask_out, - cairo_surface_attributes_t *src_attributes, - cairo_surface_attributes_t *mask_attributes) -{ - cairo_int_status_t status; - cairo_pattern_union_t src_tmp, mask_tmp; - - if (src->status) - return src->status; - if (mask && mask->status) - return mask->status; - - /* If src and mask are both solid, then the mask alpha can be - * combined into src and mask can be ignored. */ - - /* XXX: This optimization assumes that there is no color - * information in mask, so this will need to change when we - * support RENDER-style 4-channel masks. */ - if (src->type == CAIRO_PATTERN_TYPE_SOLID && - mask && mask->type == CAIRO_PATTERN_TYPE_SOLID) - { - cairo_color_t combined; - cairo_solid_pattern_t *src_solid = (cairo_solid_pattern_t *) src; - cairo_solid_pattern_t *mask_solid = (cairo_solid_pattern_t *) mask; - - combined = src_solid->color; - _cairo_color_multiply_alpha (&combined, mask_solid->color.alpha); - - _cairo_pattern_init_solid (&src_tmp.solid, &combined, CAIRO_CONTENT_COLOR_ALPHA); - - mask = NULL; - } - else - { - status = _cairo_pattern_init_copy (&src_tmp.base, src); - if (status) - return status; - } - - status = _cairo_pattern_acquire_surface (&src_tmp.base, dst, - src_x, src_y, - width, height, - src_out, src_attributes); - if (status) { - _cairo_pattern_fini (&src_tmp.base); - return status; - } - - if (mask == NULL) - { - _cairo_pattern_fini (&src_tmp.base); - *mask_out = NULL; - return CAIRO_STATUS_SUCCESS; - } - - status = _cairo_pattern_init_copy (&mask_tmp.base, mask); - if (status) - goto CLEANUP_SOURCE; - - status = _cairo_pattern_acquire_surface (&mask_tmp.base, dst, - mask_x, mask_y, - width, height, - mask_out, mask_attributes); - - _cairo_pattern_fini (&mask_tmp.base); - -CLEANUP_SOURCE: - if (status) - _cairo_pattern_release_surface (&src_tmp.base, - *src_out, src_attributes); - - _cairo_pattern_fini (&src_tmp.base); - - return status; -} - -/** - * _cairo_pattern_get_extents: - * - * Return the "target-space" extents of @pattern in @extents. - * - * For unbounded patterns, the @extents will be initialized with - * "infinite" extents, (minimum and maximum fixed-point values). - * - * XXX: Currently, bounded gradient patterns will also return - * "infinite" extents, though it would be possible to optimize these - * with a little more work. - **/ -cairo_status_t -_cairo_pattern_get_extents (cairo_pattern_t *pattern, - cairo_rectangle_int_t *extents) -{ - if (pattern->extend == CAIRO_EXTEND_NONE && - pattern->type == CAIRO_PATTERN_TYPE_SURFACE) - { - cairo_status_t status; - cairo_rectangle_int_t surface_extents; - cairo_surface_pattern_t *surface_pattern = - (cairo_surface_pattern_t *) pattern; - cairo_surface_t *surface = surface_pattern->surface; - cairo_matrix_t imatrix; - double x1, y1, x2, y2; - double pad; - - status = _cairo_surface_get_extents (surface, &surface_extents); - if (status) - return status; - - /* The filter can effectively enlarge the extents of the - * pattern, so extend as necessary. - */ - _cairo_pattern_analyze_filter (surface_pattern, &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; - - imatrix = pattern->matrix; - status = cairo_matrix_invert (&imatrix); - /* cairo_pattern_set_matrix ensures the matrix is invertible */ - assert (status == CAIRO_STATUS_SUCCESS); - - _cairo_matrix_transform_bounding_box (&imatrix, - &x1, &y1, &x2, &y2, - NULL); - - x1 = floor (x1); - 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); - if (x2 > CAIRO_RECT_INT_MAX) - x2 = CAIRO_RECT_INT_MAX; - y2 = ceil (y2); - if (y2 > CAIRO_RECT_INT_MAX) - y2 = CAIRO_RECT_INT_MAX; - - extents->x = x1; extents->width = x2 - x1; - extents->y = y1; extents->height = y2 - y1; - - return CAIRO_STATUS_SUCCESS; - } - - /* XXX: We could optimize gradients with pattern->extend of NONE - * here in some cases, (eg. radial gradients and 1 axis of - * horizontal/vertical linear gradients). - */ - - /* unbounded patterns -> 'infinite' extents */ - extents->x = CAIRO_RECT_INT_MIN; - extents->y = CAIRO_RECT_INT_MIN; - extents->width = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN; - extents->height = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN; - - return CAIRO_STATUS_SUCCESS; -} - -/** - * cairo_pattern_get_rgba - * @pattern: a #cairo_pattern_t - * @red: return value for red component of color, or %NULL - * @green: return value for green component of color, or %NULL - * @blue: return value for blue component of color, or %NULL - * @alpha: return value for alpha component of color, or %NULL - * - * Gets the solid color for a solid color pattern. - * - * Return value: %CAIRO_STATUS_SUCCESS, or - * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a solid - * color pattern. - * - * Since: 1.4 - **/ -cairo_status_t -cairo_pattern_get_rgba (cairo_pattern_t *pattern, - double *red, double *green, - double *blue, double *alpha) -{ - cairo_solid_pattern_t *solid = (cairo_solid_pattern_t*) pattern; - double r0, g0, b0, a0; - - if (pattern->type != CAIRO_PATTERN_TYPE_SOLID) - return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH); - - _cairo_color_get_rgba (&solid->color, &r0, &g0, &b0, &a0); - - if (red) - *red = r0; - if (green) - *green = g0; - if (blue) - *blue = b0; - if (alpha) - *alpha = a0; - - return CAIRO_STATUS_SUCCESS; -} - -/** - * 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. - * - * Return value: %CAIRO_STATUS_SUCCESS, or - * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a surface - * pattern. - * - * Since: 1.4 - **/ -cairo_status_t -cairo_pattern_get_surface (cairo_pattern_t *pattern, - cairo_surface_t **surface) -{ - cairo_surface_pattern_t *spat = (cairo_surface_pattern_t*) pattern; - - if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE) - return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH); - - if (surface) - *surface = spat->surface; - - return CAIRO_STATUS_SUCCESS; -} - -/** - * cairo_pattern_get_color_stop_rgba - * @pattern: a #cairo_pattern_t - * @index: index of the stop to return data for - * @offset: return value for the offset of the stop, or %NULL - * @red: return value for red component of color, or %NULL - * @green: return value for green component of color, or %NULL - * @blue: return value for blue component of color, or %NULL - * @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(). - * - * Return value: %CAIRO_STATUS_SUCCESS, or %CAIRO_STATUS_INVALID_INDEX - * if @index is not valid for the given pattern. If the pattern is - * not a gradient pattern, %CAIRO_STATUS_PATTERN_TYPE_MISMATCH is - * returned. - * - * Since: 1.4 - **/ -cairo_status_t -cairo_pattern_get_color_stop_rgba (cairo_pattern_t *pattern, - int index, double *offset, - double *red, double *green, - double *blue, double *alpha) -{ - cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t*) pattern; - - if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR && - pattern->type != CAIRO_PATTERN_TYPE_RADIAL) - return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH); - - if (index < 0 || (unsigned int) index >= gradient->n_stops) - return _cairo_error (CAIRO_STATUS_INVALID_INDEX); - - if (offset) - *offset = gradient->stops[index].offset; - if (red) - *red = gradient->stops[index].color.red; - if (green) - *green = gradient->stops[index].color.green; - if (blue) - *blue = gradient->stops[index].color.blue; - if (alpha) - *alpha = gradient->stops[index].color.alpha; - - return CAIRO_STATUS_SUCCESS; -} - -/** - * cairo_pattern_get_color_stop_count - * @pattern: a #cairo_pattern_t - * @count: return value for the number of color stops, or %NULL - * - * Gets the number of color stops specified in the given gradient - * pattern. - * - * Return value: %CAIRO_STATUS_SUCCESS, or - * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a gradient - * pattern. - * - * Since: 1.4 - */ -cairo_status_t -cairo_pattern_get_color_stop_count (cairo_pattern_t *pattern, - int *count) -{ - cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t*) pattern; - - if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR && - pattern->type != CAIRO_PATTERN_TYPE_RADIAL) - return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH); - - if (count) - *count = gradient->n_stops; - - return CAIRO_STATUS_SUCCESS; -} - -/** - * cairo_pattern_get_linear_points - * @pattern: a #cairo_pattern_t - * @x0: return value for the x coordinate of the first point, or %NULL - * @y0: return value for the y coordinate of the first point, or %NULL - * @x1: return value for the x coordinate of the second point, or %NULL - * @y1: return value for the y coordinate of the second point, or %NULL - * - * Gets the gradient endpoints for a linear gradient. - * - * Return value: %CAIRO_STATUS_SUCCESS, or - * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a linear - * gradient pattern. - * - * Since: 1.4 - **/ -cairo_status_t -cairo_pattern_get_linear_points (cairo_pattern_t *pattern, - double *x0, double *y0, - double *x1, double *y1) -{ - cairo_linear_pattern_t *linear = (cairo_linear_pattern_t*) pattern; - - if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR) - return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH); - - if (x0) - *x0 = _cairo_fixed_to_double (linear->p1.x); - if (y0) - *y0 = _cairo_fixed_to_double (linear->p1.y); - if (x1) - *x1 = _cairo_fixed_to_double (linear->p2.x); - if (y1) - *y1 = _cairo_fixed_to_double (linear->p2.y); - - return CAIRO_STATUS_SUCCESS; -} - -/** - * cairo_pattern_get_radial_circles - * @pattern: a #cairo_pattern_t - * @x0: return value for the x coordinate of the center of the first circle, or %NULL - * @y0: return value for the y coordinate of the center of the first circle, or %NULL - * @r0: return value for the radius of the first circle, or %NULL - * @x1: return value for the x coordinate of the center of the second circle, or %NULL - * @y1: return value for the y coordinate of the center of the second circle, or %NULL - * @r1: return value for the radius of the second circle, or %NULL - * - * Gets the gradient endpoint circles for a radial gradient, each - * specified as a center coordinate and a radius. - * - * Return value: %CAIRO_STATUS_SUCCESS, or - * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a radial - * gradient pattern. - * - * Since: 1.4 - **/ -cairo_status_t -cairo_pattern_get_radial_circles (cairo_pattern_t *pattern, - double *x0, double *y0, double *r0, - double *x1, double *y1, double *r1) -{ - cairo_radial_pattern_t *radial = (cairo_radial_pattern_t*) pattern; - - if (pattern->type != CAIRO_PATTERN_TYPE_RADIAL) - return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH); - - if (x0) - *x0 = _cairo_fixed_to_double (radial->c1.x); - if (y0) - *y0 = _cairo_fixed_to_double (radial->c1.y); - if (r0) - *r0 = _cairo_fixed_to_double (radial->r1); - if (x1) - *x1 = _cairo_fixed_to_double (radial->c2.x); - if (y1) - *y1 = _cairo_fixed_to_double (radial->c2.y); - if (r1) - *r1 = _cairo_fixed_to_double (radial->r2); - - return CAIRO_STATUS_SUCCESS; -} - -void -_cairo_pattern_reset_static_data (void) -{ - _cairo_pattern_reset_solid_pattern_cache (); - _cairo_pattern_reset_solid_surface_cache (); -} diff --git a/uppdev/plugin/cairo/lib/cairo-pdf-operators-private.h b/uppdev/plugin/cairo/lib/cairo-pdf-operators-private.h deleted file mode 100644 index 7ff843b1e..000000000 --- a/uppdev/plugin/cairo/lib/cairo-pdf-operators-private.h +++ /dev/null @@ -1,165 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2004 Red Hat, Inc - * Copyright © 2006 Red Hat, Inc - * Copyright © 2007 Adrian Johnson - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Kristian Høgsberg - * Carl Worth - * Adrian Johnson - */ - -#ifndef CAIRO_PDF_OPERATORS_H -#define CAIRO_PDF_OPERATORS_H - -#include "cairo-compiler-private.h" -#include "cairo-types-private.h" - -/* The glyph buffer size is based on the expected maximum glyphs in a - * line so that an entire line can be emitted in as one string. If the - * glyphs in a line exceeds this size the only downside is the slight - * overhead of emitting two strings. - */ -#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 struct _cairo_pdf_glyph { - unsigned int glyph_index; - double x_position; - double x_advance; -} cairo_pdf_glyph_t; - -typedef struct _cairo_pdf_operators { - cairo_output_stream_t *stream; - cairo_matrix_t cairo_to_pdf; - 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 in_text_object; /* inside BT/ET pair */ - - /* PDF text state */ - cairo_bool_t is_new_text_object; /* text object started but matrix and font not yet selected */ - unsigned int font_id; - unsigned int subset_id; - cairo_matrix_t text_matrix; /* PDF text matrix (Tlm in the PDF reference) */ - cairo_matrix_t cairo_to_pdftext; /* translate cairo coords to PDF text space */ - cairo_matrix_t font_matrix_inverse; - double cur_x; /* Current position in PDF text space (Tm in the PDF reference) */ - double cur_y; - int hex_width; - int num_glyphs; - cairo_pdf_glyph_t glyphs[PDF_GLYPH_BUFFER_SIZE]; - - /* PDF line style */ - cairo_bool_t has_line_style; - double line_width; - cairo_line_cap_t line_cap; - cairo_line_join_t line_join; - double miter_limit; - cairo_bool_t has_dashes; -} cairo_pdf_operators_t; - -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_private cairo_status_t -_cairo_pdf_operators_fini (cairo_pdf_operators_t *pdf_operators); - -cairo_private void -_cairo_pdf_operators_set_font_subsets_callback (cairo_pdf_operators_t *pdf_operators, - cairo_pdf_operators_use_font_subset_t use_font_subset, - void *closure); - -cairo_private void -_cairo_pdf_operators_set_stream (cairo_pdf_operators_t *pdf_operators, - cairo_output_stream_t *stream); - - -cairo_private void -_cairo_pdf_operators_set_cairo_to_pdf_matrix (cairo_pdf_operators_t *pdf_operators, - cairo_matrix_t *cairo_to_pdf); - -cairo_private cairo_status_t -_cairo_pdf_operators_flush (cairo_pdf_operators_t *pdf_operators); - -cairo_private void -_cairo_pdf_operators_reset (cairo_pdf_operators_t *pdf_operators); - -cairo_private cairo_int_status_t -_cairo_pdf_operators_clip (cairo_pdf_operators_t *pdf_operators, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule); - -cairo_private cairo_int_status_t -_cairo_pdf_operators_emit_stroke_style (cairo_pdf_operators_t *pdf_operators, - cairo_stroke_style_t *style, - double scale); - -cairo_private cairo_int_status_t -_cairo_pdf_operators_stroke (cairo_pdf_operators_t *pdf_operators, - cairo_path_fixed_t *path, - cairo_stroke_style_t *style, - cairo_matrix_t *ctm, - cairo_matrix_t *ctm_inverse); - -cairo_private cairo_int_status_t -_cairo_pdf_operators_fill (cairo_pdf_operators_t *pdf_operators, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule); - -cairo_private cairo_int_status_t -_cairo_pdf_operators_fill_stroke (cairo_pdf_operators_t *pdf_operators, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - cairo_stroke_style_t *style, - cairo_matrix_t *ctm, - cairo_matrix_t *ctm_inverse); - -cairo_private cairo_int_status_t -_cairo_pdf_operators_show_text_glyphs (cairo_pdf_operators_t *pdf_operators, - const char *utf8, - int utf8_len, - cairo_glyph_t *glyphs, - int num_glyphs, - const cairo_text_cluster_t *clusters, - int num_clusters, - cairo_text_cluster_flags_t cluster_flags, - cairo_scaled_font_t *scaled_font); - -#endif /* CAIRO_PDF_OPERATORS_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-pdf-operators.c b/uppdev/plugin/cairo/lib/cairo-pdf-operators.c deleted file mode 100644 index 819318a19..000000000 --- a/uppdev/plugin/cairo/lib/cairo-pdf-operators.c +++ /dev/null @@ -1,1450 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2004 Red Hat, Inc - * Copyright © 2006 Red Hat, Inc - * Copyright © 2007, 2008 Adrian Johnson - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Kristian Høgsberg - * Carl Worth - * Adrian Johnson - */ - -#include "cairoint.h" - -#if CAIRO_HAS_PDF_OPERATORS - -#include "cairo-pdf-operators-private.h" -#include "cairo-path-fixed-private.h" -#include "cairo-output-stream-private.h" -#include "cairo-scaled-font-subsets-private.h" - -#include - -static cairo_status_t -_cairo_pdf_operators_end_text (cairo_pdf_operators_t *pdf_operators); - - -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) -{ - pdf_operators->stream = stream; - pdf_operators->cairo_to_pdf = *cairo_to_pdf; - pdf_operators->font_subsets = font_subsets; - pdf_operators->use_font_subset = NULL; - pdf_operators->use_font_subset_closure = NULL; - pdf_operators->in_text_object = FALSE; - pdf_operators->num_glyphs = 0; - pdf_operators->has_line_style = FALSE; -} - -cairo_status_t -_cairo_pdf_operators_fini (cairo_pdf_operators_t *pdf_operators) -{ - return _cairo_pdf_operators_flush (pdf_operators); -} - -void -_cairo_pdf_operators_set_font_subsets_callback (cairo_pdf_operators_t *pdf_operators, - cairo_pdf_operators_use_font_subset_t use_font_subset, - void *closure) -{ - pdf_operators->use_font_subset = use_font_subset; - pdf_operators->use_font_subset_closure = closure; -} - -/* Change the output stream to a different stream. - * _cairo_pdf_operators_flush() should always be called before calling - * this function. - */ -void -_cairo_pdf_operators_set_stream (cairo_pdf_operators_t *pdf_operators, - cairo_output_stream_t *stream) -{ - pdf_operators->stream = stream; - pdf_operators->has_line_style = FALSE; -} - -void -_cairo_pdf_operators_set_cairo_to_pdf_matrix (cairo_pdf_operators_t *pdf_operators, - cairo_matrix_t *cairo_to_pdf) -{ - pdf_operators->cairo_to_pdf = *cairo_to_pdf; - pdf_operators->has_line_style = FALSE; -} - -/* Finish writing out any pending commands to the stream. This - * function must be called by the surface before emitting anything - * into the PDF stream. - * - * pdf_operators may leave the emitted PDF for some operations - * unfinished in case subsequent operations can be merged. This - * function will finish off any incomplete operation so the stream - * will be in a state where the surface may emit it's own PDF - * operations (eg changing patterns). - * - */ -cairo_status_t -_cairo_pdf_operators_flush (cairo_pdf_operators_t *pdf_operators) -{ - cairo_status_t status = CAIRO_STATUS_SUCCESS; - - if (pdf_operators->in_text_object) - status = _cairo_pdf_operators_end_text (pdf_operators); - - return status; -} - -/* Reset the known graphics state of the PDF consumer. ie no - * assumptions will be made about the state. The next time a - * particular graphics state is required (eg line width) the state - * operator is always emitted and then remembered for subsequent - * operatations. - * - * This should be called when starting a new stream or after emitting - * the 'Q' operator (where pdf-operators functions were called inside - * the q/Q pair). - */ -void -_cairo_pdf_operators_reset (cairo_pdf_operators_t *pdf_operators) -{ - pdf_operators->has_line_style = FALSE; -} - -/* A word wrap stream can be used as a filter to do word wrapping on - * top of an existing output stream. The word wrapping is quite - * simple, using isspace to determine characters that separate - * words. Any word that will cause the column count exceed the given - * max_column will have a '\n' character emitted before it. - * - * The stream is careful to maintain integrity for words that cross - * the boundary from one call to write to the next. - * - * Note: This stream does not guarantee that the output will never - * exceed max_column. In particular, if a single word is larger than - * max_column it will not be broken up. - */ -typedef struct _word_wrap_stream { - cairo_output_stream_t base; - cairo_output_stream_t *output; - int max_column; - int column; - cairo_bool_t last_write_was_space; - cairo_bool_t in_hexstring; - cairo_bool_t empty_hexstring; -} word_wrap_stream_t; - -static int -_count_word_up_to (const unsigned char *s, int length) -{ - int word = 0; - - while (length--) { - if (! (isspace (*s) || *s == '<')) { - s++; - word++; - } else { - return word; - } - } - - return word; -} - - -/* Count up to either the end of the ASCII hexstring or the number - * of columns remaining. - */ -static int -_count_hexstring_up_to (const unsigned char *s, int length, int columns) -{ - int word = 0; - - while (length--) { - if (*s++ != '>') - word++; - else - return word; - - columns--; - if (columns < 0 && word > 1) - return word; - } - - return word; -} - -static cairo_status_t -_word_wrap_stream_write (cairo_output_stream_t *base, - const unsigned char *data, - unsigned int length) -{ - word_wrap_stream_t *stream = (word_wrap_stream_t *) base; - cairo_bool_t newline; - int word; - - while (length) { - if (*data == '<') { - stream->in_hexstring = TRUE; - stream->empty_hexstring = TRUE; - stream->last_write_was_space = FALSE; - data++; - length--; - _cairo_output_stream_printf (stream->output, "<"); - stream->column++; - } else if (*data == '>') { - stream->in_hexstring = FALSE; - stream->last_write_was_space = FALSE; - data++; - length--; - _cairo_output_stream_printf (stream->output, ">"); - stream->column++; - } else if (isspace (*data)) { - newline = (*data == '\n' || *data == '\r'); - if (! newline && stream->column >= stream->max_column) { - _cairo_output_stream_printf (stream->output, "\n"); - stream->column = 0; - } - _cairo_output_stream_write (stream->output, data, 1); - data++; - length--; - if (newline) { - stream->column = 0; - } - else - stream->column++; - stream->last_write_was_space = TRUE; - } else { - if (stream->in_hexstring) { - word = _count_hexstring_up_to (data, length, - MAX (stream->max_column - stream->column, 0)); - } else { - word = _count_word_up_to (data, length); - } - /* Don't wrap if this word is a continuation of a non hex - * string word from a previous call to write. */ - if (stream->column + word >= stream->max_column) { - if (stream->last_write_was_space || - (stream->in_hexstring && !stream->empty_hexstring)) - { - _cairo_output_stream_printf (stream->output, "\n"); - stream->column = 0; - } - } - _cairo_output_stream_write (stream->output, data, word); - data += word; - length -= word; - stream->column += word; - stream->last_write_was_space = FALSE; - if (stream->in_hexstring) - stream->empty_hexstring = FALSE; - } - } - - return _cairo_output_stream_get_status (stream->output); -} - -static cairo_status_t -_word_wrap_stream_close (cairo_output_stream_t *base) -{ - word_wrap_stream_t *stream = (word_wrap_stream_t *) base; - - return _cairo_output_stream_get_status (stream->output); -} - -static cairo_output_stream_t * -_word_wrap_stream_create (cairo_output_stream_t *output, int max_column) -{ - word_wrap_stream_t *stream; - - if (output->status) - return _cairo_output_stream_create_in_error (output->status); - - stream = malloc (sizeof (word_wrap_stream_t)); - if (stream == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_output_stream_t *) &_cairo_output_stream_nil; - } - - _cairo_output_stream_init (&stream->base, - _word_wrap_stream_write, - _word_wrap_stream_close); - stream->output = output; - stream->max_column = max_column; - stream->column = 0; - stream->last_write_was_space = FALSE; - stream->in_hexstring = FALSE; - stream->empty_hexstring = TRUE; - - return &stream->base; -} - -typedef struct _pdf_path_info { - cairo_output_stream_t *output; - cairo_matrix_t *path_transform; - cairo_line_cap_t line_cap; - cairo_point_t last_move_to_point; - cairo_bool_t has_sub_path; -} pdf_path_info_t; - -static cairo_status_t -_cairo_pdf_path_move_to (void *closure, cairo_point_t *point) -{ - pdf_path_info_t *info = closure; - double x = _cairo_fixed_to_double (point->x); - double y = _cairo_fixed_to_double (point->y); - - info->last_move_to_point = *point; - info->has_sub_path = FALSE; - cairo_matrix_transform_point (info->path_transform, &x, &y); - _cairo_output_stream_printf (info->output, - "%g %g m ", x, y); - - return _cairo_output_stream_get_status (info->output); -} - -static cairo_status_t -_cairo_pdf_path_line_to (void *closure, cairo_point_t *point) -{ - pdf_path_info_t *info = closure; - double x = _cairo_fixed_to_double (point->x); - double y = _cairo_fixed_to_double (point->y); - - if (info->line_cap != CAIRO_LINE_CAP_ROUND && - ! info->has_sub_path && - point->x == info->last_move_to_point.x && - point->y == info->last_move_to_point.y) - { - return CAIRO_STATUS_SUCCESS; - } - - info->has_sub_path = TRUE; - cairo_matrix_transform_point (info->path_transform, &x, &y); - _cairo_output_stream_printf (info->output, - "%g %g l ", x, y); - - return _cairo_output_stream_get_status (info->output); -} - -static cairo_status_t -_cairo_pdf_path_curve_to (void *closure, - cairo_point_t *b, - cairo_point_t *c, - cairo_point_t *d) -{ - pdf_path_info_t *info = closure; - double bx = _cairo_fixed_to_double (b->x); - double by = _cairo_fixed_to_double (b->y); - double cx = _cairo_fixed_to_double (c->x); - double cy = _cairo_fixed_to_double (c->y); - double dx = _cairo_fixed_to_double (d->x); - double dy = _cairo_fixed_to_double (d->y); - - info->has_sub_path = TRUE; - cairo_matrix_transform_point (info->path_transform, &bx, &by); - cairo_matrix_transform_point (info->path_transform, &cx, &cy); - cairo_matrix_transform_point (info->path_transform, &dx, &dy); - _cairo_output_stream_printf (info->output, - "%g %g %g %g %g %g c ", - bx, by, cx, cy, dx, dy); - return _cairo_output_stream_get_status (info->output); -} - -static cairo_status_t -_cairo_pdf_path_close_path (void *closure) -{ - pdf_path_info_t *info = closure; - - if (info->line_cap != CAIRO_LINE_CAP_ROUND && - ! info->has_sub_path) - { - return CAIRO_STATUS_SUCCESS; - } - - _cairo_output_stream_printf (info->output, - "h\n"); - - return _cairo_output_stream_get_status (info->output); -} - -static cairo_status_t -_cairo_pdf_path_rectangle (pdf_path_info_t *info, cairo_box_t *box) -{ - double x1 = _cairo_fixed_to_double (box->p1.x); - double y1 = _cairo_fixed_to_double (box->p1.y); - double x2 = _cairo_fixed_to_double (box->p2.x); - double y2 = _cairo_fixed_to_double (box->p2.y); - - cairo_matrix_transform_point (info->path_transform, &x1, &y1); - cairo_matrix_transform_point (info->path_transform, &x2, &y2); - _cairo_output_stream_printf (info->output, - "%g %g %g %g re ", - x1, y1, x2 - x1, y2 - y1); - - return _cairo_output_stream_get_status (info->output); -} - -/* The line cap value is needed to workaround the fact that PostScript - * and PDF semantics for stroking degenerate sub-paths do not match - * cairo semantics. (PostScript draws something for any line cap - * value, while cairo draws something only for round caps). - * - * When using this function to emit a path to be filled, rather than - * stroked, simply pass %CAIRO_LINE_CAP_ROUND which will guarantee that - * the stroke workaround will not modify the path being emitted. - */ -static cairo_status_t -_cairo_pdf_operators_emit_path (cairo_pdf_operators_t *pdf_operators, - cairo_path_fixed_t *path, - cairo_matrix_t *path_transform, - cairo_line_cap_t line_cap) -{ - cairo_output_stream_t *word_wrap; - cairo_status_t status, status2; - pdf_path_info_t info; - cairo_box_t box; - - word_wrap = _word_wrap_stream_create (pdf_operators->stream, 72); - status = _cairo_output_stream_get_status (word_wrap); - if (status) - return _cairo_output_stream_destroy (word_wrap); - - info.output = word_wrap; - info.path_transform = path_transform; - info.line_cap = line_cap; - if (_cairo_path_fixed_is_rectangle (path, &box)) { - status = _cairo_pdf_path_rectangle (&info, &box); - } else { - status = _cairo_path_fixed_interpret (path, - CAIRO_DIRECTION_FORWARD, - _cairo_pdf_path_move_to, - _cairo_pdf_path_line_to, - _cairo_pdf_path_curve_to, - _cairo_pdf_path_close_path, - &info); - } - - status2 = _cairo_output_stream_destroy (word_wrap); - if (status == CAIRO_STATUS_SUCCESS) - status = status2; - - return status; -} - -cairo_int_status_t -_cairo_pdf_operators_clip (cairo_pdf_operators_t *pdf_operators, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule) -{ - const char *pdf_operator; - cairo_status_t status; - - if (! path->has_current_point) { - /* construct an empty path */ - _cairo_output_stream_printf (pdf_operators->stream, "0 0 m "); - } else { - status = _cairo_pdf_operators_emit_path (pdf_operators, - path, - &pdf_operators->cairo_to_pdf, - CAIRO_LINE_CAP_ROUND); - if (status) - return status; - } - - switch (fill_rule) { - case CAIRO_FILL_RULE_WINDING: - pdf_operator = "W"; - break; - case CAIRO_FILL_RULE_EVEN_ODD: - pdf_operator = "W*"; - break; - default: - ASSERT_NOT_REACHED; - } - - _cairo_output_stream_printf (pdf_operators->stream, - "%s n\n", - pdf_operator); - - return _cairo_output_stream_get_status (pdf_operators->stream); -} - -static int -_cairo_pdf_line_cap (cairo_line_cap_t cap) -{ - switch (cap) { - case CAIRO_LINE_CAP_BUTT: - return 0; - case CAIRO_LINE_CAP_ROUND: - return 1; - case CAIRO_LINE_CAP_SQUARE: - return 2; - default: - ASSERT_NOT_REACHED; - return 0; - } -} - -static int -_cairo_pdf_line_join (cairo_line_join_t join) -{ - switch (join) { - case CAIRO_LINE_JOIN_MITER: - return 0; - case CAIRO_LINE_JOIN_ROUND: - return 1; - case CAIRO_LINE_JOIN_BEVEL: - return 2; - default: - ASSERT_NOT_REACHED; - return 0; - } -} - -cairo_int_status_t -_cairo_pdf_operators_emit_stroke_style (cairo_pdf_operators_t *pdf_operators, - cairo_stroke_style_t *style, - double scale) -{ - double *dash = style->dash; - int num_dashes = style->num_dashes; - double dash_offset = style->dash_offset; - double line_width = style->line_width * scale; - - /* PostScript has "special needs" when it comes to zero-length - * dash segments with butt caps. It apparently (at least - * according to ghostscript) draws hairlines for this - * case. That's not what the cairo semantics want, so we first - * touch up the array to eliminate any 0.0 values that will - * result in "on" segments. - */ - if (num_dashes && style->line_cap == CAIRO_LINE_CAP_BUTT) { - int i; - - /* If there's an odd number of dash values they will each get - * interpreted as both on and off. So we first explicitly - * expand the array to remove the duplicate usage so that we - * can modify some of the values. - */ - if (num_dashes % 2) { - dash = _cairo_malloc_abc (num_dashes, 2, sizeof (double)); - if (dash == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - memcpy (dash, style->dash, num_dashes * sizeof (double)); - memcpy (dash + num_dashes, style->dash, num_dashes * sizeof (double)); - - num_dashes *= 2; - } - - for (i = 0; i < num_dashes; i += 2) { - if (dash[i] == 0.0) { - /* Do not modify the dashes in-place, as we may need to also - * replay this stroke to an image fallback. - */ - if (dash == style->dash) { - dash = _cairo_malloc_ab (num_dashes, sizeof (double)); - if (dash == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - memcpy (dash, style->dash, num_dashes * sizeof (double)); - } - - /* If we're at the front of the list, we first rotate - * two elements from the end of the list to the front - * of the list before folding away the 0.0. Or, if - * there are only two dash elements, then there is - * nothing at all to draw. - */ - if (i == 0) { - double last_two[2]; - - if (num_dashes == 2) { - free (dash); - return CAIRO_INT_STATUS_NOTHING_TO_DO; - } - - /* The cases of num_dashes == 0, 1, or 3 elements - * cannot exist, so the rotation of 2 elements - * will always be safe */ - memcpy (last_two, dash + num_dashes - 2, sizeof (last_two)); - memmove (dash + 2, dash, (num_dashes - 2) * sizeof (double)); - memcpy (dash, last_two, sizeof (last_two)); - dash_offset += dash[0] + dash[1]; - i = 2; - } - dash[i-1] += dash[i+1]; - num_dashes -= 2; - memmove (dash + i, dash + i + 2, (num_dashes - i) * sizeof (double)); - /* If we might have just rotated, it's possible that - * we rotated a 0.0 value to the front of the list. - * Set i to -2 so it will get incremented to 0. */ - if (i == 2) - i = -2; - } - } - } - - if (!pdf_operators->has_line_style || pdf_operators->line_width != line_width) { - _cairo_output_stream_printf (pdf_operators->stream, - "%f w\n", - line_width); - pdf_operators->line_width = line_width; - } - - if (!pdf_operators->has_line_style || pdf_operators->line_cap != style->line_cap) { - _cairo_output_stream_printf (pdf_operators->stream, - "%d J\n", - _cairo_pdf_line_cap (style->line_cap)); - pdf_operators->line_cap = style->line_cap; - } - - if (!pdf_operators->has_line_style || pdf_operators->line_join != style->line_join) { - _cairo_output_stream_printf (pdf_operators->stream, - "%d j\n", - _cairo_pdf_line_join (style->line_join)); - pdf_operators->line_join = style->line_join; - } - - if (num_dashes) { - int d; - - _cairo_output_stream_printf (pdf_operators->stream, "["); - for (d = 0; d < num_dashes; d++) - _cairo_output_stream_printf (pdf_operators->stream, " %f", dash[d] * scale); - _cairo_output_stream_printf (pdf_operators->stream, "] %f d\n", - dash_offset * scale); - pdf_operators->has_dashes = TRUE; - } else if (!pdf_operators->has_line_style || pdf_operators->has_dashes) { - _cairo_output_stream_printf (pdf_operators->stream, "[] 0.0 d\n"); - pdf_operators->has_dashes = FALSE; - } - if (dash != style->dash) - free (dash); - - if (!pdf_operators->has_line_style || pdf_operators->miter_limit != style->miter_limit) { - _cairo_output_stream_printf (pdf_operators->stream, - "%f M ", - style->miter_limit < 1.0 ? 1.0 : style->miter_limit); - pdf_operators->miter_limit = style->miter_limit; - } - pdf_operators->has_line_style = TRUE; - - return _cairo_output_stream_get_status (pdf_operators->stream); -} - -/* Scale the matrix so the largest absolute value of the non - * translation components is 1.0. Return the scale required to restore - * the matrix to the original values. - * - * eg the matrix [ 100 0 0 50 20 10 ] - * - * is rescaled to [ 1 0 0 0.5 0.2 0.1 ] - * and the scale returned is 100 - */ -static void -_cairo_matrix_factor_out_scale (cairo_matrix_t *m, double *scale) -{ - double s; - - 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); - *scale = s; - s = 1.0/s; - cairo_matrix_scale (m, s, s); -} - -static cairo_int_status_t -_cairo_pdf_operators_emit_stroke (cairo_pdf_operators_t *pdf_operators, - cairo_path_fixed_t *path, - cairo_stroke_style_t *style, - cairo_matrix_t *ctm, - cairo_matrix_t *ctm_inverse, - const char *pdf_operator) -{ - cairo_status_t status; - cairo_matrix_t m, path_transform; - cairo_bool_t has_ctm = TRUE; - double scale = 1.0; - - if (pdf_operators->in_text_object) { - status = _cairo_pdf_operators_end_text (pdf_operators); - if (status) - return status; - } - - /* Optimize away the stroke ctm when it does not affect the - * stroke. There are other ctm cases that could be optimized - * however this is the most common. - */ - if (fabs(ctm->xx) == 1.0 && fabs(ctm->yy) == 1.0 && - fabs(ctm->xy) == 0.0 && fabs(ctm->yx) == 0.0) - { - has_ctm = FALSE; - } - - /* The PDF CTM is transformed to the user space CTM when stroking - * so the corect pen shape will be used. This also requires that - * the path be transformed to user space when emitted. The - * conversion of path coordinates to user space may cause rounding - * errors. For example the device space point (1.234, 3.142) when - * transformed to a user space CTM of [100 0 0 100 0 0] will be - * emitted as (0.012, 0.031). - * - * To avoid the rounding problem we scale the user space CTM - * matrix so that all the non translation components of the matrix - * are <= 1. The line width and and dashes are scaled by the - * inverse of the scale applied to the CTM. This maintains the - * shape of the stroke pen while keeping the user space CTM within - * the range that maximizes the precision of the emitted path. - */ - if (has_ctm) { - m = *ctm; - /* Zero out the translation since it does not affect the pen - * shape however it may cause unnecessary digits to be emitted. - */ - m.x0 = 0.0; - m.y0 = 0.0; - _cairo_matrix_factor_out_scale (&m, &scale); - path_transform = m; - status = cairo_matrix_invert (&path_transform); - if (status) - return status; - - cairo_matrix_multiply (&m, &m, &pdf_operators->cairo_to_pdf); - } - - status = _cairo_pdf_operators_emit_stroke_style (pdf_operators, style, scale); - if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) - return CAIRO_STATUS_SUCCESS; - if (status) - 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); - } else { - path_transform = pdf_operators->cairo_to_pdf; - } - - status = _cairo_pdf_operators_emit_path (pdf_operators, - path, - &path_transform, - style->line_cap); - if (status) - return status; - - _cairo_output_stream_printf (pdf_operators->stream, "%s", pdf_operator); - if (has_ctm) - _cairo_output_stream_printf (pdf_operators->stream, " Q"); - - _cairo_output_stream_printf (pdf_operators->stream, "\n"); - - return _cairo_output_stream_get_status (pdf_operators->stream); -} - -cairo_int_status_t -_cairo_pdf_operators_stroke (cairo_pdf_operators_t *pdf_operators, - cairo_path_fixed_t *path, - cairo_stroke_style_t *style, - cairo_matrix_t *ctm, - cairo_matrix_t *ctm_inverse) -{ - return _cairo_pdf_operators_emit_stroke (pdf_operators, - path, - style, - ctm, - ctm_inverse, - "S"); -} - -cairo_int_status_t -_cairo_pdf_operators_fill (cairo_pdf_operators_t *pdf_operators, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule) -{ - const char *pdf_operator; - cairo_status_t status; - - if (pdf_operators->in_text_object) { - status = _cairo_pdf_operators_end_text (pdf_operators); - if (status) - return status; - } - - status = _cairo_pdf_operators_emit_path (pdf_operators, - path, - &pdf_operators->cairo_to_pdf, - CAIRO_LINE_CAP_ROUND); - if (status) - return status; - - switch (fill_rule) { - case CAIRO_FILL_RULE_WINDING: - pdf_operator = "f"; - break; - case CAIRO_FILL_RULE_EVEN_ODD: - pdf_operator = "f*"; - break; - default: - ASSERT_NOT_REACHED; - } - - _cairo_output_stream_printf (pdf_operators->stream, - "%s\n", - pdf_operator); - - return _cairo_output_stream_get_status (pdf_operators->stream); -} - -cairo_int_status_t -_cairo_pdf_operators_fill_stroke (cairo_pdf_operators_t *pdf_operators, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - cairo_stroke_style_t *style, - cairo_matrix_t *ctm, - cairo_matrix_t *ctm_inverse) -{ - const char *operator; - - switch (fill_rule) { - case CAIRO_FILL_RULE_WINDING: - operator = "B"; - break; - case CAIRO_FILL_RULE_EVEN_ODD: - operator = "B*"; - break; - default: - ASSERT_NOT_REACHED; - } - - return _cairo_pdf_operators_emit_stroke (pdf_operators, - path, - style, - ctm, - ctm_inverse, - operator); -} - -#define GLYPH_POSITION_TOLERANCE 0.001 - -/* Emit the string of glyphs using the 'Tj' operator. This requires - * that the glyphs are positioned at their natural glyph advances. */ -static cairo_status_t -_cairo_pdf_operators_emit_glyph_string (cairo_pdf_operators_t *pdf_operators, - cairo_output_stream_t *stream) -{ - int i; - - _cairo_output_stream_printf (stream, "<"); - for (i = 0; i < pdf_operators->num_glyphs; i++) { - _cairo_output_stream_printf (stream, - "%0*x", - pdf_operators->hex_width, - pdf_operators->glyphs[i].glyph_index); - pdf_operators->cur_x += pdf_operators->glyphs[i].x_advance; - } - _cairo_output_stream_printf (stream, ">Tj\n"); - - return _cairo_output_stream_get_status (stream); -} - -/* Emit the string of glyphs using the 'TJ' operator. - * - * The TJ operator takes an array of strings of glyphs. Each string of - * glyphs is displayed using the glyph advances of each glyph to - * position the glyphs. A relative adjustment to the glyph advance may - * be specified by including the adjustment between two strings. The - * adjustment is in units of text space * -1000. - */ -static cairo_status_t -_cairo_pdf_operators_emit_glyph_string_with_positioning ( - cairo_pdf_operators_t *pdf_operators, - cairo_output_stream_t *stream) -{ - int i; - - _cairo_output_stream_printf (stream, "[<"); - for (i = 0; i < pdf_operators->num_glyphs; i++) { - if (pdf_operators->glyphs[i].x_position != pdf_operators->cur_x) - { - double delta = pdf_operators->glyphs[i].x_position - pdf_operators->cur_x; - int rounded_delta; - - delta = -1000.0*delta; - /* As the delta is in 1/1000 of a unit of text space, - * rounding to an integer should still provide sufficient - * precision. We round the delta before adding to Tm_x so - * that we keep track of the accumulated rounding error in - * the PDF interpreter and compensate for it when - * calculating subsequent deltas. - */ - rounded_delta = _cairo_lround (delta); - if (rounded_delta != 0) { - _cairo_output_stream_printf (stream, - ">%d<", - rounded_delta); - } - - /* Convert the rounded delta back to text - * space before adding to the current text - * position. */ - delta = rounded_delta/-1000.0; - pdf_operators->cur_x += delta; - } - - _cairo_output_stream_printf (stream, - "%0*x", - pdf_operators->hex_width, - pdf_operators->glyphs[i].glyph_index); - pdf_operators->cur_x += pdf_operators->glyphs[i].x_advance; - } - _cairo_output_stream_printf (stream, ">]TJ\n"); - - return _cairo_output_stream_get_status (stream); -} - -static cairo_status_t -_cairo_pdf_operators_flush_glyphs (cairo_pdf_operators_t *pdf_operators) -{ - cairo_output_stream_t *word_wrap_stream; - cairo_status_t status, status2; - int i; - double x; - - if (pdf_operators->num_glyphs == 0) - return CAIRO_STATUS_SUCCESS; - - word_wrap_stream = _word_wrap_stream_create (pdf_operators->stream, 72); - status = _cairo_output_stream_get_status (word_wrap_stream); - if (status) - return _cairo_output_stream_destroy (word_wrap_stream); - - /* Check if glyph advance used to position every glyph */ - x = pdf_operators->cur_x; - for (i = 0; i < pdf_operators->num_glyphs; i++) { - if (fabs(pdf_operators->glyphs[i].x_position - x) > GLYPH_POSITION_TOLERANCE) - break; - x += pdf_operators->glyphs[i].x_advance; - } - if (i == pdf_operators->num_glyphs) { - status = _cairo_pdf_operators_emit_glyph_string (pdf_operators, - word_wrap_stream); - } else { - status = _cairo_pdf_operators_emit_glyph_string_with_positioning ( - pdf_operators, word_wrap_stream); - } - - pdf_operators->num_glyphs = 0; - status2 = _cairo_output_stream_destroy (word_wrap_stream); - if (status == CAIRO_STATUS_SUCCESS) - status = status2; - - return status; -} - -static cairo_status_t -_cairo_pdf_operators_add_glyph (cairo_pdf_operators_t *pdf_operators, - cairo_scaled_font_subsets_glyph_t *glyph, - double x_position) -{ - double x, y; - - x = glyph->x_advance; - y = glyph->y_advance; - if (glyph->is_scaled) - cairo_matrix_transform_distance (&pdf_operators->font_matrix_inverse, &x, &y); - - pdf_operators->glyphs[pdf_operators->num_glyphs].x_position = x_position; - pdf_operators->glyphs[pdf_operators->num_glyphs].glyph_index = glyph->subset_glyph_index; - pdf_operators->glyphs[pdf_operators->num_glyphs].x_advance = x; - pdf_operators->num_glyphs++; - if (pdf_operators->num_glyphs == PDF_GLYPH_BUFFER_SIZE) - return _cairo_pdf_operators_flush_glyphs (pdf_operators); - - return CAIRO_STATUS_SUCCESS; -} - -/* Use 'Tm' operator to set the PDF text matrix. */ -static cairo_status_t -_cairo_pdf_operators_set_text_matrix (cairo_pdf_operators_t *pdf_operators, - cairo_matrix_t *matrix) -{ - cairo_matrix_t inverse; - cairo_status_t status; - - /* We require the matrix to be invertable. */ - inverse = *matrix; - status = cairo_matrix_invert (&inverse); - if (status) - return status; - - pdf_operators->text_matrix = *matrix; - pdf_operators->cur_x = 0; - pdf_operators->cur_y = 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); - - pdf_operators->cairo_to_pdftext = *matrix; - status = cairo_matrix_invert (&pdf_operators->cairo_to_pdftext); - assert (status == CAIRO_STATUS_SUCCESS); - cairo_matrix_multiply (&pdf_operators->cairo_to_pdftext, - &pdf_operators->cairo_to_pdf, - &pdf_operators->cairo_to_pdftext); - - return _cairo_output_stream_get_status (pdf_operators->stream); -} - -#define TEXT_MATRIX_TOLERANCE 1e-6 - -/* Set the translation components of the PDF text matrix to x, y. The - * 'Td' operator is used to transform the text matrix. - */ -static cairo_status_t -_cairo_pdf_operators_set_text_position (cairo_pdf_operators_t *pdf_operators, - double x, - double y) -{ - cairo_matrix_t translate, inverse; - cairo_status_t status; - - /* The Td operator transforms the text_matrix with: - * - * text_matrix' = T x text_matrix - * - * where T is a translation matrix with the translation components - * set to the Td operands tx and ty. - */ - inverse = pdf_operators->text_matrix; - status = cairo_matrix_invert (&inverse); - assert (status == CAIRO_STATUS_SUCCESS); - pdf_operators->text_matrix.x0 = x; - pdf_operators->text_matrix.y0 = y; - cairo_matrix_multiply (&translate, &pdf_operators->text_matrix, &inverse); - if (fabs(translate.x0) < TEXT_MATRIX_TOLERANCE) - translate.x0 = 0.0; - if (fabs(translate.y0) < TEXT_MATRIX_TOLERANCE) - translate.y0 = 0.0; - _cairo_output_stream_printf (pdf_operators->stream, - "%f %f Td\n", - translate.x0, - translate.y0); - pdf_operators->cur_x = 0; - pdf_operators->cur_y = 0; - - pdf_operators->cairo_to_pdftext = pdf_operators->text_matrix; - status = cairo_matrix_invert (&pdf_operators->cairo_to_pdftext); - assert (status == CAIRO_STATUS_SUCCESS); - cairo_matrix_multiply (&pdf_operators->cairo_to_pdftext, - &pdf_operators->cairo_to_pdf, - &pdf_operators->cairo_to_pdftext); - - return _cairo_output_stream_get_status (pdf_operators->stream); -} - -/* Select the font using the 'Tf' operator. The font size is set to 1 - * as we use the 'Tm' operator to set the font scale. - */ -static cairo_status_t -_cairo_pdf_operators_set_font_subset (cairo_pdf_operators_t *pdf_operators, - cairo_scaled_font_subsets_glyph_t *subset_glyph) -{ - cairo_status_t status; - - _cairo_output_stream_printf (pdf_operators->stream, - "/f-%d-%d 1 Tf\n", - subset_glyph->font_id, - subset_glyph->subset_id); - if (pdf_operators->use_font_subset) { - status = pdf_operators->use_font_subset (subset_glyph->font_id, - subset_glyph->subset_id, - pdf_operators->use_font_subset_closure); - if (status) - return status; - } - pdf_operators->font_id = subset_glyph->font_id; - pdf_operators->subset_id = subset_glyph->subset_id; - - if (subset_glyph->is_composite) - pdf_operators->hex_width = 4; - else - pdf_operators->hex_width = 2; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_pdf_operators_begin_text (cairo_pdf_operators_t *pdf_operators) -{ - _cairo_output_stream_printf (pdf_operators->stream, "BT\n"); - - pdf_operators->in_text_object = TRUE; - pdf_operators->num_glyphs = 0; - - return _cairo_output_stream_get_status (pdf_operators->stream); -} - -static cairo_status_t -_cairo_pdf_operators_end_text (cairo_pdf_operators_t *pdf_operators) -{ - cairo_status_t status; - - status = _cairo_pdf_operators_flush_glyphs (pdf_operators); - if (status) - return status; - - _cairo_output_stream_printf (pdf_operators->stream, "ET\n"); - - pdf_operators->in_text_object = FALSE; - - return _cairo_output_stream_get_status (pdf_operators->stream); -} - -/* Compare the scale components of two matrices. The translation - * components are ignored. */ -static cairo_bool_t -_cairo_matrix_scale_equal (cairo_matrix_t *a, cairo_matrix_t *b) -{ - return (a->xx == b->xx && - a->xy == b->xy && - a->yx == b->yx && - a->yy == b->yy); -} - -static cairo_status_t -_cairo_pdf_operators_begin_actualtext (cairo_pdf_operators_t *pdf_operators, - const char *utf8, - int utf8_len) -{ - uint16_t *utf16; - int utf16_len; - cairo_status_t status; - int i; - - _cairo_output_stream_printf (pdf_operators->stream, "/Span << /ActualText stream, - "%04x", (int) (utf16[i])); - } - free (utf16); - } - _cairo_output_stream_printf (pdf_operators->stream, "> >> BDC\n"); - - return _cairo_output_stream_get_status (pdf_operators->stream); -} - -static cairo_status_t -_cairo_pdf_operators_end_actualtext (cairo_pdf_operators_t *pdf_operators) -{ - _cairo_output_stream_printf (pdf_operators->stream, "EMC\n"); - - return _cairo_output_stream_get_status (pdf_operators->stream); -} - -static cairo_status_t -_cairo_pdf_operators_emit_glyph (cairo_pdf_operators_t *pdf_operators, - cairo_glyph_t *glyph, - cairo_scaled_font_subsets_glyph_t *subset_glyph) -{ - double x, y; - cairo_status_t status; - - if (pdf_operators->is_new_text_object || - pdf_operators->font_id != subset_glyph->font_id || - pdf_operators->subset_id != subset_glyph->subset_id) - { - status = _cairo_pdf_operators_flush_glyphs (pdf_operators); - if (status) - return status; - - status = _cairo_pdf_operators_set_font_subset (pdf_operators, subset_glyph); - if (status) - return status; - - pdf_operators->is_new_text_object = FALSE; - } - - x = glyph->x; - y = glyph->y; - cairo_matrix_transform_point (&pdf_operators->cairo_to_pdftext, &x, &y); - - /* The TJ operator for displaying text strings can only set - * the horizontal position of the glyphs. If the y position - * (in text space) changes, use the Td operator to change the - * current position to the next glyph. We also use the Td - * operator to move the current position if the horizontal - * position changes by more than 10 (in text space - * units). This is becauses the horizontal glyph positioning - * in the TJ operator is intended for kerning and there may be - * PDF consumers that do not handle very large position - * adjustments in TJ. - */ - if (fabs(x - pdf_operators->cur_x) > 10 || - fabs(y - pdf_operators->cur_y) > GLYPH_POSITION_TOLERANCE) - { - status = _cairo_pdf_operators_flush_glyphs (pdf_operators); - if (status) - return status; - - x = glyph->x; - y = glyph->y; - cairo_matrix_transform_point (&pdf_operators->cairo_to_pdf, &x, &y); - status = _cairo_pdf_operators_set_text_position (pdf_operators, x, y); - if (status) - return status; - - x = 0.0; - y = 0.0; - } - - status = _cairo_pdf_operators_add_glyph (pdf_operators, - subset_glyph, - x); - return status; -} - -/* A utf8_len of -1 indicates no unicode text. A utf8_len = 0 is an - * empty string. - */ -static cairo_int_status_t -_cairo_pdf_operators_emit_cluster (cairo_pdf_operators_t *pdf_operators, - const char *utf8, - int utf8_len, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_text_cluster_flags_t cluster_flags, - cairo_scaled_font_t *scaled_font) -{ - cairo_scaled_font_subsets_glyph_t subset_glyph; - cairo_glyph_t *cur_glyph; - cairo_status_t status; - int i; - - /* If the cluster maps 1 glyph to 1 or more unicode characters, we - * first try _map_glyph() with the unicode string to see if it can - * use toUnicode to map our glyph to the unicode. This will fail - * if the glyph is already mapped to a different unicode string. - * - * We also go through this path if no unicode mapping was - * supplied (utf8_len < 0). - * - * Mapping a glyph to a zero length unicode string requires the - * use of ActualText. - */ - if (num_glyphs == 1 && utf8_len != 0) { - status = _cairo_scaled_font_subsets_map_glyph (pdf_operators->font_subsets, - scaled_font, - glyphs->index, - utf8, - utf8_len, - &subset_glyph); - if (status) - return status; - - if (subset_glyph.utf8_is_mapped || utf8_len < 0) { - status = _cairo_pdf_operators_emit_glyph (pdf_operators, - glyphs, - &subset_glyph); - if (status) - return status; - - return CAIRO_STATUS_SUCCESS; - } - } - - /* Fallback to using ActualText to map zero or more glyphs to a - * unicode string. */ - status = _cairo_pdf_operators_flush_glyphs (pdf_operators); - if (status) - return status; - - status = _cairo_pdf_operators_begin_actualtext (pdf_operators, utf8, utf8_len); - if (status) - return status; - - 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++) { - status = _cairo_scaled_font_subsets_map_glyph (pdf_operators->font_subsets, - scaled_font, - cur_glyph->index, - NULL, -1, - &subset_glyph); - if (status) - return status; - - status = _cairo_pdf_operators_emit_glyph (pdf_operators, - cur_glyph, - &subset_glyph); - if (status) - return status; - - if ((cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD)) - cur_glyph--; - else - cur_glyph++; - } - status = _cairo_pdf_operators_flush_glyphs (pdf_operators); - if (status) - return status; - - status = _cairo_pdf_operators_end_actualtext (pdf_operators); - - return status; -} - -cairo_int_status_t -_cairo_pdf_operators_show_text_glyphs (cairo_pdf_operators_t *pdf_operators, - const char *utf8, - int utf8_len, - cairo_glyph_t *glyphs, - int num_glyphs, - const cairo_text_cluster_t *clusters, - int num_clusters, - cairo_text_cluster_flags_t cluster_flags, - cairo_scaled_font_t *scaled_font) -{ - cairo_status_t status; - int i; - cairo_matrix_t text_matrix, invert_y_axis; - double x, y; - const char *cur_text; - cairo_glyph_t *cur_glyph; - - pdf_operators->font_matrix_inverse = scaled_font->font_matrix; - status = cairo_matrix_invert (&pdf_operators->font_matrix_inverse); - if (status == CAIRO_STATUS_INVALID_MATRIX) - return CAIRO_STATUS_SUCCESS; - if (status) - return status; - - pdf_operators->is_new_text_object = FALSE; - if (pdf_operators->in_text_object == FALSE) { - status = _cairo_pdf_operators_begin_text (pdf_operators); - if (status) - return status; - - /* Force Tm and Tf to be emitted when starting a new text - * object.*/ - pdf_operators->is_new_text_object = TRUE; - } - - cairo_matrix_init_scale (&invert_y_axis, 1, -1); - text_matrix = scaled_font->scale; - - /* Invert y axis in font space */ - cairo_matrix_multiply (&text_matrix, &text_matrix, &invert_y_axis); - - /* Invert y axis in device space */ - cairo_matrix_multiply (&text_matrix, &invert_y_axis, &text_matrix); - - if (pdf_operators->is_new_text_object || - ! _cairo_matrix_scale_equal (&pdf_operators->text_matrix, &text_matrix)) - { - status = _cairo_pdf_operators_flush_glyphs (pdf_operators); - if (status) - return status; - - x = glyphs[0].x; - y = glyphs[0].y; - cairo_matrix_transform_point (&pdf_operators->cairo_to_pdf, &x, &y); - text_matrix.x0 = x; - text_matrix.y0 = y; - status = _cairo_pdf_operators_set_text_matrix (pdf_operators, &text_matrix); - if (status == CAIRO_STATUS_INVALID_MATRIX) - return CAIRO_STATUS_SUCCESS; - if (status) - return status; - } - - if (num_clusters > 0) { - cur_text = utf8; - if ((cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD)) - cur_glyph = glyphs + num_glyphs; - else - cur_glyph = glyphs; - for (i = 0; i < num_clusters; i++) { - if ((cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD)) - cur_glyph -= clusters[i].num_glyphs; - status = _cairo_pdf_operators_emit_cluster (pdf_operators, - cur_text, - clusters[i].num_bytes, - cur_glyph, - clusters[i].num_glyphs, - cluster_flags, - scaled_font); - if (status) - return status; - - cur_text += clusters[i].num_bytes; - if (!(cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD)) - cur_glyph += clusters[i].num_glyphs; - } - } else { - for (i = 0; i < num_glyphs; i++) { - status = _cairo_pdf_operators_emit_cluster (pdf_operators, - NULL, - -1, /* no unicode string available */ - &glyphs[i], - 1, - FALSE, - scaled_font); - if (status) - return status; - } - } - - return _cairo_output_stream_get_status (pdf_operators->stream); -} - -#endif /* CAIRO_HAS_PDF_OPERATORS */ diff --git a/uppdev/plugin/cairo/lib/cairo-pdf-surface-private.h b/uppdev/plugin/cairo/lib/cairo-pdf-surface-private.h deleted file mode 100644 index ab222ded8..000000000 --- a/uppdev/plugin/cairo/lib/cairo-pdf-surface-private.h +++ /dev/null @@ -1,171 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2004 Red Hat, Inc - * Copyright © 2006 Red Hat, Inc - * Copyright © 2007, 2008 Adrian Johnson - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Kristian Høgsberg - * Carl Worth - * Adrian Johnson - */ - -#ifndef CAIRO_PDF_SURFACE_PRIVATE_H -#define CAIRO_PDF_SURFACE_PRIVATE_H - -#include "cairo-pdf.h" - -#include "cairo-surface-private.h" -#include "cairo-pdf-operators-private.h" -#include "cairo-path-fixed-private.h" - -typedef struct _cairo_pdf_resource { - unsigned int id; -} cairo_pdf_resource_t; - -typedef struct _cairo_pdf_group_resources { - cairo_array_t alphas; - cairo_array_t smasks; - cairo_array_t patterns; - cairo_array_t xobjects; - cairo_array_t fonts; -} cairo_pdf_group_resources_t; - -typedef struct _cairo_pdf_pattern { - double width; - double height; - cairo_pattern_t *pattern; - cairo_pdf_resource_t pattern_res; - cairo_pdf_resource_t gstate_res; -} cairo_pdf_pattern_t; - -typedef enum _cairo_pdf_operation { - PDF_PAINT, - PDF_MASK, - PDF_FILL, - PDF_STROKE, - PDF_SHOW_GLYPHS -} cairo_pdf_operation_t; - -typedef struct _cairo_pdf_smask_group -{ - double width; - double height; - cairo_pdf_resource_t group_res; - cairo_pdf_operation_t operation; - cairo_pattern_t *source; - cairo_pdf_resource_t source_res; - cairo_pattern_t *mask; - cairo_path_fixed_t path; - cairo_fill_rule_t fill_rule; - cairo_stroke_style_t *style; - cairo_matrix_t ctm; - cairo_matrix_t ctm_inverse; - char *utf8; - int utf8_len; - cairo_glyph_t *glyphs; - int num_glyphs; - cairo_text_cluster_t *clusters; - int num_clusters; - cairo_bool_t cluster_flags; - cairo_scaled_font_t *scaled_font; -} cairo_pdf_smask_group_t; - -typedef struct _cairo_pdf_surface cairo_pdf_surface_t; - -struct _cairo_pdf_surface { - cairo_surface_t base; - - /* Prefer the name "output" here to avoid confusion over the - * structure within a PDF document known as a "stream". */ - cairo_output_stream_t *output; - - double width; - double height; - cairo_matrix_t cairo_to_pdf; - - cairo_array_t objects; - cairo_array_t pages; - cairo_array_t rgb_linear_functions; - cairo_array_t alpha_linear_functions; - cairo_array_t patterns; - cairo_array_t smask_groups; - cairo_array_t knockout_group; - - cairo_scaled_font_subsets_t *font_subsets; - cairo_array_t fonts; - - cairo_pdf_resource_t next_available_resource; - cairo_pdf_resource_t pages_resource; - - cairo_bool_t compress_content; - - cairo_pdf_resource_t content; - cairo_pdf_resource_t content_resources; - cairo_pdf_group_resources_t resources; - cairo_bool_t has_fallback_images; - - struct { - cairo_bool_t active; - cairo_pdf_resource_t self; - cairo_pdf_resource_t length; - long start_offset; - cairo_bool_t compressed; - cairo_output_stream_t *old_output; - } pdf_stream; - - struct { - cairo_bool_t active; - cairo_output_stream_t *stream; - cairo_output_stream_t *mem_stream; - cairo_output_stream_t *old_output; - cairo_pdf_resource_t resource; - cairo_bool_t is_knockout; - } group_stream; - - cairo_pdf_operators_t pdf_operators; - cairo_paginated_mode_t paginated_mode; - cairo_bool_t select_pattern_gstate_saved; - - cairo_bool_t force_fallbacks; - - cairo_bool_t current_pattern_is_solid_color; - cairo_bool_t current_color_is_stroke; - double current_color_red; - double current_color_green; - double current_color_blue; - double current_color_alpha; - - cairo_surface_t *paginated_surface; -}; - -#endif /* CAIRO_PDF_SURFACE_PRIVATE_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-pdf-surface.c b/uppdev/plugin/cairo/lib/cairo-pdf-surface.c deleted file mode 100644 index 44f0ed839..000000000 --- a/uppdev/plugin/cairo/lib/cairo-pdf-surface.c +++ /dev/null @@ -1,4996 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2004 Red Hat, Inc - * Copyright © 2006 Red Hat, Inc - * Copyright © 2007, 2008 Adrian Johnson - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Kristian Høgsberg - * Carl Worth - * Adrian Johnson - */ - -#define _BSD_SOURCE /* for snprintf() */ -#include "cairoint.h" -#include "cairo-pdf.h" -#include "cairo-pdf-surface-private.h" -#include "cairo-pdf-operators-private.h" -#include "cairo-analysis-surface-private.h" -#include "cairo-meta-surface-private.h" -#include "cairo-output-stream-private.h" -#include "cairo-paginated-private.h" -#include "cairo-scaled-font-subsets-private.h" -#include "cairo-type3-glyph-surface-private.h" - -#include -#include - -/* Issues: - * - * - We embed an image in the stream each time it's composited. We - * could add generation counters to surfaces and remember the stream - * ID for a particular generation for a particular surface. - * - * - Backend specific meta data. - */ - -/* - * Page Structure of the Generated PDF: - * - * Each page requiring fallbacks images contains a knockout group at - * the top level. The first operation of the knockout group paints a - * group containing all the supported drawing operations. Fallback - * images (if any) are painted in the knockout group. This ensures - * that fallback images do not composite with any content under the - * fallback images. - * - * Streams: - * - * This PDF surface has three types of streams: - * - PDF Stream - * - Content Stream - * - Group Stream - * - * Calling _cairo_output_stream_printf (surface->output, ...) will - * write to the currently open stream. - * - * PDF Stream: - * A PDF Stream may be opened and closed with the following functions: - * _cairo_pdf_surface_open stream () - * _cairo_pdf_surface_close_stream () - * - * PDF Streams are written directly to the PDF file. They are used for - * fonts, images and patterns. - * - * Content Stream: - * The Content Stream is opened and closed with the following functions: - * _cairo_pdf_surface_open_content_stream () - * _cairo_pdf_surface_close_content_stream () - * - * The Content Stream contains the text and graphics operators. - * - * Group Stream: - * A Group Stream may be opened and closed with the following functions: - * _cairo_pdf_surface_open_group () - * _cairo_pdf_surface_close_group () - * - * A Group Stream is a Form XObject. It is used for short sequences - * of operators. As the content is very short the group is stored in - * memory until it is closed. This allows some optimization such as - * including the Resource dictionary and stream length inside the - * XObject instead of using an indirect object. - */ - -typedef struct _cairo_pdf_object { - long offset; -} cairo_pdf_object_t; - -typedef struct _cairo_pdf_font { - unsigned int font_id; - unsigned int subset_id; - cairo_pdf_resource_t subset_resource; -} cairo_pdf_font_t; - -typedef struct _cairo_pdf_rgb_linear_function { - cairo_pdf_resource_t resource; - double color1[3]; - double color2[3]; -} cairo_pdf_rgb_linear_function_t; - -typedef struct _cairo_pdf_alpha_linear_function { - cairo_pdf_resource_t resource; - double alpha1; - double alpha2; -} cairo_pdf_alpha_linear_function_t; - -static cairo_pdf_resource_t -_cairo_pdf_surface_new_object (cairo_pdf_surface_t *surface); - -static void -_cairo_pdf_surface_clear (cairo_pdf_surface_t *surface); - -static void -_cairo_pdf_smask_group_destroy (cairo_pdf_smask_group_t *group); - -static cairo_status_t -_cairo_pdf_surface_add_font (unsigned int font_id, - unsigned int subset_id, - void *closure); - -static void -_cairo_pdf_group_resources_init (cairo_pdf_group_resources_t *res); - -static cairo_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 -_cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface); - -static cairo_status_t -_cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface); - -static void -_cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface); - -static cairo_pdf_resource_t -_cairo_pdf_surface_write_info (cairo_pdf_surface_t *surface); - -static cairo_pdf_resource_t -_cairo_pdf_surface_write_catalog (cairo_pdf_surface_t *surface); - -static long -_cairo_pdf_surface_write_xref (cairo_pdf_surface_t *surface); - -static cairo_status_t -_cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface); - -static cairo_status_t -_cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface); - -static const cairo_surface_backend_t cairo_pdf_surface_backend; -static const cairo_paginated_surface_backend_t cairo_pdf_surface_paginated_backend; - -static cairo_pdf_resource_t -_cairo_pdf_surface_new_object (cairo_pdf_surface_t *surface) -{ - cairo_pdf_resource_t resource; - cairo_status_t status; - cairo_pdf_object_t object; - - object.offset = _cairo_output_stream_get_position (surface->output); - - status = _cairo_array_append (&surface->objects, &object); - if (status) { - resource.id = 0; - return resource; - } - - resource = surface->next_available_resource; - surface->next_available_resource.id++; - - return resource; -} - -static void -_cairo_pdf_surface_update_object (cairo_pdf_surface_t *surface, - cairo_pdf_resource_t resource) -{ - cairo_pdf_object_t *object; - - object = _cairo_array_index (&surface->objects, resource.id - 1); - object->offset = _cairo_output_stream_get_position (surface->output); -} - -static void -_cairo_pdf_surface_set_size_internal (cairo_pdf_surface_t *surface, - double width, - double height) -{ - surface->width = width; - surface->height = height; - cairo_matrix_init (&surface->cairo_to_pdf, 1, 0, 0, -1, 0, height); - _cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators, - &surface->cairo_to_pdf); -} - -static cairo_surface_t * -_cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output, - double width, - double height) -{ - cairo_pdf_surface_t *surface; - cairo_status_t status, status_ignored; - - surface = malloc (sizeof (cairo_pdf_surface_t)); - if (surface == NULL) { - /* destroy stream on behalf of caller */ - status = _cairo_output_stream_destroy (output); - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - } - - _cairo_surface_init (&surface->base, &cairo_pdf_surface_backend, - CAIRO_CONTENT_COLOR_ALPHA); - - surface->output = output; - surface->width = width; - surface->height = height; - cairo_matrix_init (&surface->cairo_to_pdf, 1, 0, 0, -1, 0, height); - - _cairo_array_init (&surface->objects, sizeof (cairo_pdf_object_t)); - _cairo_array_init (&surface->pages, sizeof (cairo_pdf_resource_t)); - _cairo_array_init (&surface->rgb_linear_functions, sizeof (cairo_pdf_rgb_linear_function_t)); - _cairo_array_init (&surface->alpha_linear_functions, sizeof (cairo_pdf_alpha_linear_function_t)); - _cairo_array_init (&surface->fonts, sizeof (cairo_pdf_font_t)); - _cairo_array_init (&surface->patterns, sizeof (cairo_pdf_pattern_t)); - _cairo_array_init (&surface->smask_groups, sizeof (cairo_pdf_smask_group_t *)); - _cairo_array_init (&surface->knockout_group, sizeof (cairo_pdf_resource_t)); - - _cairo_pdf_group_resources_init (&surface->resources); - - surface->font_subsets = _cairo_scaled_font_subsets_create_composite (); - if (! surface->font_subsets) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto BAIL0; - } - - surface->next_available_resource.id = 1; - surface->pages_resource = _cairo_pdf_surface_new_object (surface); - if (surface->pages_resource.id == 0) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto BAIL1; - } - - surface->compress_content = TRUE; - surface->pdf_stream.active = FALSE; - surface->pdf_stream.old_output = NULL; - surface->group_stream.active = FALSE; - surface->group_stream.stream = NULL; - surface->group_stream.mem_stream = NULL; - - surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE; - - surface->force_fallbacks = FALSE; - surface->select_pattern_gstate_saved = FALSE; - surface->current_pattern_is_solid_color = FALSE; - - _cairo_pdf_operators_init (&surface->pdf_operators, - surface->output, - &surface->cairo_to_pdf, - surface->font_subsets); - _cairo_pdf_operators_set_font_subsets_callback (&surface->pdf_operators, - _cairo_pdf_surface_add_font, - surface); - - /* Document header */ - _cairo_output_stream_printf (surface->output, - "%%PDF-1.4\n"); - _cairo_output_stream_printf (surface->output, - "%%%c%c%c%c\n", 181, 237, 174, 251); - - surface->paginated_surface = _cairo_paginated_surface_create ( - &surface->base, - CAIRO_CONTENT_COLOR_ALPHA, - width, height, - &cairo_pdf_surface_paginated_backend); - - status = surface->paginated_surface->status; - if (status == CAIRO_STATUS_SUCCESS) { - /* paginated keeps the only reference to surface now, drop ours */ - cairo_surface_destroy (&surface->base); - return surface->paginated_surface; - } - -BAIL1: - _cairo_scaled_font_subsets_destroy (surface->font_subsets); -BAIL0: - _cairo_array_fini (&surface->objects); - free (surface); - - /* destroy stream on behalf of caller */ - status_ignored = _cairo_output_stream_destroy (output); - - return _cairo_surface_create_in_error (status); -} - -/** - * cairo_pdf_surface_create_for_stream: - * @write_func: a #cairo_write_func_t to accept the output data, may be %NULL - * to indicate a no-op @write_func. With a no-op @write_func, - * the surface may be queried or used as a source without - * generating any temporary files. - * @closure: the closure argument for @write_func - * @width_in_points: width of the surface, in points (1 point == 1/72.0 inch) - * @height_in_points: height of the surface, in points (1 point == 1/72.0 inch) - * - * Creates a PDF surface of the specified size in points to be written - * incrementally to the stream represented by @write_func and @closure. - * - * Return value: a pointer to the newly created surface. The caller - * owns the surface and should call cairo_surface_destroy() when done - * with it. - * - * This function always returns a valid pointer, but it will return a - * pointer to a "nil" surface if an error such as out of memory - * occurs. You can use cairo_surface_status() to check for this. - * - * Since: 1.2 - */ -cairo_surface_t * -cairo_pdf_surface_create_for_stream (cairo_write_func_t write_func, - void *closure, - double width_in_points, - double height_in_points) -{ - cairo_output_stream_t *output; - - output = _cairo_output_stream_create (write_func, NULL, closure); - if (_cairo_output_stream_get_status (output)) - return _cairo_surface_create_in_error (_cairo_output_stream_destroy (output)); - - return _cairo_pdf_surface_create_for_stream_internal (output, - width_in_points, - height_in_points); -} - -/** - * cairo_pdf_surface_create: - * @filename: a filename for the PDF output (must be writable), %NULL may be - * used to specify no output. This will generate a PDF surface that - * may be queried and used as a source, without generating a - * temporary file. - * @width_in_points: width of the surface, in points (1 point == 1/72.0 inch) - * @height_in_points: height of the surface, in points (1 point == 1/72.0 inch) - * - * Creates a PDF surface of the specified size in points to be written - * to @filename. - * - * Return value: a pointer to the newly created surface. The caller - * owns the surface and should call cairo_surface_destroy() when done - * with it. - * - * This function always returns a valid pointer, but it will return a - * pointer to a "nil" surface if an error such as out of memory - * occurs. You can use cairo_surface_status() to check for this. - * - * Since: 1.2 - **/ -cairo_surface_t * -cairo_pdf_surface_create (const char *filename, - double width_in_points, - double height_in_points) -{ - cairo_output_stream_t *output; - - output = _cairo_output_stream_create_for_filename (filename); - if (_cairo_output_stream_get_status (output)) - return _cairo_surface_create_in_error (_cairo_output_stream_destroy (output)); - - return _cairo_pdf_surface_create_for_stream_internal (output, - width_in_points, - height_in_points); -} - -static cairo_bool_t -_cairo_surface_is_pdf (cairo_surface_t *surface) -{ - return surface->backend == &cairo_pdf_surface_backend; -} - -/* If the abstract_surface is a paginated surface, and that paginated - * surface's target is a pdf_surface, then set pdf_surface to that - * target. Otherwise return %CAIRO_STATUS_SURFACE_TYPE_MISMATCH. - */ -static cairo_status_t -_extract_pdf_surface (cairo_surface_t *surface, - cairo_pdf_surface_t **pdf_surface) -{ - cairo_surface_t *target; - - if (surface->status) - return surface->status; - - if (! _cairo_surface_is_paginated (surface)) - return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - - target = _cairo_paginated_surface_get_target (surface); - if (target->status) - return target->status; - - if (! _cairo_surface_is_pdf (target)) - return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - - *pdf_surface = (cairo_pdf_surface_t *) target; - - return CAIRO_STATUS_SUCCESS; -} - -/** - * cairo_pdf_surface_set_size: - * @surface: a PDF #cairo_surface_t - * @width_in_points: new surface width, in points (1 point == 1/72.0 inch) - * @height_in_points: new surface height, in points (1 point == 1/72.0 inch) - * - * Changes the size of a PDF surface for the current (and - * subsequent) pages. - * - * This function should only be called before any drawing operations - * have been performed on the current page. The simplest way to do - * this is to call this function immediately after creating the - * surface or immediately after completing a page with either - * cairo_show_page() or cairo_copy_page(). - * - * Since: 1.2 - **/ -void -cairo_pdf_surface_set_size (cairo_surface_t *surface, - double width_in_points, - double height_in_points) -{ - cairo_pdf_surface_t *pdf_surface = NULL; /* hide compiler warning */ - cairo_status_t status; - - status = _extract_pdf_surface (surface, &pdf_surface); - if (status) { - status = _cairo_surface_set_error (surface, status); - return; - } - - _cairo_pdf_surface_set_size_internal (pdf_surface, - width_in_points, - height_in_points); - status = _cairo_paginated_surface_set_size (pdf_surface->paginated_surface, - width_in_points, - height_in_points); - if (status) - status = _cairo_surface_set_error (surface, status); -} - -static void -_cairo_pdf_surface_clear (cairo_pdf_surface_t *surface) -{ - int i, size; - cairo_pdf_pattern_t *pattern; - cairo_pdf_smask_group_t *group; - - size = _cairo_array_num_elements (&surface->patterns); - for (i = 0; i < size; i++) { - pattern = (cairo_pdf_pattern_t *) _cairo_array_index (&surface->patterns, i); - cairo_pattern_destroy (pattern->pattern); - } - _cairo_array_truncate (&surface->patterns, 0); - - size = _cairo_array_num_elements (&surface->smask_groups); - for (i = 0; i < size; i++) { - _cairo_array_copy_element (&surface->smask_groups, i, &group); - _cairo_pdf_smask_group_destroy (group); - } - _cairo_array_truncate (&surface->smask_groups, 0); - _cairo_array_truncate (&surface->knockout_group, 0); -} - -static void -_cairo_pdf_group_resources_init (cairo_pdf_group_resources_t *res) -{ - _cairo_array_init (&res->alphas, sizeof (double)); - _cairo_array_init (&res->smasks, sizeof (cairo_pdf_resource_t)); - _cairo_array_init (&res->patterns, sizeof (cairo_pdf_resource_t)); - _cairo_array_init (&res->xobjects, sizeof (cairo_pdf_resource_t)); - _cairo_array_init (&res->fonts, sizeof (cairo_pdf_font_t)); -} - -static void -_cairo_pdf_group_resources_fini (cairo_pdf_group_resources_t *res) -{ - _cairo_array_fini (&res->alphas); - _cairo_array_fini (&res->smasks); - _cairo_array_fini (&res->patterns); - _cairo_array_fini (&res->xobjects); - _cairo_array_fini (&res->fonts); -} - -static void -_cairo_pdf_group_resources_clear (cairo_pdf_group_resources_t *res) -{ - _cairo_array_truncate (&res->alphas, 0); - _cairo_array_truncate (&res->smasks, 0); - _cairo_array_truncate (&res->patterns, 0); - _cairo_array_truncate (&res->xobjects, 0); - _cairo_array_truncate (&res->fonts, 0); -} - -static cairo_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_pdf_group_resources_t *res = &surface->resources; - - num_alphas = _cairo_array_num_elements (&res->alphas); - for (i = 0; i < num_alphas; i++) { - _cairo_array_copy_element (&res->alphas, i, &other); - if (alpha == other) { - *index = i; - return CAIRO_STATUS_SUCCESS; - } - } - - status = _cairo_array_append (&res->alphas, &alpha); - if (status) - return status; - - *index = _cairo_array_num_elements (&res->alphas) - 1; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_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 -_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 -_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 -_cairo_pdf_surface_add_font (unsigned int font_id, - unsigned int subset_id, - void *closure) -{ - cairo_pdf_surface_t *surface = closure; - cairo_pdf_font_t font; - int num_fonts, i; - cairo_status_t status; - cairo_pdf_group_resources_t *res = &surface->resources; - - num_fonts = _cairo_array_num_elements (&res->fonts); - for (i = 0; i < num_fonts; i++) { - _cairo_array_copy_element (&res->fonts, i, &font); - if (font.font_id == font_id && - font.subset_id == subset_id) - return CAIRO_STATUS_SUCCESS; - } - - num_fonts = _cairo_array_num_elements (&surface->fonts); - for (i = 0; i < num_fonts; i++) { - _cairo_array_copy_element (&surface->fonts, i, &font); - if (font.font_id == font_id && - font.subset_id == subset_id) - return _cairo_array_append (&res->fonts, &font); - } - - font.font_id = font_id; - font.subset_id = subset_id; - font.subset_resource = _cairo_pdf_surface_new_object (surface); - if (font.subset_resource.id == 0) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - status = _cairo_array_append (&surface->fonts, &font); - if (status) - return status; - - return _cairo_array_append (&res->fonts, &font); -} - -static cairo_pdf_resource_t -_cairo_pdf_surface_get_font_resource (cairo_pdf_surface_t *surface, - unsigned int font_id, - unsigned int subset_id) -{ - cairo_pdf_font_t font; - int num_fonts, i; - - num_fonts = _cairo_array_num_elements (&surface->fonts); - for (i = 0; i < num_fonts; i++) { - _cairo_array_copy_element (&surface->fonts, i, &font); - if (font.font_id == font_id && font.subset_id == subset_id) - return font.subset_resource; - } - - font.subset_resource.id = 0; - return font.subset_resource; -} - -static void -_cairo_pdf_surface_emit_group_resources (cairo_pdf_surface_t *surface, - cairo_pdf_group_resources_t *res) -{ - int num_alphas, num_smasks, num_resources, i; - double alpha; - cairo_pdf_resource_t *smask, *pattern, *xobject; - cairo_pdf_font_t *font; - - _cairo_output_stream_printf (surface->output, "<<\n"); - - num_alphas = _cairo_array_num_elements (&res->alphas); - num_smasks = _cairo_array_num_elements (&res->smasks); - if (num_alphas > 0 || num_smasks > 0) { - _cairo_output_stream_printf (surface->output, - " /ExtGState <<\n"); - - for (i = 0; i < num_alphas; i++) { - _cairo_array_copy_element (&res->alphas, i, &alpha); - _cairo_output_stream_printf (surface->output, - " /a%d << /CA %f /ca %f >>\n", - i, alpha, alpha); - } - - for (i = 0; i < num_smasks; i++) { - smask = _cairo_array_index (&res->smasks, i); - _cairo_output_stream_printf (surface->output, - " /s%d %d 0 R\n", - smask->id, smask->id); - } - - _cairo_output_stream_printf (surface->output, - " >>\n"); - } - - num_resources = _cairo_array_num_elements (&res->patterns); - if (num_resources > 0) { - _cairo_output_stream_printf (surface->output, - " /Pattern <<"); - for (i = 0; i < num_resources; i++) { - pattern = _cairo_array_index (&res->patterns, i); - _cairo_output_stream_printf (surface->output, - " /p%d %d 0 R", - pattern->id, pattern->id); - } - - _cairo_output_stream_printf (surface->output, - " >>\n"); - } - - num_resources = _cairo_array_num_elements (&res->xobjects); - if (num_resources > 0) { - _cairo_output_stream_printf (surface->output, - " /XObject <<"); - - for (i = 0; i < num_resources; i++) { - xobject = _cairo_array_index (&res->xobjects, i); - _cairo_output_stream_printf (surface->output, - " /x%d %d 0 R", - xobject->id, xobject->id); - } - - _cairo_output_stream_printf (surface->output, - " >>\n"); - } - - num_resources = _cairo_array_num_elements (&res->fonts); - if (num_resources > 0) { - _cairo_output_stream_printf (surface->output," /Font <<\n"); - for (i = 0; i < num_resources; i++) { - font = _cairo_array_index (&res->fonts, i); - _cairo_output_stream_printf (surface->output, - " /f-%d-%d %d 0 R\n", - font->font_id, - font->subset_id, - font->subset_resource.id); - } - _cairo_output_stream_printf (surface->output, " >>\n"); - } - - _cairo_output_stream_printf (surface->output, - ">>\n"); -} - -static cairo_pdf_smask_group_t * -_cairo_pdf_surface_create_smask_group (cairo_pdf_surface_t *surface) -{ - cairo_pdf_smask_group_t *group; - - group = calloc (1, sizeof (cairo_pdf_smask_group_t)); - if (group == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return NULL; - } - - group->group_res = _cairo_pdf_surface_new_object (surface); - if (group->group_res.id == 0) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - free (group); - return NULL; - } - group->width = surface->width; - group->height = surface->height; - - return group; -} - -static void -_cairo_pdf_smask_group_destroy (cairo_pdf_smask_group_t *group) -{ - if (group->operation == PDF_FILL || group->operation == PDF_STROKE) - _cairo_path_fixed_fini (&group->path); - if (group->source) - cairo_pattern_destroy (group->source); - if (group->mask) - cairo_pattern_destroy (group->mask); - if (group->utf8) - free (group->utf8); - if (group->glyphs) - free (group->glyphs); - if (group->clusters) - free (group->clusters); - if (group->scaled_font) - cairo_scaled_font_destroy (group->scaled_font); - free (group); -} - -static cairo_status_t -_cairo_pdf_surface_add_smask_group (cairo_pdf_surface_t *surface, - cairo_pdf_smask_group_t *group) -{ - return _cairo_array_append (&surface->smask_groups, &group); -} - -static cairo_status_t -_cairo_pdf_surface_add_pdf_pattern (cairo_pdf_surface_t *surface, - cairo_pattern_t *pattern, - cairo_pdf_resource_t *pattern_res, - cairo_pdf_resource_t *gstate_res) -{ - cairo_pdf_pattern_t pdf_pattern; - cairo_status_t status; - - /* 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; - } - - if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR || - pattern->type == CAIRO_PATTERN_TYPE_RADIAL) - { - cairo_gradient_pattern_t *gradient; - - gradient = (cairo_gradient_pattern_t *) pattern; - - /* Gradients with zero stops do not produce any output */ - if (gradient->n_stops == 0) - return CAIRO_INT_STATUS_NOTHING_TO_DO; - - /* Gradients with one stop are the same as solid colors */ - if (gradient->n_stops == 1) { - pattern_res->id = 0; - gstate_res->id = 0; - return CAIRO_STATUS_SUCCESS; - } - } - - pdf_pattern.pattern = cairo_pattern_reference (pattern); - pdf_pattern.pattern_res = _cairo_pdf_surface_new_object (surface); - if (pdf_pattern.pattern_res.id == 0) { - cairo_pattern_destroy (pattern); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - pdf_pattern.gstate_res.id = 0; - - /* gradient patterns require an smask object to implement transparency */ - if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR || - pattern->type == CAIRO_PATTERN_TYPE_RADIAL) { - if (_cairo_pattern_is_opaque (pattern) == FALSE) { - pdf_pattern.gstate_res = _cairo_pdf_surface_new_object (surface); - if (pdf_pattern.gstate_res.id == 0) { - cairo_pattern_destroy (pattern); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - } - } - - pdf_pattern.width = surface->width; - pdf_pattern.height = surface->height; - *pattern_res = pdf_pattern.pattern_res; - *gstate_res = pdf_pattern.gstate_res; - - status = _cairo_array_append (&surface->patterns, &pdf_pattern); - if (status) { - cairo_pattern_destroy (pattern); - return status; - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_pdf_surface_open_stream (cairo_pdf_surface_t *surface, - cairo_pdf_resource_t *resource, - cairo_bool_t compressed, - const char *fmt, - ...) -{ - va_list ap; - cairo_pdf_resource_t self, length; - cairo_output_stream_t *output = NULL; - - if (resource) { - self = *resource; - _cairo_pdf_surface_update_object (surface, self); - } else { - self = _cairo_pdf_surface_new_object (surface); - if (self.id == 0) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - length = _cairo_pdf_surface_new_object (surface); - if (length.id == 0) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - if (compressed) { - output = _cairo_deflate_stream_create (surface->output); - if (_cairo_output_stream_get_status (output)) - return _cairo_output_stream_destroy (output); - } - - surface->pdf_stream.active = TRUE; - surface->pdf_stream.self = self; - surface->pdf_stream.length = length; - surface->pdf_stream.compressed = compressed; - surface->current_pattern_is_solid_color = FALSE; - _cairo_pdf_operators_reset (&surface->pdf_operators); - - _cairo_output_stream_printf (surface->output, - "%d 0 obj\n" - "<< /Length %d 0 R\n", - surface->pdf_stream.self.id, - surface->pdf_stream.length.id); - if (compressed) - _cairo_output_stream_printf (surface->output, - " /Filter /FlateDecode\n"); - - if (fmt != NULL) { - va_start (ap, fmt); - _cairo_output_stream_vprintf (surface->output, fmt, ap); - va_end (ap); - } - - _cairo_output_stream_printf (surface->output, - ">>\n" - "stream\n"); - - surface->pdf_stream.start_offset = _cairo_output_stream_get_position (surface->output); - - if (compressed) { - assert (surface->pdf_stream.old_output == NULL); - surface->pdf_stream.old_output = surface->output; - surface->output = output; - _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output); - } - - return _cairo_output_stream_get_status (surface->output); -} - -static cairo_status_t -_cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface) -{ - cairo_status_t status = CAIRO_STATUS_SUCCESS; - long length; - - if (! surface->pdf_stream.active) - return CAIRO_STATUS_SUCCESS; - - status = _cairo_pdf_operators_flush (&surface->pdf_operators); - if (status) - return status; - - if (surface->pdf_stream.compressed) { - status = _cairo_output_stream_destroy (surface->output); - surface->output = surface->pdf_stream.old_output; - _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output); - surface->pdf_stream.old_output = NULL; - _cairo_output_stream_printf (surface->output, - "\n"); - } - - length = _cairo_output_stream_get_position (surface->output) - - surface->pdf_stream.start_offset; - _cairo_output_stream_printf (surface->output, - "endstream\n" - "endobj\n"); - - _cairo_pdf_surface_update_object (surface, - surface->pdf_stream.length); - _cairo_output_stream_printf (surface->output, - "%d 0 obj\n" - " %ld\n" - "endobj\n", - surface->pdf_stream.length.id, - length); - - surface->pdf_stream.active = FALSE; - - if (status == CAIRO_STATUS_SUCCESS) - status = _cairo_output_stream_get_status (surface->output); - - return status; -} - -static void -_cairo_pdf_surface_write_memory_stream (cairo_pdf_surface_t *surface, - cairo_output_stream_t *mem_stream, - cairo_pdf_resource_t resource, - cairo_pdf_group_resources_t *resources, - cairo_bool_t is_knockout_group) -{ - _cairo_pdf_surface_update_object (surface, resource); - - _cairo_output_stream_printf (surface->output, - "%d 0 obj\n" - "<< /Type /XObject\n" - " /Length %d\n", - resource.id, - _cairo_memory_stream_length (mem_stream)); - - if (surface->compress_content) { - _cairo_output_stream_printf (surface->output, - " /Filter /FlateDecode\n"); - } - - _cairo_output_stream_printf (surface->output, - " /Subtype /Form\n" - " /BBox [ 0 0 %f %f ]\n" - " /Group <<\n" - " /Type /Group\n" - " /S /Transparency\n" - " /CS /DeviceRGB\n", - surface->width, - surface->height); - - if (is_knockout_group) - _cairo_output_stream_printf (surface->output, - " /K true\n"); - - _cairo_output_stream_printf (surface->output, - " >>\n" - " /Resources\n"); - _cairo_pdf_surface_emit_group_resources (surface, resources); - _cairo_output_stream_printf (surface->output, - ">>\n" - "stream\n"); - _cairo_memory_stream_copy (mem_stream, surface->output); - _cairo_output_stream_printf (surface->output, - "endstream\n" - "endobj\n"); -} - -static cairo_status_t -_cairo_pdf_surface_open_group (cairo_pdf_surface_t *surface, - cairo_pdf_resource_t *resource) -{ - cairo_status_t status; - - assert (surface->pdf_stream.active == FALSE); - assert (surface->group_stream.active == FALSE); - - surface->group_stream.active = TRUE; - surface->current_pattern_is_solid_color = FALSE; - _cairo_pdf_operators_reset (&surface->pdf_operators); - - surface->group_stream.mem_stream = _cairo_memory_stream_create (); - - if (surface->compress_content) { - surface->group_stream.stream = - _cairo_deflate_stream_create (surface->group_stream.mem_stream); - } else { - surface->group_stream.stream = surface->group_stream.mem_stream; - } - status = _cairo_output_stream_get_status (surface->group_stream.stream); - - surface->group_stream.old_output = surface->output; - surface->output = surface->group_stream.stream; - _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output); - _cairo_pdf_group_resources_clear (&surface->resources); - - if (resource) { - surface->group_stream.resource = *resource; - } else { - surface->group_stream.resource = _cairo_pdf_surface_new_object (surface); - if (surface->group_stream.resource.id == 0) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - surface->group_stream.is_knockout = FALSE; - - return status; -} - -static cairo_status_t -_cairo_pdf_surface_open_knockout_group (cairo_pdf_surface_t *surface) -{ - cairo_status_t status; - - status = _cairo_pdf_surface_open_group (surface, NULL); - if (status) - return status; - - surface->group_stream.is_knockout = TRUE; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_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; - - assert (surface->pdf_stream.active == FALSE); - assert (surface->group_stream.active == TRUE); - - status = _cairo_pdf_operators_flush (&surface->pdf_operators); - if (status) - return status; - - if (surface->compress_content) { - status = _cairo_output_stream_destroy (surface->group_stream.stream); - surface->group_stream.stream = NULL; - - _cairo_output_stream_printf (surface->group_stream.mem_stream, - "\n"); - } - surface->output = surface->group_stream.old_output; - _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output); - surface->group_stream.active = FALSE; - _cairo_pdf_surface_write_memory_stream (surface, - surface->group_stream.mem_stream, - surface->group_stream.resource, - &surface->resources, - surface->group_stream.is_knockout); - if (group) - *group = surface->group_stream.resource; - - status2 = _cairo_output_stream_destroy (surface->group_stream.mem_stream); - if (status == CAIRO_STATUS_SUCCESS) - status = status2; - - surface->group_stream.mem_stream = NULL; - surface->group_stream.stream = NULL; - - return status; -} - -static cairo_status_t -_cairo_pdf_surface_open_content_stream (cairo_pdf_surface_t *surface, - cairo_bool_t is_form) -{ - cairo_status_t status; - - assert (surface->pdf_stream.active == FALSE); - assert (surface->group_stream.active == FALSE); - - surface->content_resources = _cairo_pdf_surface_new_object (surface); - if (surface->content_resources.id == 0) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - if (is_form) { - status = - _cairo_pdf_surface_open_stream (surface, - NULL, - surface->compress_content, - " /Type /XObject\n" - " /Subtype /Form\n" - " /BBox [ 0 0 %f %f ]\n" - " /Group <<\n" - " /Type /Group\n" - " /S /Transparency\n" - " /CS /DeviceRGB\n" - " >>\n" - " /Resources %d 0 R\n", - surface->width, - surface->height, - surface->content_resources.id); - } else { - status = - _cairo_pdf_surface_open_stream (surface, - NULL, - surface->compress_content, - NULL); - } - if (status) - return status; - - surface->content = surface->pdf_stream.self; - - _cairo_output_stream_printf (surface->output, "q\n"); - - return _cairo_output_stream_get_status (surface->output); -} - -static cairo_status_t -_cairo_pdf_surface_close_content_stream (cairo_pdf_surface_t *surface) -{ - cairo_status_t status; - - assert (surface->pdf_stream.active == TRUE); - assert (surface->group_stream.active == FALSE); - - status = _cairo_pdf_operators_flush (&surface->pdf_operators); - if (status) - return status; - - _cairo_output_stream_printf (surface->output, "Q\n"); - status = _cairo_pdf_surface_close_stream (surface); - if (status) - return status; - - _cairo_pdf_surface_update_object (surface, surface->content_resources); - _cairo_output_stream_printf (surface->output, - "%d 0 obj\n", - surface->content_resources.id); - _cairo_pdf_surface_emit_group_resources (surface, &surface->resources); - _cairo_output_stream_printf (surface->output, - "endobj\n"); - - return _cairo_output_stream_get_status (surface->output); -} - -static cairo_surface_t * -_cairo_pdf_surface_create_similar (void *abstract_surface, - cairo_content_t content, - int width, - int height) -{ - return _cairo_meta_surface_create (content, width, height); -} - -static cairo_status_t -_cairo_pdf_surface_finish (void *abstract_surface) -{ - cairo_pdf_surface_t *surface = abstract_surface; - long offset; - cairo_pdf_resource_t info, catalog; - cairo_status_t status, status2; - - status = surface->base.status; - if (status == CAIRO_STATUS_SUCCESS) - status = _cairo_pdf_surface_emit_font_subsets (surface); - - _cairo_pdf_surface_write_pages (surface); - - info = _cairo_pdf_surface_write_info (surface); - if (info.id == 0 && status == CAIRO_STATUS_SUCCESS) - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - - catalog = _cairo_pdf_surface_write_catalog (surface); - if (catalog.id == 0 && status == CAIRO_STATUS_SUCCESS) - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - - offset = _cairo_pdf_surface_write_xref (surface); - - _cairo_output_stream_printf (surface->output, - "trailer\n" - "<< /Size %d\n" - " /Root %d 0 R\n" - " /Info %d 0 R\n" - ">>\n", - surface->next_available_resource.id, - catalog.id, - info.id); - - _cairo_output_stream_printf (surface->output, - "startxref\n" - "%ld\n" - "%%%%EOF\n", - offset); - - status2 = _cairo_pdf_operators_fini (&surface->pdf_operators); - /* pdf_operators has already been flushed when the last stream was - * closed so we should never be writing anything here. */ - assert(status2 == CAIRO_STATUS_SUCCESS); - - /* close any active streams still open due to fatal errors */ - status2 = _cairo_pdf_surface_close_stream (surface); - if (status == CAIRO_STATUS_SUCCESS) - status = status2; - - if (surface->group_stream.stream != NULL) { - status2 = _cairo_output_stream_destroy (surface->group_stream.stream); - if (status == CAIRO_STATUS_SUCCESS) - status = status2; - } - if (surface->group_stream.mem_stream != NULL) { - status2 = _cairo_output_stream_destroy (surface->group_stream.mem_stream); - if (status == CAIRO_STATUS_SUCCESS) - status = status2; - } - if (surface->pdf_stream.active) - surface->output = surface->pdf_stream.old_output; - if (surface->group_stream.active) - surface->output = surface->group_stream.old_output; - - /* and finish the pdf surface */ - status2 = _cairo_output_stream_destroy (surface->output); - if (status == CAIRO_STATUS_SUCCESS) - status = status2; - - _cairo_pdf_surface_clear (surface); - _cairo_pdf_group_resources_fini (&surface->resources); - - _cairo_array_fini (&surface->objects); - _cairo_array_fini (&surface->pages); - _cairo_array_fini (&surface->rgb_linear_functions); - _cairo_array_fini (&surface->alpha_linear_functions); - _cairo_array_fini (&surface->patterns); - _cairo_array_fini (&surface->smask_groups); - _cairo_array_fini (&surface->fonts); - _cairo_array_fini (&surface->knockout_group); - - if (surface->font_subsets) { - _cairo_scaled_font_subsets_destroy (surface->font_subsets); - surface->font_subsets = NULL; - } - - return status; -} - -static cairo_int_status_t -_cairo_pdf_surface_start_page (void *abstract_surface) -{ - cairo_pdf_surface_t *surface = abstract_surface; - - _cairo_pdf_group_resources_clear (&surface->resources); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_pdf_surface_has_fallback_images (void *abstract_surface, - cairo_bool_t has_fallbacks) -{ - cairo_status_t status; - cairo_pdf_surface_t *surface = abstract_surface; - - surface->has_fallback_images = has_fallbacks; - status = _cairo_pdf_surface_open_content_stream (surface, has_fallbacks); - if (status) - return status; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_bool_t -_cairo_pdf_surface_supports_fine_grained_fallbacks (void *abstract_surface) -{ - return TRUE; -} - -/* 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. - */ -static cairo_status_t -_cairo_pdf_surface_emit_smask (cairo_pdf_surface_t *surface, - cairo_image_surface_t *image, - cairo_pdf_resource_t *stream_ret) -{ - cairo_status_t status = CAIRO_STATUS_SUCCESS; - char *alpha; - unsigned long alpha_size; - uint32_t *pixel32; - uint8_t *pixel8; - int i, x, y; - cairo_bool_t opaque; - uint8_t a; - - /* This is the only image format we support, which simplifies things. */ - assert (image->format == CAIRO_FORMAT_ARGB32 || - image->format == CAIRO_FORMAT_A8 || - image->format == CAIRO_FORMAT_A1 ); - - stream_ret->id = 0; - - if (image->format == CAIRO_FORMAT_A1) { - alpha_size = (image->width + 7) / 8 * image->height; - alpha = _cairo_malloc_ab ((image->width+7) / 8, image->height); - } else { - alpha_size = image->height * image->width; - alpha = _cairo_malloc_ab (image->height, image->width); - } - - if (alpha == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto CLEANUP; - } - - opaque = TRUE; - i = 0; - for (y = 0; y < image->height; y++) { - if (image->format == CAIRO_FORMAT_ARGB32) { - pixel32 = (uint32_t *) (image->data + y * image->stride); - - for (x = 0; x < image->width; x++, pixel32++) { - a = (*pixel32 & 0xff000000) >> 24; - alpha[i++] = a; - if (a != 0xff) - opaque = FALSE; - } - } else if (image->format == CAIRO_FORMAT_A8){ - pixel8 = (uint8_t *) (image->data + y * image->stride); - - for (x = 0; x < image->width; x++, pixel8++) { - a = *pixel8; - alpha[i++] = a; - if (a != 0xff) - opaque = FALSE; - } - } else { /* image->format == CAIRO_FORMAT_A1 */ - pixel8 = (uint8_t *) (image->data + y * image->stride); - - for (x = 0; x < (image->width + 7) / 8; x++, pixel8++) { - a = *pixel8; - a = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (a); - alpha[i++] = a; - if (a != 0xff) - opaque = FALSE; - } - } - } - - /* Bail out without emitting smask if it's all opaque. */ - if (opaque) - goto CLEANUP_ALPHA; - - status = _cairo_pdf_surface_open_stream (surface, - NULL, - TRUE, - " /Type /XObject\n" - " /Subtype /Image\n" - " /Width %d\n" - " /Height %d\n" - " /ColorSpace /DeviceGray\n" - " /BitsPerComponent %d\n", - image->width, image->height, - image->format == CAIRO_FORMAT_A1 ? 1 : 8); - if (status) - goto CLEANUP_ALPHA; - - *stream_ret = surface->pdf_stream.self; - _cairo_output_stream_write (surface->output, alpha, alpha_size); - status = _cairo_pdf_surface_close_stream (surface); - - CLEANUP_ALPHA: - free (alpha); - CLEANUP: - 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, - cairo_pdf_resource_t *image_ret) -{ - cairo_status_t status = CAIRO_STATUS_SUCCESS; - char *rgb; - unsigned long rgb_size; - uint32_t *pixel; - int i, x, y; - cairo_pdf_resource_t smask = {0}; /* squelch bogus compiler warning */ - cairo_bool_t need_smask; - - /* These are the only image formats we currently support, (which - * makes things a lot simpler here). This is enforced through - * _cairo_pdf_surface_analyze_operation which only accept source surfaces of - * CONTENT_COLOR or CONTENT_COLOR_ALPHA. - */ - assert (image->format == CAIRO_FORMAT_RGB24 || - image->format == CAIRO_FORMAT_ARGB32 || - image->format == CAIRO_FORMAT_A8 || - image->format == CAIRO_FORMAT_A1); - - rgb_size = image->height * image->width * 3; - rgb = _cairo_malloc_abc (image->width, image->height, 3); - if (rgb == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto CLEANUP; - } - - i = 0; - for (y = 0; y < image->height; y++) { - pixel = (uint32_t *) (image->data + y * image->stride); - - for (x = 0; x < image->width; x++, pixel++) { - /* XXX: We're un-premultiplying alpha here. My reading of the PDF - * specification suggests that we should be able to avoid having - * to do this by filling in the SMask's Matte dictionary - * appropriately, but my attempts to do that so far have - * failed. */ - if (image->format == CAIRO_FORMAT_ARGB32) { - uint8_t a; - a = (*pixel & 0xff000000) >> 24; - if (a == 0) { - rgb[i++] = 0; - rgb[i++] = 0; - rgb[i++] = 0; - } else { - rgb[i++] = (((*pixel & 0xff0000) >> 16) * 255 + a / 2) / a; - rgb[i++] = (((*pixel & 0x00ff00) >> 8) * 255 + a / 2) / a; - rgb[i++] = (((*pixel & 0x0000ff) >> 0) * 255 + a / 2) / a; - } - } else if (image->format == CAIRO_FORMAT_RGB24) { - rgb[i++] = (*pixel & 0x00ff0000) >> 16; - rgb[i++] = (*pixel & 0x0000ff00) >> 8; - rgb[i++] = (*pixel & 0x000000ff) >> 0; - } else { - rgb[i++] = 0; - rgb[i++] = 0; - rgb[i++] = 0; - } - } - } - - 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, &smask); - if (status) - goto CLEANUP_RGB; - - if (smask.id) - need_smask = TRUE; - } - -#define IMAGE_DICTIONARY " /Type /XObject\n" \ - " /Subtype /Image\n" \ - " /Width %d\n" \ - " /Height %d\n" \ - " /ColorSpace /DeviceRGB\n" \ - " /BitsPerComponent 8\n" - - if (need_smask) - status = _cairo_pdf_surface_open_stream (surface, - NULL, - TRUE, - IMAGE_DICTIONARY - " /SMask %d 0 R\n", - image->width, image->height, - smask.id); - else - status = _cairo_pdf_surface_open_stream (surface, - NULL, - TRUE, - IMAGE_DICTIONARY, - image->width, image->height); - if (status) - goto CLEANUP_RGB; - -#undef IMAGE_DICTIONARY - - *image_ret = surface->pdf_stream.self; - _cairo_output_stream_write (surface->output, rgb, rgb_size); - status = _cairo_pdf_surface_close_stream (surface); - -CLEANUP_RGB: - free (rgb); -CLEANUP: - return status; -} - -static cairo_status_t -_cairo_pdf_surface_emit_image_surface (cairo_pdf_surface_t *surface, - cairo_surface_pattern_t *pattern, - cairo_pdf_resource_t *resource, - int *width, - int *height) -{ - cairo_image_surface_t *image; - void *image_extra; - cairo_status_t status; - - status = _cairo_surface_acquire_source_image (pattern->surface, &image, &image_extra); - if (status) - goto BAIL; - - status = _cairo_pdf_surface_emit_image (surface, image, resource); - if (status) - goto BAIL; - - *width = image->width; - *height = image->height; - -BAIL: - _cairo_surface_release_source_image (pattern->surface, image, image_extra); - - return status; -} - -static cairo_status_t -_cairo_pdf_surface_emit_meta_surface (cairo_pdf_surface_t *surface, - cairo_surface_t *meta_surface, - cairo_pdf_resource_t *resource) -{ - double old_width, old_height; - cairo_paginated_mode_t old_paginated_mode; - cairo_clip_t *old_clip; - cairo_rectangle_int_t meta_extents; - cairo_status_t status; - int alpha = 0; - - status = _cairo_surface_get_extents (meta_surface, &meta_extents); - if (status) - return status; - - old_width = surface->width; - old_height = surface->height; - old_paginated_mode = surface->paginated_mode; - old_clip = _cairo_surface_get_clip (&surface->base); - _cairo_pdf_surface_set_size_internal (surface, - meta_extents.width, - meta_extents.height); - /* Patterns are emitted after fallback images. The paginated mode - * needs to be set to _RENDER while the meta surface is replayed - * back to this surface. - */ - surface->paginated_mode = CAIRO_PAGINATED_MODE_RENDER; - _cairo_pdf_group_resources_clear (&surface->resources); - status = _cairo_pdf_surface_open_content_stream (surface, TRUE); - if (status) - return status; - - *resource = surface->content; - if (cairo_surface_get_content (meta_surface) == CAIRO_CONTENT_COLOR) { - status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha); - if (status) - return status; - - _cairo_output_stream_printf (surface->output, - "q /a%d gs 0 0 0 rg 0 0 %f %f re f Q\n", - alpha, - surface->width, - surface->height); - } - - status = _cairo_meta_surface_replay_region (meta_surface, &surface->base, - CAIRO_META_REGION_NATIVE); - assert (status != CAIRO_INT_STATUS_UNSUPPORTED); - if (status) - return status; - - status = _cairo_surface_set_clip (&surface->base, old_clip); - if (status) - return status; - - status = _cairo_pdf_surface_close_content_stream (surface); - - _cairo_pdf_surface_set_size_internal (surface, - old_width, - old_height); - surface->paginated_mode = old_paginated_mode; - - return status; -} - -static cairo_status_t -_cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface, - cairo_pdf_pattern_t *pdf_pattern) -{ - cairo_surface_pattern_t *pattern = (cairo_surface_pattern_t *) pdf_pattern->pattern; - cairo_status_t status; - cairo_pdf_resource_t pattern_resource = {0}; /* squelch bogus compiler warning */ - cairo_matrix_t cairo_p2d, pdf_p2d; - cairo_extend_t extend = cairo_pattern_get_extend (&pattern->base); - double xstep, ystep; - cairo_rectangle_int_t surface_extents; - int pattern_width = 0; /* squelch bogus compiler warning */ - int pattern_height = 0; /* squelch bogus compiler warning */ - int bbox_x, bbox_y; - char draw_surface[200]; - - if (_cairo_surface_is_meta (pattern->surface)) { - cairo_surface_t *meta_surface = pattern->surface; - cairo_rectangle_int_t pattern_extents; - - status = _cairo_pdf_surface_emit_meta_surface (surface, - meta_surface, - &pattern_resource); - if (status) - return status; - - status = _cairo_surface_get_extents (meta_surface, &pattern_extents); - if (status) - return status; - - pattern_width = pattern_extents.width; - pattern_height = pattern_extents.height; - } else { - status = _cairo_pdf_surface_emit_image_surface (surface, - pattern, - &pattern_resource, - &pattern_width, - &pattern_height); - if (status) - return status; - } - - status = _cairo_surface_get_extents (&surface->base, &surface_extents); - if (status) - return status; - - bbox_x = pattern_width; - bbox_y = pattern_height; - switch (extend) { - /* We implement EXTEND_PAD like EXTEND_NONE for now */ - case CAIRO_EXTEND_PAD: - case CAIRO_EXTEND_NONE: - { - /* In PS/PDF, (as far as I can tell), all patterns are - * repeating. So we support cairo's EXTEND_NONE semantics - * by setting the repeat step size to a size large enough - * to guarantee that no more than a single occurrence will - * be visible. - * - * First, map the surface extents into pattern space (since - * xstep and ystep are in pattern space). Then use an upper - * bound on the length of the diagonal of the pattern image - * and the surface as repeat size. This guarantees to never - * repeat visibly. - */ - double x1 = 0.0, y1 = 0.0; - double x2 = surface->width, y2 = surface->height; - _cairo_matrix_transform_bounding_box (&pattern->base.matrix, - &x1, &y1, &x2, &y2, - NULL); - - /* Rather than computing precise bounds of the union, just - * add the surface extents unconditionally. We only - * required an answer that's large enough, we don't really - * care if it's not as tight as possible.*/ - xstep = ystep = ceil ((x2 - x1) + (y2 - y1) + - pattern_width + pattern_height); - } - break; - case CAIRO_EXTEND_REPEAT: - xstep = pattern_width; - ystep = pattern_height; - break; - case CAIRO_EXTEND_REFLECT: - bbox_x = pattern_width*2; - bbox_y = pattern_height*2; - xstep = bbox_x; - ystep = bbox_y; - break; - /* All the rest (if any) should have been analyzed away, so this - * case should be unreachable. */ - default: - ASSERT_NOT_REACHED; - xstep = 0; - ystep = 0; - } - - /* At this point, (that is, within the surface backend interface), - * the pattern's matrix maps from cairo's device space to cairo's - * pattern space, (both with their origin at the upper-left, and - * cairo's pattern space of size width,height). - * - * Then, we must emit a PDF pattern object that maps from its own - * pattern space, (which has a size that we establish in the BBox - * dictionary entry), to the PDF page's *initial* space, (which - * does not benefit from the Y-axis flipping matrix that we emit - * on each page). So the PDF patterns matrix maps from a - * (width,height) pattern space to a device space with the origin - * in the lower-left corner. - * - * So to handle all of that, we start with an identity matrix for - * the PDF pattern to device matrix. We translate it up by the - * image height then flip it in the Y direction, (moving us from - * the PDF origin to cairo's origin). We then multiply in the - * inverse of the cairo pattern matrix, (since it maps from device - * to pattern, while we're setting up pattern to device). Finally, - * we translate back down by the image height and flip again to - * end up at the lower-left origin that PDF expects. - * - * Additionally, within the stream that paints the pattern itself, - * we are using a PDF image object that has a size of (1,1) so we - * have to scale it up by the image width and height to fill our - * pattern cell. - */ - cairo_p2d = pattern->base.matrix; - status = cairo_matrix_invert (&cairo_p2d); - /* cairo_pattern_set_matrix ensures the matrix is invertible */ - assert (status == CAIRO_STATUS_SUCCESS); - - cairo_matrix_init_identity (&pdf_p2d); - cairo_matrix_translate (&pdf_p2d, 0.0, surface_extents.height); - cairo_matrix_scale (&pdf_p2d, 1.0, -1.0); - cairo_matrix_multiply (&pdf_p2d, &cairo_p2d, &pdf_p2d); - cairo_matrix_translate (&pdf_p2d, 0.0, pattern_height); - cairo_matrix_scale (&pdf_p2d, 1.0, -1.0); - - _cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res); - status = _cairo_pdf_surface_open_stream (surface, - &pdf_pattern->pattern_res, - FALSE, - " /PatternType 1\n" - " /BBox [0 0 %d %d]\n" - " /XStep %f\n" - " /YStep %f\n" - " /TilingType 1\n" - " /PaintType 1\n" - " /Matrix [ %f %f %f %f %f %f ]\n" - " /Resources << /XObject << /x%d %d 0 R >> >>\n", - bbox_x, bbox_y, - xstep, ystep, - pdf_p2d.xx, pdf_p2d.yx, - pdf_p2d.xy, pdf_p2d.yy, - pdf_p2d.x0, pdf_p2d.y0, - pattern_resource.id, - pattern_resource.id); - if (status) - return status; - - if (_cairo_surface_is_meta (pattern->surface)) { - snprintf(draw_surface, - sizeof (draw_surface), - "/x%d Do\n", - pattern_resource.id); - } else { - snprintf(draw_surface, - sizeof (draw_surface), - "q %d 0 0 %d 0 0 cm /x%d Do Q", - pattern_width, - pattern_height, - pattern_resource.id); - } - - if (extend == CAIRO_EXTEND_REFLECT) { - _cairo_output_stream_printf (surface->output, - "q 0 0 %d %d re W n %s Q\n" - "q -1 0 0 1 %d 0 cm 0 0 %d %d re W n %s Q\n" - "q 1 0 0 -1 0 %d cm 0 0 %d %d re W n %s Q\n" - "q -1 0 0 -1 %d %d cm 0 0 %d %d re W n %s Q\n", - pattern_width, pattern_height, - draw_surface, - pattern_width*2, pattern_width, pattern_height, - draw_surface, - pattern_height*2, pattern_width, pattern_height, - draw_surface, - pattern_width*2, pattern_height*2, pattern_width, pattern_height, - draw_surface); - } else { - _cairo_output_stream_printf (surface->output, - " %s \n", - draw_surface); - } - - status = _cairo_pdf_surface_close_stream (surface); - if (status) - return status; - - return _cairo_output_stream_get_status (surface->output); -} - -typedef struct _cairo_pdf_color_stop { - double offset; - double color[4]; - cairo_pdf_resource_t resource; -} cairo_pdf_color_stop_t; - -static cairo_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, - cairo_pdf_resource_t *function) -{ - int num_elems, i; - cairo_pdf_rgb_linear_function_t elem; - cairo_pdf_resource_t res; - cairo_status_t status; - - num_elems = _cairo_array_num_elements (&surface->rgb_linear_functions); - for (i = 0; i < num_elems; i++) { - _cairo_array_copy_element (&surface->rgb_linear_functions, i, &elem); - if (memcmp (&elem.color1[0], &stop1->color[0], sizeof (double)*3) != 0) - continue; - if (memcmp (&elem.color2[0], &stop2->color[0], sizeof (double)*3) != 0) - continue; - *function = elem.resource; - return CAIRO_STATUS_SUCCESS; - } - - res = _cairo_pdf_surface_new_object (surface); - if (res.id == 0) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - _cairo_output_stream_printf (surface->output, - "%d 0 obj\n" - "<< /FunctionType 2\n" - " /Domain [ 0 1 ]\n" - " /C0 [ %f %f %f ]\n" - " /C1 [ %f %f %f ]\n" - " /N 1\n" - ">>\n" - "endobj\n", - res.id, - stop1->color[0], - stop1->color[1], - stop1->color[2], - stop2->color[0], - stop2->color[1], - stop2->color[2]); - - elem.resource = res; - memcpy (&elem.color1[0], &stop1->color[0], sizeof (double)*3); - memcpy (&elem.color2[0], &stop2->color[0], sizeof (double)*3); - - status = _cairo_array_append (&surface->rgb_linear_functions, &elem); - *function = res; - - return status; -} - -static cairo_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, - cairo_pdf_resource_t *function) -{ - int num_elems, i; - cairo_pdf_alpha_linear_function_t elem; - cairo_pdf_resource_t res; - cairo_status_t status; - - num_elems = _cairo_array_num_elements (&surface->alpha_linear_functions); - for (i = 0; i < num_elems; i++) { - _cairo_array_copy_element (&surface->alpha_linear_functions, i, &elem); - if (elem.alpha1 != stop1->color[3]) - continue; - if (elem.alpha2 != stop2->color[3]) - continue; - *function = elem.resource; - return CAIRO_STATUS_SUCCESS; - } - - res = _cairo_pdf_surface_new_object (surface); - if (res.id == 0) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - _cairo_output_stream_printf (surface->output, - "%d 0 obj\n" - "<< /FunctionType 2\n" - " /Domain [ 0 1 ]\n" - " /C0 [ %f ]\n" - " /C1 [ %f ]\n" - " /N 1\n" - ">>\n" - "endobj\n", - res.id, - stop1->color[3], - stop2->color[3]); - - elem.resource = res; - elem.alpha1 = stop1->color[3]; - elem.alpha2 = stop2->color[3]; - - status = _cairo_array_append (&surface->alpha_linear_functions, &elem); - *function = res; - - return status; -} - -static cairo_status_t -_cairo_pdf_surface_emit_stitched_colorgradient (cairo_pdf_surface_t *surface, - unsigned int n_stops, - cairo_pdf_color_stop_t *stops, - cairo_bool_t is_alpha, - cairo_pdf_resource_t *function) -{ - cairo_pdf_resource_t res; - unsigned int i; - cairo_status_t status; - - /* emit linear gradients between pairs of subsequent stops... */ - for (i = 0; i < n_stops-1; i++) { - if (is_alpha) { - status = cairo_pdf_surface_emit_alpha_linear_function (surface, - &stops[i], - &stops[i+1], - &stops[i].resource); - if (status) - return status; - } else { - status = cairo_pdf_surface_emit_rgb_linear_function (surface, - &stops[i], - &stops[i+1], - &stops[i].resource); - if (status) - return status; - } - } - - /* ... and stitch them together */ - res = _cairo_pdf_surface_new_object (surface); - if (res.id == 0) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - _cairo_output_stream_printf (surface->output, - "%d 0 obj\n" - "<< /FunctionType 3\n" - " /Domain [ %f %f ]\n", - res.id, - stops[0].offset, - stops[n_stops - 1].offset); - - _cairo_output_stream_printf (surface->output, - " /Functions [ "); - for (i = 0; i < n_stops-1; i++) - _cairo_output_stream_printf (surface->output, - "%d 0 R ", stops[i].resource.id); - _cairo_output_stream_printf (surface->output, - "]\n"); - - _cairo_output_stream_printf (surface->output, - " /Bounds [ "); - for (i = 1; i < n_stops-1; i++) - _cairo_output_stream_printf (surface->output, - "%f ", stops[i].offset); - _cairo_output_stream_printf (surface->output, - "]\n"); - - _cairo_output_stream_printf (surface->output, - " /Encode [ "); - for (i = 1; i < n_stops; i++) - _cairo_output_stream_printf (surface->output, - "0 1 "); - _cairo_output_stream_printf (surface->output, - "]\n"); - - _cairo_output_stream_printf (surface->output, - ">>\n" - "endobj\n"); - - *function = res; - - return _cairo_output_stream_get_status (surface->output); -} - - -static void -calc_gradient_color (cairo_pdf_color_stop_t *new_stop, - cairo_pdf_color_stop_t *stop1, - cairo_pdf_color_stop_t *stop2) -{ - int i; - double offset = stop1->offset / (stop1->offset + 1.0 - stop2->offset); - - for (i = 0; i < 4; i++) - new_stop->color[i] = stop1->color[i] + offset*(stop2->color[i] - stop1->color[i]); -} - -#define COLOR_STOP_EPSILON 1e-6 - -static cairo_status_t -_cairo_pdf_surface_emit_pattern_stops (cairo_pdf_surface_t *surface, - cairo_gradient_pattern_t *pattern, - cairo_pdf_resource_t *color_function, - cairo_pdf_resource_t *alpha_function) -{ - cairo_pdf_color_stop_t *allstops, *stops; - unsigned int n_stops; - unsigned int i; - cairo_bool_t emit_alpha = FALSE; - cairo_status_t status; - - color_function->id = 0; - alpha_function->id = 0; - - allstops = _cairo_malloc_ab ((pattern->n_stops + 2), sizeof (cairo_pdf_color_stop_t)); - if (allstops == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - stops = &allstops[1]; - n_stops = pattern->n_stops; - - for (i = 0; i < n_stops; i++) { - stops[i].color[0] = pattern->stops[i].color.red; - stops[i].color[1] = pattern->stops[i].color.green; - stops[i].color[2] = pattern->stops[i].color.blue; - stops[i].color[3] = pattern->stops[i].color.alpha; - if (!CAIRO_ALPHA_IS_OPAQUE (stops[i].color[3])) - emit_alpha = TRUE; - stops[i].offset = pattern->stops[i].offset; - } - - if (pattern->base.extend == CAIRO_EXTEND_REPEAT || - pattern->base.extend == CAIRO_EXTEND_REFLECT) { - if (stops[0].offset > COLOR_STOP_EPSILON) { - if (pattern->base.extend == CAIRO_EXTEND_REFLECT) - memcpy (allstops, stops, sizeof (cairo_pdf_color_stop_t)); - else - calc_gradient_color (&allstops[0], &stops[0], &stops[n_stops-1]); - stops = allstops; - n_stops++; - } - stops[0].offset = 0.0; - - if (stops[n_stops-1].offset < 1.0 - COLOR_STOP_EPSILON) { - if (pattern->base.extend == CAIRO_EXTEND_REFLECT) { - memcpy (&stops[n_stops], - &stops[n_stops - 1], - sizeof (cairo_pdf_color_stop_t)); - } else { - calc_gradient_color (&stops[n_stops], &stops[0], &stops[n_stops-1]); - } - n_stops++; - } - stops[n_stops-1].offset = 1.0; - } - - if (n_stops == 2) { - /* no need for stitched function */ - status = cairo_pdf_surface_emit_rgb_linear_function (surface, - &stops[0], - &stops[1], - color_function); - if (status) - goto BAIL; - - if (emit_alpha) { - status = cairo_pdf_surface_emit_alpha_linear_function (surface, - &stops[0], - &stops[1], - alpha_function); - if (status) - goto BAIL; - } - } else { - /* multiple stops: stitch. XXX possible optimization: regularly spaced - * stops do not require stitching. XXX */ - status = _cairo_pdf_surface_emit_stitched_colorgradient (surface, - n_stops, - stops, - FALSE, - color_function); - if (status) - goto BAIL; - - if (emit_alpha) { - status = _cairo_pdf_surface_emit_stitched_colorgradient (surface, - n_stops, - stops, - TRUE, - alpha_function); - if (status) - goto BAIL; - } - } - -BAIL: - free (allstops); - return status; -} - -static cairo_status_t -_cairo_pdf_surface_emit_repeating_function (cairo_pdf_surface_t *surface, - cairo_gradient_pattern_t *pattern, - cairo_pdf_resource_t *function, - int begin, - int end) -{ - cairo_pdf_resource_t res; - int i; - - res = _cairo_pdf_surface_new_object (surface); - if (res.id == 0) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - _cairo_output_stream_printf (surface->output, - "%d 0 obj\n" - "<< /FunctionType 3\n" - " /Domain [ %d %d ]\n", - res.id, - begin, - end); - - _cairo_output_stream_printf (surface->output, - " /Functions [ "); - for (i = begin; i < end; i++) - _cairo_output_stream_printf (surface->output, - "%d 0 R ", function->id); - _cairo_output_stream_printf (surface->output, - "]\n"); - - _cairo_output_stream_printf (surface->output, - " /Bounds [ "); - for (i = begin + 1; i < end; i++) - _cairo_output_stream_printf (surface->output, - "%d ", i); - _cairo_output_stream_printf (surface->output, - "]\n"); - - _cairo_output_stream_printf (surface->output, - " /Encode [ "); - for (i = begin; i < end; i++) { - if ((i % 2) && pattern->base.extend == CAIRO_EXTEND_REFLECT) { - _cairo_output_stream_printf (surface->output, - "1 0 "); - } else { - _cairo_output_stream_printf (surface->output, - "0 1 "); - } - } - _cairo_output_stream_printf (surface->output, - "]\n"); - - _cairo_output_stream_printf (surface->output, - ">>\n" - "endobj\n"); - - *function = res; - - return _cairo_output_stream_get_status (surface->output); -} - -static cairo_status_t -cairo_pdf_surface_emit_transparency_group (cairo_pdf_surface_t *surface, - cairo_pdf_resource_t gstate_resource, - cairo_pdf_resource_t gradient_mask) -{ - cairo_pdf_resource_t smask_resource; - cairo_status_t status; - - status = _cairo_pdf_surface_open_stream (surface, - NULL, - surface->compress_content, - " /Type /XObject\n" - " /Subtype /Form\n" - " /FormType 1\n" - " /BBox [ 0 0 %f %f ]\n" - " /Resources\n" - " << /ExtGState\n" - " << /a0 << /ca 1 /CA 1 >>" - " >>\n" - " /Pattern\n" - " << /p%d %d 0 R >>\n" - " >>\n" - " /Group\n" - " << /Type /Group\n" - " /S /Transparency\n" - " /CS /DeviceGray\n" - " >>\n", - surface->width, - surface->height, - gradient_mask.id, - gradient_mask.id); - if (status) - return status; - - _cairo_output_stream_printf (surface->output, - "q\n" - "/a0 gs\n" - "/Pattern cs /p%d scn\n" - "0 0 %f %f re\n" - "f\n" - "Q\n", - gradient_mask.id, - surface->width, - surface->height); - - status = _cairo_pdf_surface_close_stream (surface); - if (status) - return status; - - smask_resource = _cairo_pdf_surface_new_object (surface); - if (smask_resource.id == 0) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - _cairo_output_stream_printf (surface->output, - "%d 0 obj\n" - "<< /Type /Mask\n" - " /S /Luminosity\n" - " /G %d 0 R\n" - ">>\n" - "endobj\n", - smask_resource.id, - surface->pdf_stream.self.id); - - /* Create GState which uses the transparency group as an SMask. */ - _cairo_pdf_surface_update_object (surface, gstate_resource); - - _cairo_output_stream_printf (surface->output, - "%d 0 obj\n" - "<< /Type /ExtGState\n" - " /SMask %d 0 R\n" - " /ca 1\n" - " /CA 1\n" - " /AIS false\n" - ">>\n" - "endobj\n", - gstate_resource.id, - smask_resource.id); - - return _cairo_output_stream_get_status (surface->output); -} - -static cairo_status_t -_cairo_pdf_surface_emit_linear_pattern (cairo_pdf_surface_t *surface, - cairo_pdf_pattern_t *pdf_pattern) -{ - cairo_linear_pattern_t *pattern = (cairo_linear_pattern_t *) pdf_pattern->pattern; - cairo_pdf_resource_t color_function, alpha_function; - double x1, y1, x2, y2; - double _x1, _y1, _x2, _y2; - cairo_matrix_t pat_to_pdf; - cairo_extend_t extend; - cairo_status_t status; - cairo_gradient_pattern_t *gradient = &pattern->base; - double first_stop, last_stop; - int repeat_begin = 0, repeat_end = 1; - - assert (pattern->base.n_stops != 0); - - extend = cairo_pattern_get_extend (pdf_pattern->pattern); - - pat_to_pdf = pattern->base.base.matrix; - status = cairo_matrix_invert (&pat_to_pdf); - /* cairo_pattern_set_matrix ensures the matrix is invertible */ - assert (status == CAIRO_STATUS_SUCCESS); - - cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &surface->cairo_to_pdf); - first_stop = gradient->stops[0].offset; - last_stop = gradient->stops[gradient->n_stops - 1].offset; - - if (pattern->base.base.extend == CAIRO_EXTEND_REPEAT || - pattern->base.base.extend == CAIRO_EXTEND_REFLECT) { - double dx, dy; - int x_rep = 0, y_rep = 0; - - x1 = _cairo_fixed_to_double (pattern->p1.x); - y1 = _cairo_fixed_to_double (pattern->p1.y); - cairo_matrix_transform_point (&pat_to_pdf, &x1, &y1); - - x2 = _cairo_fixed_to_double (pattern->p2.x); - y2 = _cairo_fixed_to_double (pattern->p2.y); - cairo_matrix_transform_point (&pat_to_pdf, &x2, &y2); - - dx = fabs (x2 - x1); - dy = fabs (y2 - y1); - if (dx > 1e-6) - x_rep = (int) ceil (surface->width/dx); - if (dy > 1e-6) - y_rep = (int) ceil (surface->height/dy); - - repeat_end = MAX (x_rep, y_rep); - repeat_begin = -repeat_end; - first_stop = repeat_begin; - last_stop = repeat_end; - } - - /* PDF requires the first and last stop to be the same as the line - * coordinates. For repeating patterns this moves the line - * coordinates out to the begin/end of the repeating function. For - * non repeating patterns this may move the line coordinates in if - * there are not stops at offset 0 and 1. */ - x1 = _cairo_fixed_to_double (pattern->p1.x); - y1 = _cairo_fixed_to_double (pattern->p1.y); - x2 = _cairo_fixed_to_double (pattern->p2.x); - y2 = _cairo_fixed_to_double (pattern->p2.y); - - _x1 = x1 + (x2 - x1)*first_stop; - _y1 = y1 + (y2 - y1)*first_stop; - _x2 = x1 + (x2 - x1)*last_stop; - _y2 = y1 + (y2 - y1)*last_stop; - - x1 = _x1; - x2 = _x2; - y1 = _y1; - y2 = _y2; - - /* For EXTEND_NONE and EXTEND_PAD if there are only two stops a - * Type 2 function is used by itself without a stitching - * function. Type 2 functions always have the domain [0 1] */ - if ((pattern->base.base.extend == CAIRO_EXTEND_NONE || - pattern->base.base.extend == CAIRO_EXTEND_PAD) && - gradient->n_stops == 2) { - first_stop = 0.0; - last_stop = 1.0; - } - - status = _cairo_pdf_surface_emit_pattern_stops (surface, - &pattern->base, - &color_function, - &alpha_function); - if (status) - return status; - - if (pattern->base.base.extend == CAIRO_EXTEND_REPEAT || - pattern->base.base.extend == CAIRO_EXTEND_REFLECT) { - status = _cairo_pdf_surface_emit_repeating_function (surface, - &pattern->base, - &color_function, - repeat_begin, - repeat_end); - if (status) - return status; - - if (alpha_function.id != 0) { - status = _cairo_pdf_surface_emit_repeating_function (surface, - &pattern->base, - &alpha_function, - repeat_begin, - repeat_end); - if (status) - return status; - } - } - - _cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res); - _cairo_output_stream_printf (surface->output, - "%d 0 obj\n" - "<< /Type /Pattern\n" - " /PatternType 2\n" - " /Matrix [ %f %f %f %f %f %f ]\n" - " /Shading\n" - " << /ShadingType 2\n" - " /ColorSpace /DeviceRGB\n" - " /Coords [ %f %f %f %f ]\n" - " /Domain [ %f %f ]\n" - " /Function %d 0 R\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, - x1, y1, x2, y2, - first_stop, last_stop, - color_function.id); - - if (extend == CAIRO_EXTEND_PAD) { - _cairo_output_stream_printf (surface->output, - " /Extend [ true true ]\n"); - } else { - _cairo_output_stream_printf (surface->output, - " /Extend [ false false ]\n"); - } - - _cairo_output_stream_printf (surface->output, - " >>\n" - ">>\n" - "endobj\n"); - - if (alpha_function.id != 0) { - cairo_pdf_resource_t mask_resource; - - assert (pdf_pattern->gstate_res.id != 0); - - /* Create pattern for SMask. */ - mask_resource = _cairo_pdf_surface_new_object (surface); - if (mask_resource.id == 0) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - _cairo_output_stream_printf (surface->output, - "%d 0 obj\n" - "<< /Type /Pattern\n" - " /PatternType 2\n" - " /Matrix [ %f %f %f %f %f %f ]\n" - " /Shading\n" - " << /ShadingType 2\n" - " /ColorSpace /DeviceGray\n" - " /Coords [ %f %f %f %f ]\n" - " /Domain [ %f %f ]\n" - " /Function %d 0 R\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, - x1, y1, x2, y2, - first_stop, last_stop, - alpha_function.id); - - if (extend == CAIRO_EXTEND_PAD) { - _cairo_output_stream_printf (surface->output, - " /Extend [ true true ]\n"); - } else { - _cairo_output_stream_printf (surface->output, - " /Extend [ false false ]\n"); - } - - _cairo_output_stream_printf (surface->output, - " >>\n" - ">>\n" - "endobj\n"); - status = _cairo_pdf_surface_add_pattern (surface, mask_resource); - if (status) - return status; - - status = cairo_pdf_surface_emit_transparency_group (surface, - pdf_pattern->gstate_res, - mask_resource); - if (status) - return status; - } - - return _cairo_output_stream_get_status (surface->output); -} - -static cairo_status_t -_cairo_pdf_surface_emit_radial_pattern (cairo_pdf_surface_t *surface, - cairo_pdf_pattern_t *pdf_pattern) -{ - cairo_pdf_resource_t color_function, alpha_function; - double x1, y1, x2, y2, r1, r2; - cairo_matrix_t pat_to_pdf; - cairo_extend_t extend; - cairo_status_t status; - cairo_radial_pattern_t *pattern = (cairo_radial_pattern_t *) pdf_pattern->pattern; - - assert (pattern->base.n_stops != 0); - - extend = cairo_pattern_get_extend (pdf_pattern->pattern); - - status = _cairo_pdf_surface_emit_pattern_stops (surface, - &pattern->base, - &color_function, - &alpha_function); - if (status) - return status; - - pat_to_pdf = pattern->base.base.matrix; - status = cairo_matrix_invert (&pat_to_pdf); - /* cairo_pattern_set_matrix ensures the matrix is invertible */ - assert (status == CAIRO_STATUS_SUCCESS); - - cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &surface->cairo_to_pdf); - x1 = _cairo_fixed_to_double (pattern->c1.x); - y1 = _cairo_fixed_to_double (pattern->c1.y); - r1 = _cairo_fixed_to_double (pattern->r1); - x2 = _cairo_fixed_to_double (pattern->c2.x); - y2 = _cairo_fixed_to_double (pattern->c2.y); - r2 = _cairo_fixed_to_double (pattern->r2); - - _cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res); - - _cairo_output_stream_printf (surface->output, - "%d 0 obj\n" - "<< /Type /Pattern\n" - " /PatternType 2\n" - " /Matrix [ %f %f %f %f %f %f ]\n" - " /Shading\n" - " << /ShadingType 3\n" - " /ColorSpace /DeviceRGB\n" - " /Coords [ %f %f %f %f %f %f ]\n" - " /Function %d 0 R\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, - x1, y1, r1, x2, y2, r2, - color_function.id); - - if (extend == CAIRO_EXTEND_PAD) { - _cairo_output_stream_printf (surface->output, - " /Extend [ true true ]\n"); - } else { - _cairo_output_stream_printf (surface->output, - " /Extend [ false false ]\n"); - } - - _cairo_output_stream_printf (surface->output, - " >>\n" - ">>\n" - "endobj\n"); - - if (alpha_function.id != 0) { - cairo_pdf_resource_t mask_resource; - - assert (pdf_pattern->gstate_res.id != 0); - - /* Create pattern for SMask. */ - mask_resource = _cairo_pdf_surface_new_object (surface); - if (mask_resource.id == 0) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - _cairo_output_stream_printf (surface->output, - "%d 0 obj\n" - "<< /Type /Pattern\n" - " /PatternType 2\n" - " /Matrix [ %f %f %f %f %f %f ]\n" - " /Shading\n" - " << /ShadingType 3\n" - " /ColorSpace /DeviceGray\n" - " /Coords [ %f %f %f %f %f %f ]\n" - " /Function %d 0 R\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, - x1, y1, r1, x2, y2, r2, - alpha_function.id); - - if (extend == CAIRO_EXTEND_PAD) { - _cairo_output_stream_printf (surface->output, - " /Extend [ true true ]\n"); - } else { - _cairo_output_stream_printf (surface->output, - " /Extend [ false false ]\n"); - } - - _cairo_output_stream_printf (surface->output, - " >>\n" - ">>\n" - "endobj\n"); - - status = cairo_pdf_surface_emit_transparency_group (surface, - pdf_pattern->gstate_res, - mask_resource); - if (status) - return status; - } - - return _cairo_output_stream_get_status (surface->output); -} - -static cairo_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; - - old_width = surface->width; - old_height = surface->height; - _cairo_pdf_surface_set_size_internal (surface, - pdf_pattern->width, - pdf_pattern->height); - - switch (pdf_pattern->pattern->type) { - case CAIRO_PATTERN_TYPE_SOLID: - ASSERT_NOT_REACHED; - status = _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH); - break; - - case CAIRO_PATTERN_TYPE_SURFACE: - status = _cairo_pdf_surface_emit_surface_pattern (surface, pdf_pattern); - break; - - case CAIRO_PATTERN_TYPE_LINEAR: - status = _cairo_pdf_surface_emit_linear_pattern (surface, pdf_pattern); - break; - - case CAIRO_PATTERN_TYPE_RADIAL: - status = _cairo_pdf_surface_emit_radial_pattern (surface, pdf_pattern); - break; - - default: - ASSERT_NOT_REACHED; - status = _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH); - break; - } - - _cairo_pdf_surface_set_size_internal (surface, - old_width, - old_height); - - return status; -} - -static cairo_status_t -_cairo_pdf_surface_select_pattern (cairo_pdf_surface_t *surface, - cairo_pattern_t *pattern, - cairo_pdf_resource_t pattern_res, - cairo_bool_t is_stroke) -{ - cairo_status_t status; - int alpha; - cairo_color_t *solid_color = NULL; - - if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) { - cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) pattern; - - solid_color = &solid->color; - } - - if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR || - pattern->type == CAIRO_PATTERN_TYPE_RADIAL) - { - cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t *) pattern; - - if (gradient->n_stops == 1) - solid_color = &gradient->stops[0].color; - } - - if (solid_color != NULL) { - if (surface->current_pattern_is_solid_color == FALSE || - surface->current_color_red != solid_color->red || - surface->current_color_green != solid_color->green || - surface->current_color_blue != solid_color->blue || - surface->current_color_is_stroke != is_stroke) - { - status = _cairo_pdf_operators_flush (&surface->pdf_operators); - if (status) - return status; - - _cairo_output_stream_printf (surface->output, - "%f %f %f ", - solid_color->red, - solid_color->green, - solid_color->blue); - - if (is_stroke) - _cairo_output_stream_printf (surface->output, "RG "); - else - _cairo_output_stream_printf (surface->output, "rg "); - - surface->current_color_red = solid_color->red; - surface->current_color_green = solid_color->green; - surface->current_color_blue = solid_color->blue; - surface->current_color_is_stroke = is_stroke; - } - - if (surface->current_pattern_is_solid_color == FALSE || - surface->current_color_alpha != solid_color->alpha) - { - status = _cairo_pdf_surface_add_alpha (surface, solid_color->alpha, &alpha); - if (status) - return status; - - status = _cairo_pdf_operators_flush (&surface->pdf_operators); - if (status) - return status; - - _cairo_output_stream_printf (surface->output, - "/a%d gs\n", - alpha); - surface->current_color_alpha = solid_color->alpha; - } - - surface->current_pattern_is_solid_color = TRUE; - } else { - status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha); - if (status) - return status; - - status = _cairo_pdf_surface_add_pattern (surface, pattern_res); - if (status) - return status; - - status = _cairo_pdf_operators_flush (&surface->pdf_operators); - if (status) - return status; - - /* fill-stroke calls select_pattern twice. Don't save if the - * gstate is already saved. */ - if (!surface->select_pattern_gstate_saved) - _cairo_output_stream_printf (surface->output, "q "); - - if (is_stroke) { - _cairo_output_stream_printf (surface->output, - "/Pattern CS /p%d SCN ", - pattern_res.id); - } else { - _cairo_output_stream_printf (surface->output, - "/Pattern cs /p%d scn ", - pattern_res.id); - } - _cairo_output_stream_printf (surface->output, - "/a%d gs\n", - alpha); - surface->select_pattern_gstate_saved = TRUE; - surface->current_pattern_is_solid_color = FALSE; - } - - return _cairo_output_stream_get_status (surface->output); -} - -static cairo_int_status_t -_cairo_pdf_surface_unselect_pattern (cairo_pdf_surface_t *surface) -{ - cairo_int_status_t status; - - if (surface->select_pattern_gstate_saved) { - status = _cairo_pdf_operators_flush (&surface->pdf_operators); - if (status) - return status; - - _cairo_output_stream_printf (surface->output, "Q\n"); - _cairo_pdf_operators_reset (&surface->pdf_operators); - } - surface->select_pattern_gstate_saved = FALSE; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_pdf_surface_show_page (void *abstract_surface) -{ - cairo_pdf_surface_t *surface = abstract_surface; - cairo_int_status_t status; - - status = _cairo_pdf_surface_close_content_stream (surface); - if (status) - return status; - - status = _cairo_pdf_surface_write_page (surface); - if (status) - return status; - - _cairo_pdf_surface_clear (surface); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_pdf_surface_get_extents (void *abstract_surface, - cairo_rectangle_int_t *rectangle) -{ - cairo_pdf_surface_t *surface = abstract_surface; - - rectangle->x = 0; - rectangle->y = 0; - - /* XXX: The conversion to integers here is pretty bogus, (not to - * mention the arbitrary limitation of width to a short(!). We - * may need to come up with a better interface for get_size. - */ - rectangle->width = (int) ceil (surface->width); - rectangle->height = (int) ceil (surface->height); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_pdf_surface_intersect_clip_path (void *abstract_surface, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_pdf_surface_t *surface = abstract_surface; - cairo_int_status_t status; - - if (path == NULL) { - status = _cairo_pdf_operators_flush (&surface->pdf_operators); - if (status) - return status; - - _cairo_output_stream_printf (surface->output, "Q q\n"); - surface->current_pattern_is_solid_color = FALSE; - _cairo_pdf_operators_reset (&surface->pdf_operators); - - return CAIRO_STATUS_SUCCESS; - } - - return _cairo_pdf_operators_clip (&surface->pdf_operators, path, fill_rule); -} - -static void -_cairo_pdf_surface_get_font_options (void *abstract_surface, - cairo_font_options_t *options) -{ - _cairo_font_options_init_default (options); - - cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_NONE); - cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF); - cairo_font_options_set_antialias (options, CAIRO_ANTIALIAS_GRAY); -} - -static cairo_pdf_resource_t -_cairo_pdf_surface_write_info (cairo_pdf_surface_t *surface) -{ - cairo_pdf_resource_t info; - - info = _cairo_pdf_surface_new_object (surface); - if (info.id == 0) - return info; - - _cairo_output_stream_printf (surface->output, - "%d 0 obj\n" - "<< /Creator (cairo %s (http://cairographics.org))\n" - " /Producer (cairo %s (http://cairographics.org))\n" - ">>\n" - "endobj\n", - info.id, - cairo_version_string (), - cairo_version_string ()); - - return info; -} - -static void -_cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface) -{ - cairo_pdf_resource_t page; - int num_pages, i; - - _cairo_pdf_surface_update_object (surface, surface->pages_resource); - _cairo_output_stream_printf (surface->output, - "%d 0 obj\n" - "<< /Type /Pages\n" - " /Kids [ ", - surface->pages_resource.id); - - num_pages = _cairo_array_num_elements (&surface->pages); - for (i = 0; i < num_pages; i++) { - _cairo_array_copy_element (&surface->pages, i, &page); - _cairo_output_stream_printf (surface->output, "%d 0 R ", page.id); - } - - _cairo_output_stream_printf (surface->output, "]\n"); - _cairo_output_stream_printf (surface->output, " /Count %d\n", num_pages); - - - /* TODO: Figure out which other defaults to be inherited by /Page - * objects. */ - _cairo_output_stream_printf (surface->output, - ">>\n" - "endobj\n"); -} - -static cairo_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; - int i; - - if (utf8 && *utf8) { - status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &utf16_len); - if (status) - return status; - } - - _cairo_output_stream_printf (surface->output, "<"); - if (utf16 == NULL || utf16_len == 0) { - /* According to the "ToUnicode Mapping File Tutorial" - * http://www.adobe.com/devnet/acrobat/pdfs/5411.ToUnicode.pdf - * - * Glyphs that do not map to a Unicode code point must be - * mapped to 0xfffd "REPLACEMENT CHARACTER". - */ - _cairo_output_stream_printf (surface->output, - "fffd"); - } else { - for (i = 0; i < utf16_len; i++) - _cairo_output_stream_printf (surface->output, - "%04x", (int) (utf16[i])); - } - _cairo_output_stream_printf (surface->output, ">"); - - if (utf16) - free (utf16); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_pdf_surface_emit_to_unicode_stream (cairo_pdf_surface_t *surface, - cairo_scaled_font_subset_t *font_subset, - cairo_bool_t is_composite, - cairo_pdf_resource_t *stream) -{ - unsigned int i, num_bfchar; - cairo_int_status_t status; - - stream->id = 0; - - status = _cairo_pdf_surface_open_stream (surface, - NULL, - surface->compress_content, - NULL); - if (status) - return status; - - _cairo_output_stream_printf (surface->output, - "/CIDInit /ProcSet findresource begin\n" - "12 dict begin\n" - "begincmap\n" - "/CIDSystemInfo\n" - "<< /Registry (Adobe)\n" - " /Ordering (UCS)\n" - " /Supplement 0\n" - ">> def\n" - "/CMapName /Adobe-Identity-UCS def\n" - "/CMapType 2 def\n" - "1 begincodespacerange\n"); - - if (is_composite) { - _cairo_output_stream_printf (surface->output, - "<0000> \n"); - } else { - _cairo_output_stream_printf (surface->output, - "<00> \n"); - } - - _cairo_output_stream_printf (surface->output, - "endcodespacerange\n"); - - num_bfchar = font_subset->num_glyphs - 1; - - /* The CMap specification has a limit of 100 characters per beginbfchar operator */ - _cairo_output_stream_printf (surface->output, - "%d beginbfchar\n", - num_bfchar > 100 ? 100 : num_bfchar); - - for (i = 0; i < num_bfchar; i++) { - if (i != 0 && i % 100 == 0) { - _cairo_output_stream_printf (surface->output, - "endbfchar\n" - "%d beginbfchar\n", - num_bfchar - i > 100 ? 100 : num_bfchar - i); - } - if (is_composite) { - _cairo_output_stream_printf (surface->output, - "<%04x> ", - i + 1); - } else { - _cairo_output_stream_printf (surface->output, - "<%02x> ", - i + 1); - } - status = _cairo_pdf_surface_emit_unicode_for_glyph (surface, - font_subset->utf8[i + 1]); - if (status) - return status; - - _cairo_output_stream_printf (surface->output, - "\n"); - } - _cairo_output_stream_printf (surface->output, - "endbfchar\n"); - - _cairo_output_stream_printf (surface->output, - "endcmap\n" - "CMapName currentdict /CMap defineresource pop\n" - "end\n" - "end\n"); - - *stream = surface->pdf_stream.self; - return _cairo_pdf_surface_close_stream (surface); -} - -static cairo_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) -{ - cairo_pdf_resource_t stream, descriptor, cidfont_dict; - cairo_pdf_resource_t subset_resource, to_unicode_stream; - cairo_pdf_font_t font; - unsigned int i; - cairo_status_t status; - - subset_resource = _cairo_pdf_surface_get_font_resource (surface, - font_subset->font_id, - font_subset->subset_id); - if (subset_resource.id == 0) - return CAIRO_STATUS_SUCCESS; - - status = _cairo_pdf_surface_open_stream (surface, - NULL, - TRUE, - " /Subtype /CIDFontType0C\n"); - if (status) - return status; - - stream = surface->pdf_stream.self; - _cairo_output_stream_write (surface->output, - subset->data, subset->data_length); - status = _cairo_pdf_surface_close_stream (surface); - if (status) - return status; - - status = _cairo_pdf_surface_emit_to_unicode_stream (surface, - font_subset, TRUE, - &to_unicode_stream); - if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - - descriptor = _cairo_pdf_surface_new_object (surface); - if (descriptor.id == 0) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - _cairo_output_stream_printf (surface->output, - "%d 0 obj\n" - "<< /Type /FontDescriptor\n" - " /FontName /%s\n" - " /Flags 4\n" - " /FontBBox [ %ld %ld %ld %ld ]\n" - " /ItalicAngle 0\n" - " /Ascent %ld\n" - " /Descent %ld\n" - " /CapHeight 500\n" - " /StemV 80\n" - " /StemH 80\n" - " /FontFile3 %u 0 R\n" - ">>\n" - "endobj\n", - descriptor.id, - subset->base_font, - subset->x_min, - subset->y_min, - subset->x_max, - subset->y_max, - subset->ascent, - subset->descent, - stream.id); - - cidfont_dict = _cairo_pdf_surface_new_object (surface); - if (cidfont_dict.id == 0) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - _cairo_output_stream_printf (surface->output, - "%d 0 obj\n" - "<< /Type /Font\n" - " /Subtype /CIDFontType0\n" - " /BaseFont /%s\n" - " /CIDSystemInfo\n" - " << /Registry (Adobe)\n" - " /Ordering (Identity)\n" - " /Supplement 0\n" - " >>\n" - " /FontDescriptor %d 0 R\n" - " /W [0 [", - cidfont_dict.id, - subset->base_font, - descriptor.id); - - for (i = 0; i < font_subset->num_glyphs; i++) - _cairo_output_stream_printf (surface->output, - " %d", - subset->widths[i]); - - _cairo_output_stream_printf (surface->output, - " ]]\n" - ">>\n" - "endobj\n"); - - _cairo_pdf_surface_update_object (surface, subset_resource); - _cairo_output_stream_printf (surface->output, - "%d 0 obj\n" - "<< /Type /Font\n" - " /Subtype /Type0\n" - " /BaseFont /%s\n" - " /Encoding /Identity-H\n" - " /DescendantFonts [ %d 0 R]\n", - subset_resource.id, - subset->base_font, - cidfont_dict.id); - - if (to_unicode_stream.id != 0) - _cairo_output_stream_printf (surface->output, - " /ToUnicode %d 0 R\n", - to_unicode_stream.id); - - _cairo_output_stream_printf (surface->output, - ">>\n" - "endobj\n"); - - font.font_id = font_subset->font_id; - font.subset_id = font_subset->subset_id; - font.subset_resource = subset_resource; - status = _cairo_array_append (&surface->fonts, &font); - - return status; -} - -static cairo_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_cff_subset_t subset; - char name[64]; - - snprintf (name, sizeof name, "CairoFont-%d-%d", - font_subset->font_id, font_subset->subset_id); - status = _cairo_cff_subset_init (&subset, name, font_subset); - if (status) - return status; - - status = _cairo_pdf_surface_emit_cff_font (surface, font_subset, &subset); - - _cairo_cff_subset_fini (&subset); - - return status; -} - -static cairo_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_cff_subset_t subset; - char name[64]; - - snprintf (name, sizeof name, "CairoFont-%d-%d", - font_subset->font_id, font_subset->subset_id); - status = _cairo_cff_fallback_init (&subset, name, font_subset); - if (status) - return status; - - status = _cairo_pdf_surface_emit_cff_font (surface, font_subset, &subset); - - _cairo_cff_fallback_fini (&subset); - - return status; -} - -static cairo_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; - unsigned long length; - unsigned int i; - - subset_resource = _cairo_pdf_surface_get_font_resource (surface, - font_subset->font_id, - font_subset->subset_id); - if (subset_resource.id == 0) - return CAIRO_STATUS_SUCCESS; - - /* We ignore the zero-trailer and set Length3 to 0. */ - length = subset->header_length + subset->data_length; - status = _cairo_pdf_surface_open_stream (surface, - NULL, - TRUE, - " /Length1 %lu\n" - " /Length2 %lu\n" - " /Length3 0\n", - subset->header_length, - subset->data_length); - if (status) - return status; - - stream = surface->pdf_stream.self; - _cairo_output_stream_write (surface->output, subset->data, length); - status = _cairo_pdf_surface_close_stream (surface); - if (status) - return status; - - status = _cairo_pdf_surface_emit_to_unicode_stream (surface, - font_subset, FALSE, - &to_unicode_stream); - if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - - descriptor = _cairo_pdf_surface_new_object (surface); - if (descriptor.id == 0) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - _cairo_output_stream_printf (surface->output, - "%d 0 obj\n" - "<< /Type /FontDescriptor\n" - " /FontName /%s\n" - " /Flags 4\n" - " /FontBBox [ %ld %ld %ld %ld ]\n" - " /ItalicAngle 0\n" - " /Ascent %ld\n" - " /Descent %ld\n" - " /CapHeight 500\n" - " /StemV 80\n" - " /StemH 80\n" - " /FontFile %u 0 R\n" - ">>\n" - "endobj\n", - descriptor.id, - subset->base_font, - subset->x_min, - subset->y_min, - subset->x_max, - subset->y_max, - subset->ascent, - subset->descent, - stream.id); - - _cairo_pdf_surface_update_object (surface, subset_resource); - _cairo_output_stream_printf (surface->output, - "%d 0 obj\n" - "<< /Type /Font\n" - " /Subtype /Type1\n" - " /BaseFont /%s\n" - " /FirstChar 0\n" - " /LastChar %d\n" - " /FontDescriptor %d 0 R\n" - " /Widths [", - subset_resource.id, - subset->base_font, - font_subset->num_glyphs - 1, - descriptor.id); - - for (i = 0; i < font_subset->num_glyphs; i++) - _cairo_output_stream_printf (surface->output, - " %d", - subset->widths[i]); - - _cairo_output_stream_printf (surface->output, - " ]\n"); - - if (to_unicode_stream.id != 0) - _cairo_output_stream_printf (surface->output, - " /ToUnicode %d 0 R\n", - to_unicode_stream.id); - - _cairo_output_stream_printf (surface->output, - ">>\n" - "endobj\n"); - - font.font_id = font_subset->font_id; - font.subset_id = font_subset->subset_id; - font.subset_resource = subset_resource; - return _cairo_array_append (&surface->fonts, &font); -} - -#if CAIRO_HAS_FT_FONT -static cairo_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_type1_subset_t subset; - char name[64]; - - snprintf (name, sizeof name, "CairoFont-%d-%d", - font_subset->font_id, font_subset->subset_id); - status = _cairo_type1_subset_init (&subset, name, font_subset, FALSE); - if (status) - return status; - - status = _cairo_pdf_surface_emit_type1_font (surface, font_subset, &subset); - - _cairo_type1_subset_fini (&subset); - return status; -} -#endif - -static cairo_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_type1_subset_t subset; - char name[64]; - - snprintf (name, sizeof name, "CairoFont-%d-%d", - font_subset->font_id, font_subset->subset_id); - status = _cairo_type1_fallback_init_binary (&subset, name, font_subset); - if (status) - return status; - - status = _cairo_pdf_surface_emit_type1_font (surface, font_subset, &subset); - - _cairo_type1_fallback_fini (&subset); - return status; -} - -#define PDF_UNITS_PER_EM 1000 - -static cairo_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_pdf_font_t font; - cairo_truetype_subset_t subset; - unsigned int i; - - subset_resource = _cairo_pdf_surface_get_font_resource (surface, - font_subset->font_id, - font_subset->subset_id); - if (subset_resource.id == 0) - return CAIRO_STATUS_SUCCESS; - - status = _cairo_truetype_subset_init (&subset, font_subset); - if (status) - return status; - - status = _cairo_pdf_surface_open_stream (surface, - NULL, - TRUE, - " /Length1 %lu\n", - subset.data_length); - if (status) { - _cairo_truetype_subset_fini (&subset); - return status; - } - - stream = surface->pdf_stream.self; - _cairo_output_stream_write (surface->output, - subset.data, subset.data_length); - status = _cairo_pdf_surface_close_stream (surface); - if (status) { - _cairo_truetype_subset_fini (&subset); - return status; - } - - status = _cairo_pdf_surface_emit_to_unicode_stream (surface, - font_subset, TRUE, - &to_unicode_stream); - if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) { - _cairo_truetype_subset_fini (&subset); - return status; - } - - descriptor = _cairo_pdf_surface_new_object (surface); - if (descriptor.id == 0) { - _cairo_truetype_subset_fini (&subset); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - _cairo_output_stream_printf (surface->output, - "%d 0 obj\n" - "<< /Type /FontDescriptor\n" - " /FontName /%s\n" - " /Flags 4\n" - " /FontBBox [ %ld %ld %ld %ld ]\n" - " /ItalicAngle 0\n" - " /Ascent %ld\n" - " /Descent %ld\n" - " /CapHeight %ld\n" - " /StemV 80\n" - " /StemH 80\n" - " /FontFile2 %u 0 R\n" - ">>\n" - "endobj\n", - descriptor.id, - subset.base_font, - (long)(subset.x_min*PDF_UNITS_PER_EM), - (long)(subset.y_min*PDF_UNITS_PER_EM), - (long)(subset.x_max*PDF_UNITS_PER_EM), - (long)(subset.y_max*PDF_UNITS_PER_EM), - (long)(subset.ascent*PDF_UNITS_PER_EM), - (long)(subset.descent*PDF_UNITS_PER_EM), - (long)(subset.y_max*PDF_UNITS_PER_EM), - stream.id); - - cidfont_dict = _cairo_pdf_surface_new_object (surface); - if (cidfont_dict.id == 0) { - _cairo_truetype_subset_fini (&subset); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - _cairo_output_stream_printf (surface->output, - "%d 0 obj\n" - "<< /Type /Font\n" - " /Subtype /CIDFontType2\n" - " /BaseFont /%s\n" - " /CIDSystemInfo\n" - " << /Registry (Adobe)\n" - " /Ordering (Identity)\n" - " /Supplement 0\n" - " >>\n" - " /FontDescriptor %d 0 R\n" - " /W [0 [", - cidfont_dict.id, - subset.base_font, - descriptor.id); - - for (i = 0; i < font_subset->num_glyphs; i++) - _cairo_output_stream_printf (surface->output, - " %ld", - (long)(subset.widths[i]*PDF_UNITS_PER_EM)); - - _cairo_output_stream_printf (surface->output, - " ]]\n" - ">>\n" - "endobj\n"); - - _cairo_pdf_surface_update_object (surface, subset_resource); - _cairo_output_stream_printf (surface->output, - "%d 0 obj\n" - "<< /Type /Font\n" - " /Subtype /Type0\n" - " /BaseFont /%s\n" - " /Encoding /Identity-H\n" - " /DescendantFonts [ %d 0 R]\n", - subset_resource.id, - subset.base_font, - cidfont_dict.id); - - if (to_unicode_stream.id != 0) - _cairo_output_stream_printf (surface->output, - " /ToUnicode %d 0 R\n", - to_unicode_stream.id); - - _cairo_output_stream_printf (surface->output, - ">>\n" - "endobj\n"); - - font.font_id = font_subset->font_id; - font.subset_id = font_subset->subset_id; - font.subset_resource = subset_resource; - status = _cairo_array_append (&surface->fonts, &font); - - _cairo_truetype_subset_fini (&subset); - - return status; -} - -static cairo_status_t -_cairo_pdf_emit_imagemask (cairo_image_surface_t *image, - cairo_output_stream_t *stream) -{ - uint8_t *byte, output_byte; - int row, col, num_cols; - - /* The only image type supported by Type 3 fonts are 1-bit image - * masks */ - assert (image->format == CAIRO_FORMAT_A1); - - _cairo_output_stream_printf (stream, - "BI\n" - "/IM true\n" - "/W %d\n" - "/H %d\n" - "/BPC 1\n" - "/D [1 0]\n", - image->width, - image->height); - - _cairo_output_stream_printf (stream, - "ID "); - - num_cols = (image->width + 7) / 8; - for (row = 0; row < image->height; row++) { - byte = image->data + row * image->stride; - for (col = 0; col < num_cols; col++) { - output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte); - _cairo_output_stream_write (stream, &output_byte, 1); - byte++; - } - } - - _cairo_output_stream_printf (stream, - "\nEI\n"); - - return _cairo_output_stream_get_status (stream); -} - -static cairo_status_t -_cairo_pdf_surface_analyze_user_font_subset (cairo_scaled_font_subset_t *font_subset, - void *closure) -{ - cairo_pdf_surface_t *surface = closure; - cairo_status_t status = CAIRO_STATUS_SUCCESS; - cairo_status_t status2; - unsigned int i; - cairo_surface_t *type3_surface; - cairo_output_stream_t *null_stream; - - null_stream = _cairo_null_stream_create (); - type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font, - null_stream, - _cairo_pdf_emit_imagemask, - surface->font_subsets); - _cairo_type3_glyph_surface_set_font_subsets_callback (type3_surface, - _cairo_pdf_surface_add_font, - surface); - - for (i = 0; i < font_subset->num_glyphs; i++) { - status = _cairo_type3_glyph_surface_analyze_glyph (type3_surface, - font_subset->glyphs[i]); - if (status) - break; - } - - cairo_surface_destroy (type3_surface); - status2 = _cairo_output_stream_destroy (null_stream); - if (status == CAIRO_STATUS_SUCCESS) - status = status2; - - return status; -} - -static cairo_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_pdf_resource_t *glyphs, encoding, char_procs, subset_resource, to_unicode_stream; - cairo_pdf_font_t font; - double *widths; - unsigned int i; - cairo_box_t font_bbox = {{0,0},{0,0}}; - cairo_box_t bbox = {{0,0},{0,0}}; - cairo_surface_t *type3_surface; - - if (font_subset->num_glyphs == 0) - return CAIRO_STATUS_SUCCESS; - - subset_resource = _cairo_pdf_surface_get_font_resource (surface, - font_subset->font_id, - font_subset->subset_id); - if (subset_resource.id == 0) - return CAIRO_STATUS_SUCCESS; - - glyphs = _cairo_malloc_ab (font_subset->num_glyphs, sizeof (cairo_pdf_resource_t)); - if (glyphs == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - widths = _cairo_malloc_ab (font_subset->num_glyphs, sizeof (double)); - if (widths == NULL) { - free (glyphs); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - _cairo_pdf_group_resources_clear (&surface->resources); - type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font, - NULL, - _cairo_pdf_emit_imagemask, - surface->font_subsets); - _cairo_type3_glyph_surface_set_font_subsets_callback (type3_surface, - _cairo_pdf_surface_add_font, - surface); - - for (i = 0; i < font_subset->num_glyphs; i++) { - status = _cairo_pdf_surface_open_stream (surface, - NULL, - surface->compress_content, - NULL); - if (status) - break; - - glyphs[i] = surface->pdf_stream.self; - status = _cairo_type3_glyph_surface_emit_glyph (type3_surface, - surface->output, - font_subset->glyphs[i], - &bbox, - &widths[i]); - if (status) - break; - - status = _cairo_pdf_surface_close_stream (surface); - if (status) - break; - - if (i == 0) { - font_bbox.p1.x = bbox.p1.x; - font_bbox.p1.y = bbox.p1.y; - font_bbox.p2.x = bbox.p2.x; - font_bbox.p2.y = bbox.p2.y; - } else { - if (bbox.p1.x < font_bbox.p1.x) - font_bbox.p1.x = bbox.p1.x; - if (bbox.p1.y < font_bbox.p1.y) - font_bbox.p1.y = bbox.p1.y; - if (bbox.p2.x > font_bbox.p2.x) - font_bbox.p2.x = bbox.p2.x; - if (bbox.p2.y > font_bbox.p2.y) - font_bbox.p2.y = bbox.p2.y; - } - } - cairo_surface_destroy (type3_surface); - if (status) { - free (glyphs); - free (widths); - return status; - } - - encoding = _cairo_pdf_surface_new_object (surface); - if (encoding.id == 0) { - free (glyphs); - free (widths); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - _cairo_output_stream_printf (surface->output, - "%d 0 obj\n" - "<< /Type /Encoding\n" - " /Differences [0", encoding.id); - for (i = 0; i < font_subset->num_glyphs; i++) - _cairo_output_stream_printf (surface->output, - " /%d", i); - _cairo_output_stream_printf (surface->output, - "]\n" - ">>\n" - "endobj\n"); - - char_procs = _cairo_pdf_surface_new_object (surface); - if (char_procs.id == 0) { - free (glyphs); - free (widths); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - _cairo_output_stream_printf (surface->output, - "%d 0 obj\n" - "<<\n", char_procs.id); - for (i = 0; i < font_subset->num_glyphs; i++) - _cairo_output_stream_printf (surface->output, - " /%d %d 0 R\n", - i, glyphs[i].id); - _cairo_output_stream_printf (surface->output, - ">>\n" - "endobj\n"); - - free (glyphs); - - status = _cairo_pdf_surface_emit_to_unicode_stream (surface, - font_subset, FALSE, - &to_unicode_stream); - if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) { - free (widths); - return status; - } - - _cairo_pdf_surface_update_object (surface, subset_resource); - _cairo_output_stream_printf (surface->output, - "%d 0 obj\n" - "<< /Type /Font\n" - " /Subtype /Type3\n" - " /FontBBox [%f %f %f %f]\n" - " /FontMatrix [ 1 0 0 1 0 0 ]\n" - " /Encoding %d 0 R\n" - " /CharProcs %d 0 R\n" - " /FirstChar 0\n" - " /LastChar %d\n", - subset_resource.id, - _cairo_fixed_to_double (font_bbox.p1.x), - - _cairo_fixed_to_double (font_bbox.p2.y), - _cairo_fixed_to_double (font_bbox.p2.x), - - _cairo_fixed_to_double (font_bbox.p1.y), - encoding.id, - char_procs.id, - font_subset->num_glyphs - 1); - - _cairo_output_stream_printf (surface->output, - " /Widths ["); - for (i = 0; i < font_subset->num_glyphs; i++) - _cairo_output_stream_printf (surface->output, " %f", widths[i]); - _cairo_output_stream_printf (surface->output, - "]\n"); - free (widths); - - _cairo_output_stream_printf (surface->output, - " /Resources\n"); - _cairo_pdf_surface_emit_group_resources (surface, &surface->resources); - - if (to_unicode_stream.id != 0) - _cairo_output_stream_printf (surface->output, - " /ToUnicode %d 0 R\n", - to_unicode_stream.id); - - _cairo_output_stream_printf (surface->output, - ">>\n" - "endobj\n"); - - font.font_id = font_subset->font_id; - font.subset_id = font_subset->subset_id; - font.subset_resource = subset_resource; - return _cairo_array_append (&surface->fonts, &font); -} - -static cairo_status_t -_cairo_pdf_surface_emit_unscaled_font_subset (cairo_scaled_font_subset_t *font_subset, - void *closure) -{ - cairo_pdf_surface_t *surface = closure; - cairo_status_t status; - - if (font_subset->is_composite) { - status = _cairo_pdf_surface_emit_cff_font_subset (surface, font_subset); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - - status = _cairo_pdf_surface_emit_truetype_font_subset (surface, font_subset); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - - status = _cairo_pdf_surface_emit_cff_fallback_font (surface, font_subset); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - } else { -#if CAIRO_HAS_FT_FONT - status = _cairo_pdf_surface_emit_type1_font_subset (surface, font_subset); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; -#endif - - status = _cairo_pdf_surface_emit_type1_fallback_font (surface, font_subset); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - - } - - ASSERT_NOT_REACHED; - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_pdf_surface_emit_scaled_font_subset (cairo_scaled_font_subset_t *font_subset, - void *closure) -{ - cairo_pdf_surface_t *surface = closure; - cairo_status_t status; - - status = _cairo_pdf_surface_emit_type3_font_subset (surface, font_subset); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - - ASSERT_NOT_REACHED; - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface) -{ - cairo_status_t status; - - status = _cairo_scaled_font_subsets_foreach_user (surface->font_subsets, - _cairo_pdf_surface_analyze_user_font_subset, - surface); - if (status) - goto BAIL; - - status = _cairo_scaled_font_subsets_foreach_unscaled (surface->font_subsets, - _cairo_pdf_surface_emit_unscaled_font_subset, - surface); - if (status) - goto BAIL; - - status = _cairo_scaled_font_subsets_foreach_scaled (surface->font_subsets, - _cairo_pdf_surface_emit_scaled_font_subset, - surface); - if (status) - goto BAIL; - - status = _cairo_scaled_font_subsets_foreach_user (surface->font_subsets, - _cairo_pdf_surface_emit_scaled_font_subset, - surface); - -BAIL: - _cairo_scaled_font_subsets_destroy (surface->font_subsets); - surface->font_subsets = NULL; - - return status; -} - -static cairo_pdf_resource_t -_cairo_pdf_surface_write_catalog (cairo_pdf_surface_t *surface) -{ - cairo_pdf_resource_t catalog; - - catalog = _cairo_pdf_surface_new_object (surface); - if (catalog.id == 0) - return catalog; - - _cairo_output_stream_printf (surface->output, - "%d 0 obj\n" - "<< /Type /Catalog\n" - " /Pages %d 0 R\n" - ">>\n" - "endobj\n", - catalog.id, - surface->pages_resource.id); - - return catalog; -} - -static long -_cairo_pdf_surface_write_xref (cairo_pdf_surface_t *surface) -{ - cairo_pdf_object_t *object; - int num_objects, i; - long offset; - char buffer[11]; - - num_objects = _cairo_array_num_elements (&surface->objects); - - offset = _cairo_output_stream_get_position (surface->output); - _cairo_output_stream_printf (surface->output, - "xref\n" - "%d %d\n", - 0, num_objects + 1); - - _cairo_output_stream_printf (surface->output, - "0000000000 65535 f \n"); - for (i = 0; i < num_objects; i++) { - object = _cairo_array_index (&surface->objects, i); - snprintf (buffer, sizeof buffer, "%010ld", object->offset); - _cairo_output_stream_printf (surface->output, - "%s 00000 n \n", buffer); - } - - return offset; -} - -static cairo_status_t -_cairo_pdf_surface_write_mask_group (cairo_pdf_surface_t *surface, - cairo_pdf_smask_group_t *group) -{ - cairo_pdf_resource_t mask_group; - cairo_pdf_resource_t smask; - cairo_pdf_smask_group_t *smask_group; - cairo_pdf_resource_t pattern_res, gstate_res; - cairo_status_t status; - - /* Create mask group */ - status = _cairo_pdf_surface_open_group (surface, NULL); - if (status) - return status; - - pattern_res.id = 0; - gstate_res.id = 0; - status = _cairo_pdf_surface_add_pdf_pattern (surface, group->mask, &pattern_res, &gstate_res); - if (status) - return status; - - if (gstate_res.id != 0) { - smask_group = _cairo_pdf_surface_create_smask_group (surface); - if (smask_group == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - smask_group->operation = PDF_PAINT; - smask_group->source = cairo_pattern_reference (group->mask); - smask_group->source_res = pattern_res; - status = _cairo_pdf_surface_add_smask_group (surface, smask_group); - if (status) { - _cairo_pdf_smask_group_destroy (smask_group); - return status; - } - - status = _cairo_pdf_surface_add_smask (surface, gstate_res); - if (status) - return status; - - status = _cairo_pdf_surface_add_xobject (surface, smask_group->group_res); - if (status) - return status; - - _cairo_output_stream_printf (surface->output, - "q /s%d gs /x%d Do Q\n", - gstate_res.id, - smask_group->group_res.id); - } else { - status = _cairo_pdf_surface_select_pattern (surface, group->mask, pattern_res, FALSE); - if (status) - return status; - - _cairo_output_stream_printf (surface->output, - "0 0 %f %f re f\n", - surface->width, surface->height); - - status = _cairo_pdf_surface_unselect_pattern (surface); - if (status) - return status; - } - - status = _cairo_pdf_surface_close_group (surface, &mask_group); - if (status) - return status; - - /* Create source group */ - status = _cairo_pdf_surface_open_group (surface, &group->source_res); - if (status) - return status; - - pattern_res.id = 0; - gstate_res.id = 0; - status = _cairo_pdf_surface_add_pdf_pattern (surface, group->source, &pattern_res, &gstate_res); - if (status) - return status; - - if (gstate_res.id != 0) { - smask_group = _cairo_pdf_surface_create_smask_group (surface); - if (smask_group == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - smask_group->operation = PDF_PAINT; - smask_group->source = cairo_pattern_reference (group->source); - smask_group->source_res = pattern_res; - status = _cairo_pdf_surface_add_smask_group (surface, smask_group); - if (status) { - _cairo_pdf_smask_group_destroy (smask_group); - return status; - } - - status = _cairo_pdf_surface_add_smask (surface, gstate_res); - if (status) - return status; - - status = _cairo_pdf_surface_add_xobject (surface, smask_group->group_res); - if (status) - return status; - - _cairo_output_stream_printf (surface->output, - "q /s%d gs /x%d Do Q\n", - gstate_res.id, - smask_group->group_res.id); - } else { - status = _cairo_pdf_surface_select_pattern (surface, group->source, pattern_res, FALSE); - if (status) - return status; - - _cairo_output_stream_printf (surface->output, - "0 0 %f %f re f\n", - surface->width, surface->height); - - status = _cairo_pdf_surface_unselect_pattern (surface); - if (status) - return status; - } - - status = _cairo_pdf_surface_close_group (surface, NULL); - if (status) - return status; - - /* Create an smask based on the alpha component of mask_group */ - smask = _cairo_pdf_surface_new_object (surface); - if (smask.id == 0) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - _cairo_output_stream_printf (surface->output, - "%d 0 obj\n" - "<< /Type /Mask\n" - " /S /Alpha\n" - " /G %d 0 R\n" - ">>\n" - "endobj\n", - smask.id, - mask_group.id); - - /* Create a GState that uses the smask */ - _cairo_pdf_surface_update_object (surface, group->group_res); - _cairo_output_stream_printf (surface->output, - "%d 0 obj\n" - "<< /Type /ExtGState\n" - " /SMask %d 0 R\n" - " /ca 1\n" - " /CA 1\n" - " /AIS false\n" - ">>\n" - "endobj\n", - group->group_res.id, - smask.id); - - return _cairo_output_stream_get_status (surface->output); -} - -static cairo_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; - - old_width = surface->width; - old_height = surface->height; - _cairo_pdf_surface_set_size_internal (surface, - group->width, - group->height); - /* _mask is a special case that requires two groups - source - * and mask as well as a smask and gstate dictionary */ - if (group->operation == PDF_MASK) - return _cairo_pdf_surface_write_mask_group (surface, group); - - status = _cairo_pdf_surface_open_group (surface, &group->group_res); - if (status) - return status; - - status = _cairo_pdf_surface_select_pattern (surface, - group->source, - group->source_res, - group->operation == PDF_STROKE); - if (status) - return status; - - switch (group->operation) { - case PDF_PAINT: - _cairo_output_stream_printf (surface->output, - "0 0 %f %f re f\n", - surface->width, surface->height); - break; - case PDF_MASK: - ASSERT_NOT_REACHED; - break; - case PDF_FILL: - status = _cairo_pdf_operators_fill (&surface->pdf_operators, - &group->path, - group->fill_rule); - break; - case PDF_STROKE: - status = _cairo_pdf_operators_stroke (&surface->pdf_operators, - &group->path, - group->style, - &group->ctm, - &group->ctm_inverse); - break; - case PDF_SHOW_GLYPHS: - status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators, - group->utf8, group->utf8_len, - group->glyphs, group->num_glyphs, - group->clusters, group->num_clusters, - group->cluster_flags, - group->scaled_font); - break; - } - if (status) - return status; - - status = _cairo_pdf_surface_unselect_pattern (surface); - if (status) - return status; - - status = _cairo_pdf_surface_close_group (surface, NULL); - - _cairo_pdf_surface_set_size_internal (surface, - old_width, - old_height); - - return status; -} - -static cairo_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; - int pattern_index, group_index; - cairo_status_t status; - - /* Writing out PDF_MASK groups will cause additional smask groups - * to be appended to surface->smask_groups. Additional patterns - * may also be appended to surface->patterns. - * - * Writing meta surface patterns will cause additional patterns - * and groups to be appended. - */ - pattern_index = 0; - group_index = 0; - while ((pattern_index < _cairo_array_num_elements (&surface->patterns)) || - (group_index < _cairo_array_num_elements (&surface->smask_groups))) - { - for (; group_index < _cairo_array_num_elements (&surface->smask_groups); group_index++) { - _cairo_array_copy_element (&surface->smask_groups, group_index, &group); - status = _cairo_pdf_surface_write_smask_group (surface, group); - if (status) - return status; - } - - for (; pattern_index < _cairo_array_num_elements (&surface->patterns); pattern_index++) { - _cairo_array_copy_element (&surface->patterns, pattern_index, &pattern); - status = _cairo_pdf_surface_emit_pattern (surface, &pattern); - if (status) - return status; - } - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface) -{ - cairo_pdf_resource_t page, knockout, res; - cairo_status_t status; - int i, len; - - _cairo_pdf_group_resources_clear (&surface->resources); - if (surface->has_fallback_images) { - status = _cairo_pdf_surface_open_knockout_group (surface); - if (status) - return status; - - len = _cairo_array_num_elements (&surface->knockout_group); - for (i = 0; i < len; i++) { - _cairo_array_copy_element (&surface->knockout_group, i, &res); - _cairo_output_stream_printf (surface->output, - "/x%d Do\n", - res.id); - status = _cairo_pdf_surface_add_xobject (surface, res); - if (status) - return status; - } - _cairo_output_stream_printf (surface->output, - "/x%d Do\n", - surface->content.id); - status = _cairo_pdf_surface_add_xobject (surface, surface->content); - if (status) - return status; - - status = _cairo_pdf_surface_close_group (surface, &knockout); - if (status) - return status; - - _cairo_pdf_group_resources_clear (&surface->resources); - status = _cairo_pdf_surface_open_content_stream (surface, FALSE); - if (status) - return status; - - _cairo_output_stream_printf (surface->output, - "/x%d Do\n", - knockout.id); - status = _cairo_pdf_surface_add_xobject (surface, knockout); - if (status) - return status; - - status = _cairo_pdf_surface_close_content_stream (surface); - if (status) - return status; - } - - page = _cairo_pdf_surface_new_object (surface); - if (page.id == 0) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - _cairo_output_stream_printf (surface->output, - "%d 0 obj\n" - "<< /Type /Page\n" - " /Parent %d 0 R\n" - " /MediaBox [ 0 0 %f %f ]\n" - " /Contents %d 0 R\n" - " /Group <<\n" - " /Type /Group\n" - " /S /Transparency\n" - " /CS /DeviceRGB\n" - " >>\n" - " /Resources %d 0 R\n" - ">>\n" - "endobj\n", - page.id, - surface->pages_resource.id, - surface->width, - surface->height, - surface->content.id, - surface->content_resources.id); - - status = _cairo_array_append (&surface->pages, &page); - if (status) - return status; - - status = _cairo_pdf_surface_write_patterns_and_smask_groups (surface); - if (status) - return status; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_pdf_surface_analyze_surface_pattern_transparency (cairo_pdf_surface_t *surface, - cairo_surface_pattern_t *pattern) -{ - cairo_image_surface_t *image; - void *image_extra; - cairo_int_status_t status; - cairo_image_transparency_t transparency; - - status = _cairo_surface_acquire_source_image (pattern->surface, - &image, - &image_extra); - if (status) - return status; - - if (image->base.status) - return image->base.status; - - transparency = _cairo_image_analyze_transparency (image); - if (transparency == CAIRO_IMAGE_IS_OPAQUE) - status = CAIRO_STATUS_SUCCESS; - else - status = CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY; - - _cairo_surface_release_source_image (pattern->surface, image, image_extra); - - return status; -} - -static cairo_bool_t -_surface_pattern_supported (cairo_surface_pattern_t *pattern) -{ - cairo_extend_t extend; - - if (_cairo_surface_is_meta (pattern->surface)) - return TRUE; - - if (pattern->surface->backend->acquire_source_image == NULL) - return FALSE; - - /* Does an ALPHA-only source surface even make sense? Maybe, but I - * don't think it's worth the extra code to support it. */ - -/* XXX: Need to write this function here... - content = cairo_surface_get_content (pattern->surface); - if (content == CAIRO_CONTENT_ALPHA) - return FALSE; -*/ - - extend = cairo_pattern_get_extend (&pattern->base); - switch (extend) { - case CAIRO_EXTEND_NONE: - case CAIRO_EXTEND_REPEAT: - case CAIRO_EXTEND_REFLECT: - /* There's no point returning FALSE for EXTEND_PAD, as the image - * surface does not currently implement it either */ - case CAIRO_EXTEND_PAD: - return TRUE; - } - - ASSERT_NOT_REACHED; - return FALSE; -} - -static cairo_bool_t -_gradient_pattern_supported (cairo_pattern_t *pattern) -{ - cairo_extend_t extend; - - extend = cairo_pattern_get_extend (pattern); - - - /* Radial gradients are currently only supported with EXTEND_NONE - * and EXTEND_PAD and when one circle is inside the other. */ - if (pattern->type == CAIRO_PATTERN_TYPE_RADIAL) { - double x1, y1, x2, y2, r1, r2, d; - cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) pattern; - - if (extend == CAIRO_EXTEND_REPEAT || - extend == CAIRO_EXTEND_REFLECT) { - return FALSE; - } - - x1 = _cairo_fixed_to_double (radial->c1.x); - y1 = _cairo_fixed_to_double (radial->c1.y); - r1 = _cairo_fixed_to_double (radial->r1); - x2 = _cairo_fixed_to_double (radial->c2.x); - y2 = _cairo_fixed_to_double (radial->c2.y); - r2 = _cairo_fixed_to_double (radial->r2); - - d = sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1)); - if (d > fabs(r2 - r1)) { - return FALSE; - } - } - - return TRUE; -} - -static cairo_bool_t -_pattern_supported (cairo_pattern_t *pattern) -{ - if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) - return TRUE; - - if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR || - pattern->type == CAIRO_PATTERN_TYPE_RADIAL) - return _gradient_pattern_supported (pattern); - - if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) - return _surface_pattern_supported ((cairo_surface_pattern_t *) pattern); - - return FALSE; -} - -static cairo_int_status_t -_cairo_pdf_surface_analyze_operation (cairo_pdf_surface_t *surface, - cairo_operator_t op, - cairo_pattern_t *pattern) -{ - if (surface->force_fallbacks && surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (! _pattern_supported (pattern)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (op == CAIRO_OPERATOR_OVER) { - if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) { - cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern; - - if ( _cairo_surface_is_meta (surface_pattern->surface)) - return CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN; - } - } - - if (op == CAIRO_OPERATOR_OVER) - return CAIRO_STATUS_SUCCESS; - - /* The SOURCE operator is supported if the pattern is opaque or if - * there is nothing painted underneath. */ - if (op == CAIRO_OPERATOR_SOURCE) { - if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) { - cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern; - - if (_cairo_surface_is_meta (surface_pattern->surface)) { - if (_cairo_pattern_is_opaque (pattern)) { - return CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN; - } else { - /* FIXME: The analysis surface does not yet have - * the capability to analyze a non opaque meta - * surface and mark it supported if there is - * nothing underneath. For now meta surfaces of - * type CONTENT_COLOR_ALPHA painted with - * OPERATOR_SOURCE will result in a fallback - * image. */ - - return CAIRO_INT_STATUS_UNSUPPORTED; - } - } else { - return _cairo_pdf_surface_analyze_surface_pattern_transparency (surface, - surface_pattern); - } - } - - if (_cairo_pattern_is_opaque (pattern)) - return CAIRO_STATUS_SUCCESS; - else - return CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY; - } - - return CAIRO_INT_STATUS_UNSUPPORTED; -} - -static cairo_bool_t -_cairo_pdf_surface_operation_supported (cairo_pdf_surface_t *surface, - cairo_operator_t op, - cairo_pattern_t *pattern) -{ - if (_cairo_pdf_surface_analyze_operation (surface, op, pattern) != CAIRO_INT_STATUS_UNSUPPORTED) - return TRUE; - else - return FALSE; -} - -static cairo_int_status_t -_cairo_pdf_surface_start_fallback (cairo_pdf_surface_t *surface) -{ - cairo_status_t status; - - status = _cairo_pdf_surface_close_content_stream (surface); - if (status) - return status; - - status = _cairo_array_append (&surface->knockout_group, &surface->content); - if (status) - return status; - - _cairo_pdf_group_resources_clear (&surface->resources); - return _cairo_pdf_surface_open_content_stream (surface, TRUE); -} - -static cairo_int_status_t -_cairo_pdf_surface_paint (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source) -{ - cairo_pdf_surface_t *surface = abstract_surface; - cairo_status_t status; - cairo_pdf_smask_group_t *group; - cairo_pdf_resource_t pattern_res, gstate_res; - - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { - return _cairo_pdf_surface_analyze_operation (surface, op, source); - } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) { - status = _cairo_pdf_surface_start_fallback (surface); - if (status) - return status; - } - - assert (_cairo_pdf_surface_operation_supported (surface, op, source)); - - pattern_res.id = 0; - gstate_res.id = 0; - status = _cairo_pdf_surface_add_pdf_pattern (surface, source, &pattern_res, &gstate_res); - if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) - return CAIRO_STATUS_SUCCESS; - if (status) - return status; - - if (gstate_res.id != 0) { - group = _cairo_pdf_surface_create_smask_group (surface); - if (group == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - group->operation = PDF_PAINT; - group->source = cairo_pattern_reference (source); - group->source_res = pattern_res; - status = _cairo_pdf_surface_add_smask_group (surface, group); - if (status) { - _cairo_pdf_smask_group_destroy (group); - return status; - } - - status = _cairo_pdf_surface_add_smask (surface, gstate_res); - if (status) - return status; - - status = _cairo_pdf_surface_add_xobject (surface, group->group_res); - if (status) - return status; - - status = _cairo_pdf_operators_flush (&surface->pdf_operators); - if (status) - return status; - - _cairo_output_stream_printf (surface->output, - "q /s%d gs /x%d Do Q\n", - gstate_res.id, - group->group_res.id); - } else { - status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, FALSE); - if (status) - return status; - - _cairo_output_stream_printf (surface->output, - "0 0 %f %f re f\n", - surface->width, surface->height); - - status = _cairo_pdf_surface_unselect_pattern (surface); - if (status) - return status; - } - - return _cairo_output_stream_get_status (surface->output); -} - -static cairo_int_status_t -_cairo_pdf_surface_mask (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_pattern_t *mask) -{ - cairo_pdf_surface_t *surface = abstract_surface; - cairo_pdf_smask_group_t *group; - cairo_status_t status; - - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { - cairo_status_t source_status, mask_status; - - source_status = _cairo_pdf_surface_analyze_operation (surface, op, source); - if (_cairo_status_is_error (source_status)) - return source_status; - - mask_status = _cairo_pdf_surface_analyze_operation (surface, op, mask); - if (_cairo_status_is_error (mask_status)) - return mask_status; - - return _cairo_analysis_surface_merge_status (source_status, - mask_status); - } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) { - status = _cairo_pdf_surface_start_fallback (surface); - if (status) - return status; - } - - assert (_cairo_pdf_surface_operation_supported (surface, op, source)); - assert (_cairo_pdf_surface_operation_supported (surface, op, mask)); - - group = _cairo_pdf_surface_create_smask_group (surface); - if (group == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - group->operation = PDF_MASK; - group->source = cairo_pattern_reference (source); - group->mask = cairo_pattern_reference (mask); - group->source_res = _cairo_pdf_surface_new_object (surface); - if (group->source_res.id == 0) { - _cairo_pdf_smask_group_destroy (group); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - status = _cairo_pdf_surface_add_smask_group (surface, group); - if (status) { - _cairo_pdf_smask_group_destroy (group); - return status; - } - - status = _cairo_pdf_surface_add_smask (surface, group->group_res); - if (status) - return status; - - status = _cairo_pdf_surface_add_xobject (surface, group->source_res); - if (status) - return status; - - status = _cairo_pdf_operators_flush (&surface->pdf_operators); - if (status) - return status; - - _cairo_output_stream_printf (surface->output, - "q /s%d gs /x%d Do Q\n", - group->group_res.id, - group->source_res.id); - - return _cairo_output_stream_get_status (surface->output); -} - -static cairo_int_status_t -_cairo_pdf_surface_stroke (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - 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_pdf_surface_t *surface = abstract_surface; - cairo_status_t status; - cairo_pdf_smask_group_t *group; - cairo_pdf_resource_t pattern_res, gstate_res; - - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return _cairo_pdf_surface_analyze_operation (surface, op, source); - - assert (_cairo_pdf_surface_operation_supported (surface, op, source)); - - pattern_res.id = 0; - gstate_res.id = 0; - status = _cairo_pdf_surface_add_pdf_pattern (surface, source, &pattern_res, &gstate_res); - if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) - return CAIRO_STATUS_SUCCESS; - if (status) - return status; - - if (gstate_res.id != 0) { - group = _cairo_pdf_surface_create_smask_group (surface); - if (group == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - group->operation = PDF_STROKE; - group->source = cairo_pattern_reference (source); - group->source_res = pattern_res; - status = _cairo_path_fixed_init_copy (&group->path, path); - if (status) { - _cairo_pdf_smask_group_destroy (group); - return status; - } - - group->style = style; - group->ctm = *ctm; - group->ctm_inverse = *ctm_inverse; - status = _cairo_pdf_surface_add_smask_group (surface, group); - if (status) { - _cairo_pdf_smask_group_destroy (group); - return status; - } - - status = _cairo_pdf_surface_add_smask (surface, gstate_res); - if (status) - return status; - - status = _cairo_pdf_surface_add_xobject (surface, group->group_res); - if (status) - return status; - - status = _cairo_pdf_operators_flush (&surface->pdf_operators); - if (status) - return status; - - _cairo_output_stream_printf (surface->output, - "q /s%d gs /x%d Do Q\n", - gstate_res.id, - group->group_res.id); - } else { - status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, TRUE); - if (status) - return status; - - status = _cairo_pdf_operators_stroke (&surface->pdf_operators, - path, - style, - ctm, - ctm_inverse); - if (status) - return status; - - status = _cairo_pdf_surface_unselect_pattern (surface); - if (status) - return status; - } - - return _cairo_output_stream_get_status (surface->output); -} - -static cairo_int_status_t -_cairo_pdf_surface_fill (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_pdf_surface_t *surface = abstract_surface; - cairo_status_t status; - cairo_pdf_smask_group_t *group; - cairo_pdf_resource_t pattern_res, gstate_res; - - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { - return _cairo_pdf_surface_analyze_operation (surface, op, source); - } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) { - status = _cairo_pdf_surface_start_fallback (surface); - if (status) - return status; - } - - assert (_cairo_pdf_surface_operation_supported (surface, op, source)); - - pattern_res.id = 0; - gstate_res.id = 0; - status = _cairo_pdf_surface_add_pdf_pattern (surface, source, &pattern_res, &gstate_res); - if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) - return CAIRO_STATUS_SUCCESS; - if (status) - return status; - - if (gstate_res.id != 0) { - group = _cairo_pdf_surface_create_smask_group (surface); - if (group == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - group->operation = PDF_FILL; - group->source = cairo_pattern_reference (source); - group->source_res = pattern_res; - status = _cairo_path_fixed_init_copy (&group->path, path); - if (status) { - _cairo_pdf_smask_group_destroy (group); - return status; - } - - group->fill_rule = fill_rule; - status = _cairo_pdf_surface_add_smask_group (surface, group); - if (status) { - _cairo_pdf_smask_group_destroy (group); - return status; - } - - status = _cairo_pdf_surface_add_smask (surface, gstate_res); - if (status) - return status; - - status = _cairo_pdf_surface_add_xobject (surface, group->group_res); - if (status) - return status; - - status = _cairo_pdf_operators_flush (&surface->pdf_operators); - if (status) - return status; - - _cairo_output_stream_printf (surface->output, - "q /s%d gs /x%d Do Q\n", - gstate_res.id, - group->group_res.id); - } else { - status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, FALSE); - if (status) - return status; - - status = _cairo_pdf_operators_fill (&surface->pdf_operators, - path, - fill_rule); - if (status) - return status; - - status = _cairo_pdf_surface_unselect_pattern (surface); - if (status) - return status; - } - - return _cairo_output_stream_get_status (surface->output); -} - -static cairo_int_status_t -_cairo_pdf_surface_fill_stroke (void *abstract_surface, - cairo_operator_t fill_op, - cairo_pattern_t *fill_source, - cairo_fill_rule_t fill_rule, - double fill_tolerance, - cairo_antialias_t fill_antialias, - cairo_path_fixed_t *path, - cairo_operator_t stroke_op, - cairo_pattern_t *stroke_source, - cairo_stroke_style_t *stroke_style, - cairo_matrix_t *stroke_ctm, - cairo_matrix_t *stroke_ctm_inverse, - double stroke_tolerance, - cairo_antialias_t stroke_antialias) -{ - cairo_pdf_surface_t *surface = abstract_surface; - cairo_status_t status; - cairo_pdf_resource_t fill_pattern_res, stroke_pattern_res, gstate_res; - - /* During analysis we return unsupported and let the _fill and - * _stroke functions that are on the fallback path do the analysis - * for us. During render we may still encounter unsupported - * combinations of fill/stroke patterns. However we can return - * unsupported anytime to let the _fill and _stroke functions take - * over. - */ - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return CAIRO_INT_STATUS_UNSUPPORTED; - - /* PDF rendering of fill-stroke is not the same as cairo when - * either the fill or stroke is not opaque. - */ - if ( !_cairo_pattern_is_opaque (fill_source) || - !_cairo_pattern_is_opaque (stroke_source)) - { - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - fill_pattern_res.id = 0; - gstate_res.id = 0; - status = _cairo_pdf_surface_add_pdf_pattern (surface, fill_source, - &fill_pattern_res, - &gstate_res); - if (status) - return status; - - assert (gstate_res.id == 0); - - stroke_pattern_res.id = 0; - gstate_res.id = 0; - status = _cairo_pdf_surface_add_pdf_pattern (surface, - stroke_source, - &stroke_pattern_res, - &gstate_res); - if (status) - return status; - - assert (gstate_res.id == 0); - - /* As PDF has separate graphics state for fill and stroke we can - * select both at the same time */ - status = _cairo_pdf_surface_select_pattern (surface, fill_source, - fill_pattern_res, FALSE); - if (status) - return status; - - status = _cairo_pdf_surface_select_pattern (surface, stroke_source, - stroke_pattern_res, TRUE); - if (status) - return status; - - status = _cairo_pdf_operators_fill_stroke (&surface->pdf_operators, - path, - fill_rule, - stroke_style, - stroke_ctm, - stroke_ctm_inverse); - if (status) - return status; - - status = _cairo_pdf_surface_unselect_pattern (surface); - if (status) - return status; - - return _cairo_output_stream_get_status (surface->output); -} - -static cairo_bool_t -_cairo_pdf_surface_has_show_text_glyphs (void *abstract_surface) -{ - return TRUE; -} - -static cairo_int_status_t -_cairo_pdf_surface_show_text_glyphs (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - const char *utf8, - int utf8_len, - cairo_glyph_t *glyphs, - int num_glyphs, - const cairo_text_cluster_t *clusters, - int num_clusters, - cairo_text_cluster_flags_t cluster_flags, - cairo_scaled_font_t *scaled_font) -{ - cairo_pdf_surface_t *surface = abstract_surface; - cairo_status_t status; - cairo_pdf_smask_group_t *group; - cairo_pdf_resource_t pattern_res, gstate_res; - - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return _cairo_pdf_surface_analyze_operation (surface, op, source); - - assert (_cairo_pdf_surface_operation_supported (surface, op, source)); - - pattern_res.id = 0; - gstate_res.id = 0; - status = _cairo_pdf_surface_add_pdf_pattern (surface, source, &pattern_res, &gstate_res); - if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) - return CAIRO_STATUS_SUCCESS; - if (status) - return status; - - if (gstate_res.id != 0) { - group = _cairo_pdf_surface_create_smask_group (surface); - if (group == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - group->operation = PDF_SHOW_GLYPHS; - group->source = cairo_pattern_reference (source); - group->source_res = pattern_res; - - if (utf8_len) { - group->utf8 = malloc (utf8_len); - if (group->utf8 == NULL) { - _cairo_pdf_smask_group_destroy (group); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - memcpy (group->utf8, utf8, utf8_len); - } - group->utf8_len = utf8_len; - - if (num_glyphs) { - group->glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t)); - if (group->glyphs == NULL) { - _cairo_pdf_smask_group_destroy (group); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - memcpy (group->glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs); - } - group->num_glyphs = num_glyphs; - - if (num_clusters) { - group->clusters = _cairo_malloc_ab (num_clusters, sizeof (cairo_text_cluster_t)); - if (group->clusters == NULL) { - _cairo_pdf_smask_group_destroy (group); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - memcpy (group->clusters, clusters, sizeof (cairo_text_cluster_t) * num_clusters); - } - group->num_clusters = num_clusters; - - group->scaled_font = cairo_scaled_font_reference (scaled_font); - status = _cairo_pdf_surface_add_smask_group (surface, group); - if (status) { - _cairo_pdf_smask_group_destroy (group); - return status; - } - - status = _cairo_pdf_surface_add_smask (surface, gstate_res); - if (status) - return status; - - status = _cairo_pdf_surface_add_xobject (surface, group->group_res); - if (status) - return status; - - status = _cairo_pdf_operators_flush (&surface->pdf_operators); - if (status) - return status; - - _cairo_output_stream_printf (surface->output, - "q /s%d gs /x%d Do Q\n", - gstate_res.id, - group->group_res.id); - } else { - status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, FALSE); - if (status) - return status; - - /* Each call to show_glyphs() with a transclucent pattern must - * be in a separate text object otherwise overlapping text - * from separate calls to show_glyphs will not composite with - * each other. */ - if (! _cairo_pattern_is_opaque (source)) { - status = _cairo_pdf_operators_flush (&surface->pdf_operators); - if (status) - return status; - } - - status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators, - utf8, utf8_len, - glyphs, num_glyphs, - clusters, num_clusters, - cluster_flags, - scaled_font); - if (status) - return status; - - status = _cairo_pdf_surface_unselect_pattern (surface); - if (status) - return status; - } - - return _cairo_output_stream_get_status (surface->output); -} - - -static void -_cairo_pdf_surface_set_paginated_mode (void *abstract_surface, - cairo_paginated_mode_t paginated_mode) -{ - cairo_pdf_surface_t *surface = abstract_surface; - - surface->paginated_mode = paginated_mode; -} - -static const cairo_surface_backend_t cairo_pdf_surface_backend = { - CAIRO_SURFACE_TYPE_PDF, - _cairo_pdf_surface_create_similar, - _cairo_pdf_surface_finish, - NULL, /* acquire_source_image */ - NULL, /* release_source_image */ - NULL, /* acquire_dest_image */ - NULL, /* release_dest_image */ - NULL, /* clone_similar */ - NULL, /* composite */ - NULL, /* fill_rectangles */ - NULL, /* composite_trapezoids */ - NULL, /* _cairo_pdf_surface_copy_page */ - _cairo_pdf_surface_show_page, - NULL, /* set_clip_region */ - _cairo_pdf_surface_intersect_clip_path, - _cairo_pdf_surface_get_extents, - NULL, /* old_show_glyphs */ - _cairo_pdf_surface_get_font_options, - NULL, /* flush */ - NULL, /* mark_dirty_rectangle */ - NULL, /* scaled_font_fini */ - NULL, /* scaled_glyph_fini */ - - /* Here are the drawing functions */ - - _cairo_pdf_surface_paint, - _cairo_pdf_surface_mask, - _cairo_pdf_surface_stroke, - _cairo_pdf_surface_fill, - NULL, /* show_glyphs */ - NULL, /* snapshot */ - - NULL, /* is_compatible */ - NULL, /* reset */ - _cairo_pdf_surface_fill_stroke, - NULL, /* create_solid_pattern_surface */ - _cairo_pdf_surface_has_show_text_glyphs, - _cairo_pdf_surface_show_text_glyphs, -}; - -static const cairo_paginated_surface_backend_t -cairo_pdf_surface_paginated_backend = { - _cairo_pdf_surface_start_page, - _cairo_pdf_surface_set_paginated_mode, - NULL, /* set_bounding_box */ - _cairo_pdf_surface_has_fallback_images, - _cairo_pdf_surface_supports_fine_grained_fallbacks, -}; diff --git a/uppdev/plugin/cairo/lib/cairo-pdf.h b/uppdev/plugin/cairo/lib/cairo-pdf.h deleted file mode 100644 index 1a066b3a1..000000000 --- a/uppdev/plugin/cairo/lib/cairo-pdf.h +++ /dev/null @@ -1,68 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - */ - -#ifndef CAIRO_PDF_H -#define CAIRO_PDF_H - -#include "cairo.h" - -#if CAIRO_HAS_PDF_SURFACE - -CAIRO_BEGIN_DECLS - -cairo_public cairo_surface_t * -cairo_pdf_surface_create (const char *filename, - double width_in_points, - double height_in_points); - -cairo_public cairo_surface_t * -cairo_pdf_surface_create_for_stream (cairo_write_func_t write_func, - void *closure, - double width_in_points, - double height_in_points); - -cairo_public void -cairo_pdf_surface_set_size (cairo_surface_t *surface, - double width_in_points, - double height_in_points); - -CAIRO_END_DECLS - -#else /* CAIRO_HAS_PDF_SURFACE */ -# error Cairo was not compiled with support for the pdf backend -#endif /* CAIRO_HAS_PDF_SURFACE */ - -#endif /* CAIRO_PDF_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-pen.c b/uppdev/plugin/cairo/lib/cairo-pen.c deleted file mode 100644 index 425b3b965..000000000 --- a/uppdev/plugin/cairo/lib/cairo-pen.c +++ /dev/null @@ -1,491 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - */ - -#include "cairoint.h" - -static int -_cairo_pen_vertices_needed (double tolerance, double radius, cairo_matrix_t *matrix); - -static void -_cairo_pen_compute_slopes (cairo_pen_t *pen); - -static void -_cairo_pen_stroke_spline_half (cairo_pen_t *pen, cairo_spline_t *spline, cairo_direction_t dir, cairo_polygon_t *polygon); - -cairo_status_t -_cairo_pen_init (cairo_pen_t *pen, - double radius, - double tolerance, - cairo_matrix_t *ctm) -{ - int i; - int reflect; - - pen->radius = radius; - pen->tolerance = tolerance; - - reflect = _cairo_matrix_compute_determinant (ctm) < 0.; - - pen->num_vertices = _cairo_pen_vertices_needed (tolerance, - radius, - ctm); - - if (pen->num_vertices > ARRAY_LENGTH (pen->vertices_embedded)) { - pen->vertices = _cairo_malloc_ab (pen->num_vertices, - sizeof (cairo_pen_vertex_t)); - if (pen->vertices == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } else { - pen->vertices = pen->vertices_embedded; - } - - /* - * Compute pen coordinates. To generate the right ellipse, compute points around - * a circle in user space and transform them to device space. To get a consistent - * orientation in device space, flip the pen if the transformation matrix - * is reflecting - */ - for (i=0; i < pen->num_vertices; i++) { - double theta = 2 * M_PI * i / (double) pen->num_vertices; - double dx = radius * cos (reflect ? -theta : theta); - double dy = radius * sin (reflect ? -theta : theta); - cairo_pen_vertex_t *v = &pen->vertices[i]; - cairo_matrix_transform_distance (ctm, &dx, &dy); - v->point.x = _cairo_fixed_from_double (dx); - v->point.y = _cairo_fixed_from_double (dy); - } - - _cairo_pen_compute_slopes (pen); - - return CAIRO_STATUS_SUCCESS; -} - -void -_cairo_pen_fini (cairo_pen_t *pen) -{ - if (pen->vertices != pen->vertices_embedded) - free (pen->vertices); - - pen->vertices = pen->vertices_embedded; - pen->num_vertices = 0; -} - -cairo_status_t -_cairo_pen_init_copy (cairo_pen_t *pen, cairo_pen_t *other) -{ - *pen = *other; - - pen->vertices = pen->vertices_embedded; - if (pen->num_vertices) { - if (pen->num_vertices > ARRAY_LENGTH (pen->vertices_embedded)) { - pen->vertices = _cairo_malloc_ab (pen->num_vertices, - sizeof (cairo_pen_vertex_t)); - if (pen->vertices == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - memcpy (pen->vertices, other->vertices, - pen->num_vertices * sizeof (cairo_pen_vertex_t)); - } - - return CAIRO_STATUS_SUCCESS; -} - -cairo_status_t -_cairo_pen_add_points (cairo_pen_t *pen, cairo_point_t *point, int num_points) -{ - cairo_status_t status; - int num_vertices; - int i; - - num_vertices = pen->num_vertices + num_points; - if (num_vertices > ARRAY_LENGTH (pen->vertices_embedded) || - pen->vertices != pen->vertices_embedded) - { - cairo_pen_vertex_t *vertices; - - if (pen->vertices == pen->vertices_embedded) { - vertices = _cairo_malloc_ab (num_vertices, - sizeof (cairo_pen_vertex_t)); - if (vertices == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - memcpy (vertices, pen->vertices, - pen->num_vertices * sizeof (cairo_pen_vertex_t)); - } else { - vertices = _cairo_realloc_ab (pen->vertices, - num_vertices, - sizeof (cairo_pen_vertex_t)); - if (vertices == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - pen->vertices = vertices; - } - - pen->num_vertices = num_vertices; - - /* initialize new vertices */ - for (i=0; i < num_points; i++) - pen->vertices[pen->num_vertices-num_points+i].point = point[i]; - - status = _cairo_hull_compute (pen->vertices, &pen->num_vertices); - if (status) - return status; - - _cairo_pen_compute_slopes (pen); - - return CAIRO_STATUS_SUCCESS; -} - -/* -The circular pen in user space is transformed into an ellipse in -device space. - -We construct the pen by computing points along the circumference -using equally spaced angles. - -We show that this approximation to the ellipse has maximum error at the -major axis of the ellipse. - -Set - - M = major axis length - m = minor axis length - -Align 'M' along the X axis and 'm' along the Y axis and draw -an ellipse parameterized by angle 't': - - x = M cos t y = m sin t - -Perturb t by ± d and compute two new points (x+,y+), (x-,y-). -The distance from the average of these two points to (x,y) represents -the maximum error in approximating the ellipse with a polygon formed -from vertices 2∆ radians apart. - - x+ = M cos (t+∆) y+ = m sin (t+∆) - x- = M cos (t-∆) y- = m sin (t-∆) - -Now compute the approximation error, E: - - Ex = (x - (x+ + x-) / 2) - Ex = (M cos(t) - (Mcos(t+∆) + Mcos(t-∆))/2) - = M (cos(t) - (cos(t)cos(∆) + sin(t)sin(∆) + - cos(t)cos(∆) - sin(t)sin(∆))/2) - = M(cos(t) - cos(t)cos(∆)) - = M cos(t) (1 - cos(∆)) - - Ey = y - (y+ - y-) / 2 - = m sin (t) - (m sin(t+∆) + m sin(t-∆)) / 2 - = m (sin(t) - (sin(t)cos(∆) + cos(t)sin(∆) + - sin(t)cos(∆) - cos(t)sin(∆))/2) - = m (sin(t) - sin(t)cos(∆)) - = m sin(t) (1 - cos(∆)) - - E² = Ex² + Ey² - = (M cos(t) (1 - cos (∆)))² + (m sin(t) (1-cos(∆)))² - = (1 - cos(∆))² (M² cos²(t) + m² sin²(t)) - = (1 - cos(∆))² ((m² + M² - m²) cos² (t) + m² sin²(t)) - = (1 - cos(∆))² (M² - m²) cos² (t) + (1 - cos(∆))² m² - -Find the extremum by differentiation wrt t and setting that to zero - -∂(E²)/∂(t) = (1-cos(∆))² (M² - m²) (-2 cos(t) sin(t)) - - 0 = 2 cos (t) sin (t) - 0 = sin (2t) - t = nÏ€ - -Which is to say that the maximum and minimum errors occur on the -axes of the ellipse at 0 and Ï€ radians: - - E²(0) = (1-cos(∆))² (M² - m²) + (1-cos(∆))² m² - = (1-cos(∆))² M² - E²(Ï€) = (1-cos(∆))² m² - -maximum error = M (1-cos(∆)) -minimum error = m (1-cos(∆)) - -We must make maximum error ≤ tolerance, so compute the ∆ needed: - - tolerance = M (1-cos(∆)) - tolerance / M = 1 - cos (∆) - cos(∆) = 1 - tolerance/M - ∆ = acos (1 - tolerance / M); - -Remembering that ∆ is half of our angle between vertices, -the number of vertices is then - - vertices = ceil(2Ï€/2∆). - = ceil(Ï€/∆). - -Note that this also equation works for M == m (a circle) as it -doesn't matter where on the circle the error is computed. -*/ - -static int -_cairo_pen_vertices_needed (double tolerance, - double radius, - cairo_matrix_t *matrix) -{ - /* - * the pen is a circle that gets transformed to an ellipse by matrix. - * compute major axis length for a pen with the specified radius. - * we don't need the minor axis length. - */ - - double major_axis = _cairo_matrix_transformed_circle_major_axis(matrix, radius); - - /* - * compute number of vertices needed - */ - int num_vertices; - - /* Where tolerance / M is > 1, we use 4 points */ - if (tolerance >= major_axis) { - num_vertices = 4; - } else { - double delta = acos (1 - tolerance / major_axis); - num_vertices = ceil (M_PI / delta); - - /* number of vertices must be even */ - if (num_vertices % 2) - num_vertices++; - - /* And we must always have at least 4 vertices. */ - if (num_vertices < 4) - num_vertices = 4; - } - - return num_vertices; -} - -static void -_cairo_pen_compute_slopes (cairo_pen_t *pen) -{ - int i, i_prev; - cairo_pen_vertex_t *prev, *v, *next; - - for (i=0, i_prev = pen->num_vertices - 1; - i < pen->num_vertices; - i_prev = i++) { - prev = &pen->vertices[i_prev]; - v = &pen->vertices[i]; - next = &pen->vertices[(i + 1) % pen->num_vertices]; - - _cairo_slope_init (&v->slope_cw, &prev->point, &v->point); - _cairo_slope_init (&v->slope_ccw, &v->point, &next->point); - } -} -/* - * Find active pen vertex for clockwise edge of stroke at the given slope. - * - * The strictness of the inequalities here is delicate. The issue is - * that the slope_ccw member of one pen vertex will be equivalent to - * the slope_cw member of the next pen vertex in a counterclockwise - * order. However, for this function, we care strongly about which - * vertex is returned. - * - * [I think the "care strongly" above has to do with ensuring that the - * pen's "extra points" from the spline's initial and final slopes are - * properly found when beginning the spline stroking.] - */ -void -_cairo_pen_find_active_cw_vertex_index (cairo_pen_t *pen, - cairo_slope_t *slope, - int *active) -{ - int i; - - for (i=0; i < pen->num_vertices; i++) { - if ((_cairo_slope_compare (slope, &pen->vertices[i].slope_ccw) < 0) && - (_cairo_slope_compare (slope, &pen->vertices[i].slope_cw) >= 0)) - break; - } - - /* If the desired slope cannot be found between any of the pen - * vertices, then we must have a degenerate pen, (such as a pen - * that's been transformed to a line). In that case, we consider - * the first pen vertex as the appropriate clockwise vertex. - */ - if (i == pen->num_vertices) - i = 0; - - *active = i; -} - -/* Find active pen vertex for counterclockwise edge of stroke at the given slope. - * - * Note: See the comments for _cairo_pen_find_active_cw_vertex_index - * for some details about the strictness of the inequalities here. - */ -void -_cairo_pen_find_active_ccw_vertex_index (cairo_pen_t *pen, - cairo_slope_t *slope, - int *active) -{ - int i; - cairo_slope_t slope_reverse; - - slope_reverse = *slope; - slope_reverse.dx = -slope_reverse.dx; - slope_reverse.dy = -slope_reverse.dy; - - for (i=pen->num_vertices-1; i >= 0; i--) { - if ((_cairo_slope_compare (&pen->vertices[i].slope_ccw, &slope_reverse) >= 0) && - (_cairo_slope_compare (&pen->vertices[i].slope_cw, &slope_reverse) < 0)) - break; - } - - /* If the desired slope cannot be found between any of the pen - * vertices, then we must have a degenerate pen, (such as a pen - * that's been transformed to a line). In that case, we consider - * the last pen vertex as the appropriate counterclockwise vertex. - */ - if (i < 0) - i = pen->num_vertices - 1; - - *active = i; -} - -static void -_cairo_pen_stroke_spline_half (cairo_pen_t *pen, - cairo_spline_t *spline, - cairo_direction_t dir, - cairo_polygon_t *polygon) -{ - int i; - int start, stop, step; - int active = 0; - cairo_point_t hull_point; - cairo_slope_t slope, initial_slope, final_slope; - cairo_point_t *point = spline->points; - int num_points = spline->num_points; - - if (dir == CAIRO_DIRECTION_FORWARD) { - start = 0; - stop = num_points; - step = 1; - initial_slope = spline->initial_slope; - final_slope = spline->final_slope; - } else { - start = num_points - 1; - stop = -1; - step = -1; - initial_slope = spline->final_slope; - initial_slope.dx = -initial_slope.dx; - initial_slope.dy = -initial_slope.dy; - final_slope = spline->initial_slope; - final_slope.dx = -final_slope.dx; - final_slope.dy = -final_slope.dy; - } - - _cairo_pen_find_active_cw_vertex_index (pen, - &initial_slope, - &active); - - i = start; - while (i != stop) { - hull_point.x = point[i].x + pen->vertices[active].point.x; - hull_point.y = point[i].y + pen->vertices[active].point.y; - - _cairo_polygon_line_to (polygon, &hull_point); - - if (i + step == stop) - slope = final_slope; - else - _cairo_slope_init (&slope, &point[i], &point[i+step]); - - /* The strict inequalities here ensure that if a spline slope - * compares identically with either of the slopes of the - * active vertex, then it remains the active vertex. This is - * very important since otherwise we can trigger an infinite - * loop in the case of a degenerate pen, (a line), where - * neither vertex considers itself active for the slope---one - * will consider it as equal and reject, and the other will - * consider it unequal and reject. This is due to the inherent - * ambiguity when comparing slopes that differ by exactly - * pi. */ - if (_cairo_slope_compare (&slope, &pen->vertices[active].slope_ccw) > 0) { - if (++active == pen->num_vertices) - active = 0; - } else if (_cairo_slope_compare (&slope, &pen->vertices[active].slope_cw) < 0) { - if (--active == -1) - active = pen->num_vertices - 1; - } else { - i += step; - } - } -} - -/* Compute outline of a given spline using the pen. - The trapezoids needed to fill that outline will be added to traps -*/ -cairo_status_t -_cairo_pen_stroke_spline (cairo_pen_t *pen, - cairo_spline_t *spline, - double tolerance, - cairo_traps_t *traps) -{ - cairo_status_t status; - cairo_polygon_t polygon; - - /* If the line width is so small that the pen is reduced to a - single point, then we have nothing to do. */ - if (pen->num_vertices <= 1) - return CAIRO_STATUS_SUCCESS; - - _cairo_polygon_init (&polygon); - - status = _cairo_spline_decompose (spline, tolerance); - if (status) - goto BAIL; - - _cairo_pen_stroke_spline_half (pen, spline, CAIRO_DIRECTION_FORWARD, &polygon); - - _cairo_pen_stroke_spline_half (pen, spline, CAIRO_DIRECTION_REVERSE, &polygon); - - _cairo_polygon_close (&polygon); - status = _cairo_polygon_status (&polygon); - if (status) - goto BAIL; - - status = _cairo_bentley_ottmann_tessellate_polygon (traps, &polygon, CAIRO_FILL_RULE_WINDING); -BAIL: - _cairo_polygon_fini (&polygon); - - return status; -} diff --git a/uppdev/plugin/cairo/lib/cairo-png.c b/uppdev/plugin/cairo/lib/cairo-png.c deleted file mode 100644 index 06e7cb557..000000000 --- a/uppdev/plugin/cairo/lib/cairo-png.c +++ /dev/null @@ -1,708 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2003 University of Southern California - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - * Kristian Høgsberg - * Chris Wilson - */ - -#include "cairoint.h" - -#include -#include - -/* Unpremultiplies data and converts native endian ARGB => RGBA bytes */ -static void -unpremultiply_data (png_structp png, png_row_infop row_info, png_bytep data) -{ - unsigned int i; - - for (i = 0; i < row_info->rowbytes; i += 4) { - uint8_t *b = &data[i]; - uint32_t pixel; - uint8_t alpha; - - memcpy (&pixel, b, sizeof (uint32_t)); - alpha = (pixel & 0xff000000) >> 24; - if (alpha == 0) { - b[0] = b[1] = b[2] = b[3] = 0; - } else { - b[0] = (((pixel & 0xff0000) >> 16) * 255 + alpha / 2) / alpha; - b[1] = (((pixel & 0x00ff00) >> 8) * 255 + alpha / 2) / alpha; - b[2] = (((pixel & 0x0000ff) >> 0) * 255 + alpha / 2) / alpha; - b[3] = alpha; - } - } -} - -/* Converts native endian xRGB => RGBx bytes */ -static void -convert_data_to_bytes (png_structp png, png_row_infop row_info, png_bytep data) -{ - unsigned int i; - - for (i = 0; i < row_info->rowbytes; i += 4) { - uint8_t *b = &data[i]; - uint32_t pixel; - - memcpy (&pixel, b, sizeof (uint32_t)); - - b[0] = (pixel & 0xff0000) >> 16; - b[1] = (pixel & 0x00ff00) >> 8; - b[2] = (pixel & 0x0000ff) >> 0; - b[3] = 0; - } -} - -/* Use a couple of simple error callbacks that do not print anything to - * stderr and rely on the user to check for errors via the #cairo_status_t - * return. - */ -static void -png_simple_error_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); - -#ifdef PNG_SETJMP_SUPPORTED - longjmp (png_jmpbuf (png), 1); -#endif - - /* if we get here, then we have to choice but to abort ... */ -} - -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 */ -} - - -/* Starting with libpng-1.2.30, we must explicitly specify an output_flush_fn. - * Otherwise, we will segfault if we are writing to a stream. */ -static void -png_simple_output_flush_fn (png_structp png_ptr) -{ -} - -static cairo_status_t -write_png (cairo_surface_t *surface, - png_rw_ptr write_func, - void *closure) -{ - int i; - cairo_status_t status; - cairo_image_surface_t *image; - void *image_extra; - png_struct *png; - png_info *info; - png_byte **volatile rows = NULL; - png_color_16 white; - int png_color_type; - int depth; - - status = _cairo_surface_acquire_source_image (surface, - &image, - &image_extra); - - if (status == CAIRO_INT_STATUS_UNSUPPORTED) - return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - else if (status) - return status; - - /* PNG complains about "Image width or height is zero in IHDR" */ - if (image->width == 0 || image->height == 0) { - status = _cairo_error (CAIRO_STATUS_WRITE_ERROR); - goto BAIL1; - } - - rows = _cairo_malloc_ab (image->height, sizeof (png_byte*)); - if (rows == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto BAIL1; - } - - for (i = 0; i < image->height; i++) - rows[i] = (png_byte *) image->data + i * image->stride; - - png = png_create_write_struct (PNG_LIBPNG_VER_STRING, &status, - png_simple_error_callback, - png_simple_warning_callback); - if (png == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto BAIL2; - } - - info = png_create_info_struct (png); - if (info == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto BAIL3; - } - -#ifdef PNG_SETJMP_SUPPORTED - if (setjmp (png_jmpbuf (png))) - goto BAIL3; -#endif - - png_set_write_fn (png, closure, write_func, png_simple_output_flush_fn); - - switch (image->format) { - case CAIRO_FORMAT_ARGB32: - depth = 8; - png_color_type = PNG_COLOR_TYPE_RGB_ALPHA; - break; - case CAIRO_FORMAT_RGB24: - depth = 8; - png_color_type = PNG_COLOR_TYPE_RGB; - break; - case CAIRO_FORMAT_A8: - depth = 8; - png_color_type = PNG_COLOR_TYPE_GRAY; - break; - case CAIRO_FORMAT_A1: - depth = 1; - png_color_type = PNG_COLOR_TYPE_GRAY; -#ifndef WORDS_BIGENDIAN - png_set_packswap (png); -#endif - break; - default: - status = _cairo_error (CAIRO_STATUS_INVALID_FORMAT); - goto BAIL3; - } - - png_set_IHDR (png, info, - image->width, - image->height, depth, - png_color_type, - PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_DEFAULT, - PNG_FILTER_TYPE_DEFAULT); - - white.gray = (1 << depth) - 1; - white.red = white.blue = white.green = white.gray; - png_set_bKGD (png, info, &white); - - if (0) { /* XXX extract meta-data from surface (i.e. creation date) */ - png_time pt; - - png_convert_from_time_t (&pt, time (NULL)); - png_set_tIME (png, info, &pt); - } - - /* We have to call png_write_info() before setting up the write - * transformation, since it stores data internally in 'png' - * that is needed for the write transformation functions to work. - */ - png_write_info (png, info); - - if (image->format == CAIRO_FORMAT_ARGB32) - png_set_write_user_transform_fn (png, unpremultiply_data); - else if (image->format == CAIRO_FORMAT_RGB24) - png_set_write_user_transform_fn (png, convert_data_to_bytes); - if (image->format == CAIRO_FORMAT_RGB24) - png_set_filler (png, 0, PNG_FILLER_AFTER); - - png_write_image (png, rows); - png_write_end (png, info); - -BAIL3: - png_destroy_write_struct (&png, &info); -BAIL2: - free (rows); -BAIL1: - _cairo_surface_release_source_image (surface, image, image_extra); - - return status; -} - -static void -stdio_write_func (png_structp png, png_bytep data, png_size_t size) -{ - FILE *fp; - - fp = png_get_io_ptr (png); - while (size) { - size_t ret = fwrite (data, 1, size, fp); - size -= ret; - data += ret; - if (size && ferror (fp)) { - cairo_status_t *error = png_get_error_ptr (png); - if (*error == CAIRO_STATUS_SUCCESS) - *error = _cairo_error (CAIRO_STATUS_WRITE_ERROR); - png_error (png, NULL); - } - } -} - -/** - * cairo_surface_write_to_png: - * @surface: a #cairo_surface_t with pixel contents - * @filename: the name of a file to write to - * - * Writes the contents of @surface to a new file @filename as a PNG - * image. - * - * Return value: %CAIRO_STATUS_SUCCESS if the PNG file was written - * successfully. Otherwise, %CAIRO_STATUS_NO_MEMORY if memory could not - * be allocated for the operation or - * %CAIRO_STATUS_SURFACE_TYPE_MISMATCH if the surface does not have - * pixel contents, or %CAIRO_STATUS_WRITE_ERROR if an I/O error occurs - * while attempting to write the file. - **/ -cairo_status_t -cairo_surface_write_to_png (cairo_surface_t *surface, - const char *filename) -{ - FILE *fp; - cairo_status_t status; - - if (surface->status) - return surface->status; - - if (surface->finished) - return _cairo_error (CAIRO_STATUS_SURFACE_FINISHED); - - fp = fopen (filename, "wb"); - if (fp == NULL) { - switch (errno) { - case ENOMEM: - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - default: - return _cairo_error (CAIRO_STATUS_WRITE_ERROR); - } - } - - status = write_png (surface, stdio_write_func, fp); - - if (fclose (fp) && status == CAIRO_STATUS_SUCCESS) - status = _cairo_error (CAIRO_STATUS_WRITE_ERROR); - - return status; -} - -struct png_write_closure_t { - cairo_write_func_t write_func; - void *closure; -}; - -static void -stream_write_func (png_structp png, png_bytep data, png_size_t size) -{ - cairo_status_t status; - struct png_write_closure_t *png_closure; - - png_closure = png_get_io_ptr (png); - status = png_closure->write_func (png_closure->closure, data, size); - if (status) { - cairo_status_t *error = png_get_error_ptr (png); - if (*error == CAIRO_STATUS_SUCCESS) - *error = status; - png_error (png, NULL); - } -} - -/** - * cairo_surface_write_to_png_stream: - * @surface: a #cairo_surface_t with pixel contents - * @write_func: a #cairo_write_func_t - * @closure: closure data for the write function - * - * Writes the image surface to the write function. - * - * Return value: %CAIRO_STATUS_SUCCESS if the PNG file was written - * successfully. Otherwise, %CAIRO_STATUS_NO_MEMORY is returned if - * memory could not be allocated for the operation, - * %CAIRO_STATUS_SURFACE_TYPE_MISMATCH if the surface does not have - * pixel contents. - **/ -cairo_status_t -cairo_surface_write_to_png_stream (cairo_surface_t *surface, - cairo_write_func_t write_func, - void *closure) -{ - struct png_write_closure_t png_closure; - - if (surface->status) - return surface->status; - - if (surface->finished) - return _cairo_error (CAIRO_STATUS_SURFACE_FINISHED); - - png_closure.write_func = write_func; - png_closure.closure = closure; - - return write_png (surface, stream_write_func, &png_closure); -} -slim_hidden_def (cairo_surface_write_to_png_stream); - -static inline int -multiply_alpha (int alpha, int color) -{ - int temp = (alpha * color) + 0x80; - return ((temp + (temp >> 8)) >> 8); -} - -/* Premultiplies data and converts RGBA bytes => native endian */ -static void -premultiply_data (png_structp png, - png_row_infop row_info, - png_bytep data) -{ - unsigned int i; - - for (i = 0; i < row_info->rowbytes; i += 4) { - uint8_t *base = &data[i]; - uint8_t alpha = base[3]; - uint32_t p; - - if (alpha == 0) { - p = 0; - } else { - uint8_t red = base[0]; - uint8_t green = base[1]; - uint8_t blue = base[2]; - - if (alpha != 0xff) { - red = multiply_alpha (alpha, red); - green = multiply_alpha (alpha, green); - blue = multiply_alpha (alpha, blue); - } - p = (alpha << 24) | (red << 16) | (green << 8) | (blue << 0); - } - memcpy (base, &p, sizeof (uint32_t)); - } -} - -/* Converts RGBx bytes to native endian xRGB */ -static void -convert_bytes_to_data (png_structp png, png_row_infop row_info, png_bytep data) -{ - unsigned int i; - - for (i = 0; i < row_info->rowbytes; i += 4) { - uint8_t *base = &data[i]; - uint8_t red = base[0]; - uint8_t green = base[1]; - uint8_t blue = base[2]; - uint32_t pixel; - - pixel = (0xff << 24) | (red << 16) | (green << 8) | (blue << 0); - memcpy (base, &pixel, sizeof (uint32_t)); - } -} - -static cairo_surface_t * -read_png (png_rw_ptr read_func, - void *closure) -{ - cairo_surface_t *surface; - png_struct *png = NULL; - png_info *info; - png_byte *data = NULL; - png_byte **row_pointers = NULL; - png_uint_32 png_width, png_height; - int depth, color_type, interlace, stride; - unsigned int i; - cairo_format_t format; - cairo_status_t status; - - /* XXX: Perhaps we'll want some other error handlers? */ - png = png_create_read_struct (PNG_LIBPNG_VER_STRING, - &status, - png_simple_error_callback, - png_simple_warning_callback); - if (png == NULL) { - surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - goto BAIL; - } - - info = png_create_info_struct (png); - if (info == NULL) { - surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - goto BAIL; - } - - png_set_read_fn (png, closure, read_func); - - status = CAIRO_STATUS_SUCCESS; -#ifdef PNG_SETJMP_SUPPORTED - if (setjmp (png_jmpbuf (png))) { - surface = _cairo_surface_create_in_error (status); - goto BAIL; - } -#endif - - png_read_info (png, info); - - png_get_IHDR (png, info, - &png_width, &png_height, &depth, - &color_type, &interlace, NULL, NULL); - if (status) { /* catch any early warnings */ - surface = _cairo_surface_create_in_error (status); - goto BAIL; - } - - /* convert palette/gray image to rgb */ - if (color_type == PNG_COLOR_TYPE_PALETTE) - png_set_palette_to_rgb (png); - - /* expand gray bit depth if needed */ - if (color_type == PNG_COLOR_TYPE_GRAY) { -#if PNG_LIBPNG_VER >= 10209 - png_set_expand_gray_1_2_4_to_8 (png); -#else - png_set_gray_1_2_4_to_8 (png); -#endif - } - - /* transform transparency to alpha */ - if (png_get_valid (png, info, PNG_INFO_tRNS)) - png_set_tRNS_to_alpha (png); - - if (depth == 16) - png_set_strip_16 (png); - - if (depth < 8) - png_set_packing (png); - - /* convert grayscale to RGB */ - if (color_type == PNG_COLOR_TYPE_GRAY || - color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - { - png_set_gray_to_rgb (png); - } - - if (interlace != PNG_INTERLACE_NONE) - png_set_interlace_handling (png); - - png_set_filler (png, 0xff, PNG_FILLER_AFTER); - - /* recheck header after setting EXPAND options */ - png_read_update_info (png, info); - png_get_IHDR (png, info, - &png_width, &png_height, &depth, - &color_type, &interlace, NULL, NULL); - if (depth != 8 || - ! (color_type == PNG_COLOR_TYPE_RGB || - color_type == PNG_COLOR_TYPE_RGB_ALPHA)) - { - surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_READ_ERROR)); - goto BAIL; - } - - switch (color_type) { - default: - ASSERT_NOT_REACHED; - /* fall-through just in case ;-) */ - - case PNG_COLOR_TYPE_RGB_ALPHA: - format = CAIRO_FORMAT_ARGB32; - png_set_read_user_transform_fn (png, premultiply_data); - break; - - case PNG_COLOR_TYPE_RGB: - format = CAIRO_FORMAT_RGB24; - png_set_read_user_transform_fn (png, convert_bytes_to_data); - break; - } - - stride = cairo_format_stride_for_width (format, png_width); - if (stride < 0) { - surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE)); - goto BAIL; - } - - data = _cairo_malloc_ab (png_height, stride); - if (data == NULL) { - surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - goto BAIL; - } - - row_pointers = _cairo_malloc_ab (png_height, sizeof (char *)); - if (row_pointers == NULL) { - surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - goto BAIL; - } - - for (i = 0; i < png_height; i++) - row_pointers[i] = &data[i * stride]; - - png_read_image (png, row_pointers); - png_read_end (png, info); - - if (status) { /* catch any late warnings - probably hit an error already */ - surface = _cairo_surface_create_in_error (status); - goto BAIL; - } - - surface = cairo_image_surface_create_for_data (data, format, - png_width, png_height, - stride); - if (surface->status) - goto BAIL; - - _cairo_image_surface_assume_ownership_of_data ((cairo_image_surface_t*)surface); - data = NULL; - - BAIL: - if (row_pointers) - free (row_pointers); - if (data) - free (data); - if (png) - png_destroy_read_struct (&png, &info, NULL); - - return surface; -} - -static void -stdio_read_func (png_structp png, png_bytep data, png_size_t size) -{ - FILE *fp; - - fp = png_get_io_ptr (png); - while (size) { - size_t ret = fread (data, 1, size, fp); - size -= ret; - data += ret; - if (size && (feof (fp) || ferror (fp))) { - cairo_status_t *error = png_get_error_ptr (png); - if (*error == CAIRO_STATUS_SUCCESS) - *error = _cairo_error (CAIRO_STATUS_READ_ERROR); - png_error (png, NULL); - } - } -} - -/** - * cairo_image_surface_create_from_png: - * @filename: name of PNG file to load - * - * Creates a new image surface and initializes the contents to the - * given PNG file. - * - * Return value: a new #cairo_surface_t initialized with the contents - * of the PNG file, or a "nil" surface if any error occurred. A nil - * surface can be checked for with cairo_surface_status(surface) which - * may return one of the following values: - * - * %CAIRO_STATUS_NO_MEMORY - * %CAIRO_STATUS_FILE_NOT_FOUND - * %CAIRO_STATUS_READ_ERROR - **/ -cairo_surface_t * -cairo_image_surface_create_from_png (const char *filename) -{ - FILE *fp; - cairo_surface_t *surface; - - fp = fopen (filename, "rb"); - if (fp == NULL) { - cairo_status_t status; - switch (errno) { - case ENOMEM: - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - break; - case ENOENT: - status = _cairo_error (CAIRO_STATUS_FILE_NOT_FOUND); - break; - default: - status = _cairo_error (CAIRO_STATUS_READ_ERROR); - break; - } - return _cairo_surface_create_in_error (status); - } - - surface = read_png (stdio_read_func, fp); - - fclose (fp); - - return surface; -} - -struct png_read_closure_t { - cairo_read_func_t read_func; - void *closure; -}; - -static void -stream_read_func (png_structp png, png_bytep data, png_size_t size) -{ - cairo_status_t status; - struct png_read_closure_t *png_closure; - - png_closure = png_get_io_ptr (png); - status = png_closure->read_func (png_closure->closure, data, size); - if (status) { - cairo_status_t *error = png_get_error_ptr (png); - if (*error == CAIRO_STATUS_SUCCESS) - *error = status; - png_error (png, NULL); - } -} - -/** - * cairo_image_surface_create_from_png_stream: - * @read_func: function called to read the data of the file - * @closure: data to pass to @read_func. - * - * Creates a new image surface from PNG data read incrementally - * via the @read_func function. - * - * Return value: a new #cairo_surface_t initialized with the contents - * of the PNG file or %NULL if the data read is not a valid PNG image or - * memory could not be allocated for the operation. - **/ -cairo_surface_t * -cairo_image_surface_create_from_png_stream (cairo_read_func_t read_func, - void *closure) -{ - struct png_read_closure_t png_closure; - - png_closure.read_func = read_func; - png_closure.closure = closure; - - return read_png (stream_read_func, &png_closure); -} diff --git a/uppdev/plugin/cairo/lib/cairo-polygon.c b/uppdev/plugin/cairo/lib/cairo-polygon.c deleted file mode 100644 index 1392bfa18..000000000 --- a/uppdev/plugin/cairo/lib/cairo-polygon.c +++ /dev/null @@ -1,149 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - */ - -#include "cairoint.h" - -void -_cairo_polygon_init (cairo_polygon_t *polygon) -{ - polygon->status = CAIRO_STATUS_SUCCESS; - - polygon->num_edges = 0; - - polygon->edges = polygon->edges_embedded; - polygon->edges_size = ARRAY_LENGTH (polygon->edges_embedded); - - polygon->has_current_point = FALSE; -} - -void -_cairo_polygon_fini (cairo_polygon_t *polygon) -{ - if (polygon->edges != polygon->edges_embedded) - free (polygon->edges); -} - -/* make room for at least one more edge */ -static cairo_bool_t -_cairo_polygon_grow (cairo_polygon_t *polygon) -{ - cairo_edge_t *new_edges; - int old_size = polygon->edges_size; - int new_size = 4 * old_size; - - if (polygon->edges == polygon->edges_embedded) { - new_edges = _cairo_malloc_ab (new_size, sizeof (cairo_edge_t)); - if (new_edges != NULL) - memcpy (new_edges, polygon->edges, old_size * sizeof (cairo_edge_t)); - } else { - new_edges = _cairo_realloc_ab (polygon->edges, - new_size, sizeof (cairo_edge_t)); - } - - if (new_edges == NULL) { - polygon->status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - return FALSE; - } - - polygon->edges = new_edges; - polygon->edges_size = new_size; - - return TRUE; -} - -static void -_cairo_polygon_add_edge (cairo_polygon_t *polygon, - const cairo_point_t *p1, - const cairo_point_t *p2) -{ - cairo_edge_t *edge; - - /* drop horizontal edges */ - if (p1->y == p2->y) - goto DONE; - - if (polygon->num_edges == polygon->edges_size) { - if (! _cairo_polygon_grow (polygon)) - return; - } - - edge = &polygon->edges[polygon->num_edges++]; - if (p1->y < p2->y) { - edge->edge.p1 = *p1; - edge->edge.p2 = *p2; - edge->clockWise = 1; - } else { - edge->edge.p1 = *p2; - edge->edge.p2 = *p1; - edge->clockWise = 0; - } - - DONE: - _cairo_polygon_move_to (polygon, p2); -} - -void -_cairo_polygon_move_to (cairo_polygon_t *polygon, - const cairo_point_t *point) -{ - if (! polygon->has_current_point) - polygon->first_point = *point; - - polygon->current_point = *point; - polygon->has_current_point = TRUE; -} - -void -_cairo_polygon_line_to (cairo_polygon_t *polygon, - const cairo_point_t *point) -{ - if (polygon->has_current_point) - _cairo_polygon_add_edge (polygon, &polygon->current_point, point); - else - _cairo_polygon_move_to (polygon, point); -} - -void -_cairo_polygon_close (cairo_polygon_t *polygon) -{ - if (polygon->has_current_point) { - _cairo_polygon_add_edge (polygon, - &polygon->current_point, - &polygon->first_point); - - polygon->has_current_point = FALSE; - } -} diff --git a/uppdev/plugin/cairo/lib/cairo-private.h b/uppdev/plugin/cairo/lib/cairo-private.h deleted file mode 100644 index 43bd2232c..000000000 --- a/uppdev/plugin/cairo/lib/cairo-private.h +++ /dev/null @@ -1,57 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Carl D. Worth - */ - -#ifndef CAIRO_PRIVATE_H -#define CAIRO_PRIVATE_H - -#include "cairo-reference-count-private.h" -#include "cairo-gstate-private.h" -#include "cairo-path-fixed-private.h" - -struct _cairo { - cairo_reference_count_t ref_count; - - cairo_status_t status; - - cairo_user_data_array_t user_data; - - cairo_gstate_t *gstate; - cairo_gstate_t gstate_tail[1]; - cairo_gstate_t *gstate_freelist; - - cairo_path_fixed_t path[1]; -}; - -#endif /* CAIRO_PRIVATE_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-ps-surface-private.h b/uppdev/plugin/cairo/lib/cairo-ps-surface-private.h deleted file mode 100644 index e78833d05..000000000 --- a/uppdev/plugin/cairo/lib/cairo-ps-surface-private.h +++ /dev/null @@ -1,100 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2003 University of Southern California - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - * Kristian Høgsberg - * Keith Packard - */ - -#ifndef CAIRO_PS_SURFACE_PRIVATE_H -#define CAIRO_PS_SURFACE_PRIVATE_H - -#include "cairo-ps.h" - -#include "cairo-surface-private.h" -#include "cairo-pdf-operators-private.h" - -#include - -typedef struct cairo_ps_surface { - cairo_surface_t base; - - /* Here final_stream corresponds to the stream/file passed to - * cairo_ps_surface_create surface is built. Meanwhile stream is a - * temporary stream in which the file output is built, (so that - * the header can be built and inserted into the target stream - * before the contents of the temporary stream are copied). */ - cairo_output_stream_t *final_stream; - - FILE *tmpfile; - cairo_output_stream_t *stream; - - cairo_bool_t eps; - cairo_content_t content; - double width; - double height; - int bbox_x1, bbox_y1, bbox_x2, bbox_y2; - cairo_matrix_t cairo_to_ps; - cairo_image_surface_t *image; - void *image_extra; - cairo_bool_t use_string_datasource; - - cairo_bool_t current_pattern_is_solid_color; - cairo_color_t current_color; - - int num_pages; - - cairo_paginated_mode_t paginated_mode; - - cairo_bool_t force_fallbacks; - cairo_bool_t has_creation_date; - time_t creation_date; - - cairo_scaled_font_subsets_t *font_subsets; - - cairo_array_t dsc_header_comments; - cairo_array_t dsc_setup_comments; - cairo_array_t dsc_page_setup_comments; - - cairo_array_t *dsc_comment_target; - - cairo_ps_level_t ps_level; - cairo_ps_level_t ps_level_used; - - cairo_pdf_operators_t pdf_operators; - cairo_surface_t *paginated_surface; -} cairo_ps_surface_t; - -#endif /* CAIRO_PS_SURFACE_PRIVATE_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-ps-surface.c b/uppdev/plugin/cairo/lib/cairo-ps-surface.c deleted file mode 100644 index bfe424dde..000000000 --- a/uppdev/plugin/cairo/lib/cairo-ps-surface.c +++ /dev/null @@ -1,3337 +0,0 @@ -/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2003 University of Southern California - * Copyright © 2005 Red Hat, Inc - * Copyright © 2007,2008 Adrian Johnson - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - * Kristian Høgsberg - * Keith Packard - * Adrian Johnson - */ - - -/* - * Design of the PS output: - * - * The PS output is harmonised with the PDF operations using PS procedures - * to emulate the PDF operators. - * - * This has a number of advantages: - * 1. A large chunk of code is shared between the PDF and PS backends. - * See cairo-pdf-operators. - * 2. Using gs to do PS -> PDF and PDF -> PS will always work well. - */ - -#define _BSD_SOURCE /* for ctime_r(), snprintf(), strdup() */ -#include "cairoint.h" -#include "cairo-ps.h" -#include "cairo-ps-surface-private.h" -#include "cairo-pdf-operators-private.h" -#include "cairo-scaled-font-subsets-private.h" -#include "cairo-paginated-private.h" -#include "cairo-meta-surface-private.h" -#include "cairo-output-stream-private.h" -#include "cairo-type3-glyph-surface-private.h" - -#include -#include -#include -#include -#include - -#define DEBUG_PS 0 - -#ifndef HAVE_CTIME_R -#define ctime_r(T, BUF) ctime (T) -#endif - -static const cairo_surface_backend_t cairo_ps_surface_backend; -static const cairo_paginated_surface_backend_t cairo_ps_surface_paginated_backend; - -static const cairo_ps_level_t _cairo_ps_levels[] = -{ - CAIRO_PS_LEVEL_2, - CAIRO_PS_LEVEL_3 -}; - -#define CAIRO_PS_LEVEL_LAST ARRAY_LENGTH (_cairo_ps_levels) - -static const char * _cairo_ps_level_strings[CAIRO_PS_LEVEL_LAST] = -{ - "PS Level 2", - "PS Level 3" -}; - -static void -_cairo_ps_surface_emit_header (cairo_ps_surface_t *surface) -{ - char ctime_buf[26]; - time_t now; - char **comments; - int i, num_comments; - int level; - const char *eps_header = ""; - - if (surface->has_creation_date) - now = surface->creation_date; - else - now = time (NULL); - - if (surface->ps_level_used == CAIRO_PS_LEVEL_2) - level = 2; - else - level = 3; - - if (surface->eps) - eps_header = " EPSF-3.0"; - - _cairo_output_stream_printf (surface->final_stream, - "%%!PS-Adobe-3.0%s\n" - "%%%%Creator: cairo %s (http://cairographics.org)\n" - "%%%%CreationDate: %s" - "%%%%Pages: %d\n" - "%%%%BoundingBox: %d %d %d %d\n", - eps_header, - cairo_version_string (), - ctime_r (&now, ctime_buf), - surface->num_pages, - surface->bbox_x1, - surface->bbox_y1, - surface->bbox_x2, - surface->bbox_y2); - - _cairo_output_stream_printf (surface->final_stream, - "%%%%DocumentData: Clean7Bit\n" - "%%%%LanguageLevel: %d\n", - level); - - num_comments = _cairo_array_num_elements (&surface->dsc_header_comments); - comments = _cairo_array_index (&surface->dsc_header_comments, 0); - for (i = 0; i < num_comments; i++) { - _cairo_output_stream_printf (surface->final_stream, - "%s\n", comments[i]); - free (comments[i]); - comments[i] = NULL; - } - - _cairo_output_stream_printf (surface->final_stream, - "%%%%EndComments\n"); - - _cairo_output_stream_printf (surface->final_stream, - "%%%%BeginProlog\n"); - - if (surface->eps) { - _cairo_output_stream_printf (surface->final_stream, - "/cairo_eps_state save def\n" - "/dict_count countdictstack def\n" - "/op_count count 1 sub def\n" - "userdict begin\n"); - } else { - _cairo_output_stream_printf (surface->final_stream, - "/languagelevel where\n" - "{ pop languagelevel } { 1 } ifelse\n" - "%d lt { /Helvetica findfont 12 scalefont setfont 50 500 moveto\n" - " (This print job requires a PostScript Language Level %d printer.) show\n" - " showpage quit } if\n", - level, - level); - } - - _cairo_output_stream_printf (surface->final_stream, - "/q { gsave } bind def\n" - "/Q { grestore } bind def\n" - "/cm { 6 array astore concat } bind def\n" - "/w { setlinewidth } bind def\n" - "/J { setlinecap } bind def\n" - "/j { setlinejoin } bind def\n" - "/M { setmiterlimit } bind def\n" - "/d { setdash } bind def\n" - "/m { moveto } bind def\n" - "/l { lineto } bind def\n" - "/c { curveto } bind def\n" - "/h { closepath } bind def\n" - "/re { exch dup neg 3 1 roll 5 3 roll moveto 0 rlineto\n" - " 0 exch rlineto 0 rlineto closepath } bind def\n" - "/S { stroke } bind def\n" - "/f { fill } bind def\n" - "/f* { eofill } bind def\n" - "/B { fill stroke } bind def\n" - "/B* { eofill stroke } bind def\n" - "/n { newpath } bind def\n" - "/W { clip } bind def\n" - "/W* { eoclip } bind def\n" - "/BT { } bind def\n" - "/ET { } bind def\n" - "/pdfmark where { pop globaldict /?pdfmark /exec load put }\n" - " { globaldict begin /?pdfmark /pop load def /pdfmark\n" - " /cleartomark load def end } ifelse\n" - "/BDC { mark 3 1 roll /BDC pdfmark } bind def\n" - "/EMC { mark /EMC pdfmark } bind def\n" - "/cairo_store_point { /cairo_point_y exch def /cairo_point_x exch def } def\n" - "/Tj { show currentpoint cairo_store_point } bind def\n" - "/TJ {\n" - " {\n" - " dup\n" - " type /stringtype eq\n" - " { show } { -0.001 mul 0 cairo_font_matrix dtransform rmoveto } ifelse\n" - " } forall\n" - " currentpoint cairo_store_point\n" - "} bind def\n" - "/cairo_selectfont { cairo_font_matrix aload pop pop pop 0 0 6 array astore\n" - " cairo_font exch selectfont cairo_point_x cairo_point_y moveto } bind def\n" - "/Tf { pop /cairo_font exch def /cairo_font_matrix where\n" - " { pop cairo_selectfont } if } bind def\n" - "/Td { matrix translate cairo_font_matrix matrix concatmatrix dup\n" - " /cairo_font_matrix exch def dup 4 get exch 5 get cairo_store_point\n" - " /cairo_font where { pop cairo_selectfont } if } bind def\n" - "/Tm { 2 copy 8 2 roll 6 array astore /cairo_font_matrix exch def\n" - " cairo_store_point /cairo_font where { pop cairo_selectfont } if } bind def\n" - "/g { setgray } bind def\n" - "/rg { setrgbcolor } bind def\n" - "/d1 { setcachedevice } bind def\n"); - - _cairo_output_stream_printf (surface->final_stream, - "%%%%EndProlog\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, - "%s\n", comments[i]); - free (comments[i]); - comments[i] = NULL; - } - - _cairo_output_stream_printf (surface->final_stream, - "%%%%EndSetup\n"); - } -} - -#if CAIRO_HAS_FT_FONT -static cairo_status_t -_cairo_ps_surface_emit_type1_font_subset (cairo_ps_surface_t *surface, - cairo_scaled_font_subset_t *font_subset) - - -{ - cairo_type1_subset_t subset; - cairo_status_t status; - int length; - char name[64]; - - snprintf (name, sizeof name, "f-%d-%d", - font_subset->font_id, font_subset->subset_id); - status = _cairo_type1_subset_init (&subset, name, font_subset, TRUE); - if (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_subset\n"); -#endif - - length = subset.header_length + subset.data_length + subset.trailer_length; - _cairo_output_stream_write (surface->final_stream, subset.data, length); - - _cairo_type1_subset_fini (&subset); - - return CAIRO_STATUS_SUCCESS; -} -#endif - -static cairo_status_t -_cairo_ps_surface_emit_type1_font_fallback (cairo_ps_surface_t *surface, - cairo_scaled_font_subset_t *font_subset) -{ - cairo_type1_subset_t subset; - cairo_status_t status; - int length; - char name[64]; - - snprintf (name, sizeof name, "f-%d-%d", - font_subset->font_id, font_subset->subset_id); - status = _cairo_type1_fallback_init_hex (&subset, name, font_subset); - if (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 - - length = subset.header_length + subset.data_length + subset.trailer_length; - _cairo_output_stream_write (surface->final_stream, subset.data, length); - - _cairo_type1_fallback_fini (&subset); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_ps_surface_emit_truetype_font_subset (cairo_ps_surface_t *surface, - cairo_scaled_font_subset_t *font_subset) - - -{ - cairo_truetype_subset_t subset; - cairo_status_t status; - unsigned int i, begin, end; - - status = _cairo_truetype_subset_init (&subset, font_subset); - if (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_truetype_font_subset\n"); -#endif - - _cairo_output_stream_printf (surface->final_stream, - "11 dict begin\n" - "/FontType 42 def\n" - "/FontName /f-%d-%d def\n" - "/PaintType 0 def\n" - "/FontMatrix [ 1 0 0 1 0 0 ] def\n" - "/FontBBox [ 0 0 0 0 ] def\n" - "/Encoding 256 array def\n" - "0 1 255 { Encoding exch /.notdef put } for\n", - font_subset->font_id, - font_subset->subset_id); - - /* FIXME: Figure out how subset->x_max etc maps to the /FontBBox */ - - for (i = 1; i < font_subset->num_glyphs; i++) { - if (font_subset->glyph_names != NULL) { - _cairo_output_stream_printf (surface->final_stream, - "Encoding %d /%s put\n", - i, font_subset->glyph_names[i]); - } else { - _cairo_output_stream_printf (surface->final_stream, - "Encoding %d /g%d put\n", i, i); - } - } - - _cairo_output_stream_printf (surface->final_stream, - "/CharStrings %d dict dup begin\n" - "/.notdef 0 def\n", - font_subset->num_glyphs); - - for (i = 1; i < font_subset->num_glyphs; i++) { - if (font_subset->glyph_names != NULL) { - _cairo_output_stream_printf (surface->final_stream, - "/%s %d def\n", - font_subset->glyph_names[i], i); - } else { - _cairo_output_stream_printf (surface->final_stream, - "/g%d %d def\n", i, i); - } - } - - _cairo_output_stream_printf (surface->final_stream, - "end readonly def\n"); - - _cairo_output_stream_printf (surface->final_stream, - "/sfnts [\n"); - begin = 0; - end = 0; - for (i = 0; i < subset.num_string_offsets; i++) { - end = subset.string_offsets[i]; - _cairo_output_stream_printf (surface->final_stream,"<"); - _cairo_output_stream_write_hex_string (surface->final_stream, - subset.data + begin, end - begin); - _cairo_output_stream_printf (surface->final_stream,"00>\n"); - begin = end; - } - if (subset.data_length > end) { - _cairo_output_stream_printf (surface->final_stream,"<"); - _cairo_output_stream_write_hex_string (surface->final_stream, - subset.data + end, subset.data_length - end); - _cairo_output_stream_printf (surface->final_stream,"00>\n"); - } - - _cairo_output_stream_printf (surface->final_stream, - "] def\n" - "FontName currentdict end definefont pop\n"); - - _cairo_truetype_subset_fini (&subset); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_ps_emit_imagemask (cairo_image_surface_t *image, - cairo_output_stream_t *stream) -{ - uint8_t *row, *byte; - int rows, cols; - - /* The only image type supported by Type 3 fonts are 1-bit image - * masks */ - assert (image->format == CAIRO_FORMAT_A1); - - _cairo_output_stream_printf (stream, - "<<\n" - " /ImageType 1\n" - " /Width %d\n" - " /Height %d\n" - " /ImageMatrix [%d 0 0 %d 0 %d]\n" - " /Decode [1 0]\n" - " /BitsPerComponent 1\n", - image->width, - image->height, - image->width, - -image->height, - image->height); - - _cairo_output_stream_printf (stream, - " /DataSource {<\n "); - for (row = image->data, rows = image->height; rows; row += image->stride, rows--) { - for (byte = row, cols = (image->width + 7) / 8; cols; byte++, cols--) { - uint8_t output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte); - _cairo_output_stream_printf (stream, "%02x ", output_byte); - } - _cairo_output_stream_printf (stream, "\n "); - } - _cairo_output_stream_printf (stream, ">}\n>>\n"); - - _cairo_output_stream_printf (stream, - "imagemask\n"); - - return _cairo_output_stream_get_status (stream); -} - -static cairo_status_t -_cairo_ps_surface_analyze_user_font_subset (cairo_scaled_font_subset_t *font_subset, - void *closure) -{ - cairo_ps_surface_t *surface = closure; - cairo_status_t status = CAIRO_STATUS_SUCCESS; - unsigned int i; - cairo_surface_t *type3_surface; - - type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font, - NULL, - _cairo_ps_emit_imagemask, - surface->font_subsets); - - for (i = 0; i < font_subset->num_glyphs; i++) { - status = _cairo_type3_glyph_surface_analyze_glyph (type3_surface, - font_subset->glyphs[i]); - if (status) - break; - - } - cairo_surface_destroy (type3_surface); - - return status; -} - -static cairo_status_t -_cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface, - cairo_scaled_font_subset_t *font_subset) - - -{ - cairo_status_t status; - unsigned int i; - cairo_box_t font_bbox = {{0,0},{0,0}}; - cairo_box_t bbox = {{0,0},{0,0}}; - cairo_surface_t *type3_surface; - double width; - - if (font_subset->num_glyphs == 0) - return CAIRO_STATUS_SUCCESS; - -#if DEBUG_PS - _cairo_output_stream_printf (surface->final_stream, - "%% _cairo_ps_surface_emit_type3_font_subset\n"); -#endif - - _cairo_output_stream_printf (surface->final_stream, - "8 dict begin\n" - "/FontType 3 def\n" - "/FontMatrix [1 0 0 1 0 0] def\n" - "/Encoding 256 array def\n" - "0 1 255 { Encoding exch /.notdef put } for\n"); - - type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font, - NULL, - _cairo_ps_emit_imagemask, - surface->font_subsets); - - for (i = 0; i < font_subset->num_glyphs; i++) { - if (font_subset->glyph_names != NULL) { - _cairo_output_stream_printf (surface->final_stream, - "Encoding %d /%s put\n", - i, font_subset->glyph_names[i]); - } else { - _cairo_output_stream_printf (surface->final_stream, - "Encoding %d /g%d put\n", i, i); - } - } - - _cairo_output_stream_printf (surface->final_stream, - "/Glyphs [\n"); - - for (i = 0; i < font_subset->num_glyphs; i++) { - _cairo_output_stream_printf (surface->final_stream, - " { %% %d\n", i); - status = _cairo_type3_glyph_surface_emit_glyph (type3_surface, - surface->final_stream, - font_subset->glyphs[i], - &bbox, - &width); - if (status) - break; - - _cairo_output_stream_printf (surface->final_stream, - " }\n"); - if (i == 0) { - font_bbox.p1.x = bbox.p1.x; - font_bbox.p1.y = bbox.p1.y; - font_bbox.p2.x = bbox.p2.x; - font_bbox.p2.y = bbox.p2.y; - } else { - if (bbox.p1.x < font_bbox.p1.x) - font_bbox.p1.x = bbox.p1.x; - if (bbox.p1.y < font_bbox.p1.y) - font_bbox.p1.y = bbox.p1.y; - if (bbox.p2.x > font_bbox.p2.x) - font_bbox.p2.x = bbox.p2.x; - if (bbox.p2.y > font_bbox.p2.y) - font_bbox.p2.y = bbox.p2.y; - } - } - cairo_surface_destroy (type3_surface); - if (status) - return status; - - _cairo_output_stream_printf (surface->final_stream, - "] def\n" - "/FontBBox [%f %f %f %f] def\n" - "/BuildChar {\n" - " exch /Glyphs get\n" - " exch get\n" - " 10 dict begin exec end\n" - "} bind def\n" - "currentdict\n" - "end\n" - "/f-%d-%d exch definefont pop\n", - _cairo_fixed_to_double (font_bbox.p1.x), - - _cairo_fixed_to_double (font_bbox.p2.y), - _cairo_fixed_to_double (font_bbox.p2.x), - - _cairo_fixed_to_double (font_bbox.p1.y), - font_subset->font_id, - font_subset->subset_id); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_ps_surface_emit_unscaled_font_subset (cairo_scaled_font_subset_t *font_subset, - void *closure) -{ - cairo_ps_surface_t *surface = closure; - cairo_status_t status; - - - status = _cairo_scaled_font_subset_create_glyph_names (font_subset); - if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - -#if CAIRO_HAS_FT_FONT - status = _cairo_ps_surface_emit_type1_font_subset (surface, font_subset); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; -#endif - - status = _cairo_ps_surface_emit_truetype_font_subset (surface, font_subset); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - - status = _cairo_ps_surface_emit_type1_font_fallback (surface, font_subset); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - - ASSERT_NOT_REACHED; - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_ps_surface_emit_scaled_font_subset (cairo_scaled_font_subset_t *font_subset, - void *closure) -{ - cairo_ps_surface_t *surface = closure; - cairo_status_t status; - - status = _cairo_scaled_font_subset_create_glyph_names (font_subset); - if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - - status = _cairo_ps_surface_emit_type3_font_subset (surface, font_subset); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - - ASSERT_NOT_REACHED; - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_ps_surface_emit_font_subsets (cairo_ps_surface_t *surface) -{ - cairo_status_t status; - -#if DEBUG_PS - _cairo_output_stream_printf (surface->final_stream, - "%% _cairo_ps_surface_emit_font_subsets\n"); -#endif - - status = _cairo_scaled_font_subsets_foreach_user (surface->font_subsets, - _cairo_ps_surface_analyze_user_font_subset, - surface); - if (status) - goto BAIL; - - status = _cairo_scaled_font_subsets_foreach_unscaled (surface->font_subsets, - _cairo_ps_surface_emit_unscaled_font_subset, - surface); - if (status) - goto BAIL; - - status = _cairo_scaled_font_subsets_foreach_scaled (surface->font_subsets, - _cairo_ps_surface_emit_scaled_font_subset, - surface); - if (status) - goto BAIL; - - status = _cairo_scaled_font_subsets_foreach_user (surface->font_subsets, - _cairo_ps_surface_emit_scaled_font_subset, - surface); -BAIL: - _cairo_scaled_font_subsets_destroy (surface->font_subsets); - surface->font_subsets = NULL; - - return status; -} - -static cairo_status_t -_cairo_ps_surface_emit_body (cairo_ps_surface_t *surface) -{ - char buf[4096]; - int n; - - if (ferror (surface->tmpfile) != 0) - return _cairo_error (CAIRO_STATUS_TEMP_FILE_ERROR); - - rewind (surface->tmpfile); - while ((n = fread (buf, 1, sizeof (buf), surface->tmpfile)) > 0) - _cairo_output_stream_write (surface->final_stream, buf, n); - - if (ferror (surface->tmpfile) != 0) - return _cairo_error (CAIRO_STATUS_TEMP_FILE_ERROR); - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_ps_surface_emit_footer (cairo_ps_surface_t *surface) -{ - _cairo_output_stream_printf (surface->final_stream, - "%%%%Trailer\n"); - - if (surface->eps) { - _cairo_output_stream_printf (surface->final_stream, - "count op_count sub {pop} repeat\n" - "countdictstack dict_count sub {end} repeat\n" - "cairo_eps_state restore\n"); - } - - _cairo_output_stream_printf (surface->final_stream, - "%%%%EOF\n"); -} - -static cairo_surface_t * -_cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream, - double width, - double height) -{ - cairo_status_t status, status_ignored; - cairo_ps_surface_t *surface; - - surface = malloc (sizeof (cairo_ps_surface_t)); - if (surface == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto CLEANUP; - } - - _cairo_surface_init (&surface->base, &cairo_ps_surface_backend, - CAIRO_CONTENT_COLOR_ALPHA); - - surface->final_stream = stream; - - surface->tmpfile = tmpfile (); - if (surface->tmpfile == NULL) { - switch (errno) { - case ENOMEM: - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - break; - default: - status = _cairo_error (CAIRO_STATUS_TEMP_FILE_ERROR); - break; - } - goto CLEANUP_SURFACE; - } - - surface->stream = _cairo_output_stream_create_for_file (surface->tmpfile); - status = _cairo_output_stream_get_status (surface->stream); - if (status) - goto CLEANUP_OUTPUT_STREAM; - - surface->font_subsets = _cairo_scaled_font_subsets_create_simple (); - if (surface->font_subsets == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto CLEANUP_OUTPUT_STREAM; - } - - surface->has_creation_date = FALSE; - surface->eps = FALSE; - surface->ps_level = CAIRO_PS_LEVEL_3; - surface->ps_level_used = CAIRO_PS_LEVEL_2; - surface->width = width; - surface->height = height; - cairo_matrix_init (&surface->cairo_to_ps, 1, 0, 0, -1, 0, height); - surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE; - surface->force_fallbacks = FALSE; - surface->content = CAIRO_CONTENT_COLOR_ALPHA; - surface->use_string_datasource = FALSE; - surface->current_pattern_is_solid_color = FALSE; - - _cairo_pdf_operators_init (&surface->pdf_operators, - surface->stream, - &surface->cairo_to_ps, - surface->font_subsets); - surface->num_pages = 0; - - _cairo_array_init (&surface->dsc_header_comments, sizeof (char *)); - _cairo_array_init (&surface->dsc_setup_comments, sizeof (char *)); - _cairo_array_init (&surface->dsc_page_setup_comments, sizeof (char *)); - - surface->dsc_comment_target = &surface->dsc_header_comments; - - surface->paginated_surface = _cairo_paginated_surface_create ( - &surface->base, - CAIRO_CONTENT_COLOR_ALPHA, - width, height, - &cairo_ps_surface_paginated_backend); - status = surface->paginated_surface->status; - if (status == CAIRO_STATUS_SUCCESS) { - /* paginated keeps the only reference to surface now, drop ours */ - cairo_surface_destroy (&surface->base); - return surface->paginated_surface; - } - - _cairo_scaled_font_subsets_destroy (surface->font_subsets); - CLEANUP_OUTPUT_STREAM: - status_ignored = _cairo_output_stream_destroy (surface->stream); - fclose (surface->tmpfile); - CLEANUP_SURFACE: - free (surface); - CLEANUP: - /* destroy stream on behalf of caller */ - status_ignored = _cairo_output_stream_destroy (stream); - - return _cairo_surface_create_in_error (status); -} - -/** - * cairo_ps_surface_create: - * @filename: a filename for the PS output (must be writable), %NULL may be - * used to specify no output. This will generate a PS surface that - * may be queried and used as a source, without generating a - * temporary file. - * @width_in_points: width of the surface, in points (1 point == 1/72.0 inch) - * @height_in_points: height of the surface, in points (1 point == 1/72.0 inch) - * - * Creates a PostScript surface of the specified size in points to be - * written to @filename. See cairo_ps_surface_create_for_stream() for - * a more flexible mechanism for handling the PostScript output than - * simply writing it to a named file. - * - * Note that the size of individual pages of the PostScript output can - * vary. See cairo_ps_surface_set_size(). - * - * Return value: a pointer to the newly created surface. The caller - * owns the surface and should call cairo_surface_destroy() when done - * with it. - * - * This function always returns a valid pointer, but it will return a - * pointer to a "nil" surface if an error such as out of memory - * occurs. You can use cairo_surface_status() to check for this. - * - * Since: 1.2 - **/ -cairo_surface_t * -cairo_ps_surface_create (const char *filename, - double width_in_points, - double height_in_points) -{ - cairo_output_stream_t *stream; - - stream = _cairo_output_stream_create_for_filename (filename); - if (_cairo_output_stream_get_status (stream)) - return _cairo_surface_create_in_error (_cairo_output_stream_destroy (stream)); - - return _cairo_ps_surface_create_for_stream_internal (stream, - width_in_points, - height_in_points); -} - -/** - * cairo_ps_surface_create_for_stream: - * @write_func: a #cairo_write_func_t to accept the output data, may be %NULL - * to indicate a no-op @write_func. With a no-op @write_func, - * the surface may be queried or used as a source without - * generating any temporary files. - * @closure: the closure argument for @write_func - * @width_in_points: width of the surface, in points (1 point == 1/72.0 inch) - * @height_in_points: height of the surface, in points (1 point == 1/72.0 inch) - * - * Creates a PostScript surface of the specified size in points to be - * written incrementally to the stream represented by @write_func and - * @closure. See cairo_ps_surface_create() for a more convenient way - * to simply direct the PostScript output to a named file. - * - * Note that the size of individual pages of the PostScript - * output can vary. See cairo_ps_surface_set_size(). - * - * Return value: a pointer to the newly created surface. The caller - * owns the surface and should call cairo_surface_destroy() when done - * with it. - * - * This function always returns a valid pointer, but it will return a - * pointer to a "nil" surface if an error such as out of memory - * occurs. You can use cairo_surface_status() to check for this. - * - * Since: 1.2 - */ -cairo_surface_t * -cairo_ps_surface_create_for_stream (cairo_write_func_t write_func, - void *closure, - double width_in_points, - double height_in_points) -{ - cairo_output_stream_t *stream; - - stream = _cairo_output_stream_create (write_func, NULL, closure); - if (_cairo_output_stream_get_status (stream)) - return _cairo_surface_create_in_error (_cairo_output_stream_destroy (stream)); - - return _cairo_ps_surface_create_for_stream_internal (stream, - width_in_points, - height_in_points); -} - -static cairo_bool_t -_cairo_surface_is_ps (cairo_surface_t *surface) -{ - return surface->backend == &cairo_ps_surface_backend; -} - -/* If the abstract_surface is a paginated surface, and that paginated - * surface's target is a ps_surface, then set ps_surface to that - * target. Otherwise return %CAIRO_STATUS_SURFACE_TYPE_MISMATCH. - */ -static cairo_status_t -_extract_ps_surface (cairo_surface_t *surface, - cairo_ps_surface_t **ps_surface) -{ - cairo_surface_t *target; - - if (surface->status) - return surface->status; - - if (! _cairo_surface_is_paginated (surface)) - return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - - target = _cairo_paginated_surface_get_target (surface); - if (target->status) - return target->status; - - if (! _cairo_surface_is_ps (target)) - return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - - *ps_surface = (cairo_ps_surface_t *) target; - - return CAIRO_STATUS_SUCCESS; -} - -/** - * cairo_ps_surface_restrict_to_level: - * @surface: a PostScript #cairo_surface_t - * @level: PostScript level - * - * Restricts the generated PostSript file to @level. See - * cairo_ps_get_levels() for a list of available level values that - * can be used here. - * - * This function should only be called before any drawing operations - * have been performed on the given surface. The simplest way to do - * this is to call this function immediately after creating the - * surface. - * - * Since: 1.6 - **/ -void -cairo_ps_surface_restrict_to_level (cairo_surface_t *surface, - cairo_ps_level_t level) -{ - cairo_ps_surface_t *ps_surface = NULL; - cairo_status_t status; - - status = _extract_ps_surface (surface, &ps_surface); - if (status) { - status = _cairo_surface_set_error (surface, status); - return; - } - - if (level < CAIRO_PS_LEVEL_LAST) - ps_surface->ps_level = level; -} - -/** - * cairo_ps_get_levels: - * @levels: supported level list - * @num_levels: list length - * - * Used to retrieve the list of supported levels. See - * cairo_ps_surface_restrict_to_level(). - * - * Since: 1.6 - **/ -void -cairo_ps_get_levels (cairo_ps_level_t const **levels, - int *num_levels) -{ - if (levels != NULL) - *levels = _cairo_ps_levels; - - if (num_levels != NULL) - *num_levels = CAIRO_PS_LEVEL_LAST; -} - -/** - * cairo_ps_level_to_string: - * @level: a level id - * - * Get the string representation of the given @level id. This function - * will return %NULL if @level id isn't valid. See cairo_ps_get_levels() - * for a way to get the list of valid level ids. - * - * Return value: the string associated to given level. - * - * Since: 1.6 - **/ -const char * -cairo_ps_level_to_string (cairo_ps_level_t level) -{ - if (level >= CAIRO_PS_LEVEL_LAST) - return NULL; - - return _cairo_ps_level_strings[level]; -} - -/** - * cairo_ps_surface_set_eps: - * @surface: a PostScript #cairo_surface_t - * @eps: %TRUE to output EPS format PostScript - * - * If @eps is %TRUE, the PostScript surface will output Encapsulated - * PostScript. - * - * This function should only be called before any drawing operations - * have been performed on the current page. The simplest way to do - * this is to call this function immediately after creating the - * surface. An Encapsulated PostScript file should never contain more - * than one page. - * - * Since: 1.6 - **/ -void -cairo_ps_surface_set_eps (cairo_surface_t *surface, - cairo_bool_t eps) -{ - cairo_ps_surface_t *ps_surface = NULL; - cairo_status_t status; - - status = _extract_ps_surface (surface, &ps_surface); - if (status) { - status = _cairo_surface_set_error (surface, status); - return; - } - - ps_surface->eps = eps; -} - -/** - * cairo_ps_surface_get_eps: - * @surface: a PostScript #cairo_surface_t - * - * Check whether the PostScript surface will output Encapsulated PostScript. - * - * Return value: %TRUE if the surface will output Encapsulated PostScript. - * - * Since: 1.6 - **/ -cairo_public cairo_bool_t -cairo_ps_surface_get_eps (cairo_surface_t *surface) -{ - cairo_ps_surface_t *ps_surface = NULL; - cairo_status_t status; - - status = _extract_ps_surface (surface, &ps_surface); - if (status) { - status = _cairo_surface_set_error (surface, status); - return FALSE; - } - - return ps_surface->eps; -} - -/** - * cairo_ps_surface_set_size: - * @surface: a PostScript #cairo_surface_t - * @width_in_points: new surface width, in points (1 point == 1/72.0 inch) - * @height_in_points: new surface height, in points (1 point == 1/72.0 inch) - * - * Changes the size of a PostScript surface for the current (and - * subsequent) pages. - * - * This function should only be called before any drawing operations - * have been performed on the current page. The simplest way to do - * this is to call this function immediately after creating the - * surface or immediately after completing a page with either - * cairo_show_page() or cairo_copy_page(). - * - * Since: 1.2 - **/ -void -cairo_ps_surface_set_size (cairo_surface_t *surface, - double width_in_points, - double height_in_points) -{ - cairo_ps_surface_t *ps_surface = NULL; - cairo_status_t status; - - status = _extract_ps_surface (surface, &ps_surface); - if (status) { - status = _cairo_surface_set_error (surface, status); - return; - } - - ps_surface->width = width_in_points; - ps_surface->height = height_in_points; - cairo_matrix_init (&ps_surface->cairo_to_ps, 1, 0, 0, -1, 0, height_in_points); - _cairo_pdf_operators_set_cairo_to_pdf_matrix (&ps_surface->pdf_operators, - &ps_surface->cairo_to_ps); - status = _cairo_paginated_surface_set_size (ps_surface->paginated_surface, - width_in_points, - height_in_points); - if (status) - status = _cairo_surface_set_error (surface, status); -} - -/** - * cairo_ps_surface_dsc_comment: - * @surface: a PostScript #cairo_surface_t - * @comment: a comment string to be emitted into the PostScript output - * - * Emit a comment into the PostScript output for the given surface. - * - * The comment is expected to conform to the PostScript Language - * Document Structuring Conventions (DSC). Please see that manual for - * details on the available comments and their meanings. In - * particular, the %%IncludeFeature comment allows a - * device-independent means of controlling printer device features. So - * the PostScript Printer Description Files Specification will also be - * a useful reference. - * - * The comment string must begin with a percent character (%) and the - * total length of the string (including any initial percent - * characters) must not exceed 255 characters. Violating either of - * these conditions will place @surface into an error state. But - * beyond these two conditions, this function will not enforce - * conformance of the comment with any particular specification. - * - * The comment string should not have a trailing newline. - * - * The DSC specifies different sections in which particular comments - * can appear. This function provides for comments to be emitted - * within three sections: the header, the Setup section, and the - * PageSetup section. Comments appearing in the first two sections - * apply to the entire document while comments in the BeginPageSetup - * section apply only to a single page. - * - * For comments to appear in the header section, this function should - * be called after the surface is created, but before a call to - * cairo_ps_surface_begin_setup(). - * - * For comments to appear in the Setup section, this function should - * be called after a call to cairo_ps_surface_begin_setup() but before - * a call to cairo_ps_surface_begin_page_setup(). - * - * For comments to appear in the PageSetup section, this function - * should be called after a call to cairo_ps_surface_begin_page_setup(). - * - * Note that it is only necessary to call cairo_ps_surface_begin_page_setup() - * for the first page of any surface. After a call to - * cairo_show_page() or cairo_copy_page() comments are unambiguously - * directed to the PageSetup section of the current page. But it - * doesn't hurt to call this function at the beginning of every page - * as that consistency may make the calling code simpler. - * - * As a final note, cairo automatically generates several comments on - * its own. As such, applications must not manually generate any of - * the following comments: - * - * Header section: %!PS-Adobe-3.0, %%Creator, %%CreationDate, %%Pages, - * %%BoundingBox, %%DocumentData, %%LanguageLevel, %%EndComments. - * - * Setup section: %%BeginSetup, %%EndSetup - * - * PageSetup section: %%BeginPageSetup, %%PageBoundingBox, - * %%EndPageSetup. - * - * Other sections: %%BeginProlog, %%EndProlog, %%Page, %%Trailer, %%EOF - * - * Here is an example sequence showing how this function might be used: - * - * - * #cairo_surface_t *surface = cairo_ps_surface_create (filename, width, height); - * ... - * cairo_ps_surface_dsc_comment (surface, "%%Title: My excellent document"); - * cairo_ps_surface_dsc_comment (surface, "%%Copyright: Copyright (C) 2006 Cairo Lover") - * ... - * cairo_ps_surface_dsc_begin_setup (surface); - * cairo_ps_surface_dsc_comment (surface, "%%IncludeFeature: *MediaColor White"); - * ... - * cairo_ps_surface_dsc_begin_page_setup (surface); - * cairo_ps_surface_dsc_comment (surface, "%%IncludeFeature: *PageSize A3"); - * cairo_ps_surface_dsc_comment (surface, "%%IncludeFeature: *InputSlot LargeCapacity"); - * cairo_ps_surface_dsc_comment (surface, "%%IncludeFeature: *MediaType Glossy"); - * cairo_ps_surface_dsc_comment (surface, "%%IncludeFeature: *MediaColor Blue"); - * ... draw to first page here .. - * cairo_show_page (cr); - * ... - * cairo_ps_surface_dsc_comment (surface, "%%IncludeFeature: *PageSize A5"); - * ... - * - * - * Since: 1.2 - **/ -void -cairo_ps_surface_dsc_comment (cairo_surface_t *surface, - const char *comment) -{ - cairo_ps_surface_t *ps_surface = NULL; - cairo_status_t status; - char *comment_copy; - - status = _extract_ps_surface (surface, &ps_surface); - if (status) { - status = _cairo_surface_set_error (surface, status); - return; - } - - /* A couple of sanity checks on the comment value. */ - if (comment == NULL) { - status = _cairo_surface_set_error (surface, CAIRO_STATUS_NULL_POINTER); - return; - } - - if (comment[0] != '%' || strlen (comment) > 255) { - status = _cairo_surface_set_error (surface, CAIRO_STATUS_INVALID_DSC_COMMENT); - return; - } - - /* Then, copy the comment and store it in the appropriate array. */ - comment_copy = strdup (comment); - if (comment_copy == NULL) { - status = _cairo_surface_set_error (surface, CAIRO_STATUS_NO_MEMORY); - return; - } - - status = _cairo_array_append (ps_surface->dsc_comment_target, &comment_copy); - if (status) { - free (comment_copy); - status = _cairo_surface_set_error (surface, status); - return; - } -} - -/** - * cairo_ps_surface_dsc_begin_setup: - * @surface: a PostScript #cairo_surface_t - * - * This function indicates that subsequent calls to - * cairo_ps_surface_dsc_comment() should direct comments to the Setup - * section of the PostScript output. - * - * This function should be called at most once per surface, and must - * be called before any call to cairo_ps_surface_dsc_begin_page_setup() - * and before any drawing is performed to the surface. - * - * See cairo_ps_surface_dsc_comment() for more details. - * - * Since: 1.2 - **/ -void -cairo_ps_surface_dsc_begin_setup (cairo_surface_t *surface) -{ - cairo_ps_surface_t *ps_surface = NULL; - cairo_status_t status; - - status = _extract_ps_surface (surface, &ps_surface); - if (status) { - status = _cairo_surface_set_error (surface, status); - return; - } - - if (ps_surface->dsc_comment_target == &ps_surface->dsc_header_comments) - { - ps_surface->dsc_comment_target = &ps_surface->dsc_setup_comments; - } -} - -/** - * cairo_ps_surface_dsc_begin_page_setup: - * @surface: a PostScript #cairo_surface_t - * - * This function indicates that subsequent calls to - * cairo_ps_surface_dsc_comment() should direct comments to the - * PageSetup section of the PostScript output. - * - * This function call is only needed for the first page of a - * surface. It should be called after any call to - * cairo_ps_surface_dsc_begin_setup() and before any drawing is - * performed to the surface. - * - * See cairo_ps_surface_dsc_comment() for more details. - * - * Since: 1.2 - **/ -void -cairo_ps_surface_dsc_begin_page_setup (cairo_surface_t *surface) -{ - cairo_ps_surface_t *ps_surface = NULL; - cairo_status_t status; - - status = _extract_ps_surface (surface, &ps_surface); - if (status) { - status = _cairo_surface_set_error (surface, status); - return; - } - - if (ps_surface->dsc_comment_target == &ps_surface->dsc_header_comments || - ps_surface->dsc_comment_target == &ps_surface->dsc_setup_comments) - { - ps_surface->dsc_comment_target = &ps_surface->dsc_page_setup_comments; - } -} - -static cairo_surface_t * -_cairo_ps_surface_create_similar (void *abstract_surface, - cairo_content_t content, - int width, - int height) -{ - return _cairo_meta_surface_create (content, width, height); -} - -static cairo_status_t -_cairo_ps_surface_finish (void *abstract_surface) -{ - cairo_status_t status, status2; - cairo_ps_surface_t *surface = abstract_surface; - int i, num_comments; - char **comments; - - _cairo_ps_surface_emit_header (surface); - - status = _cairo_ps_surface_emit_font_subsets (surface); - if (status) - goto CLEANUP; - - status = _cairo_ps_surface_emit_body (surface); - if (status) - goto CLEANUP; - - _cairo_ps_surface_emit_footer (surface); - -CLEANUP: - status2 = _cairo_output_stream_destroy (surface->stream); - if (status == CAIRO_STATUS_SUCCESS) - status = status2; - - fclose (surface->tmpfile); - - status2 = _cairo_output_stream_destroy (surface->final_stream); - if (status == CAIRO_STATUS_SUCCESS) - status = status2; - - num_comments = _cairo_array_num_elements (&surface->dsc_header_comments); - comments = _cairo_array_index (&surface->dsc_header_comments, 0); - for (i = 0; i < num_comments; i++) - free (comments[i]); - _cairo_array_fini (&surface->dsc_header_comments); - - num_comments = _cairo_array_num_elements (&surface->dsc_setup_comments); - comments = _cairo_array_index (&surface->dsc_setup_comments, 0); - for (i = 0; i < num_comments; i++) - free (comments[i]); - _cairo_array_fini (&surface->dsc_setup_comments); - - num_comments = _cairo_array_num_elements (&surface->dsc_page_setup_comments); - comments = _cairo_array_index (&surface->dsc_page_setup_comments, 0); - for (i = 0; i < num_comments; i++) - free (comments[i]); - _cairo_array_fini (&surface->dsc_page_setup_comments); - - return status; -} - -static cairo_int_status_t -_cairo_ps_surface_start_page (void *abstract_surface) -{ - cairo_ps_surface_t *surface = abstract_surface; - - /* Increment before print so page numbers start at 1. */ - surface->num_pages++; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_ps_surface_end_page (cairo_ps_surface_t *surface) -{ - cairo_int_status_t status; - - status = _cairo_pdf_operators_flush (&surface->pdf_operators); - if (status) - return status; - - _cairo_output_stream_printf (surface->stream, - "Q\n"); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_ps_surface_show_page (void *abstract_surface) -{ - cairo_ps_surface_t *surface = abstract_surface; - cairo_int_status_t status; - - status = _cairo_ps_surface_end_page (surface); - if (status) - return status; - - _cairo_output_stream_printf (surface->stream, "showpage\n"); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_bool_t -color_is_gray (double red, double green, double blue) -{ - const double epsilon = 0.00001; - - return (fabs (red - green) < epsilon && - fabs (red - blue) < epsilon); -} - -static cairo_int_status_t -_cairo_ps_surface_analyze_surface_pattern_transparency (cairo_ps_surface_t *surface, - cairo_surface_pattern_t *pattern) -{ - cairo_image_surface_t *image; - void *image_extra; - cairo_int_status_t status; - cairo_image_transparency_t transparency; - - status = _cairo_surface_acquire_source_image (pattern->surface, - &image, - &image_extra); - if (status) - return status; - - if (image->base.status) - return image->base.status; - - transparency = _cairo_image_analyze_transparency (image); - switch (transparency) { - case CAIRO_IMAGE_IS_OPAQUE: - status = CAIRO_STATUS_SUCCESS; - break; - - case CAIRO_IMAGE_HAS_BILEVEL_ALPHA: - if (surface->ps_level == CAIRO_PS_LEVEL_2) { - status = CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY; - } else { - surface->ps_level_used = CAIRO_PS_LEVEL_3; - status = CAIRO_STATUS_SUCCESS; - } - break; - - case CAIRO_IMAGE_HAS_ALPHA: - status = CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY; - break; - - case CAIRO_IMAGE_UNKNOWN: - ASSERT_NOT_REACHED; - } - - _cairo_surface_release_source_image (pattern->surface, image, image_extra); - - return status; -} - -static cairo_bool_t -surface_pattern_supported (cairo_surface_pattern_t *pattern) -{ - cairo_extend_t extend; - - if (_cairo_surface_is_meta (pattern->surface)) - return TRUE; - - if (pattern->surface->backend->acquire_source_image == NULL) - return FALSE; - - /* Does an ALPHA-only source surface even make sense? Maybe, but I - * don't think it's worth the extra code to support it. */ - -/* XXX: Need to write this function here... - content = cairo_surface_get_content (pattern->surface); - if (content == CAIRO_CONTENT_ALPHA) - return FALSE; -*/ - - /* Cast away the const, trusting get_extend not to muck with it. - * And I really wish I had a way to cast away just the const, and - * not potentially coerce this pointer to an incorrect type at the - * same time. :-( - */ - extend = cairo_pattern_get_extend ((cairo_pattern_t*)&pattern->base); - switch (extend) { - case CAIRO_EXTEND_NONE: - case CAIRO_EXTEND_REPEAT: - case CAIRO_EXTEND_REFLECT: - /* There's no point returning FALSE for EXTEND_PAD, as the image - * surface does not currently implement it either */ - case CAIRO_EXTEND_PAD: - return TRUE; - } - - ASSERT_NOT_REACHED; - return FALSE; -} - -static cairo_bool_t -_gradient_pattern_supported (cairo_ps_surface_t *surface, - cairo_pattern_t *pattern) -{ - cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t *) pattern; - uint16_t alpha; - cairo_extend_t extend; - unsigned int i; - - if (surface->ps_level == CAIRO_PS_LEVEL_2) - return FALSE; - - if (gradient->n_stops == 0) - return TRUE; - - /* Alpha gradients are only supported (by flattening the alpha) - * if there is no variation in the alpha across the gradient. */ - alpha = gradient->stops[0].color.alpha_short; - for (i = 0; i < gradient->n_stops; i++) { - if (gradient->stops[i].color.alpha_short != alpha) - return FALSE; - } - - extend = cairo_pattern_get_extend (pattern); - - /* Radial gradients are currently only supported when one circle - * is inside the other. */ - if (pattern->type == CAIRO_PATTERN_TYPE_RADIAL) { - double x1, y1, x2, y2, r1, r2, d; - cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) pattern; - - if (extend == CAIRO_EXTEND_REPEAT || - extend == CAIRO_EXTEND_REFLECT) { - return FALSE; - } - - x1 = _cairo_fixed_to_double (radial->c1.x); - y1 = _cairo_fixed_to_double (radial->c1.y); - r1 = _cairo_fixed_to_double (radial->r1); - x2 = _cairo_fixed_to_double (radial->c2.x); - y2 = _cairo_fixed_to_double (radial->c2.y); - r2 = _cairo_fixed_to_double (radial->r2); - - d = sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1)); - if (d > fabs(r2 - r1)) { - return FALSE; - } - } - - surface->ps_level_used = CAIRO_PS_LEVEL_3; - - return TRUE; -} - -static cairo_bool_t -pattern_supported (cairo_ps_surface_t *surface, cairo_pattern_t *pattern) -{ - if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) - return TRUE; - - if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR || - pattern->type == CAIRO_PATTERN_TYPE_RADIAL) - return _gradient_pattern_supported (surface, pattern); - - if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) - return surface_pattern_supported ((cairo_surface_pattern_t *) pattern); - - return FALSE; -} - -static cairo_int_status_t -_cairo_ps_surface_analyze_operation (cairo_ps_surface_t *surface, - cairo_operator_t op, - cairo_pattern_t *pattern) -{ - if (surface->force_fallbacks && surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (! pattern_supported (surface, pattern)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (!(op == CAIRO_OPERATOR_SOURCE || - op == CAIRO_OPERATOR_OVER)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) { - cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern; - - if ( _cairo_surface_is_meta (surface_pattern->surface)) - return CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN; - } - - if (op == CAIRO_OPERATOR_SOURCE) - return CAIRO_STATUS_SUCCESS; - - /* CAIRO_OPERATOR_OVER is only supported for opaque patterns. If - * the pattern contains transparency, we return - * CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY to the analysis - * surface. If the analysis surface determines that there is - * anything drawn under this operation, a fallback image will be - * used. Otherwise the operation will be replayed during the - * render stage and we blend the transparency into the white - * background to convert the pattern to opaque. - */ - - if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) { - cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern; - - return _cairo_ps_surface_analyze_surface_pattern_transparency (surface, - surface_pattern); - } - - if (_cairo_pattern_is_opaque (pattern)) - return CAIRO_STATUS_SUCCESS; - else - return CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY; -} - -static cairo_bool_t -_cairo_ps_surface_operation_supported (cairo_ps_surface_t *surface, - cairo_operator_t op, - cairo_pattern_t *pattern) -{ - if (_cairo_ps_surface_analyze_operation (surface, op, pattern) != CAIRO_INT_STATUS_UNSUPPORTED) - return TRUE; - else - return FALSE; -} - -/* The "standard" implementation limit for PostScript string sizes is - * 65535 characters (see PostScript Language Reference, Appendix - * B). We go one short of that because we sometimes need two - * characters in a string to represent a single ASCII85 byte, (for the - * escape sequences "\\", "\(", and "\)") and we must not split these - * across two strings. So we'd be in trouble if we went right to the - * limit and one of these escape sequences just happened to land at - * the end. - */ -#define STRING_ARRAY_MAX_STRING_SIZE (65535-1) -#define STRING_ARRAY_MAX_COLUMN 72 - -typedef struct _string_array_stream { - cairo_output_stream_t base; - cairo_output_stream_t *output; - int column; - int string_size; - cairo_bool_t use_strings; -} string_array_stream_t; - -static cairo_status_t -_string_array_stream_write (cairo_output_stream_t *base, - const unsigned char *data, - unsigned int length) -{ - string_array_stream_t *stream = (string_array_stream_t *) base; - unsigned char c; - const unsigned char backslash = '\\'; - - if (length == 0) - return CAIRO_STATUS_SUCCESS; - - while (length--) { - if (stream->string_size == 0 && stream->use_strings) { - _cairo_output_stream_printf (stream->output, "("); - stream->column++; - } - - c = *data++; - if (stream->use_strings) { - switch (c) { - case '\\': - case '(': - case ')': - _cairo_output_stream_write (stream->output, &backslash, 1); - stream->column++; - stream->string_size++; - break; - } - } - /* Have to be careful to never split the final ~> sequence. */ - if (c == '~') { - _cairo_output_stream_write (stream->output, &c, 1); - stream->column++; - stream->string_size++; - - if (length-- == 0) - break; - - c = *data++; - } - _cairo_output_stream_write (stream->output, &c, 1); - stream->column++; - stream->string_size++; - - if (stream->use_strings && - stream->string_size >= STRING_ARRAY_MAX_STRING_SIZE) - { - _cairo_output_stream_printf (stream->output, ")\n"); - stream->string_size = 0; - stream->column = 0; - } - if (stream->column >= STRING_ARRAY_MAX_COLUMN) { - _cairo_output_stream_printf (stream->output, "\n "); - stream->string_size += 2; - stream->column = 1; - } - } - - return _cairo_output_stream_get_status (stream->output); -} - -static cairo_status_t -_string_array_stream_close (cairo_output_stream_t *base) -{ - cairo_status_t status; - string_array_stream_t *stream = (string_array_stream_t *) base; - - if (stream->use_strings) - _cairo_output_stream_printf (stream->output, ")\n"); - - status = _cairo_output_stream_get_status (stream->output); - - return status; -} - -/* A string_array_stream wraps an existing output stream. It takes the - * data provided to it and output one or more consecutive string - * objects, each within the standard PostScript implementation limit - * of 65k characters. - * - * The strings are each separated by a space character for easy - * inclusion within an array object, (but the array delimiters are not - * added by the string_array_stream). - * - * The string array stream is also careful to wrap the output within - * STRING_ARRAY_MAX_COLUMN columns (+/- 1). The stream also adds - * necessary escaping for special characters within a string, - * (specifically '\', '(', and ')'). - */ -static cairo_output_stream_t * -_string_array_stream_create (cairo_output_stream_t *output) -{ - string_array_stream_t *stream; - - stream = malloc (sizeof (string_array_stream_t)); - if (stream == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_output_stream_t *) &_cairo_output_stream_nil; - } - - _cairo_output_stream_init (&stream->base, - _string_array_stream_write, - _string_array_stream_close); - stream->output = output; - stream->column = 0; - stream->string_size = 0; - stream->use_strings = TRUE; - - return &stream->base; -} - -/* A base85_array_stream wraps an existing output stream. It wraps the - * output within STRING_ARRAY_MAX_COLUMN columns (+/- 1). The output - * is not enclosed in strings like string_array_stream. - */ -static cairo_output_stream_t * -_base85_array_stream_create (cairo_output_stream_t *output) -{ - string_array_stream_t *stream; - - stream = malloc (sizeof (string_array_stream_t)); - if (stream == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_output_stream_t *) &_cairo_output_stream_nil; - } - - _cairo_output_stream_init (&stream->base, - _string_array_stream_write, - _string_array_stream_close); - stream->output = output; - stream->column = 0; - stream->string_size = 0; - stream->use_strings = FALSE; - - return &stream->base; -} - - -/* PS Output - this section handles output of the parts of the meta - * surface we can render natively in PS. */ - -static cairo_status_t -_cairo_ps_surface_flatten_image_transparency (cairo_ps_surface_t *surface, - cairo_image_surface_t *image, - cairo_image_surface_t **opaque_image) -{ - const cairo_color_t *background_color; - cairo_surface_t *opaque; - cairo_surface_pattern_t pattern; - cairo_status_t status; - - if (surface->content == CAIRO_CONTENT_COLOR_ALPHA) - background_color = CAIRO_COLOR_WHITE; - else - background_color = CAIRO_COLOR_BLACK; - - opaque = cairo_image_surface_create (CAIRO_FORMAT_RGB24, - image->width, - image->height); - if (opaque->status) - return opaque->status; - - _cairo_pattern_init_for_surface (&pattern, &image->base); - - status = _cairo_surface_fill_rectangle (opaque, - CAIRO_OPERATOR_SOURCE, - background_color, - 0, 0, - image->width, image->height); - if (status) - goto fail; - - status = _cairo_surface_composite (CAIRO_OPERATOR_OVER, - &pattern.base, - NULL, - opaque, - 0, 0, - 0, 0, - 0, 0, - image->width, - image->height); - if (status) - goto fail; - - _cairo_pattern_fini (&pattern.base); - *opaque_image = (cairo_image_surface_t *) opaque; - - return CAIRO_STATUS_SUCCESS; - -fail: - _cairo_pattern_fini (&pattern.base); - cairo_surface_destroy (opaque); - - return status; -} - -static cairo_status_t -_cairo_ps_surface_emit_base85_string (cairo_ps_surface_t *surface, - unsigned char *data, - unsigned long length, - cairo_bool_t use_strings) -{ - cairo_output_stream_t *base85_stream, *string_array_stream; - cairo_status_t status, status2; - - if (use_strings) - string_array_stream = _string_array_stream_create (surface->stream); - else - string_array_stream = _base85_array_stream_create (surface->stream); - - status = _cairo_output_stream_get_status (string_array_stream); - if (status) - return _cairo_output_stream_destroy (string_array_stream); - - base85_stream = _cairo_base85_stream_create (string_array_stream); - status = _cairo_output_stream_get_status (base85_stream); - if (status) { - status2 = _cairo_output_stream_destroy (string_array_stream); - return _cairo_output_stream_destroy (base85_stream); - } - - _cairo_output_stream_write (base85_stream, data, length); - - status = _cairo_output_stream_destroy (base85_stream); - status2 = _cairo_output_stream_destroy (string_array_stream); - if (status == CAIRO_STATUS_SUCCESS) - status = status2; - - return status; -} - -static cairo_status_t -_cairo_ps_surface_emit_image (cairo_ps_surface_t *surface, - cairo_image_surface_t *image, - cairo_operator_t op) -{ - cairo_status_t status; - unsigned char *data, *data_compressed; - unsigned long data_size, data_compressed_size; - cairo_image_surface_t *opaque_image = NULL; - int x, y, i; - cairo_image_transparency_t transparency; - cairo_bool_t use_mask; - uint32_t *pixel; - int bit; - - if (image->base.status) - return image->base.status; - - transparency = _cairo_image_analyze_transparency (image); - - /* PostScript can not represent the alpha channel, so we blend the - current image over a white (or black for CONTENT_COLOR - surfaces) RGB surface to eliminate it. */ - - if (op == CAIRO_OPERATOR_SOURCE || - transparency == CAIRO_IMAGE_HAS_ALPHA || - (transparency == CAIRO_IMAGE_HAS_BILEVEL_ALPHA && - surface->ps_level == CAIRO_PS_LEVEL_2)) - { - status = _cairo_ps_surface_flatten_image_transparency (surface, - image, - &opaque_image); - if (status) - return status; - - use_mask = FALSE; - } else if (transparency == CAIRO_IMAGE_IS_OPAQUE) { - opaque_image = image; - use_mask = FALSE; - } else { - use_mask = TRUE; - } - - if (use_mask) { - /* Type 2 (mask and image interleaved) has the mask and image - * samples interleaved by row. The mask row is first, one bit - * per pixel with (bit 7 first). The row is padded to byte - * boundaries. The image data is 3 bytes per pixel RGB - * format. */ - data_size = image->height * ((image->width + 7)/8 + 3*image->width); - } else { - data_size = image->height * image->width * 3; - } - data = malloc (data_size); - if (data == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto bail1; - } - - if (use_mask) { - i = 0; - for (y = 0; y < image->height; y++) { - /* mask row */ - pixel = (uint32_t *) (image->data + y * image->stride); - bit = 7; - for (x = 0; x < image->width; x++, pixel++) { - if (bit == 7) - data[i] = 0; - if (((*pixel & 0xff000000) >> 24) > 0x80) - data[i] |= (1 << bit); - bit--; - if (bit < 0) { - bit = 7; - i++; - } - } - if (bit != 7) - i++; - - /* image row*/ - pixel = (uint32_t *) (image->data + y * image->stride); - for (x = 0; x < image->width; x++, pixel++) { - data[i++] = (*pixel & 0x00ff0000) >> 16; - data[i++] = (*pixel & 0x0000ff00) >> 8; - data[i++] = (*pixel & 0x000000ff) >> 0; - } - } - } else { - i = 0; - for (y = 0; y < opaque_image->height; y++) { - pixel = (uint32_t *) (opaque_image->data + y * opaque_image->stride); - for (x = 0; x < opaque_image->width; x++, pixel++) { - data[i++] = (*pixel & 0x00ff0000) >> 16; - data[i++] = (*pixel & 0x0000ff00) >> 8; - data[i++] = (*pixel & 0x000000ff) >> 0; - } - } - } - - /* XXX: Should fix cairo-lzw to provide a stream-based interface - * instead. */ - data_compressed_size = data_size; - data_compressed = _cairo_lzw_compress (data, &data_compressed_size); - if (data_compressed == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto bail2; - } - - if (surface->use_string_datasource) { - /* Emit the image data as a base85-encoded string which will - * be used as the data source for the image operator later. */ - _cairo_output_stream_printf (surface->stream, - "/CairoImageData [\n"); - - status = _cairo_ps_surface_emit_base85_string (surface, - data_compressed, - data_compressed_size, - TRUE); - if (status) - goto bail3; - - _cairo_output_stream_printf (surface->stream, - "] def\n"); - _cairo_output_stream_printf (surface->stream, - "/CairoImageDataIndex 0 def\n"); - } - - if (use_mask) { - _cairo_output_stream_printf (surface->stream, - "/DeviceRGB setcolorspace\n" - "5 dict dup begin\n" - " /ImageType 3 def\n" - " /InterleaveType 2 def\n" - " /DataDict 8 dict def\n" - " DataDict begin\n" - " /ImageType 1 def\n" - " /Width %d def\n" - " /Height %d def\n" - " /BitsPerComponent 8 def\n" - " /Decode [ 0 1 0 1 0 1 ] def\n", - image->width, - image->height); - - if (surface->use_string_datasource) { - _cairo_output_stream_printf (surface->stream, - " /DataSource {\n" - " CairoImageData CairoImageDataIndex get\n" - " /CairoImageDataIndex CairoImageDataIndex 1 add def\n" - " CairoImageDataIndex CairoImageData length 1 sub gt\n" - " { /CairoImageDataIndex 0 def } if\n" - " } /ASCII85Decode filter /LZWDecode filter def\n"); - } else { - _cairo_output_stream_printf (surface->stream, - " /DataSource currentfile /ASCII85Decode filter /LZWDecode filter def\n"); - } - - _cairo_output_stream_printf (surface->stream, - " /ImageMatrix [ 1 0 0 -1 0 %d ] def\n" - " end\n" - " /MaskDict 8 dict def\n" - " MaskDict begin\n" - " /ImageType 1 def\n" - " /Width %d def\n" - " /Height %d def\n" - " /BitsPerComponent 1 def\n" - " /Decode [ 1 0 ] def\n" - " /ImageMatrix [ 1 0 0 -1 0 %d ] def\n" - " end\n" - "end\n" - "image\n", - image->height, - image->width, - image->height, - image->height); - } else { - _cairo_output_stream_printf (surface->stream, - "/DeviceRGB setcolorspace\n" - "8 dict dup begin\n" - " /ImageType 1 def\n" - " /Width %d def\n" - " /Height %d def\n" - " /BitsPerComponent 8 def\n" - " /Decode [ 0 1 0 1 0 1 ] def\n", - opaque_image->width, - opaque_image->height); - if (surface->use_string_datasource) { - _cairo_output_stream_printf (surface->stream, - " /DataSource {\n" - " CairoImageData CairoImageDataIndex get\n" - " /CairoImageDataIndex CairoImageDataIndex 1 add def\n" - " CairoImageDataIndex CairoImageData length 1 sub gt\n" - " { /CairoImageDataIndex 0 def } if\n" - " } /ASCII85Decode filter /LZWDecode filter def\n"); - } else { - _cairo_output_stream_printf (surface->stream, - " /DataSource currentfile /ASCII85Decode filter /LZWDecode filter def\n"); - } - - _cairo_output_stream_printf (surface->stream, - " /ImageMatrix [ 1 0 0 -1 0 %d ] def\n" - "end\n" - "image\n", - opaque_image->height); - } - - if (!surface->use_string_datasource) { - /* Emit the image data as a base85-encoded string which will - * be used as the data source for the image operator. */ - status = _cairo_ps_surface_emit_base85_string (surface, - data_compressed, - data_compressed_size, - FALSE); - } else { - status = CAIRO_STATUS_SUCCESS; - } - -bail3: - free (data_compressed); - -bail2: - free (data); - -bail1: - if (!use_mask && opaque_image != image) - cairo_surface_destroy (&opaque_image->base); - - return status; -} - -static cairo_status_t -_cairo_ps_surface_emit_meta_surface (cairo_ps_surface_t *surface, - cairo_surface_t *meta_surface) -{ - double old_width, old_height; - cairo_matrix_t old_cairo_to_ps; - cairo_content_t old_content; - cairo_clip_t *old_clip; - cairo_rectangle_int_t meta_extents; - cairo_status_t status; - - status = _cairo_surface_get_extents (meta_surface, &meta_extents); - if (status) - return status; - - old_content = surface->content; - old_width = surface->width; - old_height = surface->height; - old_cairo_to_ps = surface->cairo_to_ps; - old_clip = _cairo_surface_get_clip (&surface->base); - surface->width = meta_extents.width; - surface->height = meta_extents.height; - surface->current_pattern_is_solid_color = FALSE; - _cairo_pdf_operators_reset (&surface->pdf_operators); - cairo_matrix_init (&surface->cairo_to_ps, 1, 0, 0, -1, 0, surface->height); - _cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators, - &surface->cairo_to_ps); - _cairo_output_stream_printf (surface->stream, - " q\n" - " 0 0 %f %f rectclip\n", - surface->width, - surface->height); - - if (cairo_surface_get_content (meta_surface) == CAIRO_CONTENT_COLOR) { - surface->content = CAIRO_CONTENT_COLOR; - _cairo_output_stream_printf (surface->stream, - " 0 g 0 0 %f %f rectfill\n", - surface->width, - surface->height); - } - - status = _cairo_meta_surface_replay_region (meta_surface, &surface->base, - CAIRO_META_REGION_NATIVE); - assert (status != CAIRO_INT_STATUS_UNSUPPORTED); - if (status) - return status; - - status = _cairo_pdf_operators_flush (&surface->pdf_operators); - if (status) - return status; - - _cairo_output_stream_printf (surface->stream, - " Q\n"); - surface->content = old_content; - surface->width = old_width; - surface->height = old_height; - surface->current_pattern_is_solid_color = FALSE; - _cairo_pdf_operators_reset (&surface->pdf_operators); - surface->cairo_to_ps = old_cairo_to_ps; - status = _cairo_surface_set_clip (&surface->base, old_clip); - if (status) - return status; - - _cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators, - &surface->cairo_to_ps); - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_ps_surface_flatten_transparency (cairo_ps_surface_t *surface, - const cairo_color_t *color, - double *red, - double *green, - double *blue) -{ - *red = color->red; - *green = color->green; - *blue = color->blue; - - if (! CAIRO_COLOR_IS_OPAQUE (color)) { - *red *= color->alpha; - *green *= color->alpha; - *blue *= color->alpha; - if (surface->content == CAIRO_CONTENT_COLOR_ALPHA) { - double one_minus_alpha = 1. - color->alpha; - *red += one_minus_alpha; - *green += one_minus_alpha; - *blue += one_minus_alpha; - } - } -} - -static void -_cairo_ps_surface_emit_solid_pattern (cairo_ps_surface_t *surface, - cairo_solid_pattern_t *pattern) -{ - double red, green, blue; - - _cairo_ps_surface_flatten_transparency (surface, &pattern->color, &red, &green, &blue); - - if (color_is_gray (red, green, blue)) - _cairo_output_stream_printf (surface->stream, - "%f g\n", - red); - else - _cairo_output_stream_printf (surface->stream, - "%f %f %f rg\n", - red, green, blue); -} - -static cairo_status_t -_cairo_ps_surface_acquire_surface (cairo_ps_surface_t *surface, - cairo_surface_pattern_t *pattern, - int *width, - int *height, - cairo_operator_t op) -{ - cairo_status_t status; - - if (_cairo_surface_is_meta (pattern->surface)) { - cairo_surface_t *meta_surface = pattern->surface; - cairo_rectangle_int_t pattern_extents; - - status = _cairo_surface_get_extents (meta_surface, &pattern_extents); - if (status) - return status; - - *width = pattern_extents.width; - *height = pattern_extents.height; - } else { - status = _cairo_surface_acquire_source_image (pattern->surface, - &surface->image, - &surface->image_extra); - if (status) - return status; - - *width = surface->image->width; - *height = surface->image->height; - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_ps_surface_emit_surface (cairo_ps_surface_t *surface, - cairo_surface_pattern_t *pattern, - cairo_operator_t op) -{ - cairo_status_t status; - - if (_cairo_surface_is_meta (pattern->surface)) { - cairo_surface_t *meta_surface = pattern->surface; - - status = _cairo_ps_surface_emit_meta_surface (surface, - meta_surface); - } else { - status = _cairo_ps_surface_emit_image (surface, surface->image, op); - } - - return status; -} - -static void -_cairo_ps_surface_release_surface (cairo_ps_surface_t *surface, - cairo_surface_pattern_t *pattern) -{ - if (!_cairo_surface_is_meta (pattern->surface)) - _cairo_surface_release_source_image (pattern->surface, surface->image, - surface->image_extra); -} - -static cairo_status_t -_cairo_ps_surface_paint_surface (cairo_ps_surface_t *surface, - cairo_surface_pattern_t *pattern, - cairo_operator_t op) -{ - cairo_status_t status; - int width, height; - cairo_matrix_t cairo_p2d, ps_p2d; - - status = _cairo_ps_surface_acquire_surface (surface, - pattern, - &width, - &height, - op); - if (status) - return status; - - cairo_p2d = pattern->base.matrix; - - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) { - double scale = cairo_p2d.xx; - - _cairo_output_stream_printf (surface->stream, - "%% Fallback Image: x=%f, y=%f, w=%d, h=%d res=%fdpi size=%ld\n", - -cairo_p2d.x0/scale, - -cairo_p2d.y0/scale, - (int)(width/scale), - (int)(height/scale), - scale*72, - (long)width*height*3); - } else { - if (op == CAIRO_OPERATOR_SOURCE) { - _cairo_output_stream_printf (surface->stream, - "%d g 0 0 %f %f rectfill\n", - surface->content == CAIRO_CONTENT_COLOR ? 0 : 1, - surface->width, - surface->height); - } - } - - status = cairo_matrix_invert (&cairo_p2d); - /* cairo_pattern_set_matrix ensures the matrix is invertible */ - assert (status == CAIRO_STATUS_SUCCESS); - - ps_p2d = surface->cairo_to_ps; - cairo_matrix_multiply (&ps_p2d, &cairo_p2d, &ps_p2d); - cairo_matrix_translate (&ps_p2d, 0.0, height); - 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); - } - - status = _cairo_ps_surface_emit_surface (surface, pattern, op); - _cairo_ps_surface_release_surface (surface, pattern); - - return status; -} - -static cairo_status_t -_cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface, - cairo_surface_pattern_t *pattern, - cairo_operator_t op) -{ - cairo_status_t status; - int pattern_width = 0; /* squelch bogus compiler warning */ - int pattern_height = 0; /* squelch bogus compiler warning */ - double xstep, ystep; - cairo_matrix_t cairo_p2d, ps_p2d; - cairo_rectangle_int_t surface_extents; - cairo_bool_t old_use_string_datasource; - - cairo_p2d = pattern->base.matrix; - status = cairo_matrix_invert (&cairo_p2d); - /* cairo_pattern_set_matrix ensures the matrix is invertible */ - assert (status == CAIRO_STATUS_SUCCESS); - - ps_p2d = surface->cairo_to_ps; - cairo_matrix_multiply (&ps_p2d, &cairo_p2d, &ps_p2d); - cairo_matrix_translate (&ps_p2d, 0.0, pattern_height); - cairo_matrix_scale (&ps_p2d, 1.0, -1.0); - - status = _cairo_ps_surface_acquire_surface (surface, - pattern, - &pattern_width, - &pattern_height, - op); - if (status) - return status; - - switch (pattern->base.extend) { - /* We implement EXTEND_PAD like EXTEND_NONE for now */ - case CAIRO_EXTEND_PAD: - case CAIRO_EXTEND_NONE: - { - /* In PS/PDF, (as far as I can tell), all patterns are - * repeating. So we support cairo's EXTEND_NONE semantics - * by setting the repeat step size to a size large enough - * to guarantee that no more than a single occurrence will - * be visible. - * - * First, map the surface extents into pattern space (since - * xstep and ystep are in pattern space). Then use an upper - * bound on the length of the diagonal of the pattern image - * and the surface as repeat size. This guarantees to never - * repeat visibly. - */ - double x1 = 0.0, y1 = 0.0; - double x2 = surface->width, y2 = surface->height; - _cairo_matrix_transform_bounding_box (&pattern->base.matrix, - &x1, &y1, &x2, &y2, - NULL); - - /* Rather than computing precise bounds of the union, just - * add the surface extents unconditionally. We only - * required an answer that's large enough, we don't really - * care if it's not as tight as possible.*/ - xstep = ystep = ceil ((x2 - x1) + (y2 - y1) + - pattern_width + pattern_height); - break; - } - case CAIRO_EXTEND_REPEAT: - xstep = pattern_width; - ystep = pattern_height; - break; - case CAIRO_EXTEND_REFLECT: - xstep = pattern_width*2; - ystep = pattern_height*2; - break; - /* All the rest (if any) should have been analyzed away, so these - * cases should be unreachable. */ - default: - ASSERT_NOT_REACHED; - xstep = 0; - ystep = 0; - } - - _cairo_output_stream_printf (surface->stream, - "/CairoPattern {\n"); - - old_use_string_datasource = surface->use_string_datasource; - surface->use_string_datasource = TRUE; - if (op == CAIRO_OPERATOR_SOURCE) { - _cairo_output_stream_printf (surface->stream, - "%d g 0 0 %f %f rectfill\n", - surface->content == CAIRO_CONTENT_COLOR ? 0 : 1, - xstep, ystep); - } - status = _cairo_ps_surface_emit_surface (surface, pattern, op); - if (status) - return status; - - surface->use_string_datasource = old_use_string_datasource; - _cairo_output_stream_printf (surface->stream, - "} bind def\n"); - - _cairo_output_stream_printf (surface->stream, - "<< /PatternType 1\n" - " /PaintType 1\n" - " /TilingType 1\n"); - _cairo_output_stream_printf (surface->stream, - " /XStep %f /YStep %f\n", - xstep, ystep); - - if (pattern->base.extend == CAIRO_EXTEND_REFLECT) { - _cairo_output_stream_printf (surface->stream, - " /BBox [0 0 %d %d]\n" - " /PaintProc {\n" - " CairoPattern\n" - " [-1 0 0 1 %d 0] concat CairoPattern\n" - " [ 1 0 0 -1 0 %d] concat CairoPattern\n" - " [-1 0 0 1 %d 0] concat CairoPattern\n" - " CairoPattern\n" - " } bind\n", - pattern_width*2, pattern_height*2, - pattern_width*2, - pattern_height*2, - pattern_width*2); - } else { - if (op == CAIRO_OPERATOR_SOURCE) { - _cairo_output_stream_printf (surface->stream, - " /BBox [0 0 %f %f]\n", - xstep, ystep); - } else { - _cairo_output_stream_printf (surface->stream, - " /BBox [0 0 %d %d]\n", - pattern_width, pattern_height); - } - _cairo_output_stream_printf (surface->stream, - " /PaintProc { CairoPattern }\n"); - } - - _cairo_output_stream_printf (surface->stream, - ">>\n"); - - status = _cairo_surface_get_extents (&surface->base, &surface_extents); - if (status) - return status; - - cairo_p2d = pattern->base.matrix; - status = cairo_matrix_invert (&cairo_p2d); - /* cairo_pattern_set_matrix ensures the matrix is invertible */ - assert (status == CAIRO_STATUS_SUCCESS); - - cairo_matrix_init_identity (&ps_p2d); - cairo_matrix_translate (&ps_p2d, 0.0, surface_extents.height); - cairo_matrix_scale (&ps_p2d, 1.0, -1.0); - cairo_matrix_multiply (&ps_p2d, &cairo_p2d, &ps_p2d); - cairo_matrix_translate (&ps_p2d, 0.0, pattern_height); - cairo_matrix_scale (&ps_p2d, 1.0, -1.0); - - _cairo_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, - "makepattern setpattern\n"); - - return CAIRO_STATUS_SUCCESS; -} - -typedef struct _cairo_ps_color_stop { - double offset; - double color[4]; -} cairo_ps_color_stop_t; - -static void -_cairo_ps_surface_emit_linear_colorgradient (cairo_ps_surface_t *surface, - cairo_ps_color_stop_t *stop1, - cairo_ps_color_stop_t *stop2) -{ - _cairo_output_stream_printf (surface->stream, - " << /FunctionType 2\n" - " /Domain [ 0 1 ]\n" - " /C0 [ %f %f %f ]\n" - " /C1 [ %f %f %f ]\n" - " /N 1\n" - " >>\n", - stop1->color[0], - stop1->color[1], - stop1->color[2], - stop2->color[0], - stop2->color[1], - stop2->color[2]); -} - -static void -_cairo_ps_surface_emit_stitched_colorgradient (cairo_ps_surface_t *surface, - unsigned int n_stops, - cairo_ps_color_stop_t stops[]) -{ - unsigned int i; - - _cairo_output_stream_printf (surface->stream, - "<< /FunctionType 3\n" - " /Domain [ 0 1 ]\n" - " /Functions [\n"); - for (i = 0; i < n_stops - 1; i++) - _cairo_ps_surface_emit_linear_colorgradient (surface, &stops[i], &stops[i+1]); - - _cairo_output_stream_printf (surface->stream, " ]\n"); - - _cairo_output_stream_printf (surface->stream, " /Bounds [ "); - for (i = 1; i < n_stops-1; i++) - _cairo_output_stream_printf (surface->stream, "%f ", stops[i].offset); - _cairo_output_stream_printf (surface->stream, "]\n"); - - _cairo_output_stream_printf (surface->stream, " /Encode [ 1 1 %d { pop 0 1 } for ]\n", - n_stops - 1); - - _cairo_output_stream_printf (surface->stream, ">>\n"); -} - -static void -calc_gradient_color (cairo_ps_color_stop_t *new_stop, - cairo_ps_color_stop_t *stop1, - cairo_ps_color_stop_t *stop2) -{ - int i; - double offset = stop1->offset / (stop1->offset + 1.0 - stop2->offset); - - for (i = 0; i < 4; i++) - new_stop->color[i] = stop1->color[i] + offset*(stop2->color[i] - stop1->color[i]); -} - -#define COLOR_STOP_EPSILON 1e-6 - -static cairo_status_t -_cairo_ps_surface_emit_pattern_stops (cairo_ps_surface_t *surface, - cairo_gradient_pattern_t *pattern) -{ - cairo_ps_color_stop_t *allstops, *stops; - unsigned int i, n_stops; - - allstops = _cairo_malloc_ab ((pattern->n_stops + 2), sizeof (cairo_ps_color_stop_t)); - if (allstops == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - stops = &allstops[1]; - n_stops = pattern->n_stops; - - for (i = 0; i < n_stops; i++) { - cairo_gradient_stop_t *stop = &pattern->stops[i]; - - stops[i].color[0] = stop->color.red; - stops[i].color[1] = stop->color.green; - stops[i].color[2] = stop->color.blue; - stops[i].color[3] = stop->color.alpha; - stops[i].offset = pattern->stops[i].offset; - } - - if (pattern->base.extend == CAIRO_EXTEND_REPEAT || - pattern->base.extend == CAIRO_EXTEND_REFLECT) { - if (stops[0].offset > COLOR_STOP_EPSILON) { - if (pattern->base.extend == CAIRO_EXTEND_REFLECT) - memcpy (allstops, stops, sizeof (cairo_ps_color_stop_t)); - else - calc_gradient_color (&allstops[0], &stops[0], &stops[n_stops-1]); - stops = allstops; - n_stops++; - } - stops[0].offset = 0.0; - - if (stops[n_stops-1].offset < 1.0 - COLOR_STOP_EPSILON) { - if (pattern->base.extend == CAIRO_EXTEND_REFLECT) { - memcpy (&stops[n_stops], - &stops[n_stops - 1], - sizeof (cairo_ps_color_stop_t)); - } else { - calc_gradient_color (&stops[n_stops], &stops[0], &stops[n_stops-1]); - } - n_stops++; - } - stops[n_stops-1].offset = 1.0; - } - - for (i = 0; i < n_stops; i++) { - double red, green, blue; - cairo_color_t color; - - _cairo_color_init_rgba (&color, - stops[i].color[0], - stops[i].color[1], - stops[i].color[2], - stops[i].color[3]); - _cairo_ps_surface_flatten_transparency (surface, &color, - &red, &green, &blue); - stops[i].color[0] = red; - stops[i].color[1] = green; - stops[i].color[2] = blue; - } - - _cairo_output_stream_printf (surface->stream, - "/CairoFunction\n"); - if (n_stops == 2) { - /* no need for stitched function */ - _cairo_ps_surface_emit_linear_colorgradient (surface, &stops[0], &stops[1]); - } else { - /* multiple stops: stitch. XXX possible optimization: regulary spaced - * stops do not require stitching. XXX */ - _cairo_ps_surface_emit_stitched_colorgradient (surface, n_stops,stops); - } - _cairo_output_stream_printf (surface->stream, - "def\n"); - - free (allstops); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_ps_surface_emit_repeating_function (cairo_ps_surface_t *surface, - cairo_gradient_pattern_t *pattern, - int begin, - int end) -{ - _cairo_output_stream_printf (surface->stream, - "/CairoFunction\n" - "<< /FunctionType 3\n" - " /Domain [ %d %d ]\n" - " /Functions [ %d {CairoFunction} repeat ]\n" - " /Bounds [ %d 1 %d {} for ]\n", - begin, - end, - end - begin, - begin + 1, - end - 1); - - if (pattern->base.extend == CAIRO_EXTEND_REFLECT) { - _cairo_output_stream_printf (surface->stream, " /Encode [ %d 1 %d { 2 mod 0 eq {0 1} {1 0} ifelse } for ]\n", - begin, - end - 1); - } else { - _cairo_output_stream_printf (surface->stream, " /Encode [ %d 1 %d { pop 0 1 } for ]\n", - begin, - end - 1); - } - - _cairo_output_stream_printf (surface->stream, ">> def\n"); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_ps_surface_emit_linear_pattern (cairo_ps_surface_t *surface, - cairo_linear_pattern_t *pattern) -{ - double x1, y1, x2, y2; - double _x1, _y1, _x2, _y2; - cairo_matrix_t pat_to_ps; - cairo_extend_t extend; - cairo_status_t status; - cairo_gradient_pattern_t *gradient = &pattern->base; - double first_stop, last_stop; - int repeat_begin = 0, repeat_end = 1; - - if (pattern->base.n_stops == 0) - return CAIRO_INT_STATUS_NOTHING_TO_DO; - - if (pattern->base.n_stops == 1) { - cairo_solid_pattern_t solid; - - _cairo_pattern_init_solid (&solid, - &pattern->base.stops[0].color, - CAIRO_CONTENT_COLOR_ALPHA); - _cairo_ps_surface_emit_solid_pattern (surface, - &solid); - _cairo_pattern_fini (&solid.base); - - return CAIRO_STATUS_SUCCESS; - } - - extend = cairo_pattern_get_extend (&pattern->base.base); - - pat_to_ps = pattern->base.base.matrix; - status = cairo_matrix_invert (&pat_to_ps); - /* cairo_pattern_set_matrix ensures the matrix is invertible */ - assert (status == CAIRO_STATUS_SUCCESS); - - cairo_matrix_multiply (&pat_to_ps, &pat_to_ps, &surface->cairo_to_ps); - first_stop = gradient->stops[0].offset; - last_stop = gradient->stops[gradient->n_stops - 1].offset; - - if (pattern->base.base.extend == CAIRO_EXTEND_REPEAT || - pattern->base.base.extend == CAIRO_EXTEND_REFLECT) { - double dx, dy; - int x_rep = 0, y_rep = 0; - - x1 = _cairo_fixed_to_double (pattern->p1.x); - y1 = _cairo_fixed_to_double (pattern->p1.y); - cairo_matrix_transform_point (&pat_to_ps, &x1, &y1); - - x2 = _cairo_fixed_to_double (pattern->p2.x); - y2 = _cairo_fixed_to_double (pattern->p2.y); - cairo_matrix_transform_point (&pat_to_ps, &x2, &y2); - - dx = fabs (x2 - x1); - dy = fabs (y2 - y1); - if (dx > 1e-6) - x_rep = (int) ceil (surface->width/dx); - if (dy > 1e-6) - y_rep = (int) ceil (surface->height/dy); - - repeat_end = MAX (x_rep, y_rep); - repeat_begin = -repeat_end; - first_stop = repeat_begin; - last_stop = repeat_end; - } - - /* PS requires the first and last stop to be the same as the line - * coordinates. For repeating patterns this moves the line - * coordinates out to the begin/end of the repeating function. For - * non repeating patterns this may move the line coordinates in if - * there are not stops at offset 0 and 1. */ - x1 = _cairo_fixed_to_double (pattern->p1.x); - y1 = _cairo_fixed_to_double (pattern->p1.y); - x2 = _cairo_fixed_to_double (pattern->p2.x); - y2 = _cairo_fixed_to_double (pattern->p2.y); - - _x1 = x1 + (x2 - x1)*first_stop; - _y1 = y1 + (y2 - y1)*first_stop; - _x2 = x1 + (x2 - x1)*last_stop; - _y2 = y1 + (y2 - y1)*last_stop; - - x1 = _x1; - x2 = _x2; - y1 = _y1; - y2 = _y2; - - /* For EXTEND_NONE and EXTEND_PAD if there are only two stops a - * Type 2 function is used by itself without a stitching - * function. Type 2 functions always have the domain [0 1] */ - if ((pattern->base.base.extend == CAIRO_EXTEND_NONE || - pattern->base.base.extend == CAIRO_EXTEND_PAD) && - gradient->n_stops == 2) { - first_stop = 0.0; - last_stop = 1.0; - } - - status = _cairo_ps_surface_emit_pattern_stops (surface, - &pattern->base); - if (status) - return status; - - if (pattern->base.base.extend == CAIRO_EXTEND_REPEAT || - pattern->base.base.extend == CAIRO_EXTEND_REFLECT) { - status = _cairo_ps_surface_emit_repeating_function (surface, - &pattern->base, - repeat_begin, - repeat_end); - if (status) - return status; - } - - _cairo_output_stream_printf (surface->stream, - "<< /PatternType 2\n" - " /Shading\n" - " << /ShadingType 2\n" - " /ColorSpace /DeviceRGB\n" - " /Coords [ %f %f %f %f ]\n" - " /Domain [ %f %f ]\n" - " /Function CairoFunction\n", - x1, y1, x2, y2, - first_stop, last_stop); - - if (extend == CAIRO_EXTEND_PAD) { - _cairo_output_stream_printf (surface->stream, - " /Extend [ true true ]\n"); - } else { - _cairo_output_stream_printf (surface->stream, - " /Extend [ false false ]\n"); - } - - _cairo_output_stream_printf (surface->stream, - " >>\n" - ">>\n"); - _cairo_output_stream_printf (surface->stream, - "[ %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); - _cairo_output_stream_printf (surface->stream, - "makepattern setpattern\n"); - - return status; -} - -static cairo_status_t -_cairo_ps_surface_emit_radial_pattern (cairo_ps_surface_t *surface, - cairo_radial_pattern_t *pattern) -{ - double x1, y1, x2, y2, r1, r2; - cairo_matrix_t pat_to_ps; - cairo_extend_t extend; - cairo_status_t status; - - if (pattern->base.n_stops == 0) - return CAIRO_INT_STATUS_NOTHING_TO_DO; - - if (pattern->base.n_stops == 1) { - cairo_solid_pattern_t solid; - - _cairo_pattern_init_solid (&solid, - &pattern->base.stops[0].color, - CAIRO_CONTENT_COLOR_ALPHA); - _cairo_ps_surface_emit_solid_pattern (surface, - &solid); - _cairo_pattern_fini (&solid.base); - - return CAIRO_STATUS_SUCCESS; - } - - extend = cairo_pattern_get_extend (&pattern->base.base); - - pat_to_ps = pattern->base.base.matrix; - status = cairo_matrix_invert (&pat_to_ps); - /* cairo_pattern_set_matrix ensures the matrix is invertible */ - assert (status == CAIRO_STATUS_SUCCESS); - - cairo_matrix_multiply (&pat_to_ps, &pat_to_ps, &surface->cairo_to_ps); - x1 = _cairo_fixed_to_double (pattern->c1.x); - y1 = _cairo_fixed_to_double (pattern->c1.y); - r1 = _cairo_fixed_to_double (pattern->r1); - x2 = _cairo_fixed_to_double (pattern->c2.x); - y2 = _cairo_fixed_to_double (pattern->c2.y); - r2 = _cairo_fixed_to_double (pattern->r2); - - status = _cairo_ps_surface_emit_pattern_stops (surface, &pattern->base); - if (status) - return status; - - _cairo_output_stream_printf (surface->stream, - "<< /PatternType 2\n" - " /Shading\n" - " << /ShadingType 3\n" - " /ColorSpace /DeviceRGB\n" - " /Coords [ %f %f %f %f %f %f ]\n" - " /Function CairoFunction\n", - x1, y1, r1, x2, y2, r2); - - if (extend == CAIRO_EXTEND_PAD) { - _cairo_output_stream_printf (surface->stream, - " /Extend [ true true ]\n"); - } else { - _cairo_output_stream_printf (surface->stream, - " /Extend [ false false ]\n"); - } - - _cairo_output_stream_printf (surface->stream, - " >>\n" - ">>\n"); - - _cairo_output_stream_printf (surface->stream, - "[ %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); - _cairo_output_stream_printf (surface->stream, - "makepattern setpattern\n"); - - return status; -} - -static cairo_status_t -_cairo_ps_surface_emit_pattern (cairo_ps_surface_t *surface, - cairo_pattern_t *pattern, - cairo_operator_t op) -{ - cairo_status_t status; - - if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) { - cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) pattern; - - if (surface->current_pattern_is_solid_color == FALSE || - ! _cairo_color_equal (&surface->current_color, &solid->color)) - { - status = _cairo_pdf_operators_flush (&surface->pdf_operators); - if (status) - return status; - - _cairo_ps_surface_emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern); - - surface->current_pattern_is_solid_color = TRUE; - surface->current_color = solid->color; - } - - return CAIRO_STATUS_SUCCESS; - } - - surface->current_pattern_is_solid_color = FALSE; - status = _cairo_pdf_operators_flush (&surface->pdf_operators); - if (status) - return status; - - switch (pattern->type) { - case CAIRO_PATTERN_TYPE_SOLID: - - _cairo_ps_surface_emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern); - break; - - case CAIRO_PATTERN_TYPE_SURFACE: - status = _cairo_ps_surface_emit_surface_pattern (surface, - (cairo_surface_pattern_t *) pattern, - op); - if (status) - return status; - break; - - case CAIRO_PATTERN_TYPE_LINEAR: - status = _cairo_ps_surface_emit_linear_pattern (surface, - (cairo_linear_pattern_t *) pattern); - if (status) - return status; - break; - - case CAIRO_PATTERN_TYPE_RADIAL: - status = _cairo_ps_surface_emit_radial_pattern (surface, - (cairo_radial_pattern_t *) pattern); - if (status) - return status; - break; - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_ps_surface_intersect_clip_path (void *abstract_surface, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_ps_surface_t *surface = abstract_surface; - cairo_output_stream_t *stream = surface->stream; - cairo_status_t status; - - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return CAIRO_STATUS_SUCCESS; - -#if DEBUG_PS - _cairo_output_stream_printf (stream, - "%% _cairo_ps_surface_intersect_clip_path\n"); -#endif - - if (path == NULL) { - status = _cairo_pdf_operators_flush (&surface->pdf_operators); - if (status) - return status; - - _cairo_output_stream_printf (stream, "Q q\n"); - surface->current_pattern_is_solid_color = FALSE; - _cairo_pdf_operators_reset (&surface->pdf_operators); - - return CAIRO_STATUS_SUCCESS; - } - - return _cairo_pdf_operators_clip (&surface->pdf_operators, - path, - fill_rule); -} - -static cairo_int_status_t -_cairo_ps_surface_get_extents (void *abstract_surface, - cairo_rectangle_int_t *rectangle) -{ - cairo_ps_surface_t *surface = abstract_surface; - - rectangle->x = 0; - rectangle->y = 0; - - /* XXX: The conversion to integers here is pretty bogus, (not to - * mention the aribitray limitation of width to a short(!). We - * may need to come up with a better interface for get_extents. - */ - rectangle->width = (int) ceil (surface->width); - rectangle->height = (int) ceil (surface->height); - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_ps_surface_get_font_options (void *abstract_surface, - cairo_font_options_t *options) -{ - _cairo_font_options_init_default (options); - - cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_NONE); - cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF); - cairo_font_options_set_antialias (options, CAIRO_ANTIALIAS_GRAY); -} - -static cairo_int_status_t -_cairo_ps_surface_paint (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source) -{ - cairo_ps_surface_t *surface = abstract_surface; - cairo_output_stream_t *stream = surface->stream; - cairo_rectangle_int_t extents; - cairo_status_t status; - - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return _cairo_ps_surface_analyze_operation (surface, op, source); - - assert (_cairo_ps_surface_operation_supported (surface, op, source)); - -#if DEBUG_PS - _cairo_output_stream_printf (stream, - "%% _cairo_ps_surface_paint\n"); -#endif - - status = _cairo_surface_get_extents (&surface->base, &extents); - if (status) - return status; - - status = _cairo_pdf_operators_flush (&surface->pdf_operators); - if (status) - return status; - - if (source->type == CAIRO_PATTERN_TYPE_SURFACE && - (source->extend == CAIRO_EXTEND_NONE || - source->extend == CAIRO_EXTEND_PAD)) - { - _cairo_output_stream_printf (stream, "q 0 0 %d %d rectclip\n", - extents.width, - extents.height); - - status = _cairo_ps_surface_paint_surface (surface, - (cairo_surface_pattern_t *) source, - op); - if (status) - return status; - - _cairo_output_stream_printf (stream, "Q\n"); - } else { - status = _cairo_ps_surface_emit_pattern (surface, source, op); - if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) - return CAIRO_STATUS_SUCCESS; - - if (status) - return status; - - _cairo_output_stream_printf (stream, "0 0 %d %d rectfill\n", - extents.width, - extents.height); - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_ps_surface_stroke (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - 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_ps_surface_t *surface = abstract_surface; - cairo_int_status_t status; - - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return _cairo_ps_surface_analyze_operation (surface, op, source); - - assert (_cairo_ps_surface_operation_supported (surface, op, source)); - -#if DEBUG_PS - _cairo_output_stream_printf (surface->stream, - "%% _cairo_ps_surface_stroke\n"); -#endif - - status = _cairo_ps_surface_emit_pattern (surface, source, op); - if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) - return CAIRO_STATUS_SUCCESS; - - return _cairo_pdf_operators_stroke (&surface->pdf_operators, - path, - style, - ctm, - ctm_inverse); -} - -static cairo_int_status_t -_cairo_ps_surface_fill (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_ps_surface_t *surface = abstract_surface; - cairo_int_status_t status; - - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return _cairo_ps_surface_analyze_operation (surface, op, source); - - assert (_cairo_ps_surface_operation_supported (surface, op, source)); - -#if DEBUG_PS - _cairo_output_stream_printf (surface->stream, - "%% _cairo_ps_surface_fill\n"); -#endif - - if (source->type == CAIRO_PATTERN_TYPE_SURFACE && - (source->extend == CAIRO_EXTEND_NONE || - source->extend == CAIRO_EXTEND_PAD)) - { - status = _cairo_pdf_operators_flush (&surface->pdf_operators); - if (status) - return status; - - _cairo_output_stream_printf (surface->stream, "q\n"); - - status = _cairo_pdf_operators_clip (&surface->pdf_operators, - path, - fill_rule); - if (status) - return status; - - status = _cairo_ps_surface_paint_surface (surface, - (cairo_surface_pattern_t *) source, - op); - if (status) - return status; - - _cairo_output_stream_printf (surface->stream, "Q\n"); - _cairo_pdf_operators_reset (&surface->pdf_operators); - } else { - status = _cairo_ps_surface_emit_pattern (surface, source, op); - if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) - return CAIRO_STATUS_SUCCESS; - - if (status) - return status; - - status = _cairo_pdf_operators_fill (&surface->pdf_operators, - path, - fill_rule); - } - - return status; -} - -static cairo_int_status_t -_cairo_ps_surface_show_glyphs (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font, - int *remaining_glyphs) -{ - cairo_ps_surface_t *surface = abstract_surface; - cairo_status_t status; - - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return _cairo_ps_surface_analyze_operation (surface, op, source); - - assert (_cairo_ps_surface_operation_supported (surface, op, source)); - -#if DEBUG_PS - _cairo_output_stream_printf (surface->stream, - "%% _cairo_ps_surface_show_glyphs\n"); -#endif - - if (num_glyphs <= 0) - return CAIRO_STATUS_SUCCESS; - - status = _cairo_ps_surface_emit_pattern (surface, source, op); - if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) - return CAIRO_STATUS_SUCCESS; - - if (status) - return status; - - return _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators, - NULL, 0, - glyphs, num_glyphs, - NULL, 0, - FALSE, - scaled_font); -} - -static void -_cairo_ps_surface_set_paginated_mode (void *abstract_surface, - cairo_paginated_mode_t paginated_mode) -{ - cairo_ps_surface_t *surface = abstract_surface; - - surface->paginated_mode = paginated_mode; -} - -static cairo_int_status_t -_cairo_ps_surface_set_bounding_box (void *abstract_surface, - cairo_box_t *bbox) -{ - cairo_ps_surface_t *surface = abstract_surface; - int i, num_comments; - char **comments; - int x1, y1, x2, y2; - - if (surface->eps) { - x1 = (int) floor (_cairo_fixed_to_double (bbox->p1.x)); - y1 = (int) floor (surface->height - _cairo_fixed_to_double (bbox->p2.y)); - x2 = (int) ceil (_cairo_fixed_to_double (bbox->p2.x)); - y2 = (int) ceil (surface->height - _cairo_fixed_to_double (bbox->p1.y)); - } else { - x1 = 0; - y1 = 0; - x2 = (int) ceil (surface->width); - y2 = (int) ceil (surface->height); - } - - _cairo_output_stream_printf (surface->stream, - "%%%%Page: %d %d\n", - surface->num_pages, - surface->num_pages); - - _cairo_output_stream_printf (surface->stream, - "%%%%BeginPageSetup\n"); - - num_comments = _cairo_array_num_elements (&surface->dsc_page_setup_comments); - comments = _cairo_array_index (&surface->dsc_page_setup_comments, 0); - for (i = 0; i < num_comments; i++) { - _cairo_output_stream_printf (surface->stream, - "%s\n", comments[i]); - free (comments[i]); - comments[i] = NULL; - } - _cairo_array_truncate (&surface->dsc_page_setup_comments, 0); - - _cairo_output_stream_printf (surface->stream, - "%%%%PageBoundingBox: %d %d %d %d\n", - x1, y1, x2, y2); - - _cairo_output_stream_printf (surface->stream, - "%%%%EndPageSetup\n" - "q\n"); - - if (surface->num_pages == 1) { - surface->bbox_x1 = x1; - surface->bbox_y1 = y1; - surface->bbox_x2 = x2; - surface->bbox_y2 = y2; - } else { - if (x1 < surface->bbox_x1) - surface->bbox_x1 = x1; - if (y1 < surface->bbox_y1) - surface->bbox_y1 = y1; - if (x2 > surface->bbox_x2) - surface->bbox_x2 = x2; - if (y2 > surface->bbox_y2) - surface->bbox_y2 = y2; - } - surface->current_pattern_is_solid_color = FALSE; - _cairo_pdf_operators_reset (&surface->pdf_operators); - - return _cairo_output_stream_get_status (surface->stream); -} - -static cairo_bool_t -_cairo_ps_surface_supports_fine_grained_fallbacks (void *abstract_surface) -{ - return TRUE; -} - -static const cairo_surface_backend_t cairo_ps_surface_backend = { - CAIRO_SURFACE_TYPE_PS, - _cairo_ps_surface_create_similar, - _cairo_ps_surface_finish, - NULL, /* acquire_source_image */ - NULL, /* release_source_image */ - NULL, /* acquire_dest_image */ - NULL, /* release_dest_image */ - NULL, /* clone_similar */ - NULL, /* composite */ - NULL, /* fill_rectangles */ - NULL, /* composite_trapezoids */ - NULL, /* cairo_ps_surface_copy_page */ - _cairo_ps_surface_show_page, - NULL, /* set_clip_region */ - _cairo_ps_surface_intersect_clip_path, - _cairo_ps_surface_get_extents, - NULL, /* old_show_glyphs */ - _cairo_ps_surface_get_font_options, - NULL, /* flush */ - NULL, /* mark_dirty_rectangle */ - NULL, /* scaled_font_fini */ - NULL, /* scaled_glyph_fini */ - - /* Here are the drawing functions */ - - _cairo_ps_surface_paint, /* paint */ - NULL, /* mask */ - _cairo_ps_surface_stroke, - _cairo_ps_surface_fill, - _cairo_ps_surface_show_glyphs, - NULL, /* snapshot */ -}; - -static const cairo_paginated_surface_backend_t cairo_ps_surface_paginated_backend = { - _cairo_ps_surface_start_page, - _cairo_ps_surface_set_paginated_mode, - _cairo_ps_surface_set_bounding_box, - NULL, /* _cairo_ps_surface_has_fallback_images, */ - _cairo_ps_surface_supports_fine_grained_fallbacks, -}; diff --git a/uppdev/plugin/cairo/lib/cairo-ps.h b/uppdev/plugin/cairo/lib/cairo-ps.h deleted file mode 100644 index 8a2cb58b1..000000000 --- a/uppdev/plugin/cairo/lib/cairo-ps.h +++ /dev/null @@ -1,114 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - */ - -#ifndef CAIRO_PS_H -#define CAIRO_PS_H - -#include "cairo.h" - -#if CAIRO_HAS_PS_SURFACE - -#include - -CAIRO_BEGIN_DECLS - -/* PS-surface functions */ - -/** - * cairo_ps_level_t: - * @CAIRO_PS_LEVEL_2: The language level 2 of the PostScript specification. - * @CAIRO_PS_LEVEL_3: The language level 3 of the PostScript specification. - * - * #cairo_ps_level_t is used to describe the language level of the - * PostScript Language Reference that a generated PostScript file will - * conform to. - */ -typedef enum _cairo_ps_level { - CAIRO_PS_LEVEL_2, - CAIRO_PS_LEVEL_3 -} cairo_ps_level_t; - -cairo_public cairo_surface_t * -cairo_ps_surface_create (const char *filename, - double width_in_points, - double height_in_points); - -cairo_public cairo_surface_t * -cairo_ps_surface_create_for_stream (cairo_write_func_t write_func, - void *closure, - double width_in_points, - double height_in_points); - -cairo_public void -cairo_ps_surface_restrict_to_level (cairo_surface_t *surface, - cairo_ps_level_t level); - -cairo_public void -cairo_ps_get_levels (cairo_ps_level_t const **levels, - int *num_levels); - -cairo_public const char * -cairo_ps_level_to_string (cairo_ps_level_t level); - -cairo_public void -cairo_ps_surface_set_eps (cairo_surface_t *surface, - cairo_bool_t eps); - -cairo_public cairo_bool_t -cairo_ps_surface_get_eps (cairo_surface_t *surface); - -cairo_public void -cairo_ps_surface_set_size (cairo_surface_t *surface, - double width_in_points, - double height_in_points); - -cairo_public void -cairo_ps_surface_dsc_comment (cairo_surface_t *surface, - const char *comment); - -cairo_public void -cairo_ps_surface_dsc_begin_setup (cairo_surface_t *surface); - -cairo_public void -cairo_ps_surface_dsc_begin_page_setup (cairo_surface_t *surface); - -CAIRO_END_DECLS - -#else /* CAIRO_HAS_PS_SURFACE */ -# error Cairo was not compiled with support for the ps backend -#endif /* CAIRO_HAS_PS_SURFACE */ - -#endif /* CAIRO_PS_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-quartz-font.c b/uppdev/plugin/cairo/lib/cairo-quartz-font.c deleted file mode 100644 index 2bca37200..000000000 --- a/uppdev/plugin/cairo/lib/cairo-quartz-font.c +++ /dev/null @@ -1,840 +0,0 @@ -/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */ -/* cairo - a vector graphics library with display and print output - * - * Copyright � 2008 Mozilla Corporation - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Mozilla Corporation. - * - * Contributor(s): - * Vladimir Vukicevic - */ - -#include "cairoint.h" - -#include - -#include "cairo-quartz.h" -#include "cairo-quartz-private.h" - -/* CreateWithFontName exists in 10.5, but not in 10.4; CreateWithName isn't public in 10.4 */ -static CGFontRef (*CGFontCreateWithFontNamePtr) (CFStringRef) = NULL; -static CGFontRef (*CGFontCreateWithNamePtr) (const char *) = NULL; - -/* These aren't public before 10.5, and some have different names in 10.4 */ -static int (*CGFontGetUnitsPerEmPtr) (CGFontRef) = NULL; -static bool (*CGFontGetGlyphAdvancesPtr) (CGFontRef, const CGGlyph[], size_t, int[]) = NULL; -static bool (*CGFontGetGlyphBBoxesPtr) (CGFontRef, const CGGlyph[], size_t, CGRect[]) = NULL; -static CGRect (*CGFontGetFontBBoxPtr) (CGFontRef) = NULL; - -/* Not public, but present */ -static void (*CGFontGetGlyphsForUnicharsPtr) (CGFontRef, const UniChar[], const CGGlyph[], size_t) = 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; - int descent; - int leading; -} quartz_CGFontMetrics; -static quartz_CGFontMetrics* (*CGFontGetHMetricsPtr) (CGFontRef fontRef) = NULL; -static int (*CGFontGetAscentPtr) (CGFontRef fontRef) = NULL; -static int (*CGFontGetDescentPtr) (CGFontRef fontRef) = NULL; -static int (*CGFontGetLeadingPtr) (CGFontRef fontRef) = NULL; - -static cairo_bool_t _cairo_quartz_font_symbol_lookup_done = FALSE; -static cairo_bool_t _cairo_quartz_font_symbols_present = FALSE; - -static void -quartz_font_ensure_symbols(void) -{ - if (_cairo_quartz_font_symbol_lookup_done) - return; - - /* Look for the 10.5 versions first */ - CGFontGetGlyphBBoxesPtr = dlsym(RTLD_DEFAULT, "CGFontGetGlyphBBoxes"); - if (!CGFontGetGlyphBBoxesPtr) - CGFontGetGlyphBBoxesPtr = dlsym(RTLD_DEFAULT, "CGFontGetGlyphBoundingBoxes"); - - CGFontGetGlyphsForUnicharsPtr = dlsym(RTLD_DEFAULT, "CGFontGetGlyphsForUnichars"); - if (!CGFontGetGlyphsForUnicharsPtr) - CGFontGetGlyphsForUnicharsPtr = dlsym(RTLD_DEFAULT, "CGFontGetGlyphsForUnicodes"); - - CGFontGetFontBBoxPtr = dlsym(RTLD_DEFAULT, "CGFontGetFontBBox"); - - /* We just need one of these two */ - CGFontCreateWithFontNamePtr = dlsym(RTLD_DEFAULT, "CGFontCreateWithFontName"); - CGFontCreateWithNamePtr = dlsym(RTLD_DEFAULT, "CGFontCreateWithName"); - - /* 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"); - CGFontGetDescentPtr = dlsym(RTLD_DEFAULT, "CGFontGetDescent"); - CGFontGetLeadingPtr = dlsym(RTLD_DEFAULT, "CGFontGetLeading"); - - if ((CGFontCreateWithFontNamePtr || CGFontCreateWithNamePtr) && - CGFontGetGlyphBBoxesPtr && - CGFontGetGlyphsForUnicharsPtr && - CGFontGetUnitsPerEmPtr && - CGFontGetGlyphAdvancesPtr && - CGFontGetGlyphPathPtr && - (CGFontGetHMetricsPtr || (CGFontGetAscentPtr && CGFontGetDescentPtr && CGFontGetLeadingPtr))) - _cairo_quartz_font_symbols_present = TRUE; - - _cairo_quartz_font_symbol_lookup_done = TRUE; -} - -typedef struct _cairo_quartz_font_face cairo_quartz_font_face_t; -typedef struct _cairo_quartz_scaled_font cairo_quartz_scaled_font_t; - -struct _cairo_quartz_scaled_font { - cairo_scaled_font_t base; -}; - -struct _cairo_quartz_font_face { - cairo_font_face_t base; - - CGFontRef cgFont; -}; - -/* - * font face backend - */ - -static void -_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); -} - -static cairo_status_t -_cairo_quartz_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_out) -{ - cairo_quartz_font_face_t *font_face = abstract_face; - cairo_quartz_scaled_font_t *font = NULL; - cairo_status_t status; - cairo_font_extents_t fs_metrics; - double ems; - CGRect bbox; - - quartz_font_ensure_symbols(); - if (!_cairo_quartz_font_symbols_present) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - font = malloc(sizeof(cairo_quartz_scaled_font_t)); - if (font == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - memset (font, 0, sizeof(cairo_quartz_scaled_font_t)); - - status = _cairo_scaled_font_init (&font->base, - &font_face->base, font_matrix, ctm, options, - &_cairo_quartz_scaled_font_backend); - if (status) - goto FINISH; - - ems = CGFontGetUnitsPerEmPtr (font_face->cgFont); - - /* initialize metrics */ - if (CGFontGetFontBBoxPtr && CGFontGetAscentPtr) { - fs_metrics.ascent = (CGFontGetAscentPtr (font_face->cgFont) / ems); - fs_metrics.descent = - (CGFontGetDescentPtr (font_face->cgFont) / ems); - fs_metrics.height = fs_metrics.ascent + fs_metrics.descent + - (CGFontGetLeadingPtr (font_face->cgFont) / ems); - - bbox = CGFontGetFontBBoxPtr (font_face->cgFont); - fs_metrics.max_x_advance = CGRectGetMaxX(bbox) / ems; - fs_metrics.max_y_advance = 0.0; - } else { - CGGlyph wGlyph; - UniChar u; - - quartz_CGFontMetrics *m; - m = CGFontGetHMetricsPtr (font_face->cgFont); - - /* On OX 10.4, GetHMetricsPtr sometimes returns NULL for unknown reasons */ - if (!m) { - status = _cairo_error(CAIRO_STATUS_NULL_POINTER); - goto FINISH; - } - - fs_metrics.ascent = (m->ascent / ems); - fs_metrics.descent = - (m->descent / ems); - fs_metrics.height = fs_metrics.ascent + fs_metrics.descent + (m->leading / ems); - - /* We kind of have to guess here; W's big, right? */ - u = (UniChar) 'W'; - CGFontGetGlyphsForUnicharsPtr (font_face->cgFont, &u, &wGlyph, 1); - if (wGlyph && CGFontGetGlyphBBoxesPtr (font_face->cgFont, &wGlyph, 1, &bbox)) { - fs_metrics.max_x_advance = CGRectGetMaxX(bbox) / ems; - fs_metrics.max_y_advance = 0.0; - } else { - fs_metrics.max_x_advance = 0.0; - fs_metrics.max_y_advance = 0.0; - } - } - - status = _cairo_scaled_font_set_metrics (&font->base, &fs_metrics); - -FINISH: - if (status != CAIRO_STATUS_SUCCESS) { - free (font); - } else { - *font_out = (cairo_scaled_font_t*) font; - } - - return status; -} - -static const cairo_font_face_backend_t _cairo_quartz_font_face_backend = { - CAIRO_FONT_TYPE_QUARTZ, - _cairo_quartz_font_face_destroy, - NULL, /* direct implementation */ - _cairo_quartz_font_face_scaled_font_create -}; - -/** - * cairo_quartz_font_face_create_for_cgfont - * @font: a #CGFontRef obtained through a method external to cairo. - * - * Creates a new font for the Quartz font backend based on a - * #CGFontRef. This font can then be used with - * cairo_set_font_face() or cairo_scaled_font_create(). - * - * Return value: a newly created #cairo_font_face_t. Free with - * cairo_font_face_destroy() when you are done using it. - * - * Since: 1.6 - */ -cairo_font_face_t * -cairo_quartz_font_face_create_for_cgfont (CGFontRef font) -{ - cairo_quartz_font_face_t *font_face; - - quartz_font_ensure_symbols(); - - font_face = malloc (sizeof (cairo_quartz_font_face_t)); - if (!font_face) { - _cairo_error (CAIRO_STATUS_NO_MEMORY); - return (cairo_font_face_t *)&_cairo_font_face_nil; - } - - font_face->cgFont = CGFontRetain (font); - - _cairo_font_face_init (&font_face->base, &_cairo_quartz_font_face_backend); - - return &font_face->base; -} - -/* - * scaled font backend - */ - -static cairo_quartz_font_face_t * -_cairo_quartz_scaled_to_face (void *abstract_font) -{ - cairo_quartz_scaled_font_t *sfont = (cairo_quartz_scaled_font_t*) abstract_font; - cairo_font_face_t *font_face = cairo_scaled_font_get_font_face (&sfont->base); - if (!font_face || font_face->backend->type != CAIRO_FONT_TYPE_QUARTZ) - return NULL; - - return (cairo_quartz_font_face_t*) font_face; -} - -static cairo_status_t -_cairo_quartz_font_get_implementation (cairo_toy_font_face_t *toy_face, - cairo_scaled_font_t **font_face_out) -{ - static cairo_user_data_key_t impl_font_face_key; - cairo_font_face_t *face; - cairo_status_t status; - const char *family = toy_face->family; - char *full_name = malloc(strlen(family) + 64); // give us a bit of room to tack on Bold, Oblique, etc. - CFStringRef cgFontName = NULL; - CGFontRef cgFont = NULL; - int loop; - - face = cairo_font_face_get_user_data (&toy_face->base, - &impl_font_face_key); - if (face) { - *font_face_out = face; - return CAIRO_STATUS_SUCCESS; - } - - quartz_font_ensure_symbols(); - if (! _cairo_quartz_font_symbols_present) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - /* handle CSS-ish faces */ - if (!strcmp(family, "serif") || !strcmp(family, "Times Roman")) - family = "Times"; - else if (!strcmp(family, "sans-serif") || !strcmp(family, "sans")) - family = "Helvetica"; - else if (!strcmp(family, "cursive")) - family = "Apple Chancery"; - else if (!strcmp(family, "fantasy")) - family = "Papyrus"; - else if (!strcmp(family, "monospace") || !strcmp(family, "mono")) - family = "Courier"; - - /* Try to build up the full name, e.g. "Helvetica Bold Oblique" first, - * then drop the bold, then drop the slant, then drop both.. finally - * just use "Helvetica". And if Helvetica doesn't exist, give up. - */ - for (loop = 0; loop < 5; loop++) { - if (loop == 4) - family = "Helvetica"; - - strcpy (full_name, family); - - if (loop < 3 && (loop & 1) == 0) { - if (toy_face->weight == CAIRO_FONT_WEIGHT_BOLD) - strcat (full_name, " Bold"); - } - - if (loop < 3 && (loop & 2) == 0) { - if (toy_face->slant == CAIRO_FONT_SLANT_ITALIC) - strcat (full_name, " Italic"); - else if (toy_face->slant == CAIRO_FONT_SLANT_OBLIQUE) - strcat (full_name, " Oblique"); - } - - if (CGFontCreateWithFontNamePtr) { - cgFontName = CFStringCreateWithCString (NULL, full_name, kCFStringEncodingASCII); - cgFont = CGFontCreateWithFontNamePtr (cgFontName); - CFRelease (cgFontName); - } else { - cgFont = CGFontCreateWithNamePtr (full_name); - } - - if (cgFont) - break; - } - - if (!cgFont) { - /* Give up */ - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - face = cairo_quartz_font_face_create_for_cgfont (cgFont); - CGFontRelease (cgFont); - - if (face->status) - return face->status; - - status = cairo_font_face_set_user_data (&toy_face->base, - &impl_font_face_key, - face, - (cairo_destroy_func_t) cairo_font_face_destroy); - - if (status) { - cairo_font_face_destroy (face); - return status; - } - - *font_face_out = face; - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_quartz_font_create_toy (cairo_toy_font_face_t *toy_face, - const cairo_matrix_t *font_matrix, - const cairo_matrix_t *ctm, - const cairo_font_options_t *options, - cairo_scaled_font_t **font_out) -{ - cairo_font_face_t *face; - cairo_scaled_font_t *scaled_font; - cairo_status_t status; - - status = _cairo_quartz_font_get_implementation (toy_face, &face); - if (status) - return status; - - status = _cairo_quartz_font_face_scaled_font_create (face, - font_matrix, ctm, - options, - &scaled_font); - cairo_font_face_destroy (face); - if (status) - return status; - - *font_out = scaled_font; - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_quartz_font_fini(void *abstract_font) -{ -} - -#define INVALID_GLYPH 0x00 - -static inline CGGlyph -_cairo_quartz_scaled_glyph_index (cairo_scaled_glyph_t *scaled_glyph) { - unsigned long index = _cairo_scaled_glyph_index (scaled_glyph); - if (index > 0xffff) - return INVALID_GLYPH; - return (CGGlyph) index; -} - -static inline cairo_status_t -_cairo_matrix_to_unit_quartz_matrix (const cairo_matrix_t *m, CGAffineTransform *txout, - double *xout, double *yout) -{ - CGAffineTransform transform; - double xscale, yscale; - cairo_status_t status; - - status = _cairo_matrix_compute_basis_scale_factors (m, &xscale, &yscale, 1); - if (status) - return status; - - transform = CGAffineTransformMake (m->xx, - m->yx, - - m->xy, m->yy, - 0.0f, 0.0f); - if (xout) - *xout = xscale; - if (yout) - *yout = yscale; - - if (xscale) - xscale = 1.0 / xscale; - if (yscale) - yscale = 1.0 / yscale; - - *txout = CGAffineTransformScale (transform, xscale, yscale); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_quartz_init_glyph_metrics (cairo_quartz_scaled_font_t *font, - cairo_scaled_glyph_t *scaled_glyph) -{ - cairo_int_status_t status = CAIRO_STATUS_SUCCESS; - - cairo_quartz_font_face_t *font_face = _cairo_quartz_scaled_to_face(font); - cairo_text_extents_t extents = {0, 0, 0, 0, 0, 0}; - CGAffineTransform textMatrix; - CGGlyph glyph = _cairo_quartz_scaled_glyph_index (scaled_glyph); - int advance; - CGRect bbox; - double emscale = CGFontGetUnitsPerEmPtr (font_face->cgFont); - double xscale, yscale; - double xmin, ymin, xmax, ymax; - - if (glyph == INVALID_GLYPH) - goto FAIL; - - if (!CGFontGetGlyphAdvancesPtr (font_face->cgFont, &glyph, 1, &advance) || - !CGFontGetGlyphBBoxesPtr (font_face->cgFont, &glyph, 1, &bbox)) - goto FAIL; - - status = _cairo_matrix_compute_basis_scale_factors (&font->base.scale, - &xscale, &yscale, 1); - if (status) - goto FAIL; - - bbox = CGRectMake (bbox.origin.x / emscale, - bbox.origin.y / emscale, - bbox.size.width / emscale, - bbox.size.height / emscale); - - /* Should we want to always integer-align glyph extents, we can do so in this way */ -#if 0 - { - CGAffineTransform textMatrix; - textMatrix = CGAffineTransformMake (font->base.scale.xx, - -font->base.scale.yx, - -font->base.scale.xy, - font->base.scale.yy, - 0.0f, 0.0f); - - bbox = CGRectApplyAffineTransform (bbox, textMatrix); - bbox = CGRectIntegral (bbox); - bbox = CGRectApplyAffineTransform (bbox, CGAffineTransformInvert (textMatrix)); - } -#endif - -#if 0 - fprintf (stderr, "[0x%04x] bbox: %f %f %f %f\n", glyph, - bbox.origin.x / emscale, bbox.origin.y / emscale, - bbox.size.width / emscale, bbox.size.height / emscale); -#endif - - xmin = CGRectGetMinX(bbox); - ymin = CGRectGetMinY(bbox); - xmax = CGRectGetMaxX(bbox); - ymax = CGRectGetMaxY(bbox); - - extents.x_bearing = xmin; - extents.y_bearing = - ymax; - extents.width = xmax - xmin; - extents.height = ymax - ymin; - - extents.x_advance = (double) advance / emscale; - extents.y_advance = 0.0; - -#if 0 - fprintf (stderr, "[0x%04x] extents: bearings: %f %f dim: %f %f adv: %f\n\n", glyph, - extents.x_bearing, extents.y_bearing, extents.width, extents.height, extents.x_advance); -#endif - - FAIL: - _cairo_scaled_glyph_set_metrics (scaled_glyph, - &font->base, - &extents); - - return status; -} - -static void -_cairo_quartz_path_apply_func (void *info, const CGPathElement *el) -{ - cairo_path_fixed_t *path = (cairo_path_fixed_t *) info; - - switch (el->type) { - case kCGPathElementMoveToPoint: - _cairo_path_fixed_move_to (path, - _cairo_fixed_from_double(el->points[0].x), - _cairo_fixed_from_double(el->points[0].y)); - break; - case kCGPathElementAddLineToPoint: - _cairo_path_fixed_line_to (path, - _cairo_fixed_from_double(el->points[0].x), - _cairo_fixed_from_double(el->points[0].y)); - break; - case kCGPathElementAddQuadCurveToPoint: { - cairo_fixed_t fx, fy; - double x, y; - if (!_cairo_path_fixed_get_current_point (path, &fx, &fy)) - fx = fy = 0; - x = _cairo_fixed_to_double (fx); - y = _cairo_fixed_to_double (fy); - - _cairo_path_fixed_curve_to (path, - _cairo_fixed_from_double((x + el->points[0].x * 2.0) / 3.0), - _cairo_fixed_from_double((y + el->points[0].y * 2.0) / 3.0), - _cairo_fixed_from_double((el->points[0].x * 2.0 + el->points[1].x) / 3.0), - _cairo_fixed_from_double((el->points[0].y * 2.0 + el->points[1].y) / 3.0), - _cairo_fixed_from_double(el->points[1].x), - _cairo_fixed_from_double(el->points[1].y)); - } - break; - case kCGPathElementAddCurveToPoint: - _cairo_path_fixed_curve_to (path, - _cairo_fixed_from_double(el->points[0].x), - _cairo_fixed_from_double(el->points[0].y), - _cairo_fixed_from_double(el->points[1].x), - _cairo_fixed_from_double(el->points[1].y), - _cairo_fixed_from_double(el->points[2].x), - _cairo_fixed_from_double(el->points[2].y)); - break; - case kCGPathElementCloseSubpath: - _cairo_path_fixed_close_path (path); - break; - } -} - -static cairo_int_status_t -_cairo_quartz_init_glyph_path (cairo_quartz_scaled_font_t *font, - cairo_scaled_glyph_t *scaled_glyph) -{ - cairo_quartz_font_face_t *font_face = _cairo_quartz_scaled_to_face(font); - CGGlyph glyph = _cairo_quartz_scaled_glyph_index (scaled_glyph); - CGAffineTransform textMatrix; - CGPathRef glyphPath; - cairo_path_fixed_t *path; - - if (glyph == INVALID_GLYPH) { - _cairo_scaled_glyph_set_path (scaled_glyph, &font->base, _cairo_path_fixed_create()); - return CAIRO_STATUS_SUCCESS; - } - - textMatrix = CGAffineTransformMake (font->base.scale.xx, - -font->base.scale.yx, - -font->base.scale.xy, - font->base.scale.yy, - font->base.scale.x0, - font->base.scale.y0); - - textMatrix = CGAffineTransformConcat (textMatrix, CGAffineTransformMake (1.0, 0.0, 0.0, -1.0, 0.0, 0.0)); - - glyphPath = CGFontGetGlyphPathPtr (font_face->cgFont, &textMatrix, 0, glyph); - if (!glyphPath) - return CAIRO_INT_STATUS_UNSUPPORTED; - - path = _cairo_path_fixed_create (); - if (!path) { - CGPathRelease (glyphPath); - return _cairo_error(CAIRO_STATUS_NO_MEMORY); - } - - CGPathApply (glyphPath, path, _cairo_quartz_path_apply_func); - - CGPathRelease (glyphPath); - - _cairo_scaled_glyph_set_path (scaled_glyph, &font->base, path); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_quartz_init_glyph_surface (cairo_quartz_scaled_font_t *font, - cairo_scaled_glyph_t *scaled_glyph) -{ - cairo_int_status_t status = CAIRO_STATUS_SUCCESS; - - cairo_quartz_font_face_t *font_face = _cairo_quartz_scaled_to_face(font); - - cairo_image_surface_t *surface = NULL; - - CGGlyph glyph = _cairo_quartz_scaled_glyph_index (scaled_glyph); - - int advance; - CGRect bbox; - double width, height; - double xscale, yscale; - double emscale = CGFontGetUnitsPerEmPtr (font_face->cgFont); - - CGColorSpaceRef gray; - CGContextRef cgContext = NULL; - CGAffineTransform textMatrix; - CGRect glyphRect, glyphRectInt; - CGPoint glyphOrigin; - - //fprintf (stderr, "scaled_glyph: %p surface: %p\n", scaled_glyph, scaled_glyph->surface); - - /* Create blank 2x2 image if we don't have this character. - * Maybe we should draw a better missing-glyph slug or something, - * but this is ok for now. - */ - if (glyph == INVALID_GLYPH) { - surface = (cairo_image_surface_t*) cairo_image_surface_create (CAIRO_FORMAT_A8, 2, 2); - status = cairo_surface_status ((cairo_surface_t *) surface); - if (status) - return status; - - _cairo_scaled_glyph_set_surface (scaled_glyph, - &font->base, - surface); - return CAIRO_STATUS_SUCCESS; - } - - if (!CGFontGetGlyphAdvancesPtr (font_face->cgFont, &glyph, 1, &advance) || - !CGFontGetGlyphBBoxesPtr (font_face->cgFont, &glyph, 1, &bbox)) - { - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - status = _cairo_matrix_compute_basis_scale_factors (&font->base.scale, - &xscale, &yscale, 1); - if (status) - return status; - - textMatrix = CGAffineTransformMake (font->base.scale.xx, - -font->base.scale.yx, - -font->base.scale.xy, - font->base.scale.yy, - 0.0f, 0.0f); - glyphRect = CGRectMake (bbox.origin.x / emscale, - bbox.origin.y / emscale, - bbox.size.width / emscale, - bbox.size.height / emscale); - - glyphRect = CGRectApplyAffineTransform (glyphRect, textMatrix); - - /* Round the rectangle outwards, so that we don't have to deal - * with non-integer-pixel origins or dimensions. - */ - glyphRectInt = CGRectIntegral (glyphRect); - -#if 0 - fprintf (stderr, "glyphRect[o]: %f %f %f %f\n", - glyphRect.origin.x, glyphRect.origin.y, glyphRect.size.width, glyphRect.size.height); - fprintf (stderr, "glyphRectInt: %f %f %f %f\n", - glyphRectInt.origin.x, glyphRectInt.origin.y, glyphRectInt.size.width, glyphRectInt.size.height); -#endif - - glyphOrigin = glyphRectInt.origin; - - //textMatrix = CGAffineTransformConcat (textMatrix, CGAffineTransformInvert (ctm)); - - width = glyphRectInt.size.width; - height = glyphRectInt.size.height; - - //fprintf (stderr, "glyphRect[n]: %f %f %f %f\n", glyphRect.origin.x, glyphRect.origin.y, glyphRect.size.width, glyphRect.size.height); - - surface = (cairo_image_surface_t*) cairo_image_surface_create (CAIRO_FORMAT_A8, width, height); - if (surface->base.status) - return surface->base.status; - - gray = CGColorSpaceCreateDeviceGray (); - cgContext = CGBitmapContextCreate (surface->data, - surface->width, - surface->height, - 8, - surface->stride, - gray, - kCGImageAlphaNone); - CGColorSpaceRelease (gray); - - CGContextSetFont (cgContext, font_face->cgFont); - CGContextSetFontSize (cgContext, 1.0); - CGContextSetTextMatrix (cgContext, textMatrix); - - CGContextClearRect (cgContext, CGRectMake (0.0f, 0.0f, width, height)); - - if (font->base.options.antialias == CAIRO_ANTIALIAS_NONE) - CGContextSetShouldAntialias (cgContext, false); - - CGContextSetRGBFillColor (cgContext, 1.0, 1.0, 1.0, 1.0); - CGContextShowGlyphsAtPoint (cgContext, - glyphOrigin.x, - glyphOrigin.y, &glyph, 1); - - CGContextRelease (cgContext); - - cairo_surface_set_device_offset (&surface->base, - - glyphOrigin.x, - height + glyphOrigin.y); - - _cairo_scaled_glyph_set_surface (scaled_glyph, &font->base, surface); - - return status; -} - -static cairo_int_status_t -_cairo_quartz_font_scaled_glyph_init (void *abstract_font, - cairo_scaled_glyph_t *scaled_glyph, - cairo_scaled_glyph_info_t info) -{ - cairo_quartz_scaled_font_t *font = (cairo_quartz_scaled_font_t *) abstract_font; - cairo_int_status_t status = CAIRO_STATUS_SUCCESS; - - if (!status && (info & CAIRO_SCALED_GLYPH_INFO_METRICS)) - status = _cairo_quartz_init_glyph_metrics (font, scaled_glyph); - - if (!status && (info & CAIRO_SCALED_GLYPH_INFO_PATH)) - status = _cairo_quartz_init_glyph_path (font, scaled_glyph); - - if (!status && (info & CAIRO_SCALED_GLYPH_INFO_SURFACE)) - status = _cairo_quartz_init_glyph_surface (font, scaled_glyph); - - return status; -} - -static unsigned long -_cairo_quartz_ucs4_to_index (void *abstract_font, - uint32_t ucs4) -{ - cairo_quartz_scaled_font_t *font = (cairo_quartz_scaled_font_t*) abstract_font; - cairo_quartz_font_face_t *ffont = _cairo_quartz_scaled_to_face(font); - UniChar u = (UniChar) ucs4; - CGGlyph glyph; - - CGFontGetGlyphsForUnicharsPtr (ffont->cgFont, &u, &glyph, 1); - - return glyph; -} - -const cairo_scaled_font_backend_t _cairo_quartz_scaled_font_backend = { - CAIRO_FONT_TYPE_QUARTZ, - _cairo_quartz_font_get_implementation, - _cairo_quartz_font_create_toy, - _cairo_quartz_font_fini, - _cairo_quartz_font_scaled_glyph_init, - NULL, /* text_to_glyphs */ - _cairo_quartz_ucs4_to_index, - NULL, /* show_glyphs */ - NULL, /* load_truetype_table */ - NULL, /* map_glyphs_to_unicode */ -}; - -/* - * private methods that the quartz surface uses - */ - -CGFontRef -_cairo_quartz_scaled_font_get_cg_font_ref (cairo_scaled_font_t *abstract_font) -{ - cairo_quartz_font_face_t *ffont = _cairo_quartz_scaled_to_face(abstract_font); - - return ffont->cgFont; -} - - -/* - * compat with old ATSUI backend - */ - -/** - * cairo_quartz_font_face_create_for_atsu_font_id - * @font_id: an ATSUFontID for the font. - * - * Creates a new font for the Quartz font backend based on an - * #ATSUFontID. This font can then be used with - * cairo_set_font_face() or cairo_scaled_font_create(). - * - * Return value: a newly created #cairo_font_face_t. Free with - * cairo_font_face_destroy() when you are done using it. - * - * Since: 1.6 - **/ -cairo_font_face_t * -cairo_quartz_font_face_create_for_atsu_font_id (ATSUFontID font_id) -{ - ATSFontRef atsFont = FMGetATSFontRefFromFont (font_id); - CGFontRef cgFont = CGFontCreateWithPlatformFont (&atsFont); - cairo_font_face_t *ff; - - ff = cairo_quartz_font_face_create_for_cgfont (cgFont); - - CGFontRelease (cgFont); - - return ff; -} - -/* This is the old name for the above function, exported for compat purposes */ -cairo_font_face_t *cairo_atsui_font_face_create_for_atsu_font_id (ATSUFontID font_id); - -cairo_font_face_t * -cairo_atsui_font_face_create_for_atsu_font_id (ATSUFontID font_id) -{ - return cairo_quartz_font_face_create_for_atsu_font_id (font_id); -} diff --git a/uppdev/plugin/cairo/lib/cairo-quartz-image-surface.c b/uppdev/plugin/cairo/lib/cairo-quartz-image-surface.c deleted file mode 100644 index 3eee2c112..000000000 --- a/uppdev/plugin/cairo/lib/cairo-quartz-image-surface.c +++ /dev/null @@ -1,286 +0,0 @@ -/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */ -/* cairo - a vector graphics library with display and print output - * - * Copyright � 2008 Mozilla Corporation - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Mozilla Corporation. - * - * Contributor(s): - * Vladimir Vukicevic - */ - -#include "cairoint.h" - -#include "cairo-quartz-image.h" -#include "cairo-quartz-private.h" - -#define SURFACE_ERROR_NO_MEMORY (_cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_NO_MEMORY))) -#define SURFACE_ERROR_TYPE_MISMATCH (_cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_SURFACE_TYPE_MISMATCH))) -#define SURFACE_ERROR_INVALID_FORMAT (_cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_INVALID_FORMAT))) - -static void -DataProviderReleaseCallback (void *info, const void *data, size_t size) -{ - cairo_surface_t *surface = (cairo_surface_t *) info; - cairo_surface_destroy (surface); -} - -static cairo_surface_t * -_cairo_quartz_image_surface_create_similar (void *asurface, - cairo_content_t content, - int width, - int height) -{ - cairo_surface_t *result; - cairo_surface_t *isurf = cairo_image_surface_create (_cairo_format_from_content (content), - width, - height); - if (cairo_surface_status(isurf)) - return isurf; - - result = cairo_quartz_image_surface_create (isurf); - cairo_surface_destroy (isurf); - - return result; -} - -static cairo_status_t -_cairo_quartz_image_surface_finish (void *asurface) -{ - cairo_quartz_image_surface_t *surface = (cairo_quartz_image_surface_t *) asurface; - - /* the imageSurface will be destroyed by the data provider's release callback */ - CGImageRelease (surface->image); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_quartz_image_surface_acquire_source_image (void *asurface, - cairo_image_surface_t **image_out, - void **image_extra) -{ - cairo_quartz_image_surface_t *surface = (cairo_quartz_image_surface_t *) asurface; - - *image_out = surface->imageSurface; - *image_extra = NULL; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_quartz_image_surface_acquire_dest_image (void *asurface, - cairo_rectangle_int_t *interest_rect, - cairo_image_surface_t **image_out, - cairo_rectangle_int_t *image_rect, - void **image_extra) -{ - cairo_quartz_image_surface_t *surface = (cairo_quartz_image_surface_t *) asurface; - - *image_out = surface->imageSurface; - *image_rect = surface->extents; - *image_extra = NULL; - - return CAIRO_STATUS_SUCCESS; - -} - -static cairo_int_status_t -_cairo_quartz_image_surface_get_extents (void *asurface, - cairo_rectangle_int_t *extents) -{ - cairo_quartz_image_surface_t *surface = (cairo_quartz_image_surface_t *) asurface; - - *extents = surface->extents; - - return CAIRO_STATUS_SUCCESS; -} - -/* we assume some drawing happened to the image buffer; make sure it's - * represented in the CGImage on flush() - */ - -static cairo_status_t -_cairo_quartz_image_surface_flush (void *asurface) -{ - cairo_quartz_image_surface_t *surface = (cairo_quartz_image_surface_t *) asurface; - CGImageRef oldImage = surface->image; - CGImageRef newImage = NULL; - - /* To be released by the ReleaseCallback */ - cairo_surface_reference ((cairo_surface_t*) surface->imageSurface); - - newImage = _cairo_quartz_create_cgimage (surface->imageSurface->format, - surface->imageSurface->width, - surface->imageSurface->height, - surface->imageSurface->stride, - surface->imageSurface->data, - TRUE, - NULL, - DataProviderReleaseCallback, - surface->imageSurface); - - surface->image = newImage; - CGImageRelease (oldImage); - - return CAIRO_STATUS_SUCCESS; -} - -static const cairo_surface_backend_t cairo_quartz_image_surface_backend = { - CAIRO_SURFACE_TYPE_QUARTZ_IMAGE, - _cairo_quartz_image_surface_create_similar, - _cairo_quartz_image_surface_finish, - _cairo_quartz_image_surface_acquire_source_image, - NULL, /* release_source_image */ - _cairo_quartz_image_surface_acquire_dest_image, - NULL, /* release_dest_image */ - NULL, /* clone_similar */ - NULL, /* composite */ - NULL, /* fill_rectangles */ - NULL, /* composite_trapezoids */ - NULL, /* copy_page */ - NULL, /* show_page */ - NULL, /* set_clip_region */ - NULL, /* intersect_clip_path */ - _cairo_quartz_image_surface_get_extents, - NULL, /* old_show_glyphs */ - NULL, /* get_font_options */ - _cairo_quartz_image_surface_flush, - NULL, /* mark_dirty_rectangle */ - NULL, /* scaled_font_fini */ - NULL, /* scaled_glyph_fini */ - - NULL, /* paint */ - NULL, /* mask */ - NULL, /* stroke */ - NULL, /* fill */ - NULL, /* surface_show_glyphs */ - NULL, /* snapshot */ - NULL, /* is_similar */ - NULL, /* reset */ - NULL /* fill_stroke */ - -}; - -/** - * cairo_quartz_image_surface_create - * @surface: a cairo image surface to wrap with a quartz image surface - * - * Creates a Quartz surface backed by a CGImageRef that references the - * given image surface. The resulting surface can be rendered quickly - * when used as a source when rendering to a #cairo_quartz_surface. If - * the data in the image surface is ever updated, cairo_surface_flush() - * must be called on the #cairo_quartz_image_surface to ensure that the - * CGImageRef refers to the updated data. - * - * Return value: the newly created surface. - * - * Since: 1.6 - */ -cairo_surface_t * -cairo_quartz_image_surface_create (cairo_surface_t *surface) -{ - cairo_quartz_image_surface_t *qisurf; - - CGImageRef image; - - cairo_image_surface_t *image_surface; - int width, height, stride; - cairo_format_t format; - unsigned char *data; - - if (cairo_surface_get_type(surface) != CAIRO_SURFACE_TYPE_IMAGE) - return SURFACE_ERROR_TYPE_MISMATCH; - - image_surface = (cairo_image_surface_t*) surface; - width = image_surface->width; - height = image_surface->height; - stride = image_surface->stride; - format = image_surface->format; - data = image_surface->data; - - if (!_cairo_quartz_verify_surface_size(width, height)) - return SURFACE_ERROR_NO_MEMORY; - - if (width == 0 || height == 0) - return SURFACE_ERROR_NO_MEMORY; - - if (format != CAIRO_FORMAT_ARGB32 && format != CAIRO_FORMAT_RGB24) - return SURFACE_ERROR_INVALID_FORMAT; - - qisurf = malloc(sizeof(cairo_quartz_image_surface_t)); - if (qisurf == NULL) - return SURFACE_ERROR_NO_MEMORY; - - memset (qisurf, 0, sizeof(cairo_quartz_image_surface_t)); - - /* In case the create_cgimage fails, this ref will - * be released via the callback (which will be called in - * case of failure.) - */ - cairo_surface_reference (surface); - - image = _cairo_quartz_create_cgimage (format, - width, height, - stride, - data, - TRUE, - NULL, - DataProviderReleaseCallback, - image_surface); - - if (!image) { - free (qisurf); - return SURFACE_ERROR_NO_MEMORY; - } - - _cairo_surface_init (&qisurf->base, - &cairo_quartz_image_surface_backend, - _cairo_content_from_format (format)); - - qisurf->extents.x = qisurf->extents.y = 0; - qisurf->extents.width = width; - qisurf->extents.height = height; - - qisurf->image = image; - qisurf->imageSurface = image_surface; - - return &qisurf->base; -} - - -cairo_surface_t * -cairo_quartz_image_surface_get_image (cairo_surface_t *asurface) -{ - cairo_quartz_image_surface_t *surface = (cairo_quartz_image_surface_t*) asurface; - - if (cairo_surface_get_type(asurface) != CAIRO_SURFACE_TYPE_QUARTZ_IMAGE) - return NULL; - - return (cairo_surface_t*) surface->imageSurface; -} diff --git a/uppdev/plugin/cairo/lib/cairo-quartz-image.h b/uppdev/plugin/cairo/lib/cairo-quartz-image.h deleted file mode 100644 index d6b7b1b57..000000000 --- a/uppdev/plugin/cairo/lib/cairo-quartz-image.h +++ /dev/null @@ -1,59 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2008 Mozilla Corporation - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Mozilla Corporation. - * - * Contributor(s): - * Vladimir Vukicevic - */ - -#ifndef CAIRO_QUARTZ_IMAGE_H -#define CAIRO_QUARTZ_IMAGE_H - -#include "cairo.h" - -#if CAIRO_HAS_QUARTZ_IMAGE_SURFACE - -#include - -CAIRO_BEGIN_DECLS - -cairo_public cairo_surface_t * -cairo_quartz_image_surface_create (cairo_surface_t *image_surface); - -cairo_public cairo_surface_t * -cairo_quartz_image_surface_get_image (cairo_surface_t *surface); - -CAIRO_END_DECLS - -#else /* CAIRO_HAS_QUARTZ_IMAGE_SURFACE */ -# error Cairo was not compiled with support for the quartz-image backend -#endif /* CAIRO_HAS_QUARTZ_IMAGE_SURFACE */ - -#endif /* CAIRO_QUARTZ_IMAGE_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-quartz-private.h b/uppdev/plugin/cairo/lib/cairo-quartz-private.h deleted file mode 100644 index 8ba896874..000000000 --- a/uppdev/plugin/cairo/lib/cairo-quartz-private.h +++ /dev/null @@ -1,104 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2004 Calum Robinson - * Copyright (C) 2006,2007 Mozilla Corporation - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Calum Robinson - * - * Contributor(s): - * Calum Robinson - * Vladimir Vukicevic - */ - -#ifndef CAIRO_QUARTZ_PRIVATE_H -#define CAIRO_QUARTZ_PRIVATE_H - -#include "cairoint.h" - -#if CAIRO_HAS_QUARTZ_SURFACE -#include "cairo-quartz.h" - -typedef struct cairo_quartz_surface { - cairo_surface_t base; - - CGContextRef cgContext; - CGAffineTransform cgContextBaseCTM; - - void *imageData; - cairo_surface_t *imageSurfaceEquiv; - - cairo_rectangle_int_t extents; - - /* These are stored while drawing operations are in place, set up - * by quartz_setup_source() and quartz_finish_source() - */ - CGAffineTransform sourceTransform; - - CGImageRef sourceImage; - cairo_surface_t *sourceImageSurface; - CGRect sourceImageRect; - - CGShadingRef sourceShading; - CGPatternRef sourcePattern; - - CGInterpolationQuality oldInterpolationQuality; -} cairo_quartz_surface_t; - -typedef struct cairo_quartz_image_surface { - cairo_surface_t base; - - cairo_rectangle_int_t extents; - - CGImageRef image; - cairo_image_surface_t *imageSurface; -} cairo_quartz_image_surface_t; - -cairo_bool_t -_cairo_quartz_verify_surface_size(int width, int height); - -CGImageRef -_cairo_quartz_create_cgimage (cairo_format_t format, - unsigned int width, - unsigned int height, - unsigned int stride, - void *data, - cairo_bool_t interpolate, - CGColorSpaceRef colorSpaceOverride, - CGDataProviderReleaseDataCallback releaseCallback, - void *releaseInfo); - -CGFontRef -_cairo_quartz_scaled_font_get_cg_font_ref (cairo_scaled_font_t *sfont); - -#else - -# error Cairo was not compiled with support for the quartz backend - -#endif /* CAIRO_HAS_QUARTZ_SURFACE */ - -#endif /* CAIRO_QUARTZ_PRIVATE_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-quartz-surface.c b/uppdev/plugin/cairo/lib/cairo-quartz-surface.c deleted file mode 100644 index 41fde0be1..000000000 --- a/uppdev/plugin/cairo/lib/cairo-quartz-surface.c +++ /dev/null @@ -1,2752 +0,0 @@ -/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */ -/* cairo - a vector graphics library with display and print output - * - * Copyright � 2006, 2007 Mozilla Corporation - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Mozilla Corporation. - * - * Contributor(s): - * Vladimir Vukicevic - */ - -#include "cairoint.h" - -#include "cairo-quartz-private.h" - -#include - -/* The 10.5 SDK includes a funky new definition of FloatToFixed which - * causes all sorts of breakage; so reset to old-style definition - */ -#ifdef FloatToFixed -#undef FloatToFixed -#define FloatToFixed(a) ((Fixed)((float)(a) * fixed1)) -#endif - -#include - -#undef QUARTZ_DEBUG - -#ifdef QUARTZ_DEBUG -#define ND(_x) fprintf _x -#else -#define ND(_x) do {} while(0) -#endif - -#define IS_EMPTY(s) ((s)->extents.width == 0 || (s)->extents.height == 0) - -/* This method is private, but it exists. Its params are are exposed - * as args to the NS* method, but not as CG. - */ -enum PrivateCGCompositeMode { - kPrivateCGCompositeClear = 0, - kPrivateCGCompositeCopy = 1, - kPrivateCGCompositeSourceOver = 2, - kPrivateCGCompositeSourceIn = 3, - kPrivateCGCompositeSourceOut = 4, - kPrivateCGCompositeSourceAtop = 5, - kPrivateCGCompositeDestinationOver = 6, - kPrivateCGCompositeDestinationIn = 7, - kPrivateCGCompositeDestinationOut = 8, - kPrivateCGCompositeDestinationAtop = 9, - kPrivateCGCompositeXOR = 10, - kPrivateCGCompositePlusDarker = 11, // (max (0, (1-d) + (1-s))) - kPrivateCGCompositePlusLighter = 12, // (min (1, s + d)) -}; -typedef enum PrivateCGCompositeMode PrivateCGCompositeMode; -CG_EXTERN void CGContextSetCompositeOperation (CGContextRef, PrivateCGCompositeMode); -CG_EXTERN void CGContextResetCTM (CGContextRef); -CG_EXTERN void CGContextSetCTM (CGContextRef, CGAffineTransform); -CG_EXTERN void CGContextResetClip (CGContextRef); -CG_EXTERN CGSize CGContextGetPatternPhase (CGContextRef); - -/* We need to work with the 10.3 SDK as well (and 10.3 machines; luckily, 10.3.9 - * has all the stuff we care about, just some of it isn't exported in the SDK. - */ -#ifndef kCGBitmapByteOrder32Host -#define USE_10_3_WORKAROUNDS -#define kCGBitmapAlphaInfoMask 0x1F -#define kCGBitmapByteOrderMask 0x7000 -#define kCGBitmapByteOrder32Host 0 - -typedef uint32_t CGBitmapInfo; - -/* public in 10.4, present in 10.3.9 */ -CG_EXTERN void CGContextReplacePathWithStrokedPath (CGContextRef); -CG_EXTERN CGImageRef CGBitmapContextCreateImage (CGContextRef); -#endif - -/* Some of these are present in earlier versions of the OS than where - * they are public; others are not public at all (CGContextCopyPath, - * CGContextReplacePathWithClipPath, many of the getters, etc.) - */ -static void (*CGContextClipToMaskPtr) (CGContextRef, CGRect, CGImageRef) = NULL; -static void (*CGContextDrawTiledImagePtr) (CGContextRef, CGRect, CGImageRef) = NULL; -static unsigned int (*CGContextGetTypePtr) (CGContextRef) = NULL; -static void (*CGContextSetShouldAntialiasFontsPtr) (CGContextRef, bool) = NULL; -static bool (*CGContextGetShouldAntialiasFontsPtr) (CGContextRef) = NULL; -static bool (*CGContextGetShouldSmoothFontsPtr) (CGContextRef) = NULL; -static void (*CGContextSetAllowsFontSmoothingPtr) (CGContextRef, bool) = NULL; -static bool (*CGContextGetAllowsFontSmoothingPtr) (CGContextRef) = NULL; -static CGPathRef (*CGContextCopyPathPtr) (CGContextRef) = NULL; -static void (*CGContextReplacePathWithClipPathPtr) (CGContextRef) = NULL; - -static SInt32 _cairo_quartz_osx_version = 0x0; - -static cairo_bool_t _cairo_quartz_symbol_lookup_done = FALSE; - -/* - * Utility functions - */ - -#ifdef QUARTZ_DEBUG -static void quartz_surface_to_png (cairo_quartz_surface_t *nq, char *dest); -static void quartz_image_to_png (CGImageRef, char *dest); -#endif - -static cairo_quartz_surface_t * -_cairo_quartz_surface_create_internal (CGContextRef cgContext, - cairo_content_t content, - unsigned int width, - unsigned int height); - -/* Load all extra symbols */ -static void quartz_ensure_symbols(void) -{ - if (_cairo_quartz_symbol_lookup_done) - return; - - CGContextClipToMaskPtr = dlsym(RTLD_DEFAULT, "CGContextClipToMask"); - CGContextDrawTiledImagePtr = dlsym(RTLD_DEFAULT, "CGContextDrawTiledImage"); - CGContextGetTypePtr = dlsym(RTLD_DEFAULT, "CGContextGetType"); - CGContextSetShouldAntialiasFontsPtr = dlsym(RTLD_DEFAULT, "CGContextSetShouldAntialiasFonts"); - CGContextGetShouldAntialiasFontsPtr = dlsym(RTLD_DEFAULT, "CGContextGetShouldAntialiasFonts"); - CGContextGetShouldSmoothFontsPtr = dlsym(RTLD_DEFAULT, "CGContextGetShouldSmoothFonts"); - CGContextCopyPathPtr = dlsym(RTLD_DEFAULT, "CGContextCopyPath"); - CGContextReplacePathWithClipPathPtr = dlsym(RTLD_DEFAULT, "CGContextReplacePathWithClipPath"); - CGContextGetAllowsFontSmoothingPtr = dlsym(RTLD_DEFAULT, "CGContextGetAllowsFontSmoothing"); - CGContextSetAllowsFontSmoothingPtr = dlsym(RTLD_DEFAULT, "CGContextSetAllowsFontSmoothing"); - - if (Gestalt(gestaltSystemVersion, &_cairo_quartz_osx_version) != noErr) { - // assume 10.4 - _cairo_quartz_osx_version = 0x1040; - } - - _cairo_quartz_symbol_lookup_done = TRUE; -} - -CGImageRef -_cairo_quartz_create_cgimage (cairo_format_t format, - unsigned int width, - unsigned int height, - unsigned int stride, - void *data, - cairo_bool_t interpolate, - CGColorSpaceRef colorSpaceOverride, - CGDataProviderReleaseDataCallback releaseCallback, - void *releaseInfo) -{ - CGImageRef image = NULL; - CGDataProviderRef dataProvider = NULL; - CGColorSpaceRef colorSpace = colorSpaceOverride; - CGBitmapInfo bitinfo; - int bitsPerComponent, bitsPerPixel; - - switch (format) { - case CAIRO_FORMAT_ARGB32: - if (colorSpace == NULL) - colorSpace = CGColorSpaceCreateDeviceRGB(); - bitinfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host; - bitsPerComponent = 8; - bitsPerPixel = 32; - break; - - case CAIRO_FORMAT_RGB24: - if (colorSpace == NULL) - colorSpace = CGColorSpaceCreateDeviceRGB(); - bitinfo = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host; - bitsPerComponent = 8; - bitsPerPixel = 32; - break; - - /* XXX -- should use CGImageMaskCreate! */ - case CAIRO_FORMAT_A8: - if (colorSpace == NULL) - colorSpace = CGColorSpaceCreateDeviceGray(); - bitinfo = kCGImageAlphaNone; - bitsPerComponent = 8; - bitsPerPixel = 8; - break; - - case CAIRO_FORMAT_A1: - default: - return NULL; - } - - dataProvider = CGDataProviderCreateWithData (releaseInfo, - data, - height * stride, - releaseCallback); - - if (!dataProvider) { - // manually release - if (releaseCallback) - releaseCallback (releaseInfo, data, height * stride); - goto FINISH; - } - - image = CGImageCreate (width, height, - bitsPerComponent, - bitsPerPixel, - stride, - colorSpace, - bitinfo, - dataProvider, - NULL, - interpolate, - kCGRenderingIntentDefault); - -FINISH: - - CGDataProviderRelease (dataProvider); - - if (colorSpace != colorSpaceOverride) - CGColorSpaceRelease (colorSpace); - - return image; -} - -static inline cairo_bool_t -_cairo_quartz_is_cgcontext_bitmap_context (CGContextRef cgc) { - if (cgc == NULL) - return FALSE; - - if (CGContextGetTypePtr) { - /* 4 is the type value of a bitmap context */ - if (CGContextGetTypePtr(cgc) == 4) - return TRUE; - return FALSE; - } - - /* This will cause a (harmless) warning to be printed if called on a non-bitmap context */ - return CGBitmapContextGetBitsPerPixel(cgc) != 0; -} - -/* CoreGraphics limitation with flipped CTM surfaces: height must be less than signed 16-bit max */ - -#define CG_MAX_HEIGHT SHRT_MAX -#define CG_MAX_WIDTH USHRT_MAX - -/* is the desired size of the surface within bounds? */ -cairo_bool_t -_cairo_quartz_verify_surface_size(int width, int height) -{ - /* hmmm, allow width, height == 0 ? */ - if (width < 0 || height < 0) { - return FALSE; - } - - if (width > CG_MAX_WIDTH || height > CG_MAX_HEIGHT) { - return FALSE; - } - - return TRUE; -} - -/* - * Cairo path -> Quartz path conversion helpers - */ - -typedef struct _quartz_stroke { - CGContextRef cgContext; - cairo_matrix_t *ctm_inverse; -} quartz_stroke_t; - -/* cairo path -> execute in context */ -static cairo_status_t -_cairo_path_to_quartz_context_move_to (void *closure, cairo_point_t *point) -{ - //ND((stderr, "moveto: %f %f\n", _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y))); - quartz_stroke_t *stroke = (quartz_stroke_t *)closure; - double x = _cairo_fixed_to_double (point->x); - double y = _cairo_fixed_to_double (point->y); - - if (stroke->ctm_inverse) - cairo_matrix_transform_point (stroke->ctm_inverse, &x, &y); - - CGContextMoveToPoint (stroke->cgContext, x, y); - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_path_to_quartz_context_line_to (void *closure, cairo_point_t *point) -{ - //ND((stderr, "lineto: %f %f\n", _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y))); - quartz_stroke_t *stroke = (quartz_stroke_t *)closure; - double x = _cairo_fixed_to_double (point->x); - double y = _cairo_fixed_to_double (point->y); - - if (stroke->ctm_inverse) - cairo_matrix_transform_point (stroke->ctm_inverse, &x, &y); - - if (CGContextIsPathEmpty (stroke->cgContext)) - CGContextMoveToPoint (stroke->cgContext, x, y); - else - CGContextAddLineToPoint (stroke->cgContext, x, y); - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_path_to_quartz_context_curve_to (void *closure, cairo_point_t *p0, cairo_point_t *p1, cairo_point_t *p2) -{ - //ND( (stderr, "curveto: %f,%f %f,%f %f,%f\n", - // _cairo_fixed_to_double(p0->x), _cairo_fixed_to_double(p0->y), - // _cairo_fixed_to_double(p1->x), _cairo_fixed_to_double(p1->y), - // _cairo_fixed_to_double(p2->x), _cairo_fixed_to_double(p2->y))); - quartz_stroke_t *stroke = (quartz_stroke_t *)closure; - double x0 = _cairo_fixed_to_double (p0->x); - double y0 = _cairo_fixed_to_double (p0->y); - double x1 = _cairo_fixed_to_double (p1->x); - double y1 = _cairo_fixed_to_double (p1->y); - double x2 = _cairo_fixed_to_double (p2->x); - double y2 = _cairo_fixed_to_double (p2->y); - - if (stroke->ctm_inverse) { - cairo_matrix_transform_point (stroke->ctm_inverse, &x0, &y0); - cairo_matrix_transform_point (stroke->ctm_inverse, &x1, &y1); - cairo_matrix_transform_point (stroke->ctm_inverse, &x2, &y2); - } - - CGContextAddCurveToPoint (stroke->cgContext, - x0, y0, x1, y1, x2, y2); - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_path_to_quartz_context_close_path (void *closure) -{ - //ND((stderr, "closepath\n")); - quartz_stroke_t *stroke = (quartz_stroke_t *)closure; - CGContextClosePath (stroke->cgContext); - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_quartz_cairo_path_to_quartz_context (cairo_path_fixed_t *path, - quartz_stroke_t *stroke) -{ - return _cairo_path_fixed_interpret (path, - CAIRO_DIRECTION_FORWARD, - _cairo_path_to_quartz_context_move_to, - _cairo_path_to_quartz_context_line_to, - _cairo_path_to_quartz_context_curve_to, - _cairo_path_to_quartz_context_close_path, - stroke); -} - -/* - * Misc helpers/callbacks - */ - -static PrivateCGCompositeMode -_cairo_quartz_cairo_operator_to_quartz (cairo_operator_t op) -{ - switch (op) { - case CAIRO_OPERATOR_CLEAR: - return kPrivateCGCompositeClear; - case CAIRO_OPERATOR_SOURCE: - return kPrivateCGCompositeCopy; - case CAIRO_OPERATOR_OVER: - return kPrivateCGCompositeSourceOver; - case CAIRO_OPERATOR_IN: - /* XXX This doesn't match image output */ - return kPrivateCGCompositeSourceIn; - case CAIRO_OPERATOR_OUT: - /* XXX This doesn't match image output */ - return kPrivateCGCompositeSourceOut; - case CAIRO_OPERATOR_ATOP: - return kPrivateCGCompositeSourceAtop; - - case CAIRO_OPERATOR_DEST: - /* XXX this is handled specially (noop)! */ - return kPrivateCGCompositeCopy; - case CAIRO_OPERATOR_DEST_OVER: - return kPrivateCGCompositeDestinationOver; - case CAIRO_OPERATOR_DEST_IN: - /* XXX This doesn't match image output */ - return kPrivateCGCompositeDestinationIn; - case CAIRO_OPERATOR_DEST_OUT: - return kPrivateCGCompositeDestinationOut; - case CAIRO_OPERATOR_DEST_ATOP: - /* XXX This doesn't match image output */ - return kPrivateCGCompositeDestinationAtop; - - case CAIRO_OPERATOR_XOR: - return kPrivateCGCompositeXOR; /* This will generate strange results */ - case CAIRO_OPERATOR_ADD: - return kPrivateCGCompositePlusLighter; - case CAIRO_OPERATOR_SATURATE: - /* XXX This doesn't match image output for SATURATE; there's no equivalent */ - return kPrivateCGCompositePlusDarker; /* ??? */ - } - - - return kPrivateCGCompositeCopy; -} - -static inline CGLineCap -_cairo_quartz_cairo_line_cap_to_quartz (cairo_line_cap_t ccap) -{ - switch (ccap) { - case CAIRO_LINE_CAP_BUTT: return kCGLineCapButt; break; - case CAIRO_LINE_CAP_ROUND: return kCGLineCapRound; break; - case CAIRO_LINE_CAP_SQUARE: return kCGLineCapSquare; break; - } - - return kCGLineCapButt; -} - -static inline CGLineJoin -_cairo_quartz_cairo_line_join_to_quartz (cairo_line_join_t cjoin) -{ - switch (cjoin) { - case CAIRO_LINE_JOIN_MITER: return kCGLineJoinMiter; break; - case CAIRO_LINE_JOIN_ROUND: return kCGLineJoinRound; break; - case CAIRO_LINE_JOIN_BEVEL: return kCGLineJoinBevel; break; - } - - return kCGLineJoinMiter; -} - -static inline CGInterpolationQuality -_cairo_quartz_filter_to_quartz (cairo_filter_t filter) -{ - switch (filter) { - case CAIRO_FILTER_NEAREST: - return kCGInterpolationNone; - - case CAIRO_FILTER_FAST: - return kCGInterpolationLow; - - case CAIRO_FILTER_BEST: - case CAIRO_FILTER_GOOD: - case CAIRO_FILTER_BILINEAR: - case CAIRO_FILTER_GAUSSIAN: - return kCGInterpolationDefault; - } - - return kCGInterpolationDefault; -} - -static inline void -_cairo_quartz_cairo_matrix_to_quartz (const cairo_matrix_t *src, - CGAffineTransform *dst) -{ - dst->a = src->xx; - dst->b = src->yx; - dst->c = src->xy; - dst->d = src->yy; - dst->tx = src->x0; - dst->ty = src->y0; -} - -typedef struct { - bool isClipping; - CGGlyph *cg_glyphs; - CGSize *cg_advances; - size_t nglyphs; - CGAffineTransform textTransform; - CGFontRef font; - CGPoint origin; -} unbounded_show_glyphs_t; - -typedef struct { - CGPathRef cgPath; - cairo_fill_rule_t fill_rule; -} unbounded_stroke_fill_t; - -typedef struct { - CGImageRef mask; - CGAffineTransform maskTransform; -} unbounded_mask_t; - -typedef enum { - UNBOUNDED_STROKE_FILL, - UNBOUNDED_SHOW_GLYPHS, - UNBOUNDED_MASK -} unbounded_op_t; - -typedef struct { - unbounded_op_t op; - union { - unbounded_stroke_fill_t stroke_fill; - unbounded_show_glyphs_t show_glyphs; - unbounded_mask_t mask; - } u; -} unbounded_op_data_t; - -static void -_cairo_quartz_fixup_unbounded_operation (cairo_quartz_surface_t *surface, - unbounded_op_data_t *op, - cairo_antialias_t antialias) -{ - CGColorSpaceRef gray; - CGRect clipBox, clipBoxRound; - CGContextRef cgc; - CGImageRef maskImage; - - if (!CGContextClipToMaskPtr) - return; - - clipBox = CGContextGetClipBoundingBox (surface->cgContext); - clipBoxRound = CGRectIntegral (clipBox); - - gray = CGColorSpaceCreateDeviceGray (); - cgc = CGBitmapContextCreate (NULL, - clipBoxRound.size.width, - clipBoxRound.size.height, - 8, - clipBoxRound.size.width, - gray, - kCGImageAlphaNone); - CGColorSpaceRelease (gray); - - if (!cgc) - return; - - /* We want to mask out whatever we just rendered, so we fill the - * surface with white, and then we'll render with black. - */ - CGContextSetRGBFillColor (cgc, 1.0f, 1.0f, 1.0f, 1.0f); - CGContextFillRect (cgc, CGRectMake (0, 0, clipBoxRound.size.width, clipBoxRound.size.height)); - - CGContextSetRGBFillColor (cgc, 0.0f, 0.0f, 0.0f, 1.0f); - CGContextSetShouldAntialias (cgc, (antialias != CAIRO_ANTIALIAS_NONE)); - - CGContextTranslateCTM (cgc, -clipBoxRound.origin.x, -clipBoxRound.origin.y); - - /* We need to either render the path that was given to us, or the glyph op */ - if (op->op == UNBOUNDED_STROKE_FILL) { - CGContextBeginPath (cgc); - CGContextAddPath (cgc, op->u.stroke_fill.cgPath); - - if (op->u.stroke_fill.fill_rule == CAIRO_FILL_RULE_WINDING) - CGContextFillPath (cgc); - else - CGContextEOFillPath (cgc); - } else if (op->op == UNBOUNDED_SHOW_GLYPHS) { - CGContextSetFont (cgc, op->u.show_glyphs.font); - CGContextSetFontSize (cgc, 1.0); - CGContextSetTextMatrix (cgc, op->u.show_glyphs.textTransform); - CGContextTranslateCTM (cgc, op->u.show_glyphs.origin.x, op->u.show_glyphs.origin.y); - - if (op->u.show_glyphs.isClipping) { - /* Note that the comment in show_glyphs about kCGTextClip - * and the text transform still applies here; however, the - * cg_advances we have were already transformed, so we - * don't have to do anything. */ - CGContextSetTextDrawingMode (cgc, kCGTextClip); - CGContextSaveGState (cgc); - } - - CGContextShowGlyphsWithAdvances (cgc, - op->u.show_glyphs.cg_glyphs, - op->u.show_glyphs.cg_advances, - op->u.show_glyphs.nglyphs); - - if (op->u.show_glyphs.isClipping) { - CGContextFillRect (cgc, CGRectMake (0.0, 0.0, clipBoxRound.size.width, clipBoxRound.size.height)); - CGContextRestoreGState (cgc); - } - } else if (op->op == UNBOUNDED_MASK) { - CGContextSaveGState (cgc); - CGContextConcatCTM (cgc, op->u.mask.maskTransform); - CGContextClipToMask (cgc, CGRectMake (0.0f, 0.0f, - CGImageGetWidth(op->u.mask.mask), CGImageGetHeight(op->u.mask.mask)), - op->u.mask.mask); - CGContextFillRect (cgc, CGRectMake (0.0, 0.0, clipBoxRound.size.width, clipBoxRound.size.height)); - CGContextRestoreGState (cgc); - } - - /* Also mask out the portion of the clipbox that we rounded out, if any */ - if (!CGRectEqualToRect (clipBox, clipBoxRound)) { - CGContextBeginPath (cgc); - CGContextAddRect (cgc, CGRectMake (0.0, 0.0, clipBoxRound.size.width, clipBoxRound.size.height)); - CGContextAddRect (cgc, CGRectMake (clipBoxRound.origin.x - clipBox.origin.x, - clipBoxRound.origin.y - clipBox.origin.y, - clipBox.size.width, - clipBox.size.height)); - CGContextEOFillPath (cgc); - } - - maskImage = CGBitmapContextCreateImage (cgc); - CGContextRelease (cgc); - - if (!maskImage) - return; - - /* Then render with the mask */ - CGContextSaveGState (surface->cgContext); - - CGContextSetCompositeOperation (surface->cgContext, kPrivateCGCompositeCopy); - CGContextClipToMaskPtr (surface->cgContext, clipBoxRound, maskImage); - CGImageRelease (maskImage); - - /* Finally, clear out the entire clipping region through our mask */ - CGContextClearRect (surface->cgContext, clipBoxRound); - - CGContextRestoreGState (surface->cgContext); -} - -/* - * Source -> Quartz setup and finish functions - */ - -static void -ComputeGradientValue (void *info, const float *in, float *out) -{ - double fdist = *in; - cairo_gradient_pattern_t *grad = (cairo_gradient_pattern_t*) info; - unsigned int i; - - /* Put fdist back in the 0.0..1.0 range if we're doing - * REPEAT/REFLECT - */ - if (grad->base.extend == CAIRO_EXTEND_REPEAT) { - fdist = fdist - floor(fdist); - } else if (grad->base.extend == CAIRO_EXTEND_REFLECT) { - fdist = fmod(fabs(fdist), 2.0); - if (fdist > 1.0) { - fdist = 2.0 - fdist; - } - } - - for (i = 0; i < grad->n_stops; i++) { - if (grad->stops[i].offset > fdist) - break; - } - - if (i == 0 || i == grad->n_stops) { - if (i == grad->n_stops) - --i; - out[0] = grad->stops[i].color.red; - out[1] = grad->stops[i].color.green; - out[2] = grad->stops[i].color.blue; - out[3] = grad->stops[i].color.alpha; - } else { - float ax = grad->stops[i-1].offset; - float bx = grad->stops[i].offset - ax; - float bp = (fdist - ax)/bx; - float ap = 1.0 - bp; - - out[0] = - grad->stops[i-1].color.red * ap + - grad->stops[i].color.red * bp; - out[1] = - grad->stops[i-1].color.green * ap + - grad->stops[i].color.green * bp; - out[2] = - grad->stops[i-1].color.blue * ap + - grad->stops[i].color.blue * bp; - out[3] = - grad->stops[i-1].color.alpha * ap + - grad->stops[i].color.alpha * bp; - } -} - -static CGFunctionRef -CreateGradientFunction (cairo_gradient_pattern_t *gpat) -{ - float input_value_range[2] = { 0.f, 1.f }; - float output_value_ranges[8] = { 0.f, 1.f, 0.f, 1.f, 0.f, 1.f, 0.f, 1.f }; - CGFunctionCallbacks callbacks = { - 0, ComputeGradientValue, (CGFunctionReleaseInfoCallback) cairo_pattern_destroy - }; - - return CGFunctionCreate (gpat, - 1, - input_value_range, - 4, - output_value_ranges, - &callbacks); -} - -static CGFunctionRef -CreateRepeatingGradientFunction (cairo_quartz_surface_t *surface, - cairo_gradient_pattern_t *gpat, - CGPoint *start, CGPoint *end, - CGAffineTransform matrix) -{ - float input_value_range[2]; - float output_value_ranges[8] = { 0.f, 1.f, 0.f, 1.f, 0.f, 1.f, 0.f, 1.f }; - CGFunctionCallbacks callbacks = { - 0, ComputeGradientValue, (CGFunctionReleaseInfoCallback) cairo_pattern_destroy - }; - - CGPoint mstart, mend; - - double dx, dy; - int x_rep_start = 0, x_rep_end = 0; - int y_rep_start = 0, y_rep_end = 0; - - int rep_start, rep_end; - - // figure out how many times we'd need to repeat the gradient pattern - // to cover the whole (transformed) surface area - mstart = CGPointApplyAffineTransform (*start, matrix); - mend = CGPointApplyAffineTransform (*end, matrix); - - dx = fabs (mend.x - mstart.x); - dy = fabs (mend.y - mstart.y); - - if (dx > 1e-6) { - x_rep_start = (int) ceil(MIN(mstart.x, mend.x) / dx); - x_rep_end = (int) ceil((surface->extents.width - MAX(mstart.x, mend.x)) / dx); - - if (mend.x < mstart.x) { - int swap = x_rep_end; - x_rep_end = x_rep_start; - x_rep_start = swap; - } - } - - if (dy > 1e-6) { - y_rep_start = (int) ceil(MIN(mstart.y, mend.y) / dy); - y_rep_end = (int) ceil((surface->extents.width - MAX(mstart.y, mend.y)) / dy); - - if (mend.y < mstart.y) { - int swap = y_rep_end; - y_rep_end = y_rep_start; - y_rep_start = swap; - } - } - - rep_start = MAX(x_rep_start, y_rep_start); - rep_end = MAX(x_rep_end, y_rep_end); - - // extend the line between start and end by rep_start times from the start - // and rep_end times from the end - - dx = end->x - start->x; - dy = end->y - start->y; - - start->x = start->x - dx * rep_start; - start->y = start->y - dy * rep_start; - - end->x = end->x + dx * rep_end; - end->y = end->y + dy * rep_end; - - // set the input range for the function -- the function knows how to - // map values outside of 0.0 .. 1.0 to that range for REPEAT/REFLECT. - input_value_range[0] = 0.0 - 1.0 * rep_start; - input_value_range[1] = 1.0 + 1.0 * rep_end; - - return CGFunctionCreate (gpat, - 1, - input_value_range, - 4, - output_value_ranges, - &callbacks); -} - -/* Obtain a CGImageRef from a #cairo_surface_t * */ - -static void -DataProviderReleaseCallback (void *info, const void *data, size_t size) -{ - cairo_surface_t *surface = (cairo_surface_t *) info; - cairo_surface_destroy (surface); -} - -static cairo_status_t -_cairo_surface_to_cgimage (cairo_surface_t *target, - cairo_surface_t *source, - CGImageRef *image_out) -{ - cairo_status_t status = CAIRO_STATUS_SUCCESS; - cairo_surface_type_t stype = cairo_surface_get_type (source); - cairo_image_surface_t *isurf; - CGImageRef image; - void *image_extra; - - if (stype == CAIRO_SURFACE_TYPE_QUARTZ_IMAGE) { - cairo_quartz_image_surface_t *surface = (cairo_quartz_image_surface_t *) source; - *image_out = CGImageRetain (surface->image); - return CAIRO_STATUS_SUCCESS; - } - - if (stype == CAIRO_SURFACE_TYPE_QUARTZ) { - cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) source; - if (IS_EMPTY(surface)) { - *image_out = NULL; - return CAIRO_STATUS_SUCCESS; - } - - if (_cairo_quartz_is_cgcontext_bitmap_context (surface->cgContext)) { - *image_out = CGBitmapContextCreateImage (surface->cgContext); - if (*image_out) - return CAIRO_STATUS_SUCCESS; - } - } - - if (stype != CAIRO_SURFACE_TYPE_IMAGE) { - status = _cairo_surface_acquire_source_image (source, &isurf, &image_extra); - if (status) - return status; - } else { - isurf = (cairo_image_surface_t *) source; - } - - if (isurf->width == 0 || isurf->height == 0) { - *image_out = NULL; - } else { - cairo_image_surface_t *isurf_snap = NULL; - isurf_snap = (cairo_image_surface_t*) _cairo_surface_snapshot ((cairo_surface_t*) isurf); - if (isurf_snap == NULL) - return CAIRO_STATUS_NO_MEMORY; - - if (isurf_snap->base.type != CAIRO_SURFACE_TYPE_IMAGE) - return CAIRO_STATUS_SURFACE_TYPE_MISMATCH; - - image = _cairo_quartz_create_cgimage (isurf_snap->format, - isurf_snap->width, - isurf_snap->height, - isurf_snap->stride, - isurf_snap->data, - TRUE, - NULL, - DataProviderReleaseCallback, - isurf_snap); - - *image_out = image; - } - - if ((cairo_surface_t*) isurf != source) - _cairo_surface_release_source_image (source, isurf, image_extra); - - return status; -} - -/* Generic #cairo_pattern_t -> CGPattern function */ - -typedef struct { - CGImageRef image; - CGRect imageBounds; - cairo_bool_t do_reflect; -} SurfacePatternDrawInfo; - -static void -SurfacePatternDrawFunc (void *ainfo, CGContextRef context) -{ - SurfacePatternDrawInfo *info = (SurfacePatternDrawInfo*) ainfo; - - CGContextTranslateCTM (context, 0, info->imageBounds.size.height); - CGContextScaleCTM (context, 1, -1); - - CGContextDrawImage (context, info->imageBounds, info->image); - if (info->do_reflect) { - /* draw 3 more copies of the image, flipped. - * DrawImage draws the image according to the current Y-direction into the rectangle given - * (imageBounds); at the time of the first DrawImage above, the origin is at the bottom left - * of the base image position, and the Y axis is extending upwards. - */ - - /* Make the y axis extend downwards, and draw a flipped image below */ - CGContextScaleCTM (context, 1, -1); - CGContextDrawImage (context, info->imageBounds, info->image); - - /* Shift over to the right, and flip vertically (translation is 2x, - * since we'll be flipping and thus rendering the rectangle "backwards" - */ - CGContextTranslateCTM (context, 2 * info->imageBounds.size.width, 0); - CGContextScaleCTM (context, -1, 1); - CGContextDrawImage (context, info->imageBounds, info->image); - - /* Then unflip the Y-axis again, and draw the image above the point. */ - CGContextScaleCTM (context, 1, -1); - CGContextDrawImage (context, info->imageBounds, info->image); - } -} - -static void -SurfacePatternReleaseInfoFunc (void *ainfo) -{ - SurfacePatternDrawInfo *info = (SurfacePatternDrawInfo*) ainfo; - - CGImageRelease (info->image); - free (info); -} - -static cairo_int_status_t -_cairo_quartz_cairo_repeating_surface_pattern_to_quartz (cairo_quartz_surface_t *dest, - cairo_pattern_t *apattern, - CGPatternRef *cgpat) -{ - cairo_surface_pattern_t *spattern; - cairo_surface_t *pat_surf; - cairo_rectangle_int_t extents; - - CGImageRef image; - CGRect pbounds; - CGAffineTransform ptransform, stransform; - CGPatternCallbacks cb = { 0, - SurfacePatternDrawFunc, - SurfacePatternReleaseInfoFunc }; - SurfacePatternDrawInfo *info; - float rw, rh; - cairo_status_t status; - - cairo_matrix_t m; - - /* SURFACE is the only type we'll handle here */ - if (apattern->type != CAIRO_PATTERN_TYPE_SURFACE) - return CAIRO_INT_STATUS_UNSUPPORTED; - - spattern = (cairo_surface_pattern_t *) apattern; - pat_surf = spattern->surface; - - status = _cairo_surface_get_extents (pat_surf, &extents); - if (status) - return status; - - status = _cairo_surface_to_cgimage ((cairo_surface_t*) dest, pat_surf, &image); - if (status != CAIRO_STATUS_SUCCESS) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (image == NULL) - return CAIRO_INT_STATUS_NOTHING_TO_DO; - - info = malloc(sizeof(SurfacePatternDrawInfo)); - if (!info) - return CAIRO_STATUS_NO_MEMORY; - - /* XXX -- if we're printing, we may need to call CGImageCreateCopy to make sure - * that the data will stick around for this image when the printer gets to it. - * Otherwise, the underlying data store may disappear from under us! - * - * _cairo_surface_to_cgimage will copy when it converts non-Quartz surfaces, - * since the Quartz surfaces have a higher chance of sticking around. If the - * source is a quartz image surface, then it's set up to retain a ref to the - * image surface that it's backed by. - */ - info->image = image; - info->imageBounds = CGRectMake (0, 0, extents.width, extents.height); - info->do_reflect = FALSE; - - pbounds.origin.x = 0; - pbounds.origin.y = 0; - - if (spattern->base.extend == CAIRO_EXTEND_REFLECT) { - pbounds.size.width = 2.0 * extents.width; - pbounds.size.height = 2.0 * extents.height; - info->do_reflect = TRUE; - } else { - pbounds.size.width = extents.width; - pbounds.size.height = extents.height; - } - rw = pbounds.size.width; - rh = pbounds.size.height; - - m = spattern->base.matrix; - cairo_matrix_invert(&m); - _cairo_quartz_cairo_matrix_to_quartz (&m, &stransform); - - /* The pattern matrix is relative to the bottom left, again; the - * incoming cairo pattern matrix is relative to the upper left. - * So we take the pattern matrix and the original context matrix, - * which gives us the correct base translation/y flip. - */ - ptransform = CGAffineTransformConcat(stransform, dest->cgContextBaseCTM); - -#ifdef QUARTZ_DEBUG - ND((stderr, " pbounds: %f %f %f %f\n", pbounds.origin.x, pbounds.origin.y, pbounds.size.width, pbounds.size.height)); - ND((stderr, " pattern xform: t: %f %f xx: %f xy: %f yx: %f yy: %f\n", ptransform.tx, ptransform.ty, ptransform.a, ptransform.b, ptransform.c, ptransform.d)); - CGAffineTransform xform = CGContextGetCTM(dest->cgContext); - ND((stderr, " context xform: t: %f %f xx: %f xy: %f yx: %f yy: %f\n", xform.tx, xform.ty, xform.a, xform.b, xform.c, xform.d)); -#endif - - *cgpat = CGPatternCreate (info, - pbounds, - ptransform, - rw, rh, - kCGPatternTilingConstantSpacing, /* kCGPatternTilingNoDistortion, */ - TRUE, - &cb); - - return CAIRO_STATUS_SUCCESS; -} - -typedef enum { - DO_SOLID, - DO_SHADING, - DO_PATTERN, - DO_IMAGE, - DO_UNSUPPORTED, - DO_NOTHING, - DO_TILED_IMAGE -} cairo_quartz_action_t; - -static cairo_quartz_action_t -_cairo_quartz_setup_fallback_source (cairo_quartz_surface_t *surface, - cairo_pattern_t *source) -{ - CGRect clipBox = CGContextGetClipBoundingBox (surface->cgContext); - CGAffineTransform ctm; - double x0, y0, w, h; - - cairo_surface_t *fallback; - cairo_t *fallback_cr; - CGImageRef img; - - cairo_status_t status; - - if (clipBox.size.width == 0.0f || - clipBox.size.height == 0.0f) - return DO_NOTHING; - - // the clipBox is in userspace, so: - ctm = CGContextGetCTM (surface->cgContext); - ctm = CGAffineTransformInvert (ctm); - clipBox = CGRectApplyAffineTransform (clipBox, ctm); - - // get the Y flip right -- the CTM will always have a Y flip in place - clipBox.origin.y = surface->extents.height - (clipBox.origin.y + clipBox.size.height); - - x0 = floor(clipBox.origin.x); - y0 = floor(clipBox.origin.y); - w = ceil(clipBox.origin.x + clipBox.size.width) - x0; - h = ceil(clipBox.origin.y + clipBox.size.height) - y0; - - /* Create a temporary the size of the clip surface, and position - * it so that the device origin coincides with the original surface */ - fallback = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, (int) w, (int) h); - cairo_surface_set_device_offset (fallback, -x0, -y0); - - /* Paint the source onto our temporary */ - fallback_cr = cairo_create (fallback); - cairo_set_operator (fallback_cr, CAIRO_OPERATOR_SOURCE); - cairo_set_source (fallback_cr, source); - cairo_paint (fallback_cr); - cairo_destroy (fallback_cr); - - status = _cairo_surface_to_cgimage ((cairo_surface_t*) surface, fallback, &img); - if (status == CAIRO_STATUS_SUCCESS && img == NULL) - return DO_NOTHING; - if (status) - return DO_UNSUPPORTED; - - surface->sourceImageRect = CGRectMake (0.0, 0.0, w, h); - surface->sourceImage = img; - surface->sourceImageSurface = fallback; - surface->sourceTransform = CGAffineTransformMakeTranslation (x0, y0); - - return DO_IMAGE; -} - -static cairo_quartz_action_t -_cairo_quartz_setup_linear_source (cairo_quartz_surface_t *surface, - cairo_linear_pattern_t *lpat) -{ - cairo_pattern_t *abspat = (cairo_pattern_t *) lpat; - cairo_matrix_t mat; - CGPoint start, end; - CGFunctionRef gradFunc; - CGColorSpaceRef rgb; - bool extend = abspat->extend == CAIRO_EXTEND_PAD; - - if (lpat->base.n_stops == 0) { - CGContextSetRGBStrokeColor (surface->cgContext, 0., 0., 0., 0.); - CGContextSetRGBFillColor (surface->cgContext, 0., 0., 0., 0.); - return DO_SOLID; - } - - cairo_pattern_get_matrix (abspat, &mat); - cairo_matrix_invert (&mat); - _cairo_quartz_cairo_matrix_to_quartz (&mat, &surface->sourceTransform); - - rgb = CGColorSpaceCreateDeviceRGB(); - - start = CGPointMake (_cairo_fixed_to_double (lpat->p1.x), - _cairo_fixed_to_double (lpat->p1.y)); - end = CGPointMake (_cairo_fixed_to_double (lpat->p2.x), - _cairo_fixed_to_double (lpat->p2.y)); - - // ref will be released by the CGShading's destructor - cairo_pattern_reference ((cairo_pattern_t*) lpat); - - if (abspat->extend == CAIRO_EXTEND_NONE || - abspat->extend == CAIRO_EXTEND_PAD) - { - gradFunc = CreateGradientFunction ((cairo_gradient_pattern_t*) lpat); - } else { - gradFunc = CreateRepeatingGradientFunction (surface, - (cairo_gradient_pattern_t*) lpat, - &start, &end, surface->sourceTransform); - } - - surface->sourceShading = CGShadingCreateAxial (rgb, - start, end, - gradFunc, - extend, extend); - - CGColorSpaceRelease(rgb); - CGFunctionRelease(gradFunc); - - return DO_SHADING; -} - -static cairo_quartz_action_t -_cairo_quartz_setup_radial_source (cairo_quartz_surface_t *surface, - cairo_radial_pattern_t *rpat) -{ - cairo_pattern_t *abspat = (cairo_pattern_t *)rpat; - cairo_matrix_t mat; - CGPoint start, end; - CGFunctionRef gradFunc; - CGColorSpaceRef rgb; - bool extend = abspat->extend == CAIRO_EXTEND_PAD; - - if (rpat->base.n_stops == 0) { - CGContextSetRGBStrokeColor (surface->cgContext, 0., 0., 0., 0.); - CGContextSetRGBFillColor (surface->cgContext, 0., 0., 0., 0.); - return DO_SOLID; - } - - if (abspat->extend == CAIRO_EXTEND_REPEAT || - abspat->extend == CAIRO_EXTEND_REFLECT) - { - /* I started trying to map these to Quartz, but it's much harder - * then the linear case (I think it would involve doing multiple - * Radial shadings). So, instead, let's just render an image - * for pixman to draw the shading into, and use that. - */ - return _cairo_quartz_setup_fallback_source (surface, (cairo_pattern_t*) rpat); - } - - cairo_pattern_get_matrix (abspat, &mat); - cairo_matrix_invert (&mat); - _cairo_quartz_cairo_matrix_to_quartz (&mat, &surface->sourceTransform); - - rgb = CGColorSpaceCreateDeviceRGB(); - - start = CGPointMake (_cairo_fixed_to_double (rpat->c1.x), - _cairo_fixed_to_double (rpat->c1.y)); - end = CGPointMake (_cairo_fixed_to_double (rpat->c2.x), - _cairo_fixed_to_double (rpat->c2.y)); - - // ref will be released by the CGShading's destructor - cairo_pattern_reference ((cairo_pattern_t*) rpat); - - gradFunc = CreateGradientFunction ((cairo_gradient_pattern_t*) rpat); - - surface->sourceShading = CGShadingCreateRadial (rgb, - start, - _cairo_fixed_to_double (rpat->r1), - end, - _cairo_fixed_to_double (rpat->r2), - gradFunc, - extend, extend); - - CGColorSpaceRelease(rgb); - CGFunctionRelease(gradFunc); - - return DO_SHADING; -} - -static cairo_quartz_action_t -_cairo_quartz_setup_source (cairo_quartz_surface_t *surface, - cairo_pattern_t *source) -{ - assert (!(surface->sourceImage || surface->sourceShading || surface->sourcePattern)); - - surface->oldInterpolationQuality = CGContextGetInterpolationQuality (surface->cgContext); - CGContextSetInterpolationQuality (surface->cgContext, _cairo_quartz_filter_to_quartz (source->filter)); - - if (source->type == CAIRO_PATTERN_TYPE_SOLID) { - cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) source; - - CGContextSetRGBStrokeColor (surface->cgContext, - solid->color.red, - solid->color.green, - solid->color.blue, - solid->color.alpha); - CGContextSetRGBFillColor (surface->cgContext, - solid->color.red, - solid->color.green, - solid->color.blue, - solid->color.alpha); - - return DO_SOLID; - } - - if (source->type == CAIRO_PATTERN_TYPE_LINEAR) { - cairo_linear_pattern_t *lpat = (cairo_linear_pattern_t *)source; - return _cairo_quartz_setup_linear_source (surface, lpat); - - } - - if (source->type == CAIRO_PATTERN_TYPE_RADIAL) { - cairo_radial_pattern_t *rpat = (cairo_radial_pattern_t *)source; - return _cairo_quartz_setup_radial_source (surface, rpat); - - } - - if (source->type == CAIRO_PATTERN_TYPE_SURFACE && - (source->extend == CAIRO_EXTEND_NONE || (CGContextDrawTiledImagePtr && source->extend == CAIRO_EXTEND_REPEAT))) - { - cairo_surface_pattern_t *spat = (cairo_surface_pattern_t *) source; - cairo_surface_t *pat_surf = spat->surface; - CGImageRef img; - cairo_matrix_t m = spat->base.matrix; - cairo_rectangle_int_t extents; - cairo_status_t status; - CGAffineTransform xform; - CGRect srcRect; - cairo_fixed_t fw, fh; - - status = _cairo_surface_to_cgimage ((cairo_surface_t *) surface, pat_surf, &img); - if (status == CAIRO_STATUS_SUCCESS && img == NULL) - return DO_NOTHING; - if (status) - return DO_UNSUPPORTED; - - surface->sourceImage = img; - - cairo_matrix_invert(&m); - _cairo_quartz_cairo_matrix_to_quartz (&m, &surface->sourceTransform); - - status = _cairo_surface_get_extents (pat_surf, &extents); - if (status) - return DO_UNSUPPORTED; - - if (source->extend == CAIRO_EXTEND_NONE) { - surface->sourceImageRect = CGRectMake (0, 0, extents.width, extents.height); - return DO_IMAGE; - } - - /* Quartz seems to tile images at pixel-aligned regions only -- this - * leads to seams if the image doesn't end up scaling to fill the - * space exactly. The CGPattern tiling approach doesn't have this - * problem. Check if we're going to fill up the space (within some - * epsilon), and if not, fall back to the CGPattern type. - */ - - xform = CGAffineTransformConcat (CGContextGetCTM (surface->cgContext), - surface->sourceTransform); - - srcRect = CGRectMake (0, 0, extents.width, extents.height); - srcRect = CGRectApplyAffineTransform (srcRect, xform); - - fw = _cairo_fixed_from_double (srcRect.size.width); - fh = _cairo_fixed_from_double (srcRect.size.height); - - if ((fw & CAIRO_FIXED_FRAC_MASK) <= CAIRO_FIXED_EPSILON && - (fh & CAIRO_FIXED_FRAC_MASK) <= CAIRO_FIXED_EPSILON) - { - /* We're good to use DrawTiledImage, but ensure that - * the math works out */ - - srcRect.size.width = round(srcRect.size.width); - srcRect.size.height = round(srcRect.size.height); - - xform = CGAffineTransformInvert (xform); - - srcRect = CGRectApplyAffineTransform (srcRect, xform); - - surface->sourceImageRect = srcRect; - - return DO_TILED_IMAGE; - } - - /* Fall through to generic SURFACE case */ - } - - if (source->type == CAIRO_PATTERN_TYPE_SURFACE) { - float patternAlpha = 1.0f; - CGColorSpaceRef patternSpace; - CGPatternRef pattern; - cairo_int_status_t status; - - status = _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (surface, source, &pattern); - if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) - return DO_NOTHING; - if (status) - return DO_UNSUPPORTED; - - // Save before we change the pattern, colorspace, etc. so that - // we can restore and make sure that quartz releases our - // pattern (which may be stack allocated) - CGContextSaveGState(surface->cgContext); - - patternSpace = CGColorSpaceCreatePattern(NULL); - CGContextSetFillColorSpace (surface->cgContext, patternSpace); - CGContextSetFillPattern (surface->cgContext, pattern, &patternAlpha); - CGContextSetStrokeColorSpace (surface->cgContext, patternSpace); - CGContextSetStrokePattern (surface->cgContext, pattern, &patternAlpha); - CGColorSpaceRelease (patternSpace); - - /* Quartz likes to munge the pattern phase (as yet unexplained - * why); force it to 0,0 as we've already baked in the correct - * pattern translation into the pattern matrix - */ - CGContextSetPatternPhase (surface->cgContext, CGSizeMake(0,0)); - - surface->sourcePattern = pattern; - - return DO_PATTERN; - } - - return DO_UNSUPPORTED; -} - -static void -_cairo_quartz_teardown_source (cairo_quartz_surface_t *surface, - cairo_pattern_t *source) -{ - CGContextSetInterpolationQuality (surface->cgContext, surface->oldInterpolationQuality); - - if (surface->sourceImage) { - CGImageRelease(surface->sourceImage); - surface->sourceImage = NULL; - - cairo_surface_destroy(surface->sourceImageSurface); - surface->sourceImageSurface = NULL; - } - - if (surface->sourceShading) { - CGShadingRelease(surface->sourceShading); - surface->sourceShading = NULL; - } - - if (surface->sourcePattern) { - CGPatternRelease(surface->sourcePattern); - // To tear down the pattern and colorspace - CGContextRestoreGState(surface->cgContext); - - surface->sourcePattern = NULL; - } -} - -/* - * get source/dest image implementation - */ - -/* Read the image from the surface's front buffer */ -static cairo_int_status_t -_cairo_quartz_get_image (cairo_quartz_surface_t *surface, - cairo_image_surface_t **image_out) -{ - unsigned char *imageData; - cairo_image_surface_t *isurf; - - if (IS_EMPTY(surface)) { - *image_out = (cairo_image_surface_t*) cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 0, 0); - return CAIRO_STATUS_SUCCESS; - } - - if (surface->imageSurfaceEquiv) { - *image_out = (cairo_image_surface_t*) cairo_surface_reference(surface->imageSurfaceEquiv); - return CAIRO_STATUS_SUCCESS; - } - - if (_cairo_quartz_is_cgcontext_bitmap_context(surface->cgContext)) { - unsigned int stride; - unsigned int bitinfo; - unsigned int bpc, bpp; - CGColorSpaceRef colorspace; - unsigned int color_comps; - - imageData = (unsigned char *) CGBitmapContextGetData(surface->cgContext); - -#ifdef USE_10_3_WORKAROUNDS - bitinfo = CGBitmapContextGetAlphaInfo (surface->cgContext); -#else - bitinfo = CGBitmapContextGetBitmapInfo (surface->cgContext); -#endif - stride = CGBitmapContextGetBytesPerRow (surface->cgContext); - bpp = CGBitmapContextGetBitsPerPixel (surface->cgContext); - bpc = CGBitmapContextGetBitsPerComponent (surface->cgContext); - - // let's hope they don't add YUV under us - colorspace = CGBitmapContextGetColorSpace (surface->cgContext); - color_comps = CGColorSpaceGetNumberOfComponents(colorspace); - - // XXX TODO: We can handle all of these by converting to - // pixman masks, including non-native-endian masks - if (bpc != 8) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (bpp != 32 && bpp != 8) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (color_comps != 3 && color_comps != 1) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (bpp == 32 && color_comps == 3 && - (bitinfo & kCGBitmapAlphaInfoMask) == kCGImageAlphaPremultipliedFirst && - (bitinfo & kCGBitmapByteOrderMask) == kCGBitmapByteOrder32Host) - { - isurf = (cairo_image_surface_t *) - cairo_image_surface_create_for_data (imageData, - CAIRO_FORMAT_ARGB32, - surface->extents.width, - surface->extents.height, - stride); - } else if (bpp == 32 && color_comps == 3 && - (bitinfo & kCGBitmapAlphaInfoMask) == kCGImageAlphaNoneSkipFirst && - (bitinfo & kCGBitmapByteOrderMask) == kCGBitmapByteOrder32Host) - { - isurf = (cairo_image_surface_t *) - cairo_image_surface_create_for_data (imageData, - CAIRO_FORMAT_RGB24, - surface->extents.width, - surface->extents.height, - stride); - } else if (bpp == 8 && color_comps == 1) - { - isurf = (cairo_image_surface_t *) - cairo_image_surface_create_for_data (imageData, - CAIRO_FORMAT_A8, - surface->extents.width, - surface->extents.height, - stride); - } else { - return CAIRO_INT_STATUS_UNSUPPORTED; - } - } else { - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - *image_out = isurf; - return CAIRO_STATUS_SUCCESS; -} - -/* - * Cairo surface backend implementations - */ - -static cairo_status_t -_cairo_quartz_surface_finish (void *abstract_surface) -{ - cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface; - - ND((stderr, "_cairo_quartz_surface_finish[%p] cgc: %p\n", surface, surface->cgContext)); - - if (IS_EMPTY(surface)) - return CAIRO_STATUS_SUCCESS; - - /* Restore our saved gstate that we use to reset clipping */ - CGContextRestoreGState (surface->cgContext); - - CGContextRelease (surface->cgContext); - - surface->cgContext = NULL; - - if (surface->imageSurfaceEquiv) { - cairo_surface_destroy (surface->imageSurfaceEquiv); - surface->imageSurfaceEquiv = NULL; - } - - if (surface->imageData) { - free (surface->imageData); - surface->imageData = NULL; - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_quartz_surface_acquire_source_image (void *abstract_surface, - cairo_image_surface_t **image_out, - void **image_extra) -{ - cairo_int_status_t status; - cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface; - - //ND((stderr, "%p _cairo_quartz_surface_acquire_source_image\n", surface)); - - status = _cairo_quartz_get_image (surface, image_out); - if (status) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - *image_extra = NULL; - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_quartz_surface_release_source_image (void *abstract_surface, - cairo_image_surface_t *image, - void *image_extra) -{ - cairo_surface_destroy ((cairo_surface_t *) image); -} - - -static cairo_status_t -_cairo_quartz_surface_acquire_dest_image (void *abstract_surface, - cairo_rectangle_int_t *interest_rect, - cairo_image_surface_t **image_out, - cairo_rectangle_int_t *image_rect, - void **image_extra) -{ - cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface; - cairo_int_status_t status; - - ND((stderr, "%p _cairo_quartz_surface_acquire_dest_image\n", surface)); - - status = _cairo_quartz_get_image (surface, image_out); - if (status) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - *image_rect = surface->extents; - *image_extra = NULL; - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_quartz_surface_release_dest_image (void *abstract_surface, - cairo_rectangle_int_t *interest_rect, - cairo_image_surface_t *image, - cairo_rectangle_int_t *image_rect, - void *image_extra) -{ - //cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface; - - //ND((stderr, "%p _cairo_quartz_surface_release_dest_image\n", surface)); - - cairo_surface_destroy ((cairo_surface_t *) image); -} - -static cairo_surface_t * -_cairo_quartz_surface_create_similar (void *abstract_surface, - cairo_content_t content, - int width, - int height) -{ - /*cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;*/ - - cairo_format_t format; - - if (content == CAIRO_CONTENT_COLOR_ALPHA) - format = CAIRO_FORMAT_ARGB32; - else if (content == CAIRO_CONTENT_COLOR) - format = CAIRO_FORMAT_RGB24; - else if (content == CAIRO_CONTENT_ALPHA) - format = CAIRO_FORMAT_A8; - else - return NULL; - - // verify width and height of surface - if (!_cairo_quartz_verify_surface_size(width, height)) { - return _cairo_surface_create_in_error (_cairo_error - (CAIRO_STATUS_NO_MEMORY)); - } - - return cairo_quartz_surface_create (format, width, height); -} - -static cairo_status_t -_cairo_quartz_surface_clone_similar (void *abstract_surface, - cairo_surface_t *src, - int src_x, - int src_y, - int width, - int height, - int *clone_offset_x, - int *clone_offset_y, - cairo_surface_t **clone_out) -{ - cairo_quartz_surface_t *new_surface = NULL; - cairo_format_t new_format; - CGImageRef quartz_image = NULL; - cairo_status_t status; - - *clone_out = NULL; - - // verify width and height of surface - if (!_cairo_quartz_verify_surface_size(width, height)) { - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - if (width == 0 || height == 0) { - *clone_out = (cairo_surface_t*) - _cairo_quartz_surface_create_internal (NULL, CAIRO_CONTENT_COLOR_ALPHA, - width, height); - *clone_offset_x = 0; - *clone_offset_y = 0; - return CAIRO_STATUS_SUCCESS; - } - - if (src->backend->type == CAIRO_SURFACE_TYPE_QUARTZ) { - cairo_quartz_surface_t *qsurf = (cairo_quartz_surface_t *) src; - - if (IS_EMPTY(qsurf)) { - *clone_out = (cairo_surface_t*) - _cairo_quartz_surface_create_internal (NULL, CAIRO_CONTENT_COLOR_ALPHA, - qsurf->extents.width, qsurf->extents.height); - *clone_offset_x = 0; - *clone_offset_y = 0; - return CAIRO_STATUS_SUCCESS; - } - } - - status = _cairo_surface_to_cgimage ((cairo_surface_t*) abstract_surface, src, &quartz_image); - if (status) - return CAIRO_INT_STATUS_UNSUPPORTED; - - new_format = CAIRO_FORMAT_ARGB32; /* assumed */ - if (_cairo_surface_is_image (src)) { - new_format = ((cairo_image_surface_t *) src)->format; - } - - new_surface = (cairo_quartz_surface_t *) - cairo_quartz_surface_create (new_format, width, height); - - if (quartz_image == NULL) - goto FINISH; - - if (!new_surface || new_surface->base.status) { - CGImageRelease (quartz_image); - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - CGContextSaveGState (new_surface->cgContext); - - CGContextSetCompositeOperation (new_surface->cgContext, - kPrivateCGCompositeCopy); - - CGContextTranslateCTM (new_surface->cgContext, -src_x, -src_y); - CGContextDrawImage (new_surface->cgContext, - CGRectMake (0, 0, CGImageGetWidth(quartz_image), CGImageGetHeight(quartz_image)), - quartz_image); - - CGContextRestoreGState (new_surface->cgContext); - - CGImageRelease (quartz_image); - -FINISH: - *clone_offset_x = src_x; - *clone_offset_y = src_y; - *clone_out = (cairo_surface_t*) new_surface; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_quartz_surface_get_extents (void *abstract_surface, - cairo_rectangle_int_t *extents) -{ - cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface; - - *extents = surface->extents; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_quartz_surface_paint (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source) -{ - cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface; - cairo_int_status_t rv = CAIRO_STATUS_SUCCESS; - cairo_quartz_action_t action; - - ND((stderr, "%p _cairo_quartz_surface_paint op %d source->type %d\n", surface, op, source->type)); - - if (IS_EMPTY(surface)) - return CAIRO_STATUS_SUCCESS; - - if (op == CAIRO_OPERATOR_DEST) - return CAIRO_STATUS_SUCCESS; - - CGContextSetCompositeOperation (surface->cgContext, _cairo_quartz_cairo_operator_to_quartz (op)); - - action = _cairo_quartz_setup_source (surface, source); - - if (action == DO_SOLID || action == DO_PATTERN) { - CGContextFillRect (surface->cgContext, CGRectMake(surface->extents.x, - surface->extents.y, - surface->extents.width, - surface->extents.height)); - } else if (action == DO_SHADING) { - CGContextConcatCTM (surface->cgContext, surface->sourceTransform); - CGContextDrawShading (surface->cgContext, surface->sourceShading); - } else if (action == DO_IMAGE || action == DO_TILED_IMAGE) { - CGContextSaveGState (surface->cgContext); - - CGContextConcatCTM (surface->cgContext, surface->sourceTransform); - CGContextTranslateCTM (surface->cgContext, 0, surface->sourceImageRect.size.height); - CGContextScaleCTM (surface->cgContext, 1, -1); - - if (action == DO_IMAGE) - CGContextDrawImage (surface->cgContext, surface->sourceImageRect, surface->sourceImage); - else - CGContextDrawTiledImagePtr (surface->cgContext, surface->sourceImageRect, surface->sourceImage); - CGContextRestoreGState (surface->cgContext); - } else if (action != DO_NOTHING) { - rv = CAIRO_INT_STATUS_UNSUPPORTED; - } - - _cairo_quartz_teardown_source (surface, source); - - ND((stderr, "-- paint\n")); - return rv; -} - -static cairo_int_status_t -_cairo_quartz_surface_fill (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface; - cairo_int_status_t rv = CAIRO_STATUS_SUCCESS; - cairo_quartz_action_t action; - quartz_stroke_t stroke; - cairo_box_t box; - CGPathRef path_for_unbounded = NULL; - - ND((stderr, "%p _cairo_quartz_surface_fill op %d source->type %d\n", surface, op, source->type)); - - if (IS_EMPTY(surface)) - return CAIRO_STATUS_SUCCESS; - - if (op == CAIRO_OPERATOR_DEST) - return CAIRO_STATUS_SUCCESS; - - /* Check whether the path would be a no-op */ - /* XXX handle unbounded ops */ - if (_cairo_path_fixed_is_empty(path) || - (_cairo_path_fixed_is_box(path, &box) && - box.p1.x == box.p2.x && - box.p1.y == box.p2.y)) - { - return CAIRO_STATUS_SUCCESS; - } - - CGContextSaveGState (surface->cgContext); - - CGContextSetShouldAntialias (surface->cgContext, (antialias != CAIRO_ANTIALIAS_NONE)); - CGContextSetCompositeOperation (surface->cgContext, _cairo_quartz_cairo_operator_to_quartz (op)); - - action = _cairo_quartz_setup_source (surface, source); - - CGContextBeginPath (surface->cgContext); - - stroke.cgContext = surface->cgContext; - stroke.ctm_inverse = NULL; - rv = _cairo_quartz_cairo_path_to_quartz_context (path, &stroke); - if (rv) - goto BAIL; - - if (!_cairo_operator_bounded_by_mask(op) && CGContextCopyPathPtr) - path_for_unbounded = CGContextCopyPathPtr (surface->cgContext); - - if (action == DO_SOLID || action == DO_PATTERN) { - if (fill_rule == CAIRO_FILL_RULE_WINDING) - CGContextFillPath (surface->cgContext); - else - CGContextEOFillPath (surface->cgContext); - } else if (action == DO_SHADING) { - - // we have to clip and then paint the shading; we can't fill - // with the shading - if (fill_rule == CAIRO_FILL_RULE_WINDING) - CGContextClip (surface->cgContext); - else - CGContextEOClip (surface->cgContext); - - CGContextConcatCTM (surface->cgContext, surface->sourceTransform); - CGContextDrawShading (surface->cgContext, surface->sourceShading); - } else if (action == DO_IMAGE || action == DO_TILED_IMAGE) { - if (fill_rule == CAIRO_FILL_RULE_WINDING) - CGContextClip (surface->cgContext); - else - CGContextEOClip (surface->cgContext); - - CGContextConcatCTM (surface->cgContext, surface->sourceTransform); - CGContextTranslateCTM (surface->cgContext, 0, surface->sourceImageRect.size.height); - CGContextScaleCTM (surface->cgContext, 1, -1); - - if (action == DO_IMAGE) - CGContextDrawImage (surface->cgContext, surface->sourceImageRect, surface->sourceImage); - else - CGContextDrawTiledImagePtr (surface->cgContext, surface->sourceImageRect, surface->sourceImage); - } else if (action != DO_NOTHING) { - rv = CAIRO_INT_STATUS_UNSUPPORTED; - } - - BAIL: - _cairo_quartz_teardown_source (surface, source); - - CGContextRestoreGState (surface->cgContext); - - if (path_for_unbounded) { - unbounded_op_data_t ub; - ub.op = UNBOUNDED_STROKE_FILL; - ub.u.stroke_fill.cgPath = path_for_unbounded; - ub.u.stroke_fill.fill_rule = fill_rule; - - _cairo_quartz_fixup_unbounded_operation (surface, &ub, antialias); - CGPathRelease (path_for_unbounded); - } - - ND((stderr, "-- fill\n")); - return rv; -} - -static cairo_int_status_t -_cairo_quartz_surface_stroke (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - 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_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface; - cairo_int_status_t rv = CAIRO_STATUS_SUCCESS; - cairo_quartz_action_t action; - quartz_stroke_t stroke; - CGAffineTransform origCTM, strokeTransform; - CGPathRef path_for_unbounded = NULL; - - ND((stderr, "%p _cairo_quartz_surface_stroke op %d source->type %d\n", surface, op, source->type)); - - if (IS_EMPTY(surface)) - return CAIRO_STATUS_SUCCESS; - - if (op == CAIRO_OPERATOR_DEST) - return CAIRO_STATUS_SUCCESS; - - CGContextSaveGState (surface->cgContext); - - // Turning antialiasing off used to cause misrendering with - // single-pixel lines (e.g. 20,10.5 -> 21,10.5 end up being rendered as 2 pixels). - // That's been since fixed in at least 10.5, and in the latest 10.4 dot releases. - CGContextSetShouldAntialias (surface->cgContext, (antialias != CAIRO_ANTIALIAS_NONE)); - CGContextSetLineWidth (surface->cgContext, style->line_width); - CGContextSetLineCap (surface->cgContext, _cairo_quartz_cairo_line_cap_to_quartz (style->line_cap)); - CGContextSetLineJoin (surface->cgContext, _cairo_quartz_cairo_line_join_to_quartz (style->line_join)); - CGContextSetMiterLimit (surface->cgContext, style->miter_limit); - - origCTM = CGContextGetCTM (surface->cgContext); - - _cairo_quartz_cairo_matrix_to_quartz (ctm, &strokeTransform); - CGContextConcatCTM (surface->cgContext, strokeTransform); - - if (style->dash && style->num_dashes) { -#define STATIC_DASH 32 - float sdash[STATIC_DASH]; - float *fdash = sdash; - unsigned int max_dashes = style->num_dashes; - unsigned int k; - - if (style->num_dashes%2) - max_dashes *= 2; - if (max_dashes > STATIC_DASH) - fdash = _cairo_malloc_ab (max_dashes, sizeof (float)); - if (fdash == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - for (k = 0; k < max_dashes; k++) - fdash[k] = (float) style->dash[k % style->num_dashes]; - - CGContextSetLineDash (surface->cgContext, style->dash_offset, fdash, max_dashes); - if (fdash != sdash) - free (fdash); - } - - CGContextSetCompositeOperation (surface->cgContext, _cairo_quartz_cairo_operator_to_quartz (op)); - - action = _cairo_quartz_setup_source (surface, source); - - CGContextBeginPath (surface->cgContext); - - stroke.cgContext = surface->cgContext; - stroke.ctm_inverse = ctm_inverse; - rv = _cairo_quartz_cairo_path_to_quartz_context (path, &stroke); - if (rv) - goto BAIL; - - if (!_cairo_operator_bounded_by_mask (op) && CGContextCopyPathPtr) - path_for_unbounded = CGContextCopyPathPtr (surface->cgContext); - - if (action == DO_SOLID || action == DO_PATTERN) { - CGContextStrokePath (surface->cgContext); - } else if (action == DO_IMAGE || action == DO_TILED_IMAGE) { - CGContextReplacePathWithStrokedPath (surface->cgContext); - CGContextClip (surface->cgContext); - - CGContextSetCTM (surface->cgContext, origCTM); - - CGContextConcatCTM (surface->cgContext, surface->sourceTransform); - CGContextTranslateCTM (surface->cgContext, 0, surface->sourceImageRect.size.height); - CGContextScaleCTM (surface->cgContext, 1, -1); - - if (action == DO_IMAGE) - CGContextDrawImage (surface->cgContext, surface->sourceImageRect, surface->sourceImage); - else - CGContextDrawTiledImagePtr (surface->cgContext, surface->sourceImageRect, surface->sourceImage); - } else if (action == DO_SHADING) { - CGContextReplacePathWithStrokedPath (surface->cgContext); - CGContextClip (surface->cgContext); - - CGContextSetCTM (surface->cgContext, origCTM); - - CGContextConcatCTM (surface->cgContext, surface->sourceTransform); - CGContextDrawShading (surface->cgContext, surface->sourceShading); - } else if (action != DO_NOTHING) { - rv = CAIRO_INT_STATUS_UNSUPPORTED; - } - - BAIL: - _cairo_quartz_teardown_source (surface, source); - - CGContextRestoreGState (surface->cgContext); - - if (path_for_unbounded) { - unbounded_op_data_t ub; - - CGContextBeginPath (surface->cgContext); - - /* recreate the stroke state, but without the CTM, as it's been already baked - * into the path. - */ - CGContextSetShouldAntialias (surface->cgContext, (antialias != CAIRO_ANTIALIAS_NONE)); - CGContextSetLineWidth (surface->cgContext, style->line_width); - CGContextSetLineCap (surface->cgContext, _cairo_quartz_cairo_line_cap_to_quartz (style->line_cap)); - CGContextSetLineJoin (surface->cgContext, _cairo_quartz_cairo_line_join_to_quartz (style->line_join)); - CGContextSetMiterLimit (surface->cgContext, style->miter_limit); - - CGContextAddPath (surface->cgContext, path_for_unbounded); - CGPathRelease (path_for_unbounded); - - CGContextReplacePathWithStrokedPath (surface->cgContext); - path_for_unbounded = CGContextCopyPathPtr (surface->cgContext); - - ub.op = UNBOUNDED_STROKE_FILL; - ub.u.stroke_fill.cgPath = path_for_unbounded; - ub.u.stroke_fill.fill_rule = CAIRO_FILL_RULE_WINDING; - - _cairo_quartz_fixup_unbounded_operation (surface, &ub, antialias); - - CGPathRelease (path_for_unbounded); - } - - ND((stderr, "-- stroke\n")); - return rv; -} - -#if CAIRO_HAS_QUARTZ_FONT -static cairo_int_status_t -_cairo_quartz_surface_show_glyphs (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font, - int *remaining_glyphs) -{ - CGAffineTransform textTransform, ctm; -#define STATIC_BUF_SIZE 64 - CGGlyph glyphs_static[STATIC_BUF_SIZE]; - CGSize cg_advances_static[STATIC_BUF_SIZE]; - CGGlyph *cg_glyphs = &glyphs_static[0]; - CGSize *cg_advances = &cg_advances_static[0]; - - cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface; - cairo_int_status_t rv = CAIRO_STATUS_SUCCESS; - cairo_quartz_action_t action; - float xprev, yprev; - int i; - CGFontRef cgfref = NULL; - - cairo_bool_t isClipping = FALSE; - cairo_bool_t didForceFontSmoothing = FALSE; - - if (IS_EMPTY(surface)) - return CAIRO_STATUS_SUCCESS; - - if (num_glyphs <= 0) - return CAIRO_STATUS_SUCCESS; - - if (op == CAIRO_OPERATOR_DEST) - return CAIRO_STATUS_SUCCESS; - - if (cairo_scaled_font_get_type (scaled_font) != CAIRO_FONT_TYPE_QUARTZ) - return CAIRO_INT_STATUS_UNSUPPORTED; - - CGContextSaveGState (surface->cgContext); - - action = _cairo_quartz_setup_source (surface, source); - if (action == DO_SOLID || action == DO_PATTERN) { - CGContextSetTextDrawingMode (surface->cgContext, kCGTextFill); - } else if (action == DO_IMAGE || action == DO_TILED_IMAGE || action == DO_SHADING) { - CGContextSetTextDrawingMode (surface->cgContext, kCGTextClip); - isClipping = TRUE; - } else { - if (action != DO_NOTHING) - rv = CAIRO_INT_STATUS_UNSUPPORTED; - goto BAIL; - } - - CGContextSetCompositeOperation (surface->cgContext, _cairo_quartz_cairo_operator_to_quartz (op)); - - /* this doesn't addref */ - cgfref = _cairo_quartz_scaled_font_get_cg_font_ref (scaled_font); - CGContextSetFont (surface->cgContext, cgfref); - CGContextSetFontSize (surface->cgContext, 1.0); - - switch (scaled_font->options.antialias) { - case CAIRO_ANTIALIAS_SUBPIXEL: - CGContextSetShouldAntialias (surface->cgContext, TRUE); - CGContextSetShouldSmoothFonts (surface->cgContext, TRUE); - if (CGContextSetAllowsFontSmoothingPtr && - !CGContextGetAllowsFontSmoothingPtr (surface->cgContext)) - { - didForceFontSmoothing = TRUE; - CGContextSetAllowsFontSmoothingPtr (surface->cgContext, TRUE); - } - break; - case CAIRO_ANTIALIAS_NONE: - CGContextSetShouldAntialias (surface->cgContext, FALSE); - break; - case CAIRO_ANTIALIAS_GRAY: - CGContextSetShouldAntialias (surface->cgContext, TRUE); - CGContextSetShouldSmoothFonts (surface->cgContext, FALSE); - break; - case CAIRO_ANTIALIAS_DEFAULT: - /* Don't do anything */ - break; - } - - if (num_glyphs > STATIC_BUF_SIZE) { - cg_glyphs = (CGGlyph*) _cairo_malloc_ab (num_glyphs, sizeof(CGGlyph)); - if (cg_glyphs == NULL) { - rv = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto BAIL; - } - - cg_advances = (CGSize*) _cairo_malloc_ab (num_glyphs, sizeof(CGSize)); - if (cg_advances == NULL) { - rv = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto BAIL; - } - } - - textTransform = CGAffineTransformMake (scaled_font->font_matrix.xx, - scaled_font->font_matrix.yx, - scaled_font->font_matrix.xy, - scaled_font->font_matrix.yy, - 0., 0.); - textTransform = CGAffineTransformScale (textTransform, 1.0, -1.0); - textTransform = CGAffineTransformConcat (CGAffineTransformMake(scaled_font->ctm.xx, - -scaled_font->ctm.yx, - -scaled_font->ctm.xy, - scaled_font->ctm.yy, - 0., 0.), - textTransform); - - CGContextSetTextMatrix (surface->cgContext, textTransform); - - /* Convert our glyph positions to glyph advances. We need n-1 advances, - * since the advance at index 0 is applied after glyph 0. */ - xprev = glyphs[0].x; - yprev = glyphs[0].y; - - cg_glyphs[0] = glyphs[0].index; - - for (i = 1; i < num_glyphs; i++) { - float xf = glyphs[i].x; - float yf = glyphs[i].y; - cg_glyphs[i] = glyphs[i].index; - cg_advances[i-1].width = xf - xprev; - cg_advances[i-1].height = yf - yprev; - xprev = xf; - yprev = yf; - } - - if (_cairo_quartz_osx_version >= 0x1050 && isClipping) { - /* If we're clipping, OSX 10.5 (at least as of 10.5.2) has a - * bug (apple bug ID #5834794) where the glyph - * advances/positions are not transformed by the text matrix - * if kCGTextClip is being used. So, we pre-transform here. - * 10.4 does not have this problem (as of 10.4.11). - */ - for (i = 0; i < num_glyphs - 1; i++) - cg_advances[i] = CGSizeApplyAffineTransform(cg_advances[i], textTransform); - } - -#if 0 - for (i = 0; i < num_glyphs; i++) { - ND((stderr, "[%d: %d %f,%f]\n", i, cg_glyphs[i], cg_advances[i].width, cg_advances[i].height)); - } -#endif - - /* Translate to the first glyph's position before drawing */ - ctm = CGContextGetCTM (surface->cgContext); - CGContextTranslateCTM (surface->cgContext, glyphs[0].x, glyphs[0].y); - - CGContextShowGlyphsWithAdvances (surface->cgContext, - cg_glyphs, - cg_advances, - num_glyphs); - - CGContextSetCTM (surface->cgContext, ctm); - - if (action == DO_IMAGE || action == DO_TILED_IMAGE) { - CGContextConcatCTM (surface->cgContext, surface->sourceTransform); - CGContextTranslateCTM (surface->cgContext, 0, surface->sourceImageRect.size.height); - CGContextScaleCTM (surface->cgContext, 1, -1); - - if (action == DO_IMAGE) - CGContextDrawImage (surface->cgContext, surface->sourceImageRect, surface->sourceImage); - else - CGContextDrawTiledImagePtr (surface->cgContext, surface->sourceImageRect, surface->sourceImage); - } else if (action == DO_SHADING) { - CGContextConcatCTM (surface->cgContext, surface->sourceTransform); - CGContextDrawShading (surface->cgContext, surface->sourceShading); - } - -BAIL: - _cairo_quartz_teardown_source (surface, source); - - if (didForceFontSmoothing) - CGContextSetAllowsFontSmoothingPtr (surface->cgContext, FALSE); - - CGContextRestoreGState (surface->cgContext); - - if (rv == CAIRO_STATUS_SUCCESS && - cgfref && - !_cairo_operator_bounded_by_mask (op)) - { - unbounded_op_data_t ub; - ub.op = UNBOUNDED_SHOW_GLYPHS; - - ub.u.show_glyphs.isClipping = isClipping; - ub.u.show_glyphs.cg_glyphs = cg_glyphs; - ub.u.show_glyphs.cg_advances = cg_advances; - ub.u.show_glyphs.nglyphs = num_glyphs; - ub.u.show_glyphs.textTransform = textTransform; - ub.u.show_glyphs.font = cgfref; - ub.u.show_glyphs.origin = CGPointMake (glyphs[0].x, glyphs[0].y); - - _cairo_quartz_fixup_unbounded_operation (surface, &ub, scaled_font->options.antialias); - } - - - if (cg_advances != &cg_advances_static[0]) { - free (cg_advances); - } - - if (cg_glyphs != &glyphs_static[0]) { - free (cg_glyphs); - } - - return rv; -} -#endif /* CAIRO_HAS_QUARTZ_FONT */ - -static cairo_int_status_t -_cairo_quartz_surface_mask_with_surface (cairo_quartz_surface_t *surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_surface_pattern_t *mask) -{ - cairo_rectangle_int_t extents; - CGRect rect; - CGImageRef img; - cairo_surface_t *pat_surf = mask->surface; - cairo_status_t status = CAIRO_STATUS_SUCCESS; - CGAffineTransform ctm, mask_matrix; - - status = _cairo_surface_get_extents (pat_surf, &extents); - if (status) - return status; - - // everything would be masked out, so do nothing - if (extents.width == 0 || extents.height == 0) - return CAIRO_STATUS_SUCCESS; - - status = _cairo_surface_to_cgimage ((cairo_surface_t *) surface, pat_surf, &img); - if (status == CAIRO_STATUS_SUCCESS && img == NULL) - return CAIRO_STATUS_SUCCESS; - if (status) - return status; - - rect = CGRectMake (0.0f, 0.0f, extents.width, extents.height); - - CGContextSaveGState (surface->cgContext); - - /* ClipToMask is essentially drawing an image, so we need to flip the CTM - * to get the image to appear oriented the right way */ - ctm = CGContextGetCTM (surface->cgContext); - - _cairo_quartz_cairo_matrix_to_quartz (&mask->base.matrix, &mask_matrix); - CGContextConcatCTM (surface->cgContext, CGAffineTransformInvert(mask_matrix)); - CGContextTranslateCTM (surface->cgContext, 0.0f, rect.size.height); - CGContextScaleCTM (surface->cgContext, 1.0f, -1.0f); - - CGContextClipToMaskPtr (surface->cgContext, rect, img); - - CGContextSetCTM (surface->cgContext, ctm); - - status = _cairo_quartz_surface_paint (surface, op, source); - - CGContextRestoreGState (surface->cgContext); - - if (!_cairo_operator_bounded_by_mask (op)) { - unbounded_op_data_t ub; - ub.op = UNBOUNDED_MASK; - ub.u.mask.mask = img; - ub.u.mask.maskTransform = CGAffineTransformInvert(mask_matrix); - _cairo_quartz_fixup_unbounded_operation (surface, &ub, CAIRO_ANTIALIAS_NONE); - } - - CGImageRelease (img); - - return status; -} - -/* This is somewhat less than ideal, but it gets the job done; - * it would be better to avoid calling back into cairo. This - * creates a temporary surface to use as the mask. - */ -static cairo_int_status_t -_cairo_quartz_surface_mask_with_generic (cairo_quartz_surface_t *surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_pattern_t *mask) -{ - int width = surface->extents.width - surface->extents.x; - int height = surface->extents.height - surface->extents.y; - - cairo_surface_t *gradient_surf = NULL; - cairo_t *gradient_surf_cr = NULL; - - cairo_surface_pattern_t surface_pattern; - cairo_int_status_t status; - - /* Render the gradient to a surface */ - gradient_surf = cairo_quartz_surface_create (CAIRO_FORMAT_ARGB32, - width, - height); - gradient_surf_cr = cairo_create(gradient_surf); - cairo_set_source (gradient_surf_cr, mask); - cairo_set_operator (gradient_surf_cr, CAIRO_OPERATOR_SOURCE); - cairo_paint (gradient_surf_cr); - status = cairo_status (gradient_surf_cr); - cairo_destroy (gradient_surf_cr); - - if (status) - goto BAIL; - - _cairo_pattern_init_for_surface (&surface_pattern, gradient_surf); - - status = _cairo_quartz_surface_mask_with_surface (surface, op, source, &surface_pattern); - - _cairo_pattern_fini (&surface_pattern.base); - - BAIL: - if (gradient_surf) - cairo_surface_destroy (gradient_surf); - - return status; -} - -static cairo_int_status_t -_cairo_quartz_surface_mask (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_pattern_t *mask) -{ - cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface; - cairo_int_status_t rv = CAIRO_STATUS_SUCCESS; - - ND((stderr, "%p _cairo_quartz_surface_mask op %d source->type %d mask->type %d\n", surface, op, source->type, mask->type)); - - if (IS_EMPTY(surface)) - return CAIRO_STATUS_SUCCESS; - - if (mask->type == CAIRO_PATTERN_TYPE_SOLID) { - /* This is easy; we just need to paint with the alpha. */ - cairo_solid_pattern_t *solid_mask = (cairo_solid_pattern_t *) mask; - - CGContextSetAlpha (surface->cgContext, solid_mask->color.alpha); - rv = _cairo_quartz_surface_paint (surface, op, source); - CGContextSetAlpha (surface->cgContext, 1.0); - - return rv; - } - - /* If we have CGContextClipToMask, we can do more complex masks */ - if (CGContextClipToMaskPtr) { - /* For these, we can skip creating a temporary surface, since we already have one */ - if (mask->type == CAIRO_PATTERN_TYPE_SURFACE && mask->extend == CAIRO_EXTEND_NONE) - return _cairo_quartz_surface_mask_with_surface (surface, op, source, (cairo_surface_pattern_t *) mask); - - return _cairo_quartz_surface_mask_with_generic (surface, op, source, mask); - } - - /* So, CGContextClipToMask is not present in 10.3.9, so we're - * doomed; if we have imageData, we can do fallback, otherwise - * just pretend success. - */ - if (surface->imageData) - return CAIRO_INT_STATUS_UNSUPPORTED; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_quartz_surface_intersect_clip_path (void *abstract_surface, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface; - quartz_stroke_t stroke; - cairo_status_t status; - - ND((stderr, "%p _cairo_quartz_surface_intersect_clip_path path: %p\n", surface, path)); - - if (IS_EMPTY(surface)) - return CAIRO_STATUS_SUCCESS; - - if (path == NULL) { - /* If we're being asked to reset the clip, we can only do it - * by restoring the gstate to our previous saved one, and - * saving it again. - * - * Note that this assumes that ALL quartz surface creation - * functions will do a SaveGState first; we do this in create_internal. - */ - CGContextRestoreGState (surface->cgContext); - CGContextSaveGState (surface->cgContext); - } else { - CGContextBeginPath (surface->cgContext); - stroke.cgContext = surface->cgContext; - stroke.ctm_inverse = NULL; - - CGContextSetShouldAntialias (surface->cgContext, (antialias != CAIRO_ANTIALIAS_NONE)); - - /* path must not be empty. */ - CGContextMoveToPoint (surface->cgContext, 0, 0); - status = _cairo_quartz_cairo_path_to_quartz_context (path, &stroke); - if (status) - return status; - - if (fill_rule == CAIRO_FILL_RULE_WINDING) - CGContextClip (surface->cgContext); - else - CGContextEOClip (surface->cgContext); - } - - ND((stderr, "-- intersect_clip_path\n")); - - return CAIRO_STATUS_SUCCESS; -} - -// XXXtodo implement show_page; need to figure out how to handle begin/end - -static const struct _cairo_surface_backend cairo_quartz_surface_backend = { - CAIRO_SURFACE_TYPE_QUARTZ, - _cairo_quartz_surface_create_similar, - _cairo_quartz_surface_finish, - _cairo_quartz_surface_acquire_source_image, - _cairo_quartz_surface_release_source_image, - _cairo_quartz_surface_acquire_dest_image, - _cairo_quartz_surface_release_dest_image, - _cairo_quartz_surface_clone_similar, - NULL, /* composite */ - NULL, /* fill_rectangles */ - NULL, /* composite_trapezoids */ - NULL, /* copy_page */ - NULL, /* show_page */ - NULL, /* set_clip_region */ - _cairo_quartz_surface_intersect_clip_path, - _cairo_quartz_surface_get_extents, - NULL, /* old_show_glyphs */ - NULL, /* get_font_options */ - NULL, /* flush */ - NULL, /* mark_dirty_rectangle */ - NULL, /* scaled_font_fini */ - NULL, /* scaled_glyph_fini */ - - _cairo_quartz_surface_paint, - _cairo_quartz_surface_mask, - _cairo_quartz_surface_stroke, - _cairo_quartz_surface_fill, -#if CAIRO_HAS_QUARTZ_FONT - _cairo_quartz_surface_show_glyphs, -#else - NULL, /* show_glyphs */ -#endif - - NULL, /* snapshot */ - NULL, /* is_similar */ - NULL, /* reset */ - NULL /* fill_stroke */ -}; - -cairo_quartz_surface_t * -_cairo_quartz_surface_create_internal (CGContextRef cgContext, - cairo_content_t content, - unsigned int width, - unsigned int height) -{ - cairo_quartz_surface_t *surface; - - quartz_ensure_symbols(); - - /* Init the base surface */ - surface = malloc(sizeof(cairo_quartz_surface_t)); - if (surface == NULL) - return (cairo_quartz_surface_t*) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - memset(surface, 0, sizeof(cairo_quartz_surface_t)); - - _cairo_surface_init(&surface->base, &cairo_quartz_surface_backend, - content); - - /* Save our extents */ - surface->extents.x = surface->extents.y = 0; - surface->extents.width = width; - surface->extents.height = height; - - if (IS_EMPTY(surface)) { - surface->cgContext = NULL; - surface->cgContextBaseCTM = CGAffineTransformIdentity; - surface->imageData = NULL; - return surface; - } - - /* Save so we can always get back to a known-good CGContext -- this is - * required for proper behaviour of intersect_clip_path(NULL) - */ - CGContextSaveGState (cgContext); - - surface->cgContext = cgContext; - surface->cgContextBaseCTM = CGContextGetCTM (cgContext); - - surface->imageData = NULL; - surface->imageSurfaceEquiv = NULL; - - return surface; -} - -/** - * cairo_quartz_surface_create_for_cg_context - * @cgContext: the existing CGContext for which to create the surface - * @width: width of the surface, in pixels - * @height: height of the surface, in pixels - * - * Creates a Quartz surface that wraps the given CGContext. The - * CGContext is assumed to be in the standard Cairo coordinate space - * (that is, with the origin at the upper left and the Y axis - * increasing downward). If the CGContext is in the Quartz coordinate - * space (with the origin at the bottom left), then it should be - * flipped before this function is called. The flip can be accomplished - * using a translate and a scale; for example: - * - * - * CGContextTranslateCTM (cgContext, 0.0, height); - * CGContextScaleCTM (cgContext, 1.0, -1.0); - * - * - * All Cairo operations are implemented in terms of Quartz operations, - * as long as Quartz-compatible elements are used (such as Quartz fonts). - * - * Return value: the newly created Cairo surface. - * - * Since: 1.4 - **/ - -cairo_surface_t * -cairo_quartz_surface_create_for_cg_context (CGContextRef cgContext, - unsigned int width, - unsigned int height) -{ - cairo_quartz_surface_t *surf; - - CGContextRetain (cgContext); - - surf = _cairo_quartz_surface_create_internal (cgContext, CAIRO_CONTENT_COLOR_ALPHA, - width, height); - if (surf->base.status) { - CGContextRelease (cgContext); - // create_internal will have set an error - return (cairo_surface_t*) surf; - } - - return (cairo_surface_t *) surf; -} - -/** - * cairo_quartz_surface_create - * @format: format of pixels in the surface to create - * @width: width of the surface, in pixels - * @height: height of the surface, in pixels - * - * Creates a Quartz surface backed by a CGBitmap. The surface is - * created using the Device RGB (or Device Gray, for A8) color space. - * All Cairo operations, including those that require software - * rendering, will succeed on this surface. - * - * Return value: the newly created surface. - * - * Since: 1.4 - **/ -cairo_surface_t * -cairo_quartz_surface_create (cairo_format_t format, - unsigned int width, - unsigned int height) -{ - cairo_quartz_surface_t *surf; - CGContextRef cgc; - CGColorSpaceRef cgColorspace; - CGBitmapInfo bitinfo; - void *imageData; - int stride; - int bitsPerComponent; - - // verify width and height of surface - if (!_cairo_quartz_verify_surface_size(width, height)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - if (width == 0 || height == 0) { - return (cairo_surface_t*) _cairo_quartz_surface_create_internal (NULL, _cairo_content_from_format (format), - width, height); - } - - if (format == CAIRO_FORMAT_ARGB32 || - format == CAIRO_FORMAT_RGB24) - { - cgColorspace = CGColorSpaceCreateDeviceRGB(); - bitinfo = kCGBitmapByteOrder32Host; - if (format == CAIRO_FORMAT_ARGB32) - bitinfo |= kCGImageAlphaPremultipliedFirst; - else - bitinfo |= kCGImageAlphaNoneSkipFirst; - bitsPerComponent = 8; - - /* The Apple docs say that for best performance, the stride and the data - * pointer should be 16-byte aligned. malloc already aligns to 16-bytes, - * so we don't have to anything special on allocation. - */ - stride = width * 4; - stride += (16 - (stride & 15)) & 15; - } else if (format == CAIRO_FORMAT_A8) { - cgColorspace = CGColorSpaceCreateDeviceGray(); - if (width % 4 == 0) - stride = width; - else - stride = (width & ~3) + 4; - bitinfo = kCGImageAlphaNone; - bitsPerComponent = 8; - } else if (format == CAIRO_FORMAT_A1) { - /* I don't think we can usefully support this, as defined by - * cairo_format_t -- these are 1-bit pixels stored in 32-bit - * quantities. - */ - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); - } else { - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); - } - - imageData = _cairo_malloc_ab (height, stride); - if (!imageData) { - CGColorSpaceRelease (cgColorspace); - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - } - - /* zero the memory to match the image surface behaviour */ - memset (imageData, 0, height * stride); - - cgc = CGBitmapContextCreate (imageData, - width, - height, - bitsPerComponent, - stride, - cgColorspace, - bitinfo); - CGColorSpaceRelease (cgColorspace); - - if (!cgc) { - free (imageData); - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - } - - /* flip the Y axis */ - CGContextTranslateCTM (cgc, 0.0, height); - CGContextScaleCTM (cgc, 1.0, -1.0); - - surf = _cairo_quartz_surface_create_internal (cgc, _cairo_content_from_format (format), - width, height); - if (surf->base.status) { - CGContextRelease (cgc); - free (imageData); - // create_internal will have set an error - return (cairo_surface_t*) surf; - } - - surf->imageData = imageData; - surf->imageSurfaceEquiv = cairo_image_surface_create_for_data (imageData, format, width, height, stride); - - return (cairo_surface_t *) surf; -} - -/** - * cairo_quartz_surface_get_cg_context - * @surface: the Cairo Quartz surface - * - * Returns the CGContextRef that the given Quartz surface is backed - * by. - * - * Return value: the CGContextRef for the given surface. - * - * Since: 1.4 - **/ -CGContextRef -cairo_quartz_surface_get_cg_context (cairo_surface_t *surface) -{ - cairo_quartz_surface_t *quartz = (cairo_quartz_surface_t*)surface; - - if (cairo_surface_get_type(surface) != CAIRO_SURFACE_TYPE_QUARTZ) - return NULL; - - return quartz->cgContext; -} - - -/* Debug stuff */ - -#ifdef QUARTZ_DEBUG - -#include - -void ExportCGImageToPNGFile(CGImageRef inImageRef, char* dest) -{ - Handle dataRef = NULL; - OSType dataRefType; - CFStringRef inPath = CFStringCreateWithCString(NULL, dest, kCFStringEncodingASCII); - - GraphicsExportComponent grex = 0; - unsigned long sizeWritten; - - ComponentResult result; - - // create the data reference - result = QTNewDataReferenceFromFullPathCFString(inPath, kQTNativeDefaultPathStyle, - 0, &dataRef, &dataRefType); - - if (NULL != dataRef && noErr == result) { - // get the PNG exporter - result = OpenADefaultComponent(GraphicsExporterComponentType, kQTFileTypePNG, - &grex); - - if (grex) { - // tell the exporter where to find its source image - result = GraphicsExportSetInputCGImage(grex, inImageRef); - - if (noErr == result) { - // tell the exporter where to save the exporter image - result = GraphicsExportSetOutputDataReference(grex, dataRef, - dataRefType); - - if (noErr == result) { - // write the PNG file - result = GraphicsExportDoExport(grex, &sizeWritten); - } - } - - // remember to close the component - CloseComponent(grex); - } - - // remember to dispose of the data reference handle - DisposeHandle(dataRef); - } -} - -void -quartz_image_to_png (CGImageRef imgref, char *dest) -{ - static int sctr = 0; - char sptr[] = "/Users/vladimir/Desktop/barXXXXX.png"; - - if (dest == NULL) { - fprintf (stderr, "** Writing %p to bar%d\n", imgref, sctr); - sprintf (sptr, "/Users/vladimir/Desktop/bar%d.png", sctr); - sctr++; - dest = sptr; - } - - ExportCGImageToPNGFile(imgref, dest); -} - -void -quartz_surface_to_png (cairo_quartz_surface_t *nq, char *dest) -{ - static int sctr = 0; - char sptr[] = "/Users/vladimir/Desktop/fooXXXXX.png"; - - if (nq->base.type != CAIRO_SURFACE_TYPE_QUARTZ) { - fprintf (stderr, "** quartz_surface_to_png: surface %p isn't quartz!\n", nq); - return; - } - - if (dest == NULL) { - fprintf (stderr, "** Writing %p to foo%d\n", nq, sctr); - sprintf (sptr, "/Users/vladimir/Desktop/foo%d.png", sctr); - sctr++; - dest = sptr; - } - - CGImageRef imgref = CGBitmapContextCreateImage (nq->cgContext); - if (imgref == NULL) { - fprintf (stderr, "quartz surface at %p is not a bitmap context!\n", nq); - return; - } - - ExportCGImageToPNGFile(imgref, dest); - - CGImageRelease(imgref); -} - -#endif /* QUARTZ_DEBUG */ diff --git a/uppdev/plugin/cairo/lib/cairo-quartz.h b/uppdev/plugin/cairo/lib/cairo-quartz.h deleted file mode 100644 index 769b29f48..000000000 --- a/uppdev/plugin/cairo/lib/cairo-quartz.h +++ /dev/null @@ -1,82 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2006, 2007 Mozilla Corporation - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Mozilla Corporation. - * - * Contributor(s): - * Vladimir Vukicevic - */ - -#ifndef CAIRO_QUARTZ_H -#define CAIRO_QUARTZ_H - -#include "cairo.h" - -#if CAIRO_HAS_QUARTZ_SURFACE - -#include - -CAIRO_BEGIN_DECLS - -cairo_public cairo_surface_t * -cairo_quartz_surface_create (cairo_format_t format, - unsigned int width, - unsigned int height); - -cairo_public cairo_surface_t * -cairo_quartz_surface_create_for_cg_context (CGContextRef cgContext, - unsigned int width, - unsigned int height); - -cairo_public CGContextRef -cairo_quartz_surface_get_cg_context (cairo_surface_t *surface); - -#if CAIRO_HAS_QUARTZ_FONT - -/* - * Quartz font support - */ - -cairo_public cairo_font_face_t * -cairo_quartz_font_face_create_for_cgfont (CGFontRef font); - -cairo_public cairo_font_face_t * -cairo_quartz_font_face_create_for_atsu_font_id (ATSUFontID font_id); - -#endif /* CAIRO_HAS_QUARTZ_FONT */ - -CAIRO_END_DECLS - -#else - -# error Cairo was not compiled with support for the quartz backend - -#endif /* CAIRO_HAS_QUARTZ_SURFACE */ - -#endif /* CAIRO_QUARTZ_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-rectangle.c b/uppdev/plugin/cairo/lib/cairo-rectangle.c deleted file mode 100644 index 2143f0c64..000000000 --- a/uppdev/plugin/cairo/lib/cairo-rectangle.c +++ /dev/null @@ -1,225 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * Copyright © 2005 Red Hat, Inc. - * Copyright © 2006 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - */ - -#include "cairoint.h" - -cairo_private void -_cairo_box_from_doubles (cairo_box_t *box, - double *x1, double *y1, - double *x2, double *y2) -{ - box->p1.x = _cairo_fixed_from_double (*x1); - box->p1.y = _cairo_fixed_from_double (*y1); - box->p2.x = _cairo_fixed_from_double (*x2); - box->p2.y = _cairo_fixed_from_double (*y2); -} - -cairo_private void -_cairo_box_to_doubles (const cairo_box_t *box, - double *x1, double *y1, - double *x2, double *y2) -{ - *x1 = _cairo_fixed_to_double (box->p1.x); - *y1 = _cairo_fixed_to_double (box->p1.y); - *x2 = _cairo_fixed_to_double (box->p2.x); - *y2 = _cairo_fixed_to_double (box->p2.y); -} - -void -_cairo_box_from_rectangle (cairo_box_t *box, - const cairo_rectangle_int_t *rect) -{ - box->p1.x = _cairo_fixed_from_int (rect->x); - box->p1.y = _cairo_fixed_from_int (rect->y); - box->p2.x = _cairo_fixed_from_int (rect->x + rect->width); - box->p2.y = _cairo_fixed_from_int (rect->y + rect->height); -} - -/* XXX We currently have a confusing mix of boxes and rectangles as - * exemplified by this function. A #cairo_box_t is a rectangular area - * represented by the coordinates of the upper left and lower right - * corners, expressed in fixed point numbers. A #cairo_rectangle_int_t is - * also a rectangular area, but represented by the upper left corner - * and the width and the height, as integer numbers. - * - * This function converts a #cairo_box_t to a #cairo_rectangle_int_t by - * increasing the area to the nearest integer coordinates. We should - * standardize on #cairo_rectangle_fixed_t and #cairo_rectangle_int_t, and - * this function could be renamed to the more reasonable - * _cairo_rectangle_fixed_round. - */ - -void -_cairo_box_round_to_rectangle (const cairo_box_t *box, - cairo_rectangle_int_t *rectangle) -{ - rectangle->x = _cairo_fixed_integer_floor (box->p1.x); - rectangle->y = _cairo_fixed_integer_floor (box->p1.y); - rectangle->width = _cairo_fixed_integer_ceil (box->p2.x) - rectangle->x; - rectangle->height = _cairo_fixed_integer_ceil (box->p2.y) - rectangle->y; -} - -cairo_bool_t -_cairo_rectangle_intersect (cairo_rectangle_int_t *dst, - const cairo_rectangle_int_t *src) -{ - int x1, y1, x2, y2; - - x1 = MAX (dst->x, src->x); - y1 = MAX (dst->y, src->y); - /* Beware the unsigned promotion, fortunately we have bits to spare - * as (CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN) < UINT_MAX - */ - x2 = MIN (dst->x + (int) dst->width, src->x + (int) src->width); - y2 = MIN (dst->y + (int) dst->height, src->y + (int) src->height); - - if (x1 >= x2 || y1 >= y2) { - dst->x = 0; - dst->y = 0; - dst->width = 0; - dst->height = 0; - - return FALSE; - } else { - dst->x = x1; - dst->y = y1; - dst->width = x2 - x1; - dst->height = y2 - y1; - - return TRUE; - } -} - -#define P1x (line->p1.x) -#define P1y (line->p1.y) -#define P2x (line->p2.x) -#define P2y (line->p2.y) -#define B1x (box->p1.x) -#define B1y (box->p1.y) -#define B2x (box->p2.x) -#define B2y (box->p2.y) - -/* - * Check whether any part of line intersects box. This function essentially - * computes whether the ray starting at line->p1 in the direction of line->p2 - * intersects the box before it reaches p2. Normally, this is done - * by dividing by the lengths of the line projected onto each axis. Because - * we're in fixed point, this function does a bit more work to avoid having to - * do the division -- we don't care about the actual intersection point, so - * it's of no interest to us. - */ - -cairo_bool_t -_cairo_box_intersects_line_segment (cairo_box_t *box, cairo_line_t *line) -{ - cairo_fixed_t t1=0, t2=0, t3=0, t4=0; - cairo_int64_t t1y, t2y, t3x, t4x; - - cairo_fixed_t xlen, ylen; - - if (_cairo_box_contains_point(box, &line->p1) || - _cairo_box_contains_point(box, &line->p2)) - return TRUE; - - xlen = P2x - P1x; - ylen = P2y - P1y; - - if (xlen) { - if (xlen > 0) { - t1 = B1x - P1x; - t2 = B2x - P1x; - } else { - t1 = P1x - B2x; - t2 = P1x - B1x; - xlen = - xlen; - } - - if ((t1 < 0 || t1 > xlen) && - (t2 < 0 || t2 > xlen)) - return FALSE; - } else { - /* Fully vertical line -- check that X is in bounds */ - if (P1x < B1x || P1x > B2x) - return FALSE; - } - - if (ylen) { - if (ylen > 0) { - t3 = B1y - P1y; - t4 = B2y - P1y; - } else { - t3 = P1y - B2y; - t4 = P1y - B1y; - ylen = - ylen; - } - - if ((t3 < 0 || t3 > ylen) && - (t4 < 0 || t4 > ylen)) - return FALSE; - } else { - /* Fully horizontal line -- check Y */ - if (P1y < B1y || P1y > B2y) - return FALSE; - } - - /* If we had a horizontal or vertical line, then it's already been checked */ - if (P1x == P2x || P1y == P2y) - return TRUE; - - /* Check overlap. Note that t1 < t2 and t3 < t4 here. */ - t1y = _cairo_int32x32_64_mul (t1, ylen); - t2y = _cairo_int32x32_64_mul (t2, ylen); - t3x = _cairo_int32x32_64_mul (t3, xlen); - t4x = _cairo_int32x32_64_mul (t4, xlen); - - if (_cairo_int64_lt(t1y, t4x) && - _cairo_int64_lt(t3x, t2y)) - return TRUE; - - return FALSE; -} - -cairo_bool_t -_cairo_box_contains_point (cairo_box_t *box, cairo_point_t *point) -{ - if (point->x < box->p1.x || point->x > box->p2.x || - point->y < box->p1.y || point->y > box->p2.y) - return FALSE; - return TRUE; -} diff --git a/uppdev/plugin/cairo/lib/cairo-reference-count-private.h b/uppdev/plugin/cairo/lib/cairo-reference-count-private.h deleted file mode 100644 index d6adaad96..000000000 --- a/uppdev/plugin/cairo/lib/cairo-reference-count-private.h +++ /dev/null @@ -1,62 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2007 Chris Wilson - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Chris Wilson - */ - -#ifndef CAIRO_REFRENCE_COUNT_PRIVATE_H -#define CAIRO_REFRENCE_COUNT_PRIVATE_H - -#include "cairo-atomic-private.h" - -/* Encapsulate operations on the object's reference count */ -typedef struct { - cairo_atomic_int_t ref_count; -} cairo_reference_count_t; - -#define _cairo_reference_count_inc(RC) _cairo_atomic_int_inc (&(RC)->ref_count) -#define _cairo_reference_count_dec_and_test(RC) _cairo_atomic_int_dec_and_test (&(RC)->ref_count) - -#define CAIRO_REFERENCE_COUNT_INIT(RC, VALUE) ((RC)->ref_count = (VALUE)) - -#define CAIRO_REFERENCE_COUNT_GET_VALUE(RC) _cairo_atomic_int_get (&(RC)->ref_count) -#define CAIRO_REFERENCE_COUNT_SET_VALUE(RC, VALUE) _cairo_atomic_int_set (&(RC)->ref_count, (VALUE)) - -#define CAIRO_REFERENCE_COUNT_INVALID_VALUE ((cairo_atomic_int_t) -1) -#define CAIRO_REFERENCE_COUNT_INVALID {CAIRO_REFERENCE_COUNT_INVALID_VALUE} - -#define CAIRO_REFERENCE_COUNT_IS_INVALID(RC) (CAIRO_REFERENCE_COUNT_GET_VALUE (RC) == CAIRO_REFERENCE_COUNT_INVALID_VALUE) - -#define CAIRO_REFERENCE_COUNT_HAS_REFERENCE(RC) (CAIRO_REFERENCE_COUNT_GET_VALUE (RC) > 0) - -#endif diff --git a/uppdev/plugin/cairo/lib/cairo-region-private.h b/uppdev/plugin/cairo/lib/cairo-region-private.h deleted file mode 100644 index 588762e51..000000000 --- a/uppdev/plugin/cairo/lib/cairo-region-private.h +++ /dev/null @@ -1,117 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* Cairo - a vector graphics library with display and print output - * - * Copyright © 2007 Mozilla Corporation - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Mozilla Corporation - * - * Contributor(s): - * Vladimir Vukicevic - */ - -#ifndef CAIRO_REGION_PRIVATE_H -#define CAIRO_REGION_PRIVATE_H - -#include "cairo-compiler-private.h" -#include "cairo-types-private.h" - -#include - -CAIRO_BEGIN_DECLS - -/* #cairo_region_t is defined in cairoint.h */ - -struct _cairo_region { - pixman_region32_t rgn; -}; - -cairo_private void -_cairo_region_init (cairo_region_t *region); - -cairo_private void -_cairo_region_init_rect (cairo_region_t *region, - cairo_rectangle_int_t *rect); - -cairo_private cairo_int_status_t -_cairo_region_init_boxes (cairo_region_t *region, - cairo_box_int_t *boxes, - int count); - -cairo_private void -_cairo_region_fini (cairo_region_t *region); - -cairo_private cairo_int_status_t -_cairo_region_copy (cairo_region_t *dst, - cairo_region_t *src); - -cairo_private int -_cairo_region_num_boxes (cairo_region_t *region); - -cairo_private cairo_int_status_t -_cairo_region_get_boxes (cairo_region_t *region, - int *num_boxes, - cairo_box_int_t **boxes); - -cairo_private void -_cairo_region_boxes_fini (cairo_region_t *region, - cairo_box_int_t *boxes); - -cairo_private void -_cairo_region_get_extents (cairo_region_t *region, - cairo_rectangle_int_t *extents); - -cairo_private cairo_int_status_t -_cairo_region_subtract (cairo_region_t *dst, - cairo_region_t *a, - cairo_region_t *b); - -cairo_private cairo_int_status_t -_cairo_region_intersect (cairo_region_t *dst, - cairo_region_t *a, - cairo_region_t *b); - -cairo_private cairo_int_status_t -_cairo_region_union_rect (cairo_region_t *dst, - cairo_region_t *src, - cairo_rectangle_int_t *rect); - -cairo_private cairo_bool_t -_cairo_region_not_empty (cairo_region_t *region); - -cairo_private void -_cairo_region_translate (cairo_region_t *region, - int x, int y); - -cairo_private pixman_region_overlap_t -_cairo_region_contains_rectangle (cairo_region_t *region, - const cairo_rectangle_int_t *box); - - -CAIRO_END_DECLS - -#endif /* CAIRO_REGION_PRIVATE_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-region.c b/uppdev/plugin/cairo/lib/cairo-region.c deleted file mode 100644 index 23a042fd7..000000000 --- a/uppdev/plugin/cairo/lib/cairo-region.c +++ /dev/null @@ -1,221 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* cairo - a vector graphics library with display and print output - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Owen Taylor - * Vladimir Vukicevic - */ - -#include "cairoint.h" - -void -_cairo_region_init (cairo_region_t *region) -{ - pixman_region32_init (®ion->rgn); -} - -void -_cairo_region_init_rect (cairo_region_t *region, - cairo_rectangle_int_t *rect) -{ - pixman_region32_init_rect (®ion->rgn, - rect->x, rect->y, - rect->width, rect->height); -} - -cairo_int_status_t -_cairo_region_init_boxes (cairo_region_t *region, - cairo_box_int_t *boxes, - int count) -{ - pixman_box32_t stack_pboxes[CAIRO_STACK_ARRAY_LENGTH (pixman_box32_t)]; - pixman_box32_t *pboxes = stack_pboxes; - cairo_int_status_t status = CAIRO_STATUS_SUCCESS; - int i; - - if (count > ARRAY_LENGTH(stack_pboxes)) { - pboxes = _cairo_malloc_ab (count, sizeof(pixman_box32_t)); - if (pboxes == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - for (i = 0; i < count; i++) { - pboxes[i].x1 = boxes[i].p1.x; - pboxes[i].y1 = boxes[i].p1.y; - pboxes[i].x2 = boxes[i].p2.x; - pboxes[i].y2 = boxes[i].p2.y; - } - - if (!pixman_region32_init_rects (®ion->rgn, pboxes, count)) - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - - if (pboxes != stack_pboxes) - free (pboxes); - - return status; -} - -void -_cairo_region_fini (cairo_region_t *region) -{ - pixman_region32_fini (®ion->rgn); -} - -cairo_int_status_t -_cairo_region_copy (cairo_region_t *dst, cairo_region_t *src) -{ - if (!pixman_region32_copy (&dst->rgn, &src->rgn)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - return CAIRO_STATUS_SUCCESS; -} - -int -_cairo_region_num_boxes (cairo_region_t *region) -{ - return pixman_region32_n_rects (®ion->rgn); -} - -cairo_int_status_t -_cairo_region_get_boxes (cairo_region_t *region, int *num_boxes, cairo_box_int_t **boxes) -{ - int nboxes; - pixman_box32_t *pboxes; - cairo_box_int_t *cboxes; - int i; - - pboxes = pixman_region32_rectangles (®ion->rgn, &nboxes); - - if (nboxes == 0) { - *num_boxes = 0; - *boxes = NULL; - return CAIRO_STATUS_SUCCESS; - } - - cboxes = _cairo_malloc_ab (nboxes, sizeof(cairo_box_int_t)); - if (cboxes == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - for (i = 0; i < nboxes; i++) { - cboxes[i].p1.x = pboxes[i].x1; - cboxes[i].p1.y = pboxes[i].y1; - cboxes[i].p2.x = pboxes[i].x2; - cboxes[i].p2.y = pboxes[i].y2; - } - - *num_boxes = nboxes; - *boxes = cboxes; - - return CAIRO_STATUS_SUCCESS; -} - -void -_cairo_region_boxes_fini (cairo_region_t *region, cairo_box_int_t *boxes) -{ - free (boxes); -} - -/** - * _cairo_region_get_extents: - * @region: a #cairo_region_t - * @rect: rectangle into which to store the extents - * - * Gets the bounding box of a region as a #cairo_rectangle_int_t - **/ -void -_cairo_region_get_extents (cairo_region_t *region, cairo_rectangle_int_t *extents) -{ - pixman_box32_t *pextents = pixman_region32_extents (®ion->rgn); - - extents->x = pextents->x1; - extents->y = pextents->y1; - extents->width = pextents->x2 - pextents->x1; - extents->height = pextents->y2 - pextents->y1; -} - -cairo_int_status_t -_cairo_region_subtract (cairo_region_t *dst, cairo_region_t *a, cairo_region_t *b) -{ - if (!pixman_region32_subtract (&dst->rgn, &a->rgn, &b->rgn)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - return CAIRO_STATUS_SUCCESS; -} - -cairo_int_status_t -_cairo_region_intersect (cairo_region_t *dst, cairo_region_t *a, cairo_region_t *b) -{ - if (!pixman_region32_intersect (&dst->rgn, &a->rgn, &b->rgn)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - return CAIRO_STATUS_SUCCESS; -} - -cairo_int_status_t -_cairo_region_union_rect (cairo_region_t *dst, - cairo_region_t *src, - cairo_rectangle_int_t *rect) -{ - if (!pixman_region32_union_rect (&dst->rgn, &src->rgn, - rect->x, rect->y, - rect->width, rect->height)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - return CAIRO_STATUS_SUCCESS; -} - -cairo_bool_t -_cairo_region_not_empty (cairo_region_t *region) -{ - return (cairo_bool_t) pixman_region32_not_empty (®ion->rgn); -} - -void -_cairo_region_translate (cairo_region_t *region, - int x, int y) -{ - pixman_region32_translate (®ion->rgn, x, y); -} - -pixman_region_overlap_t -_cairo_region_contains_rectangle (cairo_region_t *region, - const cairo_rectangle_int_t *rect) -{ - pixman_box32_t pbox; - - pbox.x1 = rect->x; - pbox.y1 = rect->y; - pbox.x2 = rect->x + rect->width; - pbox.y2 = rect->y + rect->height; - - return pixman_region32_contains_rectangle (®ion->rgn, &pbox); -} diff --git a/uppdev/plugin/cairo/lib/cairo-scaled-font-private.h b/uppdev/plugin/cairo/lib/cairo-scaled-font-private.h deleted file mode 100644 index c1d87ae02..000000000 --- a/uppdev/plugin/cairo/lib/cairo-scaled-font-private.h +++ /dev/null @@ -1,119 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - */ - -#ifndef CAIRO_SCALED_FONT_PRIVATE_H -#define CAIRO_SCALED_FONT_PRIVATE_H - -#include "cairo.h" - -#include "cairo-types-private.h" -#include "cairo-mutex-type-private.h" -#include "cairo-reference-count-private.h" - -struct _cairo_scaled_font { - /* For most cairo objects, the rule for multiple threads is that - * the user is responsible for any locking if the same object is - * manipulated from multiple threads simultaneously. - * - * However, with the caching that cairo does for scaled fonts, a - * user can easily end up with the same cairo_scaled_font object - * being manipulated from multiple threads without the user ever - * being aware of this, (and in fact, unable to control it). - * - * So, as a special exception, the cairo implementation takes care - * of all locking needed for cairo_scaled_font_t. Most of what is - * in the scaled font is immutable, (which is what allows for the - * sharing in the first place). The things that are modified and - * the locks protecting them are as follows: - * - * 1. The reference count (scaled_font->ref_count) - * - * Modifications to the reference count are protected by the - * _cairo_scaled_font_map_mutex. This is because the reference - * count of a scaled font is intimately related with the font - * map itself, (and the magic holdovers array). - * - * 2. The cache of glyphs (scaled_font->glyphs) - * 3. The backend private data (scaled_font->surface_backend, - * scaled_font->surface_private) - * - * Modifications to these fields are protected with locks on - * scaled_font->mutex in the generic scaled_font code. - */ - - /* must be first to be stored in a hash table */ - cairo_hash_entry_t hash_entry; - - /* useful bits for _cairo_scaled_font_nil */ - cairo_status_t status; - cairo_reference_count_t ref_count; - cairo_user_data_array_t user_data; - - /* hash key members */ - cairo_font_face_t *font_face; /* may be NULL */ - cairo_matrix_t font_matrix; /* font space => user space */ - cairo_matrix_t ctm; /* user space => device space */ - cairo_font_options_t options; - - cairo_bool_t placeholder; /* protected by fontmap mutex */ - - cairo_bool_t finished; - - /* "live" scaled_font members */ - cairo_matrix_t scale; /* font space => device space */ - cairo_matrix_t scale_inverse; /* device space => font space */ - double max_scale; /* maximum x/y expansion of scale */ - cairo_font_extents_t extents; /* user space */ - - /* The mutex protects modification to all subsequent fields. */ - cairo_mutex_t mutex; - - cairo_cache_t *glyphs; /* glyph index -> cairo_scaled_glyph_t */ - - /* - * One surface backend may store data in each glyph. - * Whichever surface manages to store its pointer here - * first gets to store data in each glyph - */ - const cairo_surface_backend_t *surface_backend; - void *surface_private; - - /* font backend managing this scaled font */ - const cairo_scaled_font_backend_t *backend; -}; - -#endif /* CAIRO_SCALED_FONT_PRIVATE_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-scaled-font-subsets-private.h b/uppdev/plugin/cairo/lib/cairo-scaled-font-subsets-private.h deleted file mode 100644 index 88dedb59b..000000000 --- a/uppdev/plugin/cairo/lib/cairo-scaled-font-subsets-private.h +++ /dev/null @@ -1,640 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2006 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - */ - -#ifndef CAIRO_SCALED_FONT_SUBSETS_PRIVATE_H -#define CAIRO_SCALED_FONT_SUBSETS_PRIVATE_H - -#include "cairoint.h" - -#if CAIRO_HAS_FONT_SUBSET - -typedef struct _cairo_scaled_font_subsets_glyph { - unsigned int font_id; - unsigned int subset_id; - unsigned int subset_glyph_index; - cairo_bool_t is_scaled; - cairo_bool_t is_composite; - double x_advance; - double y_advance; - cairo_bool_t utf8_is_mapped; - uint32_t unicode; -} cairo_scaled_font_subsets_glyph_t; - -/** - * _cairo_scaled_font_subsets_create_scaled: - * - * Create a new #cairo_scaled_font_subsets_t object which can be used - * to create subsets of any number of #cairo_scaled_font_t - * objects. This allows the (arbitrarily large and sparse) glyph - * indices of a #cairo_scaled_font_t to be mapped to one or more font - * subsets with glyph indices packed into the range - * [0 .. max_glyphs_per_subset). - * - * Return value: a pointer to the newly creates font subsets. The - * caller owns this object and should call - * _cairo_scaled_font_subsets_destroy() when done with it. - **/ -cairo_private cairo_scaled_font_subsets_t * -_cairo_scaled_font_subsets_create_scaled (void); - -/** - * _cairo_scaled_font_subsets_create_simple: - * - * Create a new #cairo_scaled_font_subsets_t object which can be used - * to create font subsets suitable for embedding as Postscript or PDF - * simple fonts. - * - * Glyphs with an outline path available will be mapped to one font - * subset for each font face. Glyphs from bitmap fonts will mapped to - * separate font subsets for each #cairo_scaled_font_t object. - * - * The maximum number of glyphs per subset is 256. Each subset - * reserves the first glyph for the .notdef glyph. - * - * Return value: a pointer to the newly creates font subsets. The - * caller owns this object and should call - * _cairo_scaled_font_subsets_destroy() when done with it. - **/ -cairo_private cairo_scaled_font_subsets_t * -_cairo_scaled_font_subsets_create_simple (void); - -/** - * _cairo_scaled_font_subsets_create_composite: - * - * Create a new #cairo_scaled_font_subsets_t object which can be used - * to create font subsets suitable for embedding as Postscript or PDF - * composite fonts. - * - * Glyphs with an outline path available will be mapped to one font - * subset for each font face. Each unscaled subset has a maximum of - * 65536 glyphs except for Type1 fonts which have a maximum of 256 glyphs. - * - * Glyphs from bitmap fonts will mapped to separate font subsets for - * each #cairo_scaled_font_t object. Each unscaled subset has a maximum - * of 256 glyphs. - * - * Each subset reserves the first glyph for the .notdef glyph. - * - * Return value: a pointer to the newly creates font subsets. The - * caller owns this object and should call - * _cairo_scaled_font_subsets_destroy() when done with it. - **/ -cairo_private cairo_scaled_font_subsets_t * -_cairo_scaled_font_subsets_create_composite (void); - -/** - * _cairo_scaled_font_subsets_destroy: - * @font_subsets: a #cairo_scaled_font_subsets_t object to be destroyed - * - * Destroys @font_subsets and all resources associated with it. - **/ -cairo_private void -_cairo_scaled_font_subsets_destroy (cairo_scaled_font_subsets_t *font_subsets); - -/** - * _cairo_scaled_font_subsets_map_glyph: - * @font_subsets: a #cairo_scaled_font_subsets_t - * @scaled_font: the font of the glyph to be mapped - * @scaled_font_glyph_index: the index of the glyph to be mapped - * @utf8: a string of text encoded in UTF-8 - * @utf8_len: length of @utf8 in bytes - * @subset_glyph_ret: return structure containing subset font and glyph id - * - * Map a glyph from a #cairo_scaled_font to a new index within a - * subset of that font. The mapping performed is from the tuple: - * - * (scaled_font, scaled_font_glyph_index) - * - * to the tuple: - * - * (font_id, subset_id, subset_glyph_index) - * - * This mapping is 1:1. If the input tuple has previously mapped, the - * the output tuple previously returned will be returned again. - * - * Otherwise, the return tuple will be constructed as follows: - * - * 1) There is a 1:1 correspondence between the input scaled_font - * value and the output font_id value. If no mapping has been - * previously performed with the scaled_font value then the - * smallest unused font_id value will be returned. - * - * 2) Within the set of output tuples of the same font_id value the - * smallest value of subset_id will be returned such that - * subset_glyph_index does not exceed max_glyphs_per_subset (as - * passed to _cairo_scaled_font_subsets_create()) and that the - * resulting tuple is unique. - * - * 3) The smallest value of subset_glyph_index is returned such that - * the resulting tuple is unique. - * - * The net result is that any #cairo_scaled_font_t will be represented - * by one or more font subsets. Each subset is effectively a tuple of - * (scaled_font, font_id, subset_id) and within each subset there - * exists a mapping of scaled_glyph_font_index to subset_glyph_index. - * - * This final description of a font subset is the same representation - * used by #cairo_scaled_font_subset_t as provided by - * _cairo_scaled_font_subsets_foreach. - * - * @utf8 and @utf8_len specify a string of unicode characters that the - * glyph @scaled_font_glyph_index maps to. If @utf8_is_mapped in - * @subset_glyph_ret is %TRUE, the font subsetting will (where index to - * unicode mapping is supported) ensure that @scaled_font_glyph_index - * maps to @utf8. If @utf8_is_mapped is %FALSE, - * @scaled_font_glyph_index has already been mapped to a different - * unicode string. - * - * The returned values in the #cairo_scaled_font_subsets_glyph_t struct are: - * - * @font_id: The font ID of the mapped glyph - * @subset_id : The subset ID of the mapped glyph within the @font_id - * @subset_glyph_index: The index of the mapped glyph within the @subset_id subset - * @is_scaled: If true, the mapped glyph is from a bitmap font, and separate font - * subset is created for each font scale used. If false, the outline of the mapped glyph - * is available. One font subset for each font face is created. - * @x_advance, @y_advance: When @is_scaled is true, @x_advance and @y_advance contain - * the x and y advance for the mapped glyph in device space. - * When @is_scaled is false, @x_advance and @y_advance contain the x and y advance for - * the the mapped glyph from an unhinted 1 point font. - * @utf8_is_mapped: If true the utf8 string provided to _cairo_scaled_font_subsets_map_glyph() - * is (or already was) the utf8 string mapped to this glyph. If false the glyph is already - * mapped to a different utf8 string. - * @unicode: the unicode character mapped to this glyph by the font backend. - * - * Return value: %CAIRO_STATUS_SUCCESS if successful, or a non-zero - * value indicating an error. Possible errors include - * %CAIRO_STATUS_NO_MEMORY. - **/ -cairo_private cairo_status_t -_cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *font_subsets, - cairo_scaled_font_t *scaled_font, - unsigned long scaled_font_glyph_index, - const char * utf8, - int utf8_len, - cairo_scaled_font_subsets_glyph_t *subset_glyph_ret); - -typedef cairo_status_t -(*cairo_scaled_font_subset_callback_func_t) (cairo_scaled_font_subset_t *font_subset, - void *closure); - -/** - * _cairo_scaled_font_subsets_foreach: - * @font_subsets: a #cairo_scaled_font_subsets_t - * @font_subset_callback: a function to be called for each font subset - * @closure: closure data for the callback function - * - * Iterate over each unique scaled font subset as created by calls to - * _cairo_scaled_font_subsets_map_glyph(). A subset is determined by - * unique pairs of (font_id, subset_id) as returned by - * _cairo_scaled_font_subsets_map_glyph(). - * - * For each subset, @font_subset_callback will be called and will be - * provided with both a #cairo_scaled_font_subset_t object containing - * all the glyphs in the subset as well as the value of @closure. - * - * The #cairo_scaled_font_subset_t object contains the scaled_font, - * the font_id, and the subset_id corresponding to all glyphs - * belonging to the subset. In addition, it contains an array providing - * a mapping between subset glyph indices and the original scaled font - * glyph indices. - * - * The index of the array corresponds to subset_glyph_index values - * returned by _cairo_scaled_font_subsets_map_glyph() while the - * values of the array correspond to the scaled_font_glyph_index - * values passed as input to the same function. - * - * Return value: %CAIRO_STATUS_SUCCESS if successful, or a non-zero - * value indicating an error. Possible errors include - * %CAIRO_STATUS_NO_MEMORY. - **/ -cairo_private cairo_status_t -_cairo_scaled_font_subsets_foreach_scaled (cairo_scaled_font_subsets_t *font_subsets, - cairo_scaled_font_subset_callback_func_t font_subset_callback, - void *closure); - -/** - * _cairo_scaled_font_subsets_foreach_unscaled: - * @font_subsets: a #cairo_scaled_font_subsets_t - * @font_subset_callback: a function to be called for each font subset - * @closure: closure data for the callback function - * - * Iterate over each unique unscaled font subset as created by calls to - * _cairo_scaled_font_subsets_map_glyph(). A subset is determined by - * unique pairs of (font_id, subset_id) as returned by - * _cairo_scaled_font_subsets_map_glyph(). - * - * For each subset, @font_subset_callback will be called and will be - * provided with both a #cairo_scaled_font_subset_t object containing - * all the glyphs in the subset as well as the value of @closure. - * - * The #cairo_scaled_font_subset_t object contains the scaled_font, - * the font_id, and the subset_id corresponding to all glyphs - * belonging to the subset. In addition, it contains an array providing - * a mapping between subset glyph indices and the original scaled font - * glyph indices. - * - * The index of the array corresponds to subset_glyph_index values - * returned by _cairo_scaled_font_subsets_map_glyph() while the - * values of the array correspond to the scaled_font_glyph_index - * values passed as input to the same function. - * - * Return value: %CAIRO_STATUS_SUCCESS if successful, or a non-zero - * value indicating an error. Possible errors include - * %CAIRO_STATUS_NO_MEMORY. - **/ -cairo_private cairo_status_t -_cairo_scaled_font_subsets_foreach_unscaled (cairo_scaled_font_subsets_t *font_subsets, - cairo_scaled_font_subset_callback_func_t font_subset_callback, - void *closure); - -/** - * _cairo_scaled_font_subsets_foreach_user: - * @font_subsets: a #cairo_scaled_font_subsets_t - * @font_subset_callback: a function to be called for each font subset - * @closure: closure data for the callback function - * - * Iterate over each unique scaled font subset as created by calls to - * _cairo_scaled_font_subsets_map_glyph(). A subset is determined by - * unique pairs of (font_id, subset_id) as returned by - * _cairo_scaled_font_subsets_map_glyph(). - * - * For each subset, @font_subset_callback will be called and will be - * provided with both a #cairo_scaled_font_subset_t object containing - * all the glyphs in the subset as well as the value of @closure. - * - * The #cairo_scaled_font_subset_t object contains the scaled_font, - * the font_id, and the subset_id corresponding to all glyphs - * belonging to the subset. In addition, it contains an array providing - * a mapping between subset glyph indices and the original scaled font - * glyph indices. - * - * The index of the array corresponds to subset_glyph_index values - * returned by _cairo_scaled_font_subsets_map_glyph() while the - * values of the array correspond to the scaled_font_glyph_index - * values passed as input to the same function. - * - * Return value: %CAIRO_STATUS_SUCCESS if successful, or a non-zero - * value indicating an error. Possible errors include - * %CAIRO_STATUS_NO_MEMORY. - **/ -cairo_private cairo_status_t -_cairo_scaled_font_subsets_foreach_user (cairo_scaled_font_subsets_t *font_subsets, - cairo_scaled_font_subset_callback_func_t font_subset_callback, - void *closure); - -/** - * _cairo_scaled_font_subset_create_glyph_names: - * @font_subsets: a #cairo_scaled_font_subsets_t - * - * Create an array of strings containing the glyph name for each glyph - * in @font_subsets. The array as store in font_subsets->glyph_names. - * - * Return value: %CAIRO_STATUS_SUCCESS if successful, - * %CAIRO_INT_STATUS_UNSUPPORTED if the font backend does not support - * mapping the glyph indices to unicode characters. Possible errors - * include %CAIRO_STATUS_NO_MEMORY. - **/ -cairo_private cairo_int_status_t -_cairo_scaled_font_subset_create_glyph_names (cairo_scaled_font_subset_t *subset); - -typedef struct _cairo_cff_subset { - char *base_font; - int *widths; - long x_min, y_min, x_max, y_max; - long ascent, descent; - char *data; - unsigned long data_length; -} cairo_cff_subset_t; - -/** - * _cairo_cff_subset_init: - * @cff_subset: a #cairo_cff_subset_t to initialize - * @font_subset: the #cairo_scaled_font_subset_t to initialize from - * - * If possible (depending on the format of the underlying - * #cairo_scaled_font_t and the font backend in use) generate a - * cff file corresponding to @font_subset and initialize - * @cff_subset with information about the subset and the cff - * data. - * - * Return value: %CAIRO_STATUS_SUCCESS if successful, - * %CAIRO_INT_STATUS_UNSUPPORTED if the font can't be subset as a - * cff file, or an non-zero value indicating an error. Possible - * errors include %CAIRO_STATUS_NO_MEMORY. - **/ -cairo_private cairo_status_t -_cairo_cff_subset_init (cairo_cff_subset_t *cff_subset, - const char *name, - cairo_scaled_font_subset_t *font_subset); - -/** - * _cairo_cff_subset_fini: - * @cff_subset: a #cairo_cff_subset_t - * - * Free all resources associated with @cff_subset. After this - * call, @cff_subset should not be used again without a - * subsequent call to _cairo_cff_subset_init() again first. - **/ -cairo_private void -_cairo_cff_subset_fini (cairo_cff_subset_t *cff_subset); - -/** - * _cairo_cff_fallback_init: - * @cff_subset: a #cairo_cff_subset_t to initialize - * @font_subset: the #cairo_scaled_font_subset_t to initialize from - * - * If possible (depending on the format of the underlying - * #cairo_scaled_font_t and the font backend in use) generate a cff - * file corresponding to @font_subset and initialize @cff_subset - * with information about the subset and the cff data. - * - * Return value: %CAIRO_STATUS_SUCCESS if successful, - * %CAIRO_INT_STATUS_UNSUPPORTED if the font can't be subset as a - * cff file, or an non-zero value indicating an error. Possible - * errors include %CAIRO_STATUS_NO_MEMORY. - **/ -cairo_private cairo_status_t -_cairo_cff_fallback_init (cairo_cff_subset_t *cff_subset, - const char *name, - cairo_scaled_font_subset_t *font_subset); - -/** - * _cairo_cff_fallback_fini: - * @cff_subset: a #cairo_cff_subset_t - * - * Free all resources associated with @cff_subset. After this - * call, @cff_subset should not be used again without a - * subsequent call to _cairo_cff_subset_init() again first. - **/ -cairo_private void -_cairo_cff_fallback_fini (cairo_cff_subset_t *cff_subset); - -typedef struct _cairo_truetype_subset { - char *base_font; - double *widths; - double x_min, y_min, x_max, y_max; - double ascent, descent; - unsigned char *data; - unsigned long data_length; - unsigned long *string_offsets; - unsigned long num_string_offsets; -} cairo_truetype_subset_t; - -/** - * _cairo_truetype_subset_init: - * @truetype_subset: a #cairo_truetype_subset_t to initialize - * @font_subset: the #cairo_scaled_font_subset_t to initialize from - * - * If possible (depending on the format of the underlying - * #cairo_scaled_font_t and the font backend in use) generate a - * truetype file corresponding to @font_subset and initialize - * @truetype_subset with information about the subset and the truetype - * data. - * - * Return value: %CAIRO_STATUS_SUCCESS if successful, - * %CAIRO_INT_STATUS_UNSUPPORTED if the font can't be subset as a - * truetype file, or an non-zero value indicating an error. Possible - * errors include %CAIRO_STATUS_NO_MEMORY. - **/ -cairo_private cairo_status_t -_cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset, - cairo_scaled_font_subset_t *font_subset); - -/** - * _cairo_truetype_subset_fini: - * @truetype_subset: a #cairo_truetype_subset_t - * - * Free all resources associated with @truetype_subset. After this - * call, @truetype_subset should not be used again without a - * subsequent call to _cairo_truetype_subset_init() again first. - **/ -cairo_private void -_cairo_truetype_subset_fini (cairo_truetype_subset_t *truetype_subset); - - - -typedef struct _cairo_type1_subset { - char *base_font; - int *widths; - long x_min, y_min, x_max, y_max; - long ascent, descent; - char *data; - unsigned long header_length; - unsigned long data_length; - unsigned long trailer_length; -} cairo_type1_subset_t; - - -#if CAIRO_HAS_FT_FONT - -/** - * _cairo_type1_subset_init: - * @type1_subset: a #cairo_type1_subset_t to initialize - * @font_subset: the #cairo_scaled_font_subset_t to initialize from - * @hex_encode: if true the encrypted portion of the font is hex encoded - * - * If possible (depending on the format of the underlying - * #cairo_scaled_font_t and the font backend in use) generate a type1 - * file corresponding to @font_subset and initialize @type1_subset - * with information about the subset and the type1 data. - * - * Return value: %CAIRO_STATUS_SUCCESS if successful, - * %CAIRO_INT_STATUS_UNSUPPORTED if the font can't be subset as a type1 - * file, or an non-zero value indicating an error. Possible errors - * include %CAIRO_STATUS_NO_MEMORY. - **/ -cairo_private cairo_status_t -_cairo_type1_subset_init (cairo_type1_subset_t *type_subset, - const char *name, - cairo_scaled_font_subset_t *font_subset, - cairo_bool_t hex_encode); - -/** - * _cairo_type1_subset_fini: - * @type1_subset: a #cairo_type1_subset_t - * - * Free all resources associated with @type1_subset. After this call, - * @type1_subset should not be used again without a subsequent call to - * _cairo_truetype_type1_init() again first. - **/ -cairo_private void -_cairo_type1_subset_fini (cairo_type1_subset_t *subset); - -#endif /* CAIRO_HAS_FT_FONT */ - - -/** - * _cairo_type1_scaled_font_is_type1: - * @scaled_font: a #cairo_scaled_font_t - * - * Return %TRUE if @scaled_font is a Type 1 font, otherwise return %FALSE. - **/ -cairo_private cairo_bool_t -_cairo_type1_scaled_font_is_type1 (cairo_scaled_font_t *scaled_font); - -/** - * _cairo_type1_fallback_init_binary: - * @type1_subset: a #cairo_type1_subset_t to initialize - * @font_subset: the #cairo_scaled_font_subset_t to initialize from - * - * If possible (depending on the format of the underlying - * #cairo_scaled_font_t and the font backend in use) generate a type1 - * file corresponding to @font_subset and initialize @type1_subset - * with information about the subset and the type1 data. The encrypted - * part of the font is binary encoded. - * - * Return value: %CAIRO_STATUS_SUCCESS if successful, - * %CAIRO_INT_STATUS_UNSUPPORTED if the font can't be subset as a type1 - * file, or an non-zero value indicating an error. Possible errors - * include %CAIRO_STATUS_NO_MEMORY. - **/ -cairo_private cairo_status_t -_cairo_type1_fallback_init_binary (cairo_type1_subset_t *type_subset, - const char *name, - cairo_scaled_font_subset_t *font_subset); - -/** - * _cairo_type1_fallback_init_hexencode: - * @type1_subset: a #cairo_type1_subset_t to initialize - * @font_subset: the #cairo_scaled_font_subset_t to initialize from - * - * If possible (depending on the format of the underlying - * #cairo_scaled_font_t and the font backend in use) generate a type1 - * file corresponding to @font_subset and initialize @type1_subset - * with information about the subset and the type1 data. The encrypted - * part of the font is hex encoded. - * - * Return value: %CAIRO_STATUS_SUCCESS if successful, - * %CAIRO_INT_STATUS_UNSUPPORTED if the font can't be subset as a type1 - * file, or an non-zero value indicating an error. Possible errors - * include %CAIRO_STATUS_NO_MEMORY. - **/ -cairo_private cairo_status_t -_cairo_type1_fallback_init_hex (cairo_type1_subset_t *type_subset, - const char *name, - cairo_scaled_font_subset_t *font_subset); - -/** - * _cairo_type1_fallback_fini: - * @type1_subset: a #cairo_type1_subset_t - * - * Free all resources associated with @type1_subset. After this call, - * @type1_subset should not be used again without a subsequent call to - * _cairo_truetype_type1_init() again first. - **/ -cairo_private void -_cairo_type1_fallback_fini (cairo_type1_subset_t *subset); - -typedef struct _cairo_type2_charstrings { - int *widths; - long x_min, y_min, x_max, y_max; - long ascent, descent; - cairo_array_t charstrings; -} cairo_type2_charstrings_t; - -/** - * _cairo_type2_charstrings_init: - * @type2_subset: a #cairo_type2_subset_t to initialize - * @font_subset: the #cairo_scaled_font_subset_t to initialize from - * - * If possible (depending on the format of the underlying - * #cairo_scaled_font_t and the font backend in use) generate type2 - * charstrings to @font_subset and initialize @type2_subset - * with information about the subset. - * - * Return value: %CAIRO_STATUS_SUCCESS if successful, - * %CAIRO_INT_STATUS_UNSUPPORTED if the font can't be subset as a type2 - * charstrings, or an non-zero value indicating an error. Possible errors - * include %CAIRO_STATUS_NO_MEMORY. - **/ -cairo_private cairo_status_t -_cairo_type2_charstrings_init (cairo_type2_charstrings_t *charstrings, - cairo_scaled_font_subset_t *font_subset); - -/** - * _cairo_type2_charstrings_fini: - * @subset: a #cairo_type2_charstrings_t - * - * Free all resources associated with @type2_charstring. After this call, - * @type2_charstring should not be used again without a subsequent call to - * _cairo_type2_charstring_init() again first. - **/ -cairo_private void -_cairo_type2_charstrings_fini (cairo_type2_charstrings_t *charstrings); - -/** - * _cairo_truetype_create_glyph_to_unicode_map: - * @font_subset: the #cairo_scaled_font_subset_t to initialize from - * - * If possible (depending on the format of the underlying - * #cairo_scaled_font_t and the font backend in use) assign - * the unicode character of each glyph in font_subset to - * fontsubset->to_unicode. - * - * Return value: %CAIRO_STATUS_SUCCESS if successful, - * %CAIRO_INT_STATUS_UNSUPPORTED if the unicode encoding of - * the glyphs is not available. Possible errors include - * %CAIRO_STATUS_NO_MEMORY. - **/ -cairo_private cairo_int_status_t -_cairo_truetype_create_glyph_to_unicode_map (cairo_scaled_font_subset_t *font_subset); - -/** - * _cairo_truetype_index_to_ucs4: - * @scaled_font: the #cairo_scaled_font_t - * @index: the glyph index - * @ucs4: return value for the unicode value of the glyph - * - * If possible (depending on the format of the underlying - * #cairo_scaled_font_t and the font backend in use) assign - * the unicode character of the glyph to @ucs4. - * - * If mapping glyph indices to unicode is supported but the unicode - * value of the specified glyph is not available, @ucs4 is set to -1. - * - * Return value: %CAIRO_STATUS_SUCCESS if successful, - * %CAIRO_INT_STATUS_UNSUPPORTED if mapping glyph indices to unicode - * is not supported. Possible errors include %CAIRO_STATUS_NO_MEMORY. - **/ -cairo_private cairo_int_status_t -_cairo_truetype_index_to_ucs4 (cairo_scaled_font_t *scaled_font, - unsigned long index, - uint32_t *ucs4); - -#endif /* CAIRO_HAS_FONT_SUBSET */ - -#endif /* CAIRO_SCALED_FONT_SUBSETS_PRIVATE_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-scaled-font-subsets.c b/uppdev/plugin/cairo/lib/cairo-scaled-font-subsets.c deleted file mode 100644 index 066f63781..000000000 --- a/uppdev/plugin/cairo/lib/cairo-scaled-font-subsets.c +++ /dev/null @@ -1,1077 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2003 University of Southern California - * Copyright © 2005 Red Hat, Inc - * Copyright © 2006 Keith Packard - * Copyright © 2006 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - * Kristian Høgsberg - * Keith Packard - * Adrian Johnson - */ - -#define _BSD_SOURCE /* for snprintf(), strdup() */ -#include "cairoint.h" - -#if CAIRO_HAS_FONT_SUBSET - -#include "cairo-scaled-font-subsets-private.h" -#include "cairo-user-font-private.h" - -#define MAX_GLYPHS_PER_SIMPLE_FONT 256 -#define MAX_GLYPHS_PER_COMPOSITE_FONT 65536 - -typedef enum { - CAIRO_SUBSETS_SCALED, - CAIRO_SUBSETS_SIMPLE, - CAIRO_SUBSETS_COMPOSITE -} cairo_subsets_type_t; - -typedef enum { - CAIRO_SUBSETS_FOREACH_UNSCALED, - CAIRO_SUBSETS_FOREACH_SCALED, - CAIRO_SUBSETS_FOREACH_USER -} cairo_subsets_foreach_type_t; - -typedef struct _cairo_sub_font { - cairo_hash_entry_t base; - - cairo_bool_t is_scaled; - cairo_bool_t is_composite; - cairo_bool_t is_user; - cairo_scaled_font_subsets_t *parent; - cairo_scaled_font_t *scaled_font; - unsigned int font_id; - - int current_subset; - int num_glyphs_in_current_subset; - int max_glyphs_per_subset; - - cairo_hash_table_t *sub_font_glyphs; - struct _cairo_sub_font *next; -} cairo_sub_font_t; - -struct _cairo_scaled_font_subsets { - cairo_subsets_type_t type; - - int max_glyphs_per_unscaled_subset_used; - cairo_hash_table_t *unscaled_sub_fonts; - cairo_sub_font_t *unscaled_sub_fonts_list; - cairo_sub_font_t *unscaled_sub_fonts_list_end; - - int max_glyphs_per_scaled_subset_used; - cairo_hash_table_t *scaled_sub_fonts; - cairo_sub_font_t *scaled_sub_fonts_list; - cairo_sub_font_t *scaled_sub_fonts_list_end; - - int num_sub_fonts; -}; - -typedef struct _cairo_sub_font_glyph { - cairo_hash_entry_t base; - - unsigned int subset_id; - unsigned int subset_glyph_index; - double x_advance; - double y_advance; - - cairo_bool_t is_mapped; - uint32_t unicode; - char *utf8; - int utf8_len; -} cairo_sub_font_glyph_t; - -typedef struct _cairo_sub_font_collection { - unsigned long *glyphs; /* scaled_font_glyph_index */ - char **utf8; - unsigned int glyphs_size; - unsigned int max_glyph; - unsigned int num_glyphs; - - unsigned int subset_id; - - cairo_status_t status; - cairo_scaled_font_subset_callback_func_t font_subset_callback; - void *font_subset_callback_closure; -} cairo_sub_font_collection_t; - -typedef struct _cairo_string_entry { - cairo_hash_entry_t base; - char *string; -} cairo_string_entry_t; - -static cairo_status_t -_cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font, - unsigned long scaled_font_glyph_index, - const char * utf8, - int utf8_len, - cairo_scaled_font_subsets_glyph_t *subset_glyph); - -static void -_cairo_sub_font_glyph_init_key (cairo_sub_font_glyph_t *sub_font_glyph, - unsigned long scaled_font_glyph_index) -{ - sub_font_glyph->base.hash = scaled_font_glyph_index; -} - -static cairo_bool_t -_cairo_sub_font_glyphs_equal (const void *key_a, const void *key_b) -{ - const cairo_sub_font_glyph_t *sub_font_glyph_a = key_a; - const cairo_sub_font_glyph_t *sub_font_glyph_b = key_b; - - return sub_font_glyph_a->base.hash == sub_font_glyph_b->base.hash; -} - -static cairo_sub_font_glyph_t * -_cairo_sub_font_glyph_create (unsigned long scaled_font_glyph_index, - unsigned int subset_id, - unsigned int subset_glyph_index, - double x_advance, - double y_advance) -{ - cairo_sub_font_glyph_t *sub_font_glyph; - - sub_font_glyph = malloc (sizeof (cairo_sub_font_glyph_t)); - if (sub_font_glyph == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return NULL; - } - - _cairo_sub_font_glyph_init_key (sub_font_glyph, scaled_font_glyph_index); - sub_font_glyph->subset_id = subset_id; - sub_font_glyph->subset_glyph_index = subset_glyph_index; - sub_font_glyph->x_advance = x_advance; - sub_font_glyph->y_advance = y_advance; - sub_font_glyph->is_mapped = FALSE; - sub_font_glyph->unicode = -1; - sub_font_glyph->utf8 = NULL; - sub_font_glyph->utf8_len = 0; - - return sub_font_glyph; -} - -static void -_cairo_sub_font_glyph_destroy (cairo_sub_font_glyph_t *sub_font_glyph) -{ - if (sub_font_glyph->utf8 != NULL) - free (sub_font_glyph->utf8); - - free (sub_font_glyph); -} - -static void -_cairo_sub_font_glyph_pluck (void *entry, void *closure) -{ - cairo_sub_font_glyph_t *sub_font_glyph = entry; - cairo_hash_table_t *sub_font_glyphs = closure; - - _cairo_hash_table_remove (sub_font_glyphs, &sub_font_glyph->base); - _cairo_sub_font_glyph_destroy (sub_font_glyph); -} - -static void -_cairo_sub_font_glyph_collect (void *entry, void *closure) -{ - cairo_sub_font_glyph_t *sub_font_glyph = entry; - cairo_sub_font_collection_t *collection = closure; - unsigned long scaled_font_glyph_index; - unsigned int subset_glyph_index; - - if (sub_font_glyph->subset_id != collection->subset_id) - return; - - scaled_font_glyph_index = sub_font_glyph->base.hash; - subset_glyph_index = sub_font_glyph->subset_glyph_index; - - /* Ensure we don't exceed the allocated bounds. */ - assert (subset_glyph_index < collection->glyphs_size); - - collection->glyphs[subset_glyph_index] = scaled_font_glyph_index; - collection->utf8[subset_glyph_index] = sub_font_glyph->utf8; - if (subset_glyph_index > collection->max_glyph) - collection->max_glyph = subset_glyph_index; - - collection->num_glyphs++; -} - -static cairo_bool_t -_cairo_sub_fonts_equal (const void *key_a, const void *key_b) -{ - const cairo_sub_font_t *sub_font_a = key_a; - const cairo_sub_font_t *sub_font_b = key_b; - - if (sub_font_a->is_scaled) - return sub_font_a->scaled_font == sub_font_b->scaled_font; - else - return sub_font_a->scaled_font->font_face == sub_font_b->scaled_font->font_face; -} - -static void -_cairo_sub_font_init_key (cairo_sub_font_t *sub_font, - cairo_scaled_font_t *scaled_font) -{ - if (sub_font->is_scaled) - { - sub_font->base.hash = (unsigned long) scaled_font; - sub_font->scaled_font = scaled_font; - } - else - { - sub_font->base.hash = (unsigned long) scaled_font->font_face; - sub_font->scaled_font = scaled_font; - } -} - -static cairo_status_t -_cairo_sub_font_create (cairo_scaled_font_subsets_t *parent, - cairo_scaled_font_t *scaled_font, - unsigned int font_id, - int max_glyphs_per_subset, - cairo_bool_t is_scaled, - cairo_bool_t is_composite, - cairo_sub_font_t **sub_font_out) -{ - cairo_sub_font_t *sub_font; - cairo_status_t status; - cairo_scaled_font_subsets_glyph_t subset_glyph; - - sub_font = malloc (sizeof (cairo_sub_font_t)); - if (sub_font == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - sub_font->is_scaled = is_scaled; - sub_font->is_composite = is_composite; - sub_font->is_user = _cairo_font_face_is_user (scaled_font->font_face); - _cairo_sub_font_init_key (sub_font, scaled_font); - - sub_font->parent = parent; - sub_font->scaled_font = scaled_font; - sub_font->font_id = font_id; - - sub_font->current_subset = 0; - sub_font->num_glyphs_in_current_subset = 0; - sub_font->max_glyphs_per_subset = max_glyphs_per_subset; - - sub_font->sub_font_glyphs = _cairo_hash_table_create (_cairo_sub_font_glyphs_equal); - if (sub_font->sub_font_glyphs == NULL) { - free (sub_font); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - sub_font->next = NULL; - - /* Reserve first glyph in subset for the .notdef glyph except for - * Type 3 fonts */ - if (! _cairo_font_face_is_user (scaled_font->font_face)) { - status = _cairo_sub_font_map_glyph (sub_font, 0, NULL, -1, &subset_glyph); - if (status) { - _cairo_hash_table_destroy (sub_font->sub_font_glyphs); - free (sub_font); - return status; - } - } - - *sub_font_out = sub_font; - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_sub_font_destroy (cairo_sub_font_t *sub_font) -{ - _cairo_hash_table_foreach (sub_font->sub_font_glyphs, - _cairo_sub_font_glyph_pluck, - sub_font->sub_font_glyphs); - _cairo_hash_table_destroy (sub_font->sub_font_glyphs); - cairo_scaled_font_destroy (sub_font->scaled_font); - free (sub_font); -} - -static void -_cairo_sub_font_pluck (void *entry, void *closure) -{ - cairo_sub_font_t *sub_font = entry; - cairo_hash_table_t *sub_fonts = closure; - - _cairo_hash_table_remove (sub_fonts, &sub_font->base); - _cairo_sub_font_destroy (sub_font); -} - -static cairo_status_t -_cairo_sub_font_glyph_lookup_unicode (cairo_sub_font_glyph_t *sub_font_glyph, - cairo_scaled_font_t *scaled_font, - unsigned long scaled_font_glyph_index) -{ - uint32_t unicode; - char buf[8]; - int len; - cairo_status_t status; - - /* Do a reverse lookup on the glyph index. unicode is -1 if the - * index could not be mapped to a unicode character. */ - unicode = -1; - status = _cairo_truetype_index_to_ucs4 (scaled_font, - scaled_font_glyph_index, - &unicode); - if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - - if (unicode == (uint32_t)-1 && scaled_font->backend->index_to_ucs4) { - status = scaled_font->backend->index_to_ucs4 (scaled_font, - scaled_font_glyph_index, - &unicode); - if (status) - return status; - } - - sub_font_glyph->unicode = unicode; - sub_font_glyph->utf8 = NULL; - sub_font_glyph->utf8_len = 0; - if (unicode != (uint32_t) -1) { - len = _cairo_ucs4_to_utf8 (unicode, buf); - if (len > 0) { - sub_font_glyph->utf8 = malloc (len + 1); - if (sub_font_glyph->utf8 == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - memcpy (sub_font_glyph->utf8, buf, len); - sub_font_glyph->utf8[len] = 0; - sub_font_glyph->utf8_len = len; - } - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_bool_t -_cairo_sub_font_glyph_map_to_unicode (cairo_sub_font_glyph_t *sub_font_glyph, - const char *utf8, - int utf8_len) -{ - if (utf8_len < 0) - return FALSE; - - if (utf8 != NULL && utf8_len != 0 && utf8[utf8_len - 1] == '\0') - utf8_len--; - - if (utf8 != NULL && utf8_len != 0) { - if (sub_font_glyph->utf8 != NULL) { - if (utf8_len == sub_font_glyph->utf8_len && - memcmp (utf8, sub_font_glyph->utf8, utf8_len) == 0) - { - /* Requested utf8 mapping matches the existing mapping */ - return TRUE; - } - else - { - /* Requested utf8 mapping does not match the existing mapping */ - return FALSE; - } - } else { - /* No existing mapping. Use the requested mapping */ - sub_font_glyph->utf8 = malloc (utf8_len + 1); - memcpy (sub_font_glyph->utf8, utf8, utf8_len); - sub_font_glyph->utf8[utf8_len] = 0; - sub_font_glyph->utf8_len = utf8_len; - return TRUE; - } - } - - /* No mapping was requested. */ - return FALSE; -} - -static cairo_bool_t -_cairo_sub_font_lookup_glyph (cairo_sub_font_t *sub_font, - unsigned long scaled_font_glyph_index, - const char *utf8, - int utf8_len, - cairo_scaled_font_subsets_glyph_t *subset_glyph) -{ - cairo_sub_font_glyph_t key, *sub_font_glyph; - - _cairo_sub_font_glyph_init_key (&key, scaled_font_glyph_index); - if (_cairo_hash_table_lookup (sub_font->sub_font_glyphs, &key.base, - (cairo_hash_entry_t **) &sub_font_glyph)) - { - subset_glyph->font_id = sub_font->font_id; - subset_glyph->subset_id = sub_font_glyph->subset_id; - subset_glyph->subset_glyph_index = sub_font_glyph->subset_glyph_index; - subset_glyph->is_scaled = sub_font->is_scaled; - subset_glyph->is_composite = sub_font->is_composite; - subset_glyph->x_advance = sub_font_glyph->x_advance; - subset_glyph->y_advance = sub_font_glyph->y_advance; - subset_glyph->utf8_is_mapped = _cairo_sub_font_glyph_map_to_unicode (sub_font_glyph, utf8, utf8_len); - subset_glyph->unicode = sub_font_glyph->unicode; - - return TRUE; - } - - return FALSE; -} - -static cairo_status_t -_cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font, - unsigned long scaled_font_glyph_index, - const char *utf8, - int utf8_len, - cairo_scaled_font_subsets_glyph_t *subset_glyph) -{ - cairo_sub_font_glyph_t key, *sub_font_glyph; - cairo_status_t status; - - _cairo_sub_font_glyph_init_key (&key, scaled_font_glyph_index); - if (! _cairo_hash_table_lookup (sub_font->sub_font_glyphs, &key.base, - (cairo_hash_entry_t **) &sub_font_glyph)) - { - cairo_scaled_glyph_t *scaled_glyph; - - if (sub_font->num_glyphs_in_current_subset == sub_font->max_glyphs_per_subset) - { - cairo_scaled_font_subsets_glyph_t tmp_subset_glyph; - - sub_font->current_subset++; - sub_font->num_glyphs_in_current_subset = 0; - - /* Reserve first glyph in subset for the .notdef glyph - * except for Type 3 fonts */ - if (! _cairo_font_face_is_user (sub_font->scaled_font->font_face)) { - status = _cairo_sub_font_map_glyph (sub_font, 0, NULL, -1, &tmp_subset_glyph); - if (status) - return status; - } - } - - _cairo_scaled_font_freeze_cache (sub_font->scaled_font); - status = _cairo_scaled_glyph_lookup (sub_font->scaled_font, - scaled_font_glyph_index, - CAIRO_SCALED_GLYPH_INFO_METRICS, - &scaled_glyph); - assert (status != CAIRO_INT_STATUS_UNSUPPORTED); - if (status) { - _cairo_scaled_font_thaw_cache (sub_font->scaled_font); - return status; - } - - sub_font_glyph = _cairo_sub_font_glyph_create (scaled_font_glyph_index, - sub_font->current_subset, - sub_font->num_glyphs_in_current_subset, - scaled_glyph->metrics.x_advance, - scaled_glyph->metrics.y_advance); - _cairo_scaled_font_thaw_cache (sub_font->scaled_font); - - if (sub_font_glyph == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - status = _cairo_sub_font_glyph_lookup_unicode (sub_font_glyph, - sub_font->scaled_font, - scaled_font_glyph_index); - if (status) { - _cairo_sub_font_glyph_destroy (sub_font_glyph); - return status; - } - - status = _cairo_hash_table_insert (sub_font->sub_font_glyphs, &sub_font_glyph->base); - if (status) { - _cairo_sub_font_glyph_destroy (sub_font_glyph); - return status; - } - - sub_font->num_glyphs_in_current_subset++; - - if (sub_font->is_scaled) { - if (sub_font->num_glyphs_in_current_subset > sub_font->parent->max_glyphs_per_scaled_subset_used) - sub_font->parent->max_glyphs_per_scaled_subset_used = sub_font->num_glyphs_in_current_subset; - } else { - if (sub_font->num_glyphs_in_current_subset > sub_font->parent->max_glyphs_per_unscaled_subset_used) - sub_font->parent->max_glyphs_per_unscaled_subset_used = sub_font->num_glyphs_in_current_subset; - } - } - - subset_glyph->font_id = sub_font->font_id; - subset_glyph->subset_id = sub_font_glyph->subset_id; - subset_glyph->subset_glyph_index = sub_font_glyph->subset_glyph_index; - subset_glyph->is_scaled = sub_font->is_scaled; - subset_glyph->is_composite = sub_font->is_composite; - subset_glyph->x_advance = sub_font_glyph->x_advance; - subset_glyph->y_advance = sub_font_glyph->y_advance; - subset_glyph->utf8_is_mapped = _cairo_sub_font_glyph_map_to_unicode (sub_font_glyph, utf8, utf8_len); - subset_glyph->unicode = sub_font_glyph->unicode; - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_sub_font_collect (void *entry, void *closure) -{ - cairo_sub_font_t *sub_font = entry; - cairo_sub_font_collection_t *collection = closure; - cairo_scaled_font_subset_t subset; - int i; - unsigned int j; - - if (collection->status) - return; - - for (i = 0; i <= sub_font->current_subset; i++) { - collection->subset_id = i; - collection->num_glyphs = 0; - collection->max_glyph = 0; - - _cairo_hash_table_foreach (sub_font->sub_font_glyphs, - _cairo_sub_font_glyph_collect, collection); - if (collection->status) - break; - if (collection->num_glyphs == 0) - continue; - - /* Ensure the resulting array has no uninitialized holes */ - assert (collection->num_glyphs == collection->max_glyph + 1); - - subset.scaled_font = sub_font->scaled_font; - subset.is_composite = sub_font->is_composite; - subset.font_id = sub_font->font_id; - subset.subset_id = i; - subset.glyphs = collection->glyphs; - subset.utf8 = collection->utf8; - subset.num_glyphs = collection->num_glyphs; - subset.glyph_names = NULL; - /* No need to check for out of memory here. If to_unicode is NULL, the PDF - * surface does not emit an ToUnicode stream */ - subset.to_unicode = _cairo_malloc_ab (collection->num_glyphs, sizeof (unsigned long)); - if (subset.to_unicode) { - for (j = 0; j < collection->num_glyphs; j++) { - /* default unicode character required when mapping fails */ - subset.to_unicode[j] = 0xfffd; - } - } - collection->status = (collection->font_subset_callback) (&subset, - collection->font_subset_callback_closure); - - if (subset.to_unicode != NULL) - free (subset.to_unicode); - - if (subset.glyph_names != NULL) { - for (j = 0; j < collection->num_glyphs; j++) - free (subset.glyph_names[j]); - free (subset.glyph_names); - } - - if (collection->status) - break; - } -} - -static cairo_scaled_font_subsets_t * -_cairo_scaled_font_subsets_create_internal (cairo_subsets_type_t type) -{ - cairo_scaled_font_subsets_t *subsets; - - subsets = malloc (sizeof (cairo_scaled_font_subsets_t)); - if (subsets == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return NULL; - } - - subsets->type = type; - subsets->max_glyphs_per_unscaled_subset_used = 0; - subsets->max_glyphs_per_scaled_subset_used = 0; - subsets->num_sub_fonts = 0; - - subsets->unscaled_sub_fonts = _cairo_hash_table_create (_cairo_sub_fonts_equal); - if (! subsets->unscaled_sub_fonts) { - free (subsets); - return NULL; - } - subsets->unscaled_sub_fonts_list = NULL; - subsets->unscaled_sub_fonts_list_end = NULL; - - subsets->scaled_sub_fonts = _cairo_hash_table_create (_cairo_sub_fonts_equal); - if (! subsets->scaled_sub_fonts) { - _cairo_hash_table_destroy (subsets->unscaled_sub_fonts); - free (subsets); - return NULL; - } - subsets->scaled_sub_fonts_list = NULL; - subsets->scaled_sub_fonts_list_end = NULL; - - return subsets; -} - -cairo_scaled_font_subsets_t * -_cairo_scaled_font_subsets_create_scaled (void) -{ - return _cairo_scaled_font_subsets_create_internal (CAIRO_SUBSETS_SCALED); -} - -cairo_scaled_font_subsets_t * -_cairo_scaled_font_subsets_create_simple (void) -{ - return _cairo_scaled_font_subsets_create_internal (CAIRO_SUBSETS_SIMPLE); -} - -cairo_scaled_font_subsets_t * -_cairo_scaled_font_subsets_create_composite (void) -{ - return _cairo_scaled_font_subsets_create_internal (CAIRO_SUBSETS_COMPOSITE); -} - -void -_cairo_scaled_font_subsets_destroy (cairo_scaled_font_subsets_t *subsets) -{ - _cairo_hash_table_foreach (subsets->scaled_sub_fonts, _cairo_sub_font_pluck, subsets->scaled_sub_fonts); - _cairo_hash_table_destroy (subsets->scaled_sub_fonts); - - _cairo_hash_table_foreach (subsets->unscaled_sub_fonts, _cairo_sub_font_pluck, subsets->unscaled_sub_fonts); - _cairo_hash_table_destroy (subsets->unscaled_sub_fonts); - - free (subsets); -} - -cairo_status_t -_cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets, - cairo_scaled_font_t *scaled_font, - unsigned long scaled_font_glyph_index, - const char * utf8, - int utf8_len, - cairo_scaled_font_subsets_glyph_t *subset_glyph) -{ - cairo_sub_font_t key, *sub_font; - cairo_scaled_glyph_t *scaled_glyph; - cairo_font_face_t *font_face; - cairo_matrix_t identity; - cairo_font_options_t font_options; - cairo_scaled_font_t *unscaled_font; - cairo_status_t status; - int max_glyphs; - cairo_bool_t type1_font; - - /* Lookup glyph in unscaled subsets */ - if (subsets->type != CAIRO_SUBSETS_SCALED) { - key.is_scaled = FALSE; - _cairo_sub_font_init_key (&key, scaled_font); - if (_cairo_hash_table_lookup (subsets->unscaled_sub_fonts, &key.base, - (cairo_hash_entry_t **) &sub_font)) - { - if (_cairo_sub_font_lookup_glyph (sub_font, - scaled_font_glyph_index, - utf8, utf8_len, - subset_glyph)) - return CAIRO_STATUS_SUCCESS; - } - } - - /* Lookup glyph in scaled subsets */ - key.is_scaled = TRUE; - _cairo_sub_font_init_key (&key, scaled_font); - if (_cairo_hash_table_lookup (subsets->scaled_sub_fonts, &key.base, - (cairo_hash_entry_t **) &sub_font)) - { - if (_cairo_sub_font_lookup_glyph (sub_font, - scaled_font_glyph_index, - utf8, utf8_len, - subset_glyph)) - return CAIRO_STATUS_SUCCESS; - } - - /* Glyph not found. Determine whether the glyph is outline or - * bitmap and add to the appropriate subset. - * - * glyph_index 0 (the .notdef glyph) is a special case. Some fonts - * will return CAIRO_INT_STATUS_UNSUPPORTED when doing a - * _scaled_glyph_lookup(_GLYPH_INFO_PATH). Type1-fallback creates - * empty glyphs in this case so we can put the glyph in a unscaled - * subset. */ - if (scaled_font_glyph_index == 0 || - _cairo_font_face_is_user (scaled_font->font_face)) { - status = CAIRO_STATUS_SUCCESS; - } else { - _cairo_scaled_font_freeze_cache (scaled_font); - status = _cairo_scaled_glyph_lookup (scaled_font, - scaled_font_glyph_index, - CAIRO_SCALED_GLYPH_INFO_PATH, - &scaled_glyph); - _cairo_scaled_font_thaw_cache (scaled_font); - } - if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - - if (status == CAIRO_STATUS_SUCCESS && - subsets->type != CAIRO_SUBSETS_SCALED && - ! _cairo_font_face_is_user (scaled_font->font_face)) - { - /* Path available. Add to unscaled subset. */ - key.is_scaled = FALSE; - _cairo_sub_font_init_key (&key, scaled_font); - if (! _cairo_hash_table_lookup (subsets->unscaled_sub_fonts, &key.base, - (cairo_hash_entry_t **) &sub_font)) - { - font_face = cairo_scaled_font_get_font_face (scaled_font); - cairo_matrix_init_identity (&identity); - _cairo_font_options_init_default (&font_options); - cairo_font_options_set_hint_style (&font_options, CAIRO_HINT_STYLE_NONE); - cairo_font_options_set_hint_metrics (&font_options, CAIRO_HINT_METRICS_OFF); - unscaled_font = cairo_scaled_font_create (font_face, - &identity, - &identity, - &font_options); - if (unscaled_font->status) - return unscaled_font->status; - - subset_glyph->is_scaled = FALSE; - type1_font = FALSE; -#if CAIRO_HAS_FT_FONT - type1_font = _cairo_type1_scaled_font_is_type1 (unscaled_font); -#endif - if (subsets->type == CAIRO_SUBSETS_COMPOSITE && !type1_font) { - max_glyphs = MAX_GLYPHS_PER_COMPOSITE_FONT; - subset_glyph->is_composite = TRUE; - } else { - max_glyphs = MAX_GLYPHS_PER_SIMPLE_FONT; - subset_glyph->is_composite = FALSE; - } - - status = _cairo_sub_font_create (subsets, - unscaled_font, - subsets->num_sub_fonts, - max_glyphs, - subset_glyph->is_scaled, - subset_glyph->is_composite, - &sub_font); - - if (status) { - cairo_scaled_font_destroy (unscaled_font); - return status; - } - - status = _cairo_hash_table_insert (subsets->unscaled_sub_fonts, - &sub_font->base); - - if (status) { - _cairo_sub_font_destroy (sub_font); - return status; - } - if (!subsets->unscaled_sub_fonts_list) - subsets->unscaled_sub_fonts_list = sub_font; - else - subsets->unscaled_sub_fonts_list_end->next = sub_font; - subsets->unscaled_sub_fonts_list_end = sub_font; - subsets->num_sub_fonts++; - } - } else { - /* No path available. Add to scaled subset. */ - key.is_scaled = TRUE; - _cairo_sub_font_init_key (&key, scaled_font); - if (! _cairo_hash_table_lookup (subsets->scaled_sub_fonts, &key.base, - (cairo_hash_entry_t **) &sub_font)) - { - subset_glyph->is_scaled = TRUE; - subset_glyph->is_composite = FALSE; - if (subsets->type == CAIRO_SUBSETS_SCALED) - max_glyphs = INT_MAX; - else - max_glyphs = MAX_GLYPHS_PER_SIMPLE_FONT; - - status = _cairo_sub_font_create (subsets, - cairo_scaled_font_reference (scaled_font), - subsets->num_sub_fonts, - max_glyphs, - subset_glyph->is_scaled, - subset_glyph->is_composite, - &sub_font); - if (status) { - cairo_scaled_font_destroy (scaled_font); - return status; - } - - status = _cairo_hash_table_insert (subsets->scaled_sub_fonts, - &sub_font->base); - if (status) { - _cairo_sub_font_destroy (sub_font); - return status; - } - if (!subsets->scaled_sub_fonts_list) - subsets->scaled_sub_fonts_list = sub_font; - else - subsets->scaled_sub_fonts_list_end->next = sub_font; - subsets->scaled_sub_fonts_list_end = sub_font; - subsets->num_sub_fonts++; - } - } - - return _cairo_sub_font_map_glyph (sub_font, - scaled_font_glyph_index, - utf8, utf8_len, - subset_glyph); -} - -static cairo_status_t -_cairo_scaled_font_subsets_foreach_internal (cairo_scaled_font_subsets_t *font_subsets, - cairo_scaled_font_subset_callback_func_t font_subset_callback, - void *closure, - cairo_subsets_foreach_type_t type) -{ - cairo_sub_font_collection_t collection; - cairo_sub_font_t *sub_font; - cairo_bool_t is_scaled, is_user; - - is_scaled = FALSE; - is_user = FALSE; - - if (type == CAIRO_SUBSETS_FOREACH_USER) - is_user = TRUE; - - if (type == CAIRO_SUBSETS_FOREACH_SCALED || - type == CAIRO_SUBSETS_FOREACH_USER) - { - is_scaled = TRUE; - } - - if (is_scaled) - collection.glyphs_size = font_subsets->max_glyphs_per_scaled_subset_used; - else - collection.glyphs_size = font_subsets->max_glyphs_per_unscaled_subset_used; - - if (! collection.glyphs_size) - return CAIRO_STATUS_SUCCESS; - - collection.glyphs = _cairo_malloc_ab (collection.glyphs_size, sizeof(unsigned long)); - collection.utf8 = _cairo_malloc_ab (collection.glyphs_size, sizeof(char *)); - if (collection.glyphs == NULL || collection.utf8 == NULL) { - if (collection.glyphs != NULL) - free (collection.glyphs); - if (collection.utf8 != NULL) - free (collection.utf8); - - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - collection.font_subset_callback = font_subset_callback; - collection.font_subset_callback_closure = closure; - collection.status = CAIRO_STATUS_SUCCESS; - - if (is_scaled) - sub_font = font_subsets->scaled_sub_fonts_list; - else - sub_font = font_subsets->unscaled_sub_fonts_list; - - while (sub_font) { - if (sub_font->is_user == is_user) - _cairo_sub_font_collect (sub_font, &collection); - - sub_font = sub_font->next; - } - free (collection.utf8); - free (collection.glyphs); - - return collection.status; -} - -cairo_status_t -_cairo_scaled_font_subsets_foreach_scaled (cairo_scaled_font_subsets_t *font_subsets, - cairo_scaled_font_subset_callback_func_t font_subset_callback, - void *closure) -{ - return _cairo_scaled_font_subsets_foreach_internal (font_subsets, - font_subset_callback, - closure, - CAIRO_SUBSETS_FOREACH_SCALED); -} - -cairo_status_t -_cairo_scaled_font_subsets_foreach_unscaled (cairo_scaled_font_subsets_t *font_subsets, - cairo_scaled_font_subset_callback_func_t font_subset_callback, - void *closure) -{ - return _cairo_scaled_font_subsets_foreach_internal (font_subsets, - font_subset_callback, - closure, - CAIRO_SUBSETS_FOREACH_UNSCALED); -} - -cairo_status_t -_cairo_scaled_font_subsets_foreach_user (cairo_scaled_font_subsets_t *font_subsets, - cairo_scaled_font_subset_callback_func_t font_subset_callback, - void *closure) -{ - return _cairo_scaled_font_subsets_foreach_internal (font_subsets, - font_subset_callback, - closure, - CAIRO_SUBSETS_FOREACH_USER); -} - -static cairo_bool_t -_cairo_string_equal (const void *key_a, const void *key_b) -{ - const cairo_string_entry_t *a = key_a; - const cairo_string_entry_t *b = key_b; - - if (strcmp (a->string, b->string) == 0) - return TRUE; - else - return FALSE; -} - -static void -_cairo_string_init_key (cairo_string_entry_t *key, char *s) -{ - unsigned long sum = 0; - unsigned int i; - - for (i = 0; i < strlen(s); i++) - sum += s[i]; - key->base.hash = sum; - key->string = s; -} - -static cairo_status_t -create_string_entry (char *s, cairo_string_entry_t **entry) -{ - *entry = malloc (sizeof (cairo_string_entry_t)); - if (*entry == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - _cairo_string_init_key (*entry, s); - - return CAIRO_STATUS_SUCCESS; -} - -cairo_int_status_t -_cairo_scaled_font_subset_create_glyph_names (cairo_scaled_font_subset_t *subset) -{ - unsigned int i; - cairo_status_t status; - cairo_hash_table_t *names; - cairo_string_entry_t key, *entry; - char buf[30]; - char *utf8; - uint16_t *utf16; - int utf16_len; - - names = _cairo_hash_table_create (_cairo_string_equal); - if (names == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - subset->glyph_names = calloc (subset->num_glyphs, sizeof (char *)); - if (subset->glyph_names == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto CLEANUP_HASH; - } - - i = 0; - if (! _cairo_font_face_is_user (subset->scaled_font->font_face)) { - subset->glyph_names[0] = strdup (".notdef"); - if (subset->glyph_names[0] == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto CLEANUP_HASH; - } - - status = create_string_entry (subset->glyph_names[0], &entry); - if (status) - goto CLEANUP_HASH; - - status = _cairo_hash_table_insert (names, &entry->base); - if (status) { - free (entry); - goto CLEANUP_HASH; - } - i++; - } - - for (; i < subset->num_glyphs; i++) { - utf8 = subset->utf8[i]; - utf16 = NULL; - utf16_len = 0; - if (utf8 && *utf8) { - status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &utf16_len); - if (status) - return status; /* FIXME */ - } - - if (utf16_len == 1) { - snprintf (buf, sizeof(buf), "uni%04X", (int)(utf16[0])); - _cairo_string_init_key (&key, buf); - if (_cairo_hash_table_lookup (names, &key.base, - (cairo_hash_entry_t **) &entry)) { - snprintf (buf, sizeof(buf), "g%d", i); - } - } else { - snprintf (buf, sizeof(buf), "g%d", i); - } - if (utf16) - free (utf16); - - subset->glyph_names[i] = strdup (buf); - if (subset->glyph_names[i] == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto CLEANUP_HASH; - } - - status = create_string_entry (subset->glyph_names[i], &entry); - if (status) - goto CLEANUP_HASH; - - status = _cairo_hash_table_insert (names, &entry->base); - if (status) { - free (entry); - goto CLEANUP_HASH; - } - } - -CLEANUP_HASH: - while (1) { - entry = _cairo_hash_table_random_entry (names, NULL); - if (entry == NULL) - break; - - _cairo_hash_table_remove (names, (cairo_hash_entry_t *) entry); - free (entry); - } - _cairo_hash_table_destroy (names); - - if (status == CAIRO_STATUS_SUCCESS) - return CAIRO_STATUS_SUCCESS; - - if (subset->glyph_names != NULL) { - for (i = 0; i < subset->num_glyphs; i++) { - if (subset->glyph_names[i] != NULL) - free (subset->glyph_names[i]); - } - - free (subset->glyph_names); - subset->glyph_names = NULL; - } - - return status; -} - -#endif /* CAIRO_HAS_FONT_SUBSET */ diff --git a/uppdev/plugin/cairo/lib/cairo-scaled-font.c b/uppdev/plugin/cairo/lib/cairo-scaled-font.c deleted file mode 100644 index 3c5a95983..000000000 --- a/uppdev/plugin/cairo/lib/cairo-scaled-font.c +++ /dev/null @@ -1,2569 +0,0 @@ -/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */ -/* - * Copyright © 2005 Keith Packard - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Keith Packard - * - * Contributor(s): - * Keith Packard - * Carl D. Worth - * Graydon Hoare - * Owen Taylor - * Behdad Esfahbod - */ - -#include "cairoint.h" -#include "cairo-scaled-font-private.h" - -/* - * Notes: - * - * To store rasterizations of glyphs, we use an image surface and the - * device offset to represent the glyph origin. - * - * A device_transform converts from device space (a conceptual space) to - * surface space. For simple cases of translation only, it's called a - * device_offset and is public API (cairo_surface_[gs]et_device_offset()). - * A possibly better name for those functions could have been - * cairo_surface_[gs]et_origin(). So, that's what they do: they set where - * the device-space origin (0,0) is in the surface. If the origin is inside - * the surface, device_offset values are positive. It may look like this: - * - * Device space: - * (-x,-y) <-- negative numbers - * +----------------+ - * | . | - * | . | - * |......(0,0) <---|-- device-space origin - * | | - * | | - * +----------------+ - * (width-x,height-y) - * - * Surface space: - * (0,0) <-- surface-space origin - * +---------------+ - * | . | - * | . | - * |......(x,y) <--|-- device_offset - * | | - * | | - * +---------------+ - * (width,height) - * - * In other words: device_offset is the coordinates of the device-space - * origin relative to the top-left of the surface. - * - * We use device offsets in a couple of places: - * - * - Public API: To let toolkits like Gtk+ give user a surface that - * only represents part of the final destination (say, the expose - * area), but has the same device space as the destination. In these - * cases device_offset is typically negative. Example: - * - * application window - * +---------------+ - * | . | - * | (x,y). | - * |......+---+ | - * | | | <--|-- expose area - * | +---+ | - * +---------------+ - * - * In this case, the user of cairo API can set the device_space on - * the expose area to (-x,-y) to move the device space origin to that - * of the application window, such that drawing in the expose area - * surface and painting it in the application window has the same - * effect as drawing in the application window directly. Gtk+ has - * been using this feature. - * - * - Glyph surfaces: In most font rendering systems, glyph surfaces - * have an origin at (0,0) and a bounding box that is typically - * represented as (x_bearing,y_bearing,width,height). Depending on - * which way y progresses in the system, y_bearing may typically be - * negative (for systems similar to cairo, with origin at top left), - * or be positive (in systems like PDF with origin at bottom left). - * No matter which is the case, it is important to note that - * (x_bearing,y_bearing) is the coordinates of top-left of the glyph - * relative to the glyph origin. That is, for example: - * - * Scaled-glyph space: - * - * (x_bearing,y_bearing) <-- negative numbers - * +----------------+ - * | . | - * | . | - * |......(0,0) <---|-- glyph origin - * | | - * | | - * +----------------+ - * (width+x_bearing,height+y_bearing) - * - * Note the similarity of the origin to the device space. That is - * exactly how we use the device_offset to represent scaled glyphs: - * to use the device-space origin as the glyph origin. - * - * Now compare the scaled-glyph space to device-space and surface-space - * and convince yourself that: - * - * (x_bearing,y_bearing) = (-x,-y) = - device_offset - * - * That's right. If you are not convinced yet, contrast the definition - * of the two: - * - * "(x_bearing,y_bearing) is the coordinates of top-left of the - * glyph relative to the glyph origin." - * - * "In other words: device_offset is the coordinates of the - * device-space origin relative to the top-left of the surface." - * - * and note that glyph origin = device-space origin. - */ - -static void -_cairo_scaled_font_fini_internal (cairo_scaled_font_t *scaled_font); - -static cairo_bool_t -_cairo_scaled_glyph_keys_equal (const void *abstract_key_a, const void *abstract_key_b) -{ - const cairo_scaled_glyph_t *key_a = abstract_key_a; - const cairo_scaled_glyph_t *key_b = abstract_key_b; - - return (_cairo_scaled_glyph_index (key_a) == - _cairo_scaled_glyph_index (key_b)); -} - -static void -_cairo_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph) -{ - cairo_scaled_font_t *scaled_font = scaled_glyph->scaled_font; - const cairo_surface_backend_t *surface_backend = scaled_font->surface_backend; - - if (surface_backend != NULL && surface_backend->scaled_glyph_fini != NULL) - surface_backend->scaled_glyph_fini (scaled_glyph, scaled_font); - if (scaled_glyph->surface != NULL) - cairo_surface_destroy (&scaled_glyph->surface->base); - if (scaled_glyph->path != NULL) - _cairo_path_fixed_destroy (scaled_glyph->path); - if (scaled_glyph->meta_surface != NULL) - cairo_surface_destroy (scaled_glyph->meta_surface); -} - -static void -_cairo_scaled_glyph_destroy (void *abstract_glyph) -{ - cairo_scaled_glyph_t *scaled_glyph = abstract_glyph; - _cairo_scaled_glyph_fini (scaled_glyph); - free (scaled_glyph); -} - -#define ZOMBIE 0 -static const cairo_scaled_font_t _cairo_scaled_font_nil = { - { ZOMBIE }, /* hash_entry */ - CAIRO_STATUS_NO_MEMORY, /* status */ - CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */ - { 0, 0, 0, NULL }, /* user_data */ - NULL, /* font_face */ - { 1., 0., 0., 1., 0, 0}, /* font_matrix */ - { 1., 0., 0., 1., 0, 0}, /* ctm */ - { CAIRO_ANTIALIAS_DEFAULT, /* options */ - CAIRO_SUBPIXEL_ORDER_DEFAULT, - CAIRO_HINT_STYLE_DEFAULT, - CAIRO_HINT_METRICS_DEFAULT} , - FALSE, /* placeholder */ - TRUE, /* finished */ - { 1., 0., 0., 1., 0, 0}, /* scale */ - { 1., 0., 0., 1., 0, 0}, /* scale_inverse */ - 1., /* max_scale */ - { 0., 0., 0., 0., 0. }, /* extents */ - CAIRO_MUTEX_NIL_INITIALIZER,/* mutex */ - NULL, /* glyphs */ - NULL, /* surface_backend */ - NULL, /* surface_private */ - CAIRO_SCALED_FONT_BACKEND_DEFAULT, -}; - -/** - * _cairo_scaled_font_set_error: - * @scaled_font: a scaled_font - * @status: a status value indicating an error - * - * Atomically sets scaled_font->status to @status and calls _cairo_error; - * Does nothing if status is %CAIRO_STATUS_SUCCESS. - * - * All assignments of an error status to scaled_font->status should happen - * through _cairo_scaled_font_set_error(). Note that due to the nature of - * the atomic operation, it is not safe to call this function on the nil - * objects. - * - * The purpose of this function is to allow the user to set a - * breakpoint in _cairo_error() to generate a stack trace for when the - * user causes cairo to detect an error. - * - * Return value: the error status. - **/ -cairo_status_t -_cairo_scaled_font_set_error (cairo_scaled_font_t *scaled_font, - cairo_status_t status) -{ - if (status == CAIRO_STATUS_SUCCESS) - return status; - - /* Don't overwrite an existing error. This preserves the first - * error, which is the most significant. */ - _cairo_status_set_error (&scaled_font->status, status); - - return _cairo_error (status); -} - -/** - * cairo_scaled_font_get_type: - * @scaled_font: a #cairo_scaled_font_t - * - * This function returns the type of the backend used to create - * a scaled font. See #cairo_font_type_t for available types. - * - * Return value: The type of @scaled_font. - * - * Since: 1.2 - **/ -cairo_font_type_t -cairo_scaled_font_get_type (cairo_scaled_font_t *scaled_font) -{ - if (CAIRO_REFERENCE_COUNT_IS_INVALID (&scaled_font->ref_count)) - return CAIRO_FONT_TYPE_TOY; - - return scaled_font->backend->type; -} - -/** - * cairo_scaled_font_status: - * @scaled_font: a #cairo_scaled_font_t - * - * Checks whether an error has previously occurred for this - * scaled_font. - * - * Return value: %CAIRO_STATUS_SUCCESS or another error such as - * %CAIRO_STATUS_NO_MEMORY. - **/ -cairo_status_t -cairo_scaled_font_status (cairo_scaled_font_t *scaled_font) -{ - return scaled_font->status; -} -slim_hidden_def (cairo_scaled_font_status); - -/* Here we keep a unique mapping from - * font_face/matrix/ctm/font_options => #cairo_scaled_font_t. - * - * Here are the things that we want to map: - * - * a) All otherwise referenced #cairo_scaled_font_t's - * b) Some number of not otherwise referenced #cairo_scaled_font_t's - * - * The implementation uses a hash table which covers (a) - * completely. Then, for (b) we have an array of otherwise - * unreferenced fonts (holdovers) which are expired in - * least-recently-used order. - * - * The cairo_scaled_font_create() code gets to treat this like a regular - * hash table. All of the magic for the little holdover cache is in - * cairo_scaled_font_reference() and cairo_scaled_font_destroy(). - */ - -/* This defines the size of the holdover array ... that is, the number - * of scaled fonts we keep around even when not otherwise referenced - */ -#define CAIRO_SCALED_FONT_MAX_HOLDOVERS 256 - -typedef struct _cairo_scaled_font_map { - cairo_scaled_font_t *mru_scaled_font; - cairo_hash_table_t *hash_table; - cairo_scaled_font_t *holdovers[CAIRO_SCALED_FONT_MAX_HOLDOVERS]; - int num_holdovers; -} cairo_scaled_font_map_t; - -static cairo_scaled_font_map_t *cairo_scaled_font_map = NULL; - -static int -_cairo_scaled_font_keys_equal (const void *abstract_key_a, const void *abstract_key_b); - -static cairo_scaled_font_map_t * -_cairo_scaled_font_map_lock (void) -{ - CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex); - - if (cairo_scaled_font_map == NULL) { - cairo_scaled_font_map = malloc (sizeof (cairo_scaled_font_map_t)); - if (cairo_scaled_font_map == NULL) - goto CLEANUP_MUTEX_LOCK; - - cairo_scaled_font_map->mru_scaled_font = NULL; - cairo_scaled_font_map->hash_table = - _cairo_hash_table_create (_cairo_scaled_font_keys_equal); - - if (cairo_scaled_font_map->hash_table == NULL) - goto CLEANUP_SCALED_FONT_MAP; - - cairo_scaled_font_map->num_holdovers = 0; - } - - return cairo_scaled_font_map; - - CLEANUP_SCALED_FONT_MAP: - free (cairo_scaled_font_map); - cairo_scaled_font_map = NULL; - CLEANUP_MUTEX_LOCK: - CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex); - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return NULL; -} - -static void -_cairo_scaled_font_map_unlock (void) -{ - CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex); -} - -void -_cairo_scaled_font_map_destroy (void) -{ - cairo_scaled_font_map_t *font_map; - cairo_scaled_font_t *scaled_font; - - CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex); - - font_map = cairo_scaled_font_map; - if (font_map == NULL) { - goto CLEANUP_MUTEX_LOCK; - } - - scaled_font = font_map->mru_scaled_font; - if (scaled_font != NULL) { - CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex); - cairo_scaled_font_destroy (scaled_font); - CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex); - } - - /* remove scaled_fonts starting from the end so that font_map->holdovers - * is always in a consistent state when we release the mutex. */ - while (font_map->num_holdovers) { - scaled_font = font_map->holdovers[font_map->num_holdovers-1]; - assert (! CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&scaled_font->ref_count)); - _cairo_hash_table_remove (font_map->hash_table, - &scaled_font->hash_entry); - - font_map->num_holdovers--; - - /* This releases the font_map lock to avoid the possibility of a - * recursive deadlock when the scaled font destroy closure gets - * called - */ - _cairo_scaled_font_fini (scaled_font); - - free (scaled_font); - } - - _cairo_hash_table_destroy (font_map->hash_table); - - free (cairo_scaled_font_map); - cairo_scaled_font_map = NULL; - - CLEANUP_MUTEX_LOCK: - CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex); -} - - -/* If a scaled font wants to unlock the font map while still being - * created (needed for user-fonts), we need to take extra care not - * ending up with multiple identical scaled fonts being created. - * - * What we do is, we create a fake identical scaled font, and mark - * it as placeholder, lock its mutex, and insert that in the fontmap - * hash table. This makes other code trying to create an identical - * scaled font to just wait and retry. - * - * The reason we have to create a fake scaled font instead of just using - * scaled_font is for lifecycle management: we need to (or rather, - * other code needs to) reference the scaled_font in the hash table. - * We can't do that on the input scaled_font as it may be freed by - * font backend upon error. - */ - -cairo_status_t -_cairo_scaled_font_register_placeholder_and_unlock_font_map (cairo_scaled_font_t *scaled_font) -{ - cairo_status_t status; - cairo_scaled_font_t *placeholder_scaled_font; - - assert (CAIRO_MUTEX_IS_LOCKED (_cairo_scaled_font_map_mutex)); - - status = scaled_font->status; - if (status) - return status; - - placeholder_scaled_font = malloc (sizeof (cairo_scaled_font_t)); - if (placeholder_scaled_font == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - /* full initialization is wasteful, but who cares... */ - status = _cairo_scaled_font_init (placeholder_scaled_font, - scaled_font->font_face, - &scaled_font->font_matrix, - &scaled_font->ctm, - &scaled_font->options, - NULL); - if (status) - goto FREE_PLACEHOLDER; - - placeholder_scaled_font->placeholder = TRUE; - - status = _cairo_hash_table_insert (cairo_scaled_font_map->hash_table, - &placeholder_scaled_font->hash_entry); - if (status) - goto FINI_PLACEHOLDER; - - CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex); - CAIRO_MUTEX_LOCK (placeholder_scaled_font->mutex); - - return CAIRO_STATUS_SUCCESS; - - FINI_PLACEHOLDER: - _cairo_scaled_font_fini_internal (placeholder_scaled_font); - FREE_PLACEHOLDER: - free (placeholder_scaled_font); - - return _cairo_scaled_font_set_error (scaled_font, status); -} - -void -_cairo_scaled_font_unregister_placeholder_and_lock_font_map (cairo_scaled_font_t *scaled_font) -{ - cairo_scaled_font_t *placeholder_scaled_font; - cairo_bool_t found; - - CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex); - - found = _cairo_hash_table_lookup (cairo_scaled_font_map->hash_table, - &scaled_font->hash_entry, - (cairo_hash_entry_t**) &placeholder_scaled_font); - assert (found); - assert (placeholder_scaled_font->placeholder); - assert (CAIRO_MUTEX_IS_LOCKED (placeholder_scaled_font->mutex)); - - _cairo_hash_table_remove (cairo_scaled_font_map->hash_table, - &scaled_font->hash_entry); - - CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex); - - CAIRO_MUTEX_UNLOCK (placeholder_scaled_font->mutex); - cairo_scaled_font_destroy (placeholder_scaled_font); - - CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex); -} - -static void -_cairo_scaled_font_placeholder_wait_for_creation_to_finish (cairo_scaled_font_t *placeholder_scaled_font) -{ - /* reference the place holder so it doesn't go away */ - cairo_scaled_font_reference (placeholder_scaled_font); - - /* now unlock the fontmap mutex so creation has a chance to finish */ - CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex); - - /* wait on placeholder mutex until we are awaken */ - CAIRO_MUTEX_LOCK (placeholder_scaled_font->mutex); - - /* ok, creation done. just clean up and back out */ - CAIRO_MUTEX_UNLOCK (placeholder_scaled_font->mutex); - cairo_scaled_font_destroy (placeholder_scaled_font); - - CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex); -} - -/* Fowler / Noll / Vo (FNV) Hash (http://www.isthe.com/chongo/tech/comp/fnv/) - * - * Not necessarily better than a lot of other hashes, but should be OK, and - * well tested with binary data. - */ - -#define FNV_32_PRIME ((uint32_t)0x01000193) -#define FNV1_32_INIT ((uint32_t)0x811c9dc5) - -static uint32_t -_hash_bytes_fnv (unsigned char *buffer, - int len, - uint32_t hval) -{ - while (len--) { - hval *= FNV_32_PRIME; - hval ^= *buffer++; - } - - return hval; -} - -static void -_cairo_scaled_font_init_key (cairo_scaled_font_t *scaled_font, - cairo_font_face_t *font_face, - const cairo_matrix_t *font_matrix, - const cairo_matrix_t *ctm, - const cairo_font_options_t *options) -{ - uint32_t hash = FNV1_32_INIT; - - scaled_font->status = CAIRO_STATUS_SUCCESS; - scaled_font->placeholder = FALSE; - scaled_font->font_face = font_face; - scaled_font->font_matrix = *font_matrix; - scaled_font->ctm = *ctm; - /* ignore translation values in the ctm */ - scaled_font->ctm.x0 = 0.; - scaled_font->ctm.y0 = 0.; - _cairo_font_options_init_copy (&scaled_font->options, options); - - /* We do a bytewise hash on the font matrices */ - hash = _hash_bytes_fnv ((unsigned char *)(&scaled_font->font_matrix.xx), - sizeof(cairo_matrix_t), hash); - hash = _hash_bytes_fnv ((unsigned char *)(&scaled_font->ctm.xx), - sizeof(cairo_matrix_t), hash); - - hash ^= (unsigned long) scaled_font->font_face; - - hash ^= cairo_font_options_hash (&scaled_font->options); - - assert (hash != ZOMBIE); - scaled_font->hash_entry.hash = hash; -} - -static cairo_bool_t -_cairo_scaled_font_keys_equal (const void *abstract_key_a, const void *abstract_key_b) -{ - const cairo_scaled_font_t *key_a = abstract_key_a; - const cairo_scaled_font_t *key_b = abstract_key_b; - - return (key_a->font_face == key_b->font_face && - memcmp ((unsigned char *)(&key_a->font_matrix.xx), - (unsigned char *)(&key_b->font_matrix.xx), - sizeof(cairo_matrix_t)) == 0 && - memcmp ((unsigned char *)(&key_a->ctm.xx), - (unsigned char *)(&key_b->ctm.xx), - sizeof(cairo_matrix_t)) == 0 && - cairo_font_options_equal (&key_a->options, &key_b->options)); -} - -/* XXX: This 256 number is arbitrary---we've never done any measurement - * of this. In fact, having a per-font glyph caches each managed - * separately is probably not what we want anyway. Would probably be - * much better to have a single cache for glyphs with random - * replacement across all glyphs of all fonts. */ -#define MAX_GLYPHS_CACHED_PER_FONT 256 - -/* - * Basic #cairo_scaled_font_t object management - */ - -cairo_status_t -_cairo_scaled_font_init (cairo_scaled_font_t *scaled_font, - cairo_font_face_t *font_face, - const cairo_matrix_t *font_matrix, - const cairo_matrix_t *ctm, - const cairo_font_options_t *options, - const cairo_scaled_font_backend_t *backend) -{ - cairo_status_t status; - - status = cairo_font_options_status ((cairo_font_options_t *) options); - if (status) - return status; - - _cairo_scaled_font_init_key (scaled_font, font_face, - font_matrix, ctm, options); - - cairo_matrix_multiply (&scaled_font->scale, - &scaled_font->font_matrix, - &scaled_font->ctm); - - scaled_font->max_scale = MAX (fabs (scaled_font->scale.xx) + fabs (scaled_font->scale.xy), - fabs (scaled_font->scale.yx) + fabs (scaled_font->scale.yy)); - scaled_font->scale_inverse = scaled_font->scale; - status = cairo_matrix_invert (&scaled_font->scale_inverse); - if (status) { - /* If the font scale matrix is rank 0, just using an all-zero inverse matrix - * makes everything work correctly. This make font size 0 work without - * producing an error. - * - * FIXME: If the scale is rank 1, we still go into error mode. But then - * again, that's what we do everywhere in cairo. - * - * Also, the check for == 0. below may be too harsh... - */ - if (scaled_font->scale.xx == 0. && scaled_font->scale.xy == 0. && - scaled_font->scale.yx == 0. && scaled_font->scale.yy == 0.) - cairo_matrix_init (&scaled_font->scale_inverse, - 0, 0, 0, 0, - -scaled_font->scale.x0, - -scaled_font->scale.y0); - else - return status; - } - - scaled_font->finished = FALSE; - - scaled_font->glyphs = _cairo_cache_create (_cairo_scaled_glyph_keys_equal, - _cairo_scaled_glyph_destroy, - MAX_GLYPHS_CACHED_PER_FONT); - if (scaled_font->glyphs == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - CAIRO_REFERENCE_COUNT_INIT (&scaled_font->ref_count, 1); - - _cairo_user_data_array_init (&scaled_font->user_data); - - cairo_font_face_reference (font_face); - - CAIRO_MUTEX_INIT (scaled_font->mutex); - - scaled_font->surface_backend = NULL; - scaled_font->surface_private = NULL; - - scaled_font->backend = backend; - - return CAIRO_STATUS_SUCCESS; -} - -void -_cairo_scaled_font_freeze_cache (cairo_scaled_font_t *scaled_font) -{ - /* ensure we do not modify an error object */ - assert (scaled_font->status == CAIRO_STATUS_SUCCESS); - - CAIRO_MUTEX_LOCK (scaled_font->mutex); - _cairo_cache_freeze (scaled_font->glyphs); -} - -void -_cairo_scaled_font_thaw_cache (cairo_scaled_font_t *scaled_font) -{ - _cairo_cache_thaw (scaled_font->glyphs); - CAIRO_MUTEX_UNLOCK (scaled_font->mutex); -} - -void -_cairo_scaled_font_reset_cache (cairo_scaled_font_t *scaled_font) -{ - assert (CAIRO_MUTEX_IS_LOCKED (scaled_font->mutex)); - - _cairo_cache_destroy (scaled_font->glyphs); - scaled_font->glyphs = _cairo_cache_create (_cairo_scaled_glyph_keys_equal, - _cairo_scaled_glyph_destroy, - MAX_GLYPHS_CACHED_PER_FONT); -} - -cairo_status_t -_cairo_scaled_font_set_metrics (cairo_scaled_font_t *scaled_font, - cairo_font_extents_t *fs_metrics) -{ - cairo_status_t status; - double font_scale_x, font_scale_y; - - status = _cairo_matrix_compute_basis_scale_factors (&scaled_font->font_matrix, - &font_scale_x, &font_scale_y, - 1); - if (status) - return status; - - /* - * The font responded in unscaled units, scale by the font - * matrix scale factors to get to user space - */ - - scaled_font->extents.ascent = fs_metrics->ascent * font_scale_y; - scaled_font->extents.descent = fs_metrics->descent * font_scale_y; - scaled_font->extents.height = fs_metrics->height * font_scale_y; - scaled_font->extents.max_x_advance = fs_metrics->max_x_advance * font_scale_x; - scaled_font->extents.max_y_advance = fs_metrics->max_y_advance * font_scale_y; - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_scaled_font_fini_internal (cairo_scaled_font_t *scaled_font) -{ - scaled_font->finished = TRUE; - - if (scaled_font->font_face != NULL) - cairo_font_face_destroy (scaled_font->font_face); - - if (scaled_font->glyphs != NULL) - _cairo_cache_destroy (scaled_font->glyphs); - - CAIRO_MUTEX_FINI (scaled_font->mutex); - - if (scaled_font->surface_backend != NULL && - scaled_font->surface_backend->scaled_font_fini != NULL) - scaled_font->surface_backend->scaled_font_fini (scaled_font); - - if (scaled_font->backend != NULL && scaled_font->backend->fini != NULL) - scaled_font->backend->fini (scaled_font); - - _cairo_user_data_array_fini (&scaled_font->user_data); -} - -void -_cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font) -{ - /* Release the lock to avoid the possibility of a recursive - * deadlock when the scaled font destroy closure gets called. */ - CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex); - _cairo_scaled_font_fini_internal (scaled_font); - CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex); -} - -/** - * cairo_scaled_font_create: - * @font_face: a #cairo_font_face_t - * @font_matrix: font space to user space transformation matrix for the - * font. In the simplest case of a N point font, this matrix is - * just a scale by N, but it can also be used to shear the font - * or stretch it unequally along the two axes. See - * cairo_set_font_matrix(). - * @ctm: user to device transformation matrix with which the font will - * be used. - * @options: options to use when getting metrics for the font and - * rendering with it. - * - * Creates a #cairo_scaled_font_t object from a font face and matrices that - * describe the size of the font and the environment in which it will - * be used. - * - * Return value: a newly created #cairo_scaled_font_t. Destroy with - * cairo_scaled_font_destroy() - **/ -cairo_scaled_font_t * -cairo_scaled_font_create (cairo_font_face_t *font_face, - const cairo_matrix_t *font_matrix, - const cairo_matrix_t *ctm, - const cairo_font_options_t *options) -{ - cairo_status_t status; - cairo_font_face_t *impl_face; - cairo_scaled_font_map_t *font_map; - cairo_scaled_font_t key, *old = NULL, *scaled_font = NULL; - - if (font_face->status) - return _cairo_scaled_font_create_in_error (font_face->status); - - status = cairo_font_options_status ((cairo_font_options_t *) options); - if (status) - return _cairo_scaled_font_create_in_error (status); - - /* Note that degenerate ctm or font_matrix *are* allowed. - * We want to support a font size of 0. */ - - if (font_face->backend->get_implementation != NULL) { - /* indirect implementation, lookup the face that is used for the key */ - status = font_face->backend->get_implementation (font_face, &impl_face); - if (status) - return _cairo_scaled_font_create_in_error (status); - } else - impl_face = font_face; - - font_map = _cairo_scaled_font_map_lock (); - if (font_map == NULL) - return _cairo_scaled_font_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - _cairo_scaled_font_init_key (&key, impl_face, - font_matrix, ctm, options); - scaled_font = font_map->mru_scaled_font; - if (scaled_font != NULL && - scaled_font->hash_entry.hash == key.hash_entry.hash && - _cairo_scaled_font_keys_equal (scaled_font, &key)) - { - assert (! scaled_font->placeholder); - - if (scaled_font->status == CAIRO_STATUS_SUCCESS) { - /* We increment the reference count manually here, (rather - * than calling into cairo_scaled_font_reference), since we - * must modify the reference count while our lock is still - * held. */ - _cairo_reference_count_inc (&scaled_font->ref_count); - _cairo_scaled_font_map_unlock (); - return scaled_font; - } - - /* the font has been put into an error status - abandon the cache */ - _cairo_hash_table_remove (font_map->hash_table, &key.hash_entry); - scaled_font->hash_entry.hash = ZOMBIE; - } - else - { - while (_cairo_hash_table_lookup (font_map->hash_table, &key.hash_entry, - (cairo_hash_entry_t**) &scaled_font)) - { - if (! scaled_font->placeholder) - break; - - /* If the scaled font is being created (happens for user-font), - * just wait until it's done, then retry */ - _cairo_scaled_font_placeholder_wait_for_creation_to_finish (scaled_font); - } - - /* Return existing scaled_font if it exists in the hash table. */ - if (scaled_font != NULL) { - /* If the original reference count is 0, then this font must have - * been found in font_map->holdovers, (which means this caching is - * actually working). So now we remove it from the holdovers - * array. */ - if (! CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&scaled_font->ref_count)) { - int i; - - for (i = 0; i < font_map->num_holdovers; i++) - if (font_map->holdovers[i] == scaled_font) - break; - assert (i < font_map->num_holdovers); - - font_map->num_holdovers--; - memmove (&font_map->holdovers[i], - &font_map->holdovers[i+1], - (font_map->num_holdovers - i) * sizeof (cairo_scaled_font_t*)); - - /* reset any error status */ - scaled_font->status = CAIRO_STATUS_SUCCESS; - } - - if (scaled_font->status == CAIRO_STATUS_SUCCESS) { - /* We increment the reference count manually here, (rather - * than calling into cairo_scaled_font_reference), since we - * must modify the reference count while our lock is still - * held. */ - - old = font_map->mru_scaled_font; - font_map->mru_scaled_font = scaled_font; - /* increment reference count for the mru cache */ - _cairo_reference_count_inc (&scaled_font->ref_count); - /* and increment for the returned reference */ - _cairo_reference_count_inc (&scaled_font->ref_count); - _cairo_scaled_font_map_unlock (); - - cairo_scaled_font_destroy (old); - - return scaled_font; - } - - /* the font has been put into an error status - abandon the cache */ - _cairo_hash_table_remove (font_map->hash_table, &key.hash_entry); - scaled_font->hash_entry.hash = ZOMBIE; - } - } - - /* Otherwise create it and insert it into the hash table. */ - status = font_face->backend->scaled_font_create (font_face, font_matrix, - ctm, options, &scaled_font); - if (status) { - _cairo_scaled_font_map_unlock (); - status = _cairo_font_face_set_error (font_face, status); - return _cairo_scaled_font_create_in_error (status); - } - - status = _cairo_hash_table_insert (font_map->hash_table, - &scaled_font->hash_entry); - if (status == CAIRO_STATUS_SUCCESS) { - old = font_map->mru_scaled_font; - font_map->mru_scaled_font = scaled_font; - _cairo_reference_count_inc (&scaled_font->ref_count); - } - - _cairo_scaled_font_map_unlock (); - - if (status) { - /* We can't call _cairo_scaled_font_destroy here since it expects - * that the font has already been successfully inserted into the - * hash table. */ - _cairo_scaled_font_fini_internal (scaled_font); - free (scaled_font); - return _cairo_scaled_font_create_in_error (status); - } - - cairo_scaled_font_destroy (old); - - return scaled_font; -} -slim_hidden_def (cairo_scaled_font_create); - -static cairo_scaled_font_t *_cairo_scaled_font_nil_objects[CAIRO_STATUS_LAST_STATUS + 1]; - -/* XXX This should disappear in favour of a common pool of error objects. */ -cairo_scaled_font_t * -_cairo_scaled_font_create_in_error (cairo_status_t status) -{ - cairo_scaled_font_t *scaled_font; - - assert (status != CAIRO_STATUS_SUCCESS); - - if (status == CAIRO_STATUS_NO_MEMORY) - return (cairo_scaled_font_t *) &_cairo_scaled_font_nil; - - CAIRO_MUTEX_LOCK (_cairo_scaled_font_error_mutex); - scaled_font = _cairo_scaled_font_nil_objects[status]; - if (scaled_font == NULL) { - scaled_font = malloc (sizeof (cairo_scaled_font_t)); - if (scaled_font == NULL) { - CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_error_mutex); - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_scaled_font_t *) &_cairo_scaled_font_nil; - } - - *scaled_font = _cairo_scaled_font_nil; - scaled_font->status = status; - _cairo_scaled_font_nil_objects[status] = scaled_font; - } - CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_error_mutex); - - return scaled_font; -} - -void -_cairo_scaled_font_reset_static_data (void) -{ - int status; - - CAIRO_MUTEX_LOCK (_cairo_scaled_font_error_mutex); - for (status = CAIRO_STATUS_SUCCESS; - status <= CAIRO_STATUS_LAST_STATUS; - status++) - { - if (_cairo_scaled_font_nil_objects[status] != NULL) { - free (_cairo_scaled_font_nil_objects[status]); - _cairo_scaled_font_nil_objects[status] = NULL; - } - } - CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_error_mutex); -} - -/** - * cairo_scaled_font_reference: - * @scaled_font: a #cairo_scaled_font_t, (may be %NULL in which case - * this function does nothing) - * - * Increases the reference count on @scaled_font by one. This prevents - * @scaled_font from being destroyed until a matching call to - * cairo_scaled_font_destroy() is made. - * - * The number of references to a #cairo_scaled_font_t can be get using - * cairo_scaled_font_get_reference_count(). - * - * Returns: the referenced #cairo_scaled_font_t - **/ -cairo_scaled_font_t * -cairo_scaled_font_reference (cairo_scaled_font_t *scaled_font) -{ - if (scaled_font == NULL || - CAIRO_REFERENCE_COUNT_IS_INVALID (&scaled_font->ref_count)) - return scaled_font; - - assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&scaled_font->ref_count)); - - _cairo_reference_count_inc (&scaled_font->ref_count); - - return scaled_font; -} -slim_hidden_def (cairo_scaled_font_reference); - -/** - * cairo_scaled_font_destroy: - * @scaled_font: a #cairo_scaled_font_t - * - * Decreases the reference count on @font by one. If the result - * is zero, then @font and all associated resources are freed. - * See cairo_scaled_font_reference(). - **/ -void -cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font) -{ - cairo_scaled_font_t *lru = NULL; - cairo_scaled_font_map_t *font_map; - - assert (CAIRO_MUTEX_IS_UNLOCKED (_cairo_scaled_font_map_mutex)); - - if (scaled_font == NULL || - CAIRO_REFERENCE_COUNT_IS_INVALID (&scaled_font->ref_count)) - return; - - assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&scaled_font->ref_count)); - - font_map = _cairo_scaled_font_map_lock (); - assert (font_map != NULL); - - if (_cairo_reference_count_dec_and_test (&scaled_font->ref_count)) { - - - if (!scaled_font->placeholder && scaled_font->hash_entry.hash != ZOMBIE) { - /* Rather than immediately destroying this object, we put it into - * the font_map->holdovers array in case it will get used again - * soon (and is why we must hold the lock over the atomic op on - * the reference count). To make room for it, we do actually - * destroy the least-recently-used holdover. - */ - - if (font_map->num_holdovers == CAIRO_SCALED_FONT_MAX_HOLDOVERS) - { - lru = font_map->holdovers[0]; - assert (! CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&lru->ref_count)); - - _cairo_hash_table_remove (font_map->hash_table, &lru->hash_entry); - - font_map->num_holdovers--; - memmove (&font_map->holdovers[0], - &font_map->holdovers[1], - font_map->num_holdovers * sizeof (cairo_scaled_font_t*)); - } - - font_map->holdovers[font_map->num_holdovers] = scaled_font; - font_map->num_holdovers++; - } else - lru = scaled_font; - - } - - _cairo_scaled_font_map_unlock (); - - /* If we pulled an item from the holdovers array, (while the font - * map lock was held, of course), then there is no way that anyone - * else could have acquired a reference to it. So we can now - * safely call fini on it without any lock held. This is desirable - * as we never want to call into any backend function with a lock - * held. */ - if (lru) { - _cairo_scaled_font_fini_internal (lru); - free (lru); - } -} -slim_hidden_def (cairo_scaled_font_destroy); - -/** - * cairo_scaled_font_get_reference_count: - * @scaled_font: a #cairo_scaled_font_t - * - * Returns the current reference count of @scaled_font. - * - * Return value: the current reference count of @scaled_font. If the - * object is a nil object, 0 will be returned. - * - * Since: 1.4 - **/ -unsigned int -cairo_scaled_font_get_reference_count (cairo_scaled_font_t *scaled_font) -{ - if (scaled_font == NULL || - CAIRO_REFERENCE_COUNT_IS_INVALID (&scaled_font->ref_count)) - return 0; - - return CAIRO_REFERENCE_COUNT_GET_VALUE (&scaled_font->ref_count); -} - -/** - * cairo_scaled_font_get_user_data: - * @scaled_font: a #cairo_scaled_font_t - * @key: the address of the #cairo_user_data_key_t the user data was - * attached to - * - * Return user data previously attached to @scaled_font using the - * specified key. If no user data has been attached with the given - * key this function returns %NULL. - * - * Return value: the user data previously attached or %NULL. - * - * Since: 1.4 - **/ -void * -cairo_scaled_font_get_user_data (cairo_scaled_font_t *scaled_font, - const cairo_user_data_key_t *key) -{ - return _cairo_user_data_array_get_data (&scaled_font->user_data, - key); -} - -/** - * cairo_scaled_font_set_user_data: - * @scaled_font: a #cairo_scaled_font_t - * @key: the address of a #cairo_user_data_key_t to attach the user data to - * @user_data: the user data to attach to the #cairo_scaled_font_t - * @destroy: a #cairo_destroy_func_t which will be called when the - * #cairo_t is destroyed or when new user data is attached using the - * same key. - * - * Attach user data to @scaled_font. To remove user data from a surface, - * call this function with the key that was used to set it and %NULL - * for @data. - * - * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a - * slot could not be allocated for the user data. - * - * Since: 1.4 - **/ -cairo_status_t -cairo_scaled_font_set_user_data (cairo_scaled_font_t *scaled_font, - const cairo_user_data_key_t *key, - void *user_data, - cairo_destroy_func_t destroy) -{ - if (CAIRO_REFERENCE_COUNT_IS_INVALID (&scaled_font->ref_count)) - return scaled_font->status; - - return _cairo_user_data_array_set_data (&scaled_font->user_data, - key, user_data, destroy); -} - -static cairo_bool_t -_cairo_scaled_font_is_frozen (cairo_scaled_font_t *scaled_font) -{ - return CAIRO_MUTEX_IS_LOCKED (scaled_font->mutex) && - scaled_font->glyphs->freeze_count > 0; -} - -/* Public font API follows. */ - -/** - * cairo_scaled_font_extents: - * @scaled_font: a #cairo_scaled_font_t - * @extents: a #cairo_font_extents_t which to store the retrieved extents. - * - * Gets the metrics for a #cairo_scaled_font_t. - **/ -void -cairo_scaled_font_extents (cairo_scaled_font_t *scaled_font, - cairo_font_extents_t *extents) -{ - if (scaled_font->status) { - extents->ascent = 0.0; - extents->descent = 0.0; - extents->height = 0.0; - extents->max_x_advance = 0.0; - extents->max_y_advance = 0.0; - return; - } - - *extents = scaled_font->extents; -} -slim_hidden_def (cairo_scaled_font_extents); - -/** - * cairo_scaled_font_text_extents: - * @scaled_font: a #cairo_scaled_font_t - * @utf8: a NUL-terminated string of text, encoded in UTF-8 - * @extents: a #cairo_text_extents_t which to store the retrieved extents. - * - * Gets the extents for a string of text. The extents describe a - * user-space rectangle that encloses the "inked" portion of the text - * drawn at the origin (0,0) (as it would be drawn by cairo_show_text() - * if the cairo graphics state were set to the same font_face, - * font_matrix, ctm, and font_options as @scaled_font). Additionally, - * the x_advance and y_advance values indicate the amount by which the - * current point would be advanced by cairo_show_text(). - * - * Note that whitespace characters do not directly contribute to the - * size of the rectangle (extents.width and extents.height). They do - * contribute indirectly by changing the position of non-whitespace - * characters. In particular, trailing whitespace characters are - * likely to not affect the size of the rectangle, though they will - * affect the x_advance and y_advance values. - * - * Since: 1.2 - **/ -void -cairo_scaled_font_text_extents (cairo_scaled_font_t *scaled_font, - const char *utf8, - cairo_text_extents_t *extents) -{ - cairo_status_t status; - cairo_glyph_t *glyphs = NULL; - int num_glyphs; - - if (scaled_font->status) - goto ZERO_EXTENTS; - - if (utf8 == NULL) - goto ZERO_EXTENTS; - - status = cairo_scaled_font_text_to_glyphs (scaled_font, 0., 0., - utf8, -1, - &glyphs, &num_glyphs, - NULL, NULL, - NULL); - if (status) { - status = _cairo_scaled_font_set_error (scaled_font, status); - goto ZERO_EXTENTS; - } - - cairo_scaled_font_glyph_extents (scaled_font, glyphs, num_glyphs, extents); - free (glyphs); - - return; - -ZERO_EXTENTS: - extents->x_bearing = 0.0; - extents->y_bearing = 0.0; - extents->width = 0.0; - extents->height = 0.0; - extents->x_advance = 0.0; - extents->y_advance = 0.0; -} - -/** - * cairo_scaled_font_glyph_extents: - * @scaled_font: a #cairo_scaled_font_t - * @glyphs: an array of glyph IDs with X and Y offsets. - * @num_glyphs: the number of glyphs in the @glyphs array - * @extents: a #cairo_text_extents_t which to store the retrieved extents. - * - * Gets the extents for an array of glyphs. The extents describe a - * user-space rectangle that encloses the "inked" portion of the - * glyphs, (as they would be drawn by cairo_show_glyphs() if the cairo - * graphics state were set to the same font_face, font_matrix, ctm, - * and font_options as @scaled_font). Additionally, the x_advance and - * y_advance values indicate the amount by which the current point - * would be advanced by cairo_show_glyphs(). - * - * Note that whitespace glyphs do not contribute to the size of the - * rectangle (extents.width and extents.height). - **/ -void -cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font, - const cairo_glyph_t *glyphs, - int num_glyphs, - cairo_text_extents_t *extents) -{ - cairo_status_t status; - int i; - double min_x = 0.0, min_y = 0.0, max_x = 0.0, max_y = 0.0; - cairo_bool_t visible = FALSE; - cairo_scaled_glyph_t *scaled_glyph = NULL; - - extents->x_bearing = 0.0; - extents->y_bearing = 0.0; - extents->width = 0.0; - extents->height = 0.0; - extents->x_advance = 0.0; - extents->y_advance = 0.0; - - if (scaled_font->status) - return; - - if (num_glyphs == 0) - return; - - if (num_glyphs < 0) { - _cairo_error_throw (CAIRO_STATUS_NEGATIVE_COUNT); - /* XXX Can't propagate error */ - return; - } - - if (glyphs == NULL) { - _cairo_error_throw (CAIRO_STATUS_NULL_POINTER); - /* XXX Can't propagate error */ - return; - } - - _cairo_scaled_font_freeze_cache (scaled_font); - - for (i = 0; i < num_glyphs; i++) { - double left, top, right, bottom; - - status = _cairo_scaled_glyph_lookup (scaled_font, - glyphs[i].index, - CAIRO_SCALED_GLYPH_INFO_METRICS, - &scaled_glyph); - if (status) { - status = _cairo_scaled_font_set_error (scaled_font, status); - goto UNLOCK; - } - - /* "Ink" extents should skip "invisible" glyphs */ - if (scaled_glyph->metrics.width == 0 || scaled_glyph->metrics.height == 0) - continue; - - left = scaled_glyph->metrics.x_bearing + glyphs[i].x; - right = left + scaled_glyph->metrics.width; - top = scaled_glyph->metrics.y_bearing + glyphs[i].y; - bottom = top + scaled_glyph->metrics.height; - - if (!visible) { - visible = TRUE; - min_x = left; - max_x = right; - min_y = top; - max_y = bottom; - } else { - if (left < min_x) min_x = left; - if (right > max_x) max_x = right; - if (top < min_y) min_y = top; - if (bottom > max_y) max_y = bottom; - } - } - - if (visible) { - extents->x_bearing = min_x - glyphs[0].x; - extents->y_bearing = min_y - glyphs[0].y; - extents->width = max_x - min_x; - extents->height = max_y - min_y; - } else { - extents->x_bearing = 0.0; - extents->y_bearing = 0.0; - extents->width = 0.0; - extents->height = 0.0; - } - - if (num_glyphs) { - double x0, y0, x1, y1; - - x0 = glyphs[0].x; - y0 = glyphs[0].y; - - /* scaled_glyph contains the glyph for num_glyphs - 1 already. */ - x1 = glyphs[num_glyphs - 1].x + scaled_glyph->metrics.x_advance; - y1 = glyphs[num_glyphs - 1].y + scaled_glyph->metrics.y_advance; - - extents->x_advance = x1 - x0; - extents->y_advance = y1 - y0; - } else { - extents->x_advance = 0.0; - extents->y_advance = 0.0; - } - - UNLOCK: - _cairo_scaled_font_thaw_cache (scaled_font); -} -slim_hidden_def (cairo_scaled_font_glyph_extents); - -/** - * cairo_scaled_font_text_to_glyphs: - * @x: X position to place first glyph - * @y: Y position to place first glyph - * @scaled_font: a #cairo_scaled_font_t - * @utf8: a string of text encoded in UTF-8 - * @utf8_len: length of @utf8 in bytes, or -1 if it is NUL-terminated - * @glyphs: pointer to array of glyphs to fill - * @num_glyphs: pointer to number of glyphs - * @clusters: pointer to array of cluster mapping information to fill, or %NULL - * @num_clusters: pointer to number of clusters, or %NULL - * @cluster_flags: pointer to location to store cluster flags corresponding to the - * output @clusters, or %NULL - * - * Converts UTF-8 text to an array of glyphs, optionally with cluster - * mapping, that can be used to render later using @scaled_font. - * - * If @glyphs initially points to a non-%NULL value, that array is used - * as a glyph buffer, and @num_glyphs should point to the number of glyph - * entries available there. If the provided glyph array is too short for - * the conversion, a new glyph array is allocated using cairo_glyph_allocate() - * and placed in @glyphs. Upon return, @num_glyphs always contains the - * number of generated glyphs. If the value @glyphs points to has changed - * after the call, the user is responsible for freeing the allocated glyph - * array using cairo_glyph_free(). This may happen even if the provided - * array was large enough. - * - * If @clusters is not %NULL, @num_clusters and @cluster_flags should not be %NULL, - * and cluster mapping will be computed. - * The semantics of how cluster array allocation works is similar to the glyph - * array. That is, - * if @clusters initially points to a non-%NULL value, that array is used - * as a cluster buffer, and @num_clusters should point to the number of cluster - * entries available there. If the provided cluster array is too short for - * the conversion, a new cluster array is allocated using cairo_text_cluster_allocate() - * and placed in @clusters. Upon return, @num_clusters always contains the - * number of generated clusters. If the value @clusters points at has changed - * after the call, the user is responsible for freeing the allocated cluster - * array using cairo_text_cluster_free(). This may happen even if the provided - * array was large enough. - * - * In the simplest case, @glyphs and @clusters can point to %NULL initially - * and a suitable array will be allocated. In code: - * - * cairo_status_t status; - * - * cairo_glyph_t *glyphs = NULL; - * int num_glyphs; - * cairo_text_cluster_t *clusters = NULL; - * int num_clusters; - * cairo_text_cluster_flags_t cluster_flags; - * - * status = cairo_scaled_font_text_to_glyphs (scaled_font, - * x, y, - * utf8, utf8_len, - * &glyphs, &num_glyphs, - * &clusters, &num_clusters, &cluster_flags); - * - * if (status == CAIRO_STATUS_SUCCESS) { - * cairo_show_text_glyphs (cr, - * utf8, utf8_len, - * *glyphs, *num_glyphs, - * *clusters, *num_clusters, *cluster_flags); - * - * cairo_glyph_free (*glyphs); - * cairo_text_cluster_free (*clusters); - * } - * - * - * If no cluster mapping is needed: - * - * cairo_status_t status; - * - * cairo_glyph_t *glyphs = NULL; - * int num_glyphs; - * - * status = cairo_scaled_font_text_to_glyphs (scaled_font, - * x, y, - * utf8, utf8_len, - * &glyphs, &num_glyphs, - * NULL, NULL, - * NULL); - * - * if (status == CAIRO_STATUS_SUCCESS) { - * cairo_show_glyphs (cr, *glyphs, *num_glyphs); - * cairo_glyph_free (*glyphs); - * } - * - * - * If stack-based glyph and cluster arrays are to be used for small - * arrays: - * - * cairo_status_t status; - * - * cairo_glyph_t stack_glyphs[40]; - * cairo_glyph_t *glyphs = stack_glyphs; - * int num_glyphs = sizeof (stack_glyphs) / sizeof (stack_glyphs[0]); - * cairo_text_cluster_t stack_clusters[40]; - * cairo_text_cluster_t *clusters = stack_clusters; - * int num_clusters = sizeof (stack_clusters) / sizeof (stack_clusters[0]); - * cairo_text_cluster_flags_t cluster_flags; - * - * status = cairo_scaled_font_text_to_glyphs (scaled_font, - * x, y, - * utf8, utf8_len, - * &glyphs, &num_glyphs, - * &clusters, &num_clusters, &cluster_flags); - * - * if (status == CAIRO_STATUS_SUCCESS) { - * cairo_show_text_glyphs (cr, - * utf8, utf8_len, - * *glyphs, *num_glyphs, - * *clusters, *num_clusters, *cluster_flags); - * - * if (glyphs != stack_glyphs) - * cairo_glyph_free (*glyphs); - * if (clusters != stack_clusters) - * cairo_text_cluster_free (*clusters); - * } - * - * - * For details of how @clusters, @num_clusters, and @cluster_flags map input - * UTF-8 text to the output glyphs see cairo_show_text_glyphs(). - * - * The output values can be readily passed to cairo_show_text_glyphs() - * cairo_show_glyphs(), or related functions, assuming that the exact - * same @scaled_font is used for the operation. - * - * Return value: %CAIRO_STATUS_SUCCESS upon success, or an error status - * if the input values are wrong or if conversion failed. If the input - * values are correct but the conversion failed, the error status is also - * set on @scaled_font. - * - * Since: 1.8 - **/ -cairo_status_t -cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font, - double x, - double y, - const char *utf8, - int utf8_len, - cairo_glyph_t **glyphs, - int *num_glyphs, - cairo_text_cluster_t **clusters, - int *num_clusters, - cairo_text_cluster_flags_t *cluster_flags) -{ - int i; - int num_chars = 0; - const char *p; - cairo_status_t status; - cairo_glyph_t *orig_glyphs; - cairo_text_cluster_t *orig_clusters; - - status = scaled_font->status; - if (status) - return status; - - /* A slew of sanity checks */ - - /* glyphs and num_glyphs can't be NULL */ - if (glyphs == NULL || - num_glyphs == NULL) { - status = CAIRO_STATUS_NULL_POINTER; - goto BAIL; - } - - /* Special case for NULL and -1 */ - if (utf8 == NULL && utf8_len == -1) - utf8_len = 0; - - /* No NULLs for non-NULLs! */ - if ((utf8_len && utf8 == NULL) || - (clusters && num_clusters == NULL) || - (clusters && cluster_flags == NULL)) { - status = CAIRO_STATUS_NULL_POINTER; - goto BAIL; - } - - /* A -1 for utf8_len means NUL-terminated */ - if (utf8_len == -1) - utf8_len = strlen (utf8); - - /* A NULL *glyphs means no prealloced glyphs array */ - if (glyphs && *glyphs == NULL) - *num_glyphs = 0; - - /* A NULL *clusters means no prealloced clusters array */ - if (clusters && *clusters == NULL) - *num_clusters = 0; - - if (!clusters && num_clusters) { - num_clusters = NULL; - } - - if (cluster_flags) { - *cluster_flags = FALSE; - } - - if (!clusters && cluster_flags) { - cluster_flags = NULL; - } - - /* Apart from that, no negatives */ - if (utf8_len < 0 || - *num_glyphs < 0 || - (num_clusters && *num_clusters < 0)) { - status = CAIRO_STATUS_NEGATIVE_COUNT; - goto BAIL; - } - - if (utf8_len == 0) { - status = CAIRO_STATUS_SUCCESS; - goto BAIL; - } - - /* validate input so backend does not have to */ - status = _cairo_utf8_to_ucs4 (utf8, utf8_len, NULL, &num_chars); - if (status) - goto BAIL; - - _cairo_scaled_font_freeze_cache (scaled_font); - - orig_glyphs = *glyphs; - orig_clusters = clusters ? *clusters : NULL; - - if (scaled_font->backend->text_to_glyphs) { - - status = scaled_font->backend->text_to_glyphs (scaled_font, x, y, - utf8, utf8_len, - glyphs, num_glyphs, - clusters, num_clusters, - cluster_flags); - - if (status != CAIRO_INT_STATUS_UNSUPPORTED) { - - if (status == CAIRO_STATUS_SUCCESS) { - - /* The checks here are crude; we only should do them in - * user-font backend, but they don't hurt here. This stuff - * can be hard to get right. */ - - if (*num_glyphs < 0) { - status = CAIRO_STATUS_NEGATIVE_COUNT; - goto DONE; - } - if (num_glyphs && *glyphs == NULL) { - status = CAIRO_STATUS_NULL_POINTER; - goto DONE; - } - - if (clusters) { - - if (*num_clusters < 0) { - status = CAIRO_STATUS_NEGATIVE_COUNT; - goto DONE; - } - if (num_clusters && *clusters == NULL) { - status = CAIRO_STATUS_NULL_POINTER; - goto DONE; - } - - /* Dont trust the backend, validate clusters! */ - status = _cairo_validate_text_clusters (utf8, utf8_len, - *glyphs, *num_glyphs, - *clusters, *num_clusters, - *cluster_flags); - } - } - - goto DONE; - } - } - - if (*num_glyphs < num_chars) { - *glyphs = cairo_glyph_allocate (num_chars); - if (*glyphs == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto DONE; - } - } - *num_glyphs = num_chars; - - if (clusters) { - if (*num_clusters < num_chars) { - *clusters = cairo_text_cluster_allocate (num_chars); - if (*clusters == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto DONE; - } - } - *num_clusters = num_chars; - } - - p = utf8; - for (i = 0; i < num_chars; i++) { - int num_bytes; - uint32_t unicode; - cairo_scaled_glyph_t *scaled_glyph; - - num_bytes = _cairo_utf8_get_char_validated (p, &unicode); - p += num_bytes; - - (*glyphs)[i].index = (*scaled_font->backend->ucs4_to_index) (scaled_font, unicode); - (*glyphs)[i].x = x; - (*glyphs)[i].y = y; - - if (clusters) { - (*clusters)[i].num_bytes = num_bytes; - (*clusters)[i].num_glyphs = 1; - } - - status = _cairo_scaled_glyph_lookup (scaled_font, - (*glyphs)[i].index, - CAIRO_SCALED_GLYPH_INFO_METRICS, - &scaled_glyph); - if (status) { - goto DONE; - } - - x += scaled_glyph->metrics.x_advance; - y += scaled_glyph->metrics.y_advance; - } - - DONE: /* error that should be logged on scaled_font happened */ - _cairo_scaled_font_thaw_cache (scaled_font); - - if (status) { - *num_glyphs = 0; - if (*glyphs != orig_glyphs) { - cairo_glyph_free (*glyphs); - *glyphs = orig_glyphs; - } - - if (clusters) { - *num_clusters = 0; - if (*clusters != orig_clusters) { - cairo_text_cluster_free (*clusters); - *clusters = orig_clusters; - } - } - } - - return _cairo_scaled_font_set_error (scaled_font, status); - - BAIL: /* error with input arguments */ - - if (num_glyphs) - *num_glyphs = 0; - - if (num_clusters) - *num_clusters = 0; - - return status; -} -slim_hidden_def (cairo_scaled_font_text_to_glyphs); - -/* - * Compute a device-space bounding box for the glyphs. - */ -cairo_status_t -_cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font, - const cairo_glyph_t *glyphs, - int num_glyphs, - cairo_rectangle_int_t *extents) -{ - cairo_status_t status = CAIRO_STATUS_SUCCESS; - int i; - cairo_point_int_t min = { CAIRO_RECT_INT_MAX, CAIRO_RECT_INT_MAX }; - cairo_point_int_t max = { CAIRO_RECT_INT_MIN, CAIRO_RECT_INT_MIN }; - - if (scaled_font->status) - return scaled_font->status; - - _cairo_scaled_font_freeze_cache (scaled_font); - - for (i = 0; i < num_glyphs; i++) { - cairo_scaled_glyph_t *scaled_glyph; - int left, top; - int right, bottom; - int x, y; - - status = _cairo_scaled_glyph_lookup (scaled_font, - glyphs[i].index, - CAIRO_SCALED_GLYPH_INFO_METRICS, - &scaled_glyph); - if (status) - break; - - /* XXX glyph images are snapped to pixel locations */ - x = _cairo_lround (glyphs[i].x); - y = _cairo_lround (glyphs[i].y); - - left = x + _cairo_fixed_integer_floor(scaled_glyph->bbox.p1.x); - top = y + _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y); - right = x + _cairo_fixed_integer_ceil(scaled_glyph->bbox.p2.x); - bottom = y + _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y); - - if (left < min.x) min.x = left; - if (right > max.x) max.x = right; - if (top < min.y) min.y = top; - if (bottom > max.y) max.y = bottom; - } - - _cairo_scaled_font_thaw_cache (scaled_font); - if (status) - return _cairo_scaled_font_set_error (scaled_font, status); - - if (min.x < max.x && min.y < max.y) { - extents->x = min.x; - extents->width = max.x - min.x; - extents->y = min.y; - extents->height = max.y - min.y; - } else { - extents->x = extents->y = 0; - extents->width = extents->height = 0; - } - - return CAIRO_STATUS_SUCCESS; -} - -cairo_status_t -_cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font, - cairo_operator_t op, - cairo_pattern_t *pattern, - cairo_surface_t *surface, - int source_x, - int source_y, - int dest_x, - int dest_y, - unsigned int width, - unsigned int height, - cairo_glyph_t *glyphs, - int num_glyphs) -{ - cairo_status_t status; - cairo_surface_t *mask = NULL; - cairo_format_t mask_format = CAIRO_FORMAT_A1; /* shut gcc up */ - cairo_surface_pattern_t mask_pattern; - cairo_solid_pattern_t white_pattern; - int i; - - /* These operators aren't interpreted the same way by the backends; - * they are implemented in terms of other operators in cairo-gstate.c - */ - assert (op != CAIRO_OPERATOR_SOURCE && op != CAIRO_OPERATOR_CLEAR); - - if (scaled_font->status) - return scaled_font->status; - - if (!num_glyphs) - return CAIRO_STATUS_SUCCESS; - - if (scaled_font->backend->show_glyphs != NULL) { - int remaining_glyphs = num_glyphs; - status = scaled_font->backend->show_glyphs (scaled_font, - op, pattern, - surface, - source_x, source_y, - dest_x, dest_y, - width, height, - glyphs, num_glyphs, &remaining_glyphs); - glyphs += num_glyphs - remaining_glyphs; - num_glyphs = remaining_glyphs; - if (remaining_glyphs == 0) - status = CAIRO_STATUS_SUCCESS; - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return _cairo_scaled_font_set_error (scaled_font, status); - } - - /* Font display routine either does not exist or failed. */ - - _cairo_pattern_init_solid (&white_pattern, CAIRO_COLOR_WHITE, CAIRO_CONTENT_COLOR); - - _cairo_scaled_font_freeze_cache (scaled_font); - - for (i = 0; i < num_glyphs; i++) { - int x, y; - cairo_surface_pattern_t glyph_pattern; - cairo_image_surface_t *glyph_surface; - cairo_scaled_glyph_t *scaled_glyph; - - status = _cairo_scaled_glyph_lookup (scaled_font, - glyphs[i].index, - CAIRO_SCALED_GLYPH_INFO_SURFACE, - &scaled_glyph); - - if (status) - goto CLEANUP_MASK; - - glyph_surface = scaled_glyph->surface; - - /* To start, create the mask using the format from the first - * glyph. Later we'll deal with different formats. */ - if (mask == NULL) { - mask_format = glyph_surface->format; - mask = cairo_image_surface_create (mask_format, - width, height); - if (mask->status) { - status = mask->status; - goto CLEANUP_MASK; - } - } - - /* If we have glyphs of different formats, we "upgrade" the mask - * to the wider of the formats. */ - if (glyph_surface->format != mask_format && - _cairo_format_bits_per_pixel (mask_format) < - _cairo_format_bits_per_pixel (glyph_surface->format) ) - { - cairo_surface_t *new_mask; - cairo_surface_pattern_t mask_pattern; - - switch (glyph_surface->format) { - case CAIRO_FORMAT_ARGB32: - case CAIRO_FORMAT_A8: - case CAIRO_FORMAT_A1: - mask_format = glyph_surface->format; - break; - case CAIRO_FORMAT_RGB24: - default: - ASSERT_NOT_REACHED; - mask_format = CAIRO_FORMAT_ARGB32; - break; - } - - new_mask = cairo_image_surface_create (mask_format, - width, height); - if (new_mask->status) { - status = new_mask->status; - cairo_surface_destroy (new_mask); - goto CLEANUP_MASK; - } - - _cairo_pattern_init_for_surface (&mask_pattern, mask); - - status = _cairo_surface_composite (CAIRO_OPERATOR_ADD, - &white_pattern.base, - &mask_pattern.base, - new_mask, - 0, 0, - 0, 0, - 0, 0, - width, height); - - _cairo_pattern_fini (&mask_pattern.base); - - if (status) { - cairo_surface_destroy (new_mask); - goto CLEANUP_MASK; - } - - cairo_surface_destroy (mask); - mask = new_mask; - } - - /* round glyph locations to the nearest pixel */ - /* XXX: FRAGILE: We're ignoring device_transform scaling here. A bug? */ - x = _cairo_lround (glyphs[i].x - glyph_surface->base.device_transform.x0); - y = _cairo_lround (glyphs[i].y - glyph_surface->base.device_transform.y0); - - _cairo_pattern_init_for_surface (&glyph_pattern, &glyph_surface->base); - - status = _cairo_surface_composite (CAIRO_OPERATOR_ADD, - &white_pattern.base, - &glyph_pattern.base, - mask, - 0, 0, - 0, 0, - x - dest_x, y - dest_y, - glyph_surface->width, - glyph_surface->height); - - _cairo_pattern_fini (&glyph_pattern.base); - - if (status) - goto CLEANUP_MASK; - } - - if (mask_format == CAIRO_FORMAT_ARGB32) - pixman_image_set_component_alpha (((cairo_image_surface_t*) mask)-> - pixman_image, TRUE); - _cairo_pattern_init_for_surface (&mask_pattern, mask); - - status = _cairo_surface_composite (op, pattern, &mask_pattern.base, - surface, - source_x, source_y, - 0, 0, - dest_x, dest_y, - width, height); - - _cairo_pattern_fini (&mask_pattern.base); - -CLEANUP_MASK: - _cairo_scaled_font_thaw_cache (scaled_font); - - _cairo_pattern_fini (&white_pattern.base); - - if (mask != NULL) - cairo_surface_destroy (mask); - return _cairo_scaled_font_set_error (scaled_font, status); -} - -typedef struct _cairo_scaled_glyph_path_closure { - cairo_point_t offset; - cairo_path_fixed_t *path; -} cairo_scaled_glyph_path_closure_t; - -static cairo_status_t -_scaled_glyph_path_move_to (void *abstract_closure, cairo_point_t *point) -{ - cairo_scaled_glyph_path_closure_t *closure = abstract_closure; - - return _cairo_path_fixed_move_to (closure->path, - point->x + closure->offset.x, - point->y + closure->offset.y); -} - -static cairo_status_t -_scaled_glyph_path_line_to (void *abstract_closure, cairo_point_t *point) -{ - cairo_scaled_glyph_path_closure_t *closure = abstract_closure; - - return _cairo_path_fixed_line_to (closure->path, - point->x + closure->offset.x, - point->y + closure->offset.y); -} - -static cairo_status_t -_scaled_glyph_path_curve_to (void *abstract_closure, - cairo_point_t *p0, - cairo_point_t *p1, - cairo_point_t *p2) -{ - cairo_scaled_glyph_path_closure_t *closure = abstract_closure; - - return _cairo_path_fixed_curve_to (closure->path, - p0->x + closure->offset.x, - p0->y + closure->offset.y, - p1->x + closure->offset.x, - p1->y + closure->offset.y, - p2->x + closure->offset.x, - p2->y + closure->offset.y); -} - -static cairo_status_t -_scaled_glyph_path_close_path (void *abstract_closure) -{ - cairo_scaled_glyph_path_closure_t *closure = abstract_closure; - - return _cairo_path_fixed_close_path (closure->path); -} - -/* Add a single-device-unit rectangle to a path. */ -static cairo_status_t -_add_unit_rectangle_to_path (cairo_path_fixed_t *path, int x, int y) -{ - cairo_status_t status; - - status = _cairo_path_fixed_move_to (path, - _cairo_fixed_from_int (x), - _cairo_fixed_from_int (y)); - if (status) - return status; - - status = _cairo_path_fixed_rel_line_to (path, - _cairo_fixed_from_int (1), - _cairo_fixed_from_int (0)); - if (status) - return status; - - status = _cairo_path_fixed_rel_line_to (path, - _cairo_fixed_from_int (0), - _cairo_fixed_from_int (1)); - if (status) - return status; - - status = _cairo_path_fixed_rel_line_to (path, - _cairo_fixed_from_int (-1), - _cairo_fixed_from_int (0)); - if (status) - return status; - - status = _cairo_path_fixed_close_path (path); - if (status) - return status; - - return CAIRO_STATUS_SUCCESS; -} - -/** - * _trace_mask_to_path: - * @bitmap: An alpha mask (either %CAIRO_FORMAT_A1 or %CAIRO_FORMAT_A8) - * @path: An initialized path to hold the result - * - * Given a mask surface, (an alpha image), fill out the provided path - * so that when filled it would result in something that approximates - * the mask. - * - * Note: The current tracing code here is extremely primitive. It - * operates only on an A1 surface, (converting an A8 surface to A1 if - * necessary), and performs the tracing by drawing a little square - * around each pixel that is on in the mask. We do not pretend that - * this is a high-quality result. But we are leaving it up to someone - * who cares enough about getting a better result to implement - * something more sophisticated. - **/ -static cairo_status_t -_trace_mask_to_path (cairo_image_surface_t *mask, - cairo_path_fixed_t *path) -{ - cairo_status_t status; - cairo_image_surface_t *a1_mask; - uint8_t *row, *byte_ptr, byte; - int rows, cols, bytes_per_row; - int x, y, bit; - double xoff, yoff; - - if (mask->format == CAIRO_FORMAT_A1) - a1_mask = (cairo_image_surface_t *) cairo_surface_reference (&mask->base); - else - a1_mask = _cairo_image_surface_clone (mask, CAIRO_FORMAT_A1); - - status = cairo_surface_status (&a1_mask->base); - if (status) { - cairo_surface_destroy (&a1_mask->base); - return status; - } - - cairo_surface_get_device_offset (&mask->base, &xoff, &yoff); - - bytes_per_row = (a1_mask->width + 7) / 8; - for (y = 0, row = a1_mask->data, rows = a1_mask->height; rows; row += a1_mask->stride, rows--, y++) { - for (x = 0, byte_ptr = row, cols = bytes_per_row; cols; byte_ptr++, cols--) { - byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte_ptr); - for (bit = 7; bit >= 0 && x < a1_mask->width; bit--, x++) { - if (byte & (1 << bit)) { - status = _add_unit_rectangle_to_path (path, - x - xoff, y - yoff); - if (status) - goto BAIL; - } - } - } - } - -BAIL: - cairo_surface_destroy (&a1_mask->base); - - return status; -} - -cairo_status_t -_cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font, - const cairo_glyph_t *glyphs, - int num_glyphs, - cairo_path_fixed_t *path) -{ - cairo_status_t status; - int i; - cairo_scaled_glyph_path_closure_t closure; - cairo_path_fixed_t *glyph_path; - - status = scaled_font->status; - if (status) - return status; - - closure.path = path; - _cairo_scaled_font_freeze_cache (scaled_font); - for (i = 0; i < num_glyphs; i++) { - cairo_scaled_glyph_t *scaled_glyph; - - status = _cairo_scaled_glyph_lookup (scaled_font, - glyphs[i].index, - CAIRO_SCALED_GLYPH_INFO_PATH, - &scaled_glyph); - if (status == CAIRO_STATUS_SUCCESS) - glyph_path = scaled_glyph->path; - else if (status != CAIRO_INT_STATUS_UNSUPPORTED) - goto BAIL; - - /* If the font is incapable of providing a path, then we'll - * have to trace our own from a surface. */ - if (status == CAIRO_INT_STATUS_UNSUPPORTED) { - status = _cairo_scaled_glyph_lookup (scaled_font, - glyphs[i].index, - CAIRO_SCALED_GLYPH_INFO_SURFACE, - &scaled_glyph); - if (status) - goto BAIL; - - glyph_path = _cairo_path_fixed_create (); - if (glyph_path == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto BAIL; - } - - status = _trace_mask_to_path (scaled_glyph->surface, glyph_path); - if (status) { - _cairo_path_fixed_destroy (glyph_path); - goto BAIL; - } - } - - closure.offset.x = _cairo_fixed_from_double (glyphs[i].x); - closure.offset.y = _cairo_fixed_from_double (glyphs[i].y); - - status = _cairo_path_fixed_interpret (glyph_path, - CAIRO_DIRECTION_FORWARD, - _scaled_glyph_path_move_to, - _scaled_glyph_path_line_to, - _scaled_glyph_path_curve_to, - _scaled_glyph_path_close_path, - &closure); - if (glyph_path != scaled_glyph->path) - _cairo_path_fixed_destroy (glyph_path); - - if (status) - goto BAIL; - } - BAIL: - _cairo_scaled_font_thaw_cache (scaled_font); - - return _cairo_scaled_font_set_error (scaled_font, status); -} - -/** - * _cairo_scaled_glyph_set_metrics: - * @scaled_glyph: a #cairo_scaled_glyph_t - * @scaled_font: a #cairo_scaled_font_t - * @fs_metrics: a #cairo_text_extents_t in font space - * - * _cairo_scaled_glyph_set_metrics() stores user space metrics - * for the specified glyph given font space metrics. It is - * called by the font backend when initializing a glyph with - * %CAIRO_SCALED_GLYPH_INFO_METRICS. - **/ -void -_cairo_scaled_glyph_set_metrics (cairo_scaled_glyph_t *scaled_glyph, - cairo_scaled_font_t *scaled_font, - cairo_text_extents_t *fs_metrics) -{ - cairo_bool_t first = TRUE; - double hm, wm; - double min_user_x = 0.0, max_user_x = 0.0, min_user_y = 0.0, max_user_y = 0.0; - double min_device_x = 0.0, max_device_x = 0.0, min_device_y = 0.0, max_device_y = 0.0; - double device_x_advance, device_y_advance; - - for (hm = 0.0; hm <= 1.0; hm += 1.0) - for (wm = 0.0; wm <= 1.0; wm += 1.0) { - double x, y; - - /* Transform this corner to user space */ - x = fs_metrics->x_bearing + fs_metrics->width * wm; - y = fs_metrics->y_bearing + fs_metrics->height * hm; - cairo_matrix_transform_point (&scaled_font->font_matrix, - &x, &y); - if (first) { - min_user_x = max_user_x = x; - min_user_y = max_user_y = y; - } else { - if (x < min_user_x) min_user_x = x; - if (x > max_user_x) max_user_x = x; - if (y < min_user_y) min_user_y = y; - if (y > max_user_y) max_user_y = y; - } - - /* Transform this corner to device space from glyph origin */ - x = fs_metrics->x_bearing + fs_metrics->width * wm; - y = fs_metrics->y_bearing + fs_metrics->height * hm; - cairo_matrix_transform_distance (&scaled_font->scale, - &x, &y); - - if (first) { - min_device_x = max_device_x = x; - min_device_y = max_device_y = y; - } else { - if (x < min_device_x) min_device_x = x; - if (x > max_device_x) max_device_x = x; - if (y < min_device_y) min_device_y = y; - if (y > max_device_y) max_device_y = y; - } - first = FALSE; - } - scaled_glyph->metrics.x_bearing = min_user_x; - scaled_glyph->metrics.y_bearing = min_user_y; - scaled_glyph->metrics.width = max_user_x - min_user_x; - scaled_glyph->metrics.height = max_user_y - min_user_y; - - scaled_glyph->metrics.x_advance = fs_metrics->x_advance; - scaled_glyph->metrics.y_advance = fs_metrics->y_advance; - cairo_matrix_transform_distance (&scaled_font->font_matrix, - &scaled_glyph->metrics.x_advance, - &scaled_glyph->metrics.y_advance); - - device_x_advance = fs_metrics->x_advance; - device_y_advance = fs_metrics->y_advance; - cairo_matrix_transform_distance (&scaled_font->scale, - &device_x_advance, - &device_y_advance); - - scaled_glyph->bbox.p1.x = _cairo_fixed_from_double (min_device_x); - scaled_glyph->bbox.p1.y = _cairo_fixed_from_double (min_device_y); - scaled_glyph->bbox.p2.x = _cairo_fixed_from_double (max_device_x); - scaled_glyph->bbox.p2.y = _cairo_fixed_from_double (max_device_y); - - scaled_glyph->x_advance = _cairo_lround (device_x_advance); - scaled_glyph->y_advance = _cairo_lround (device_y_advance); -} - -void -_cairo_scaled_glyph_set_surface (cairo_scaled_glyph_t *scaled_glyph, - cairo_scaled_font_t *scaled_font, - cairo_image_surface_t *surface) -{ - if (scaled_glyph->surface != NULL) - cairo_surface_destroy (&scaled_glyph->surface->base); - scaled_glyph->surface = surface; -} - -void -_cairo_scaled_glyph_set_path (cairo_scaled_glyph_t *scaled_glyph, - cairo_scaled_font_t *scaled_font, - cairo_path_fixed_t *path) -{ - if (scaled_glyph->path != NULL) - _cairo_path_fixed_destroy (scaled_glyph->path); - scaled_glyph->path = path; -} - -void -_cairo_scaled_glyph_set_meta_surface (cairo_scaled_glyph_t *scaled_glyph, - cairo_scaled_font_t *scaled_font, - cairo_surface_t *meta_surface) -{ - if (scaled_glyph->meta_surface != NULL) - cairo_surface_destroy (meta_surface); - scaled_glyph->meta_surface = meta_surface; -} - -/** - * _cairo_scaled_glyph_lookup: - * @scaled_font: a #cairo_scaled_font_t - * @index: the glyph to create - * @info: a #cairo_scaled_glyph_info_t marking which portions of - * the glyph should be filled in. - * @scaled_glyph_ret: a #cairo_scaled_glyph_t where the glyph - * is returned. - * - * If the desired info is not available, (for example, when trying to - * get INFO_PATH with a bitmapped font), this function will return - * %CAIRO_INT_STATUS_UNSUPPORTED. - * - * Note: This function must be called with the scaled font frozen, and it must - * remain frozen for as long as the @scaled_glyph_ret is alive. (If the scaled - * font was not frozen, then there is no guarantee that the glyph would not be - * evicted before you tried to access it.) See - * _cairo_scaled_font_freeze_cache() and _cairo_scaled_font_thaw_cache(). - * - * Returns: a glyph with the requested portions filled in. Glyph - * lookup is cached and glyph will be automatically freed along - * with the scaled_font so no explicit free is required. - * @info can be one or more of: - * %CAIRO_SCALED_GLYPH_INFO_METRICS - glyph metrics and bounding box - * %CAIRO_SCALED_GLYPH_INFO_SURFACE - surface holding glyph image - * %CAIRO_SCALED_GLYPH_INFO_PATH - path holding glyph outline in device space - **/ -cairo_int_status_t -_cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font, - unsigned long index, - cairo_scaled_glyph_info_t info, - cairo_scaled_glyph_t **scaled_glyph_ret) -{ - cairo_status_t status = CAIRO_STATUS_SUCCESS; - cairo_cache_entry_t key; - cairo_scaled_glyph_t *scaled_glyph; - cairo_scaled_glyph_info_t need_info; - - if (scaled_font->status) - return scaled_font->status; - - assert (_cairo_scaled_font_is_frozen (scaled_font)); - - key.hash = index; - /* - * Check cache for glyph - */ - info |= CAIRO_SCALED_GLYPH_INFO_METRICS; - if (!_cairo_cache_lookup (scaled_font->glyphs, &key, - (cairo_cache_entry_t **) &scaled_glyph)) - { - /* - * On miss, create glyph and insert into cache - */ - scaled_glyph = malloc (sizeof (cairo_scaled_glyph_t)); - if (scaled_glyph == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto CLEANUP; - } - - _cairo_scaled_glyph_set_index(scaled_glyph, index); - scaled_glyph->cache_entry.size = 1; /* We currently don't differentiate on glyph size at all */ - scaled_glyph->scaled_font = scaled_font; - scaled_glyph->surface = NULL; - scaled_glyph->path = NULL; - scaled_glyph->meta_surface = NULL; - scaled_glyph->surface_private = NULL; - - /* ask backend to initialize metrics and shape fields */ - status = (*scaled_font->backend-> - scaled_glyph_init) (scaled_font, scaled_glyph, info); - if (status) { - _cairo_scaled_glyph_destroy (scaled_glyph); - goto CLEANUP; - } - - /* on success, the cache takes ownership of the scaled_glyph */ - status = _cairo_cache_insert (scaled_font->glyphs, - &scaled_glyph->cache_entry); - if (status) { - _cairo_scaled_glyph_destroy (scaled_glyph); - goto CLEANUP; - } - } - /* - * Check and see if the glyph, as provided, - * already has the requested data and ammend it if not - */ - need_info = 0; - if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0 && - scaled_glyph->surface == NULL) - need_info |= CAIRO_SCALED_GLYPH_INFO_SURFACE; - - if (((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0 && - scaled_glyph->path == NULL)) - need_info |= CAIRO_SCALED_GLYPH_INFO_PATH; - - if (((info & CAIRO_SCALED_GLYPH_INFO_META_SURFACE) != 0 && - scaled_glyph->meta_surface == NULL)) - need_info |= CAIRO_SCALED_GLYPH_INFO_META_SURFACE; - - if (need_info) { - status = (*scaled_font->backend-> - scaled_glyph_init) (scaled_font, scaled_glyph, need_info); - if (status) - goto CLEANUP; - - /* Don't trust the scaled_glyph_init() return value, the font - * backend may not even know about some of the info. For example, - * no backend other than the user-fonts knows about meta-surface - * glyph info. */ - - if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0 && - scaled_glyph->surface == NULL) { - status = CAIRO_INT_STATUS_UNSUPPORTED; - goto CLEANUP; - } - - if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0 && - scaled_glyph->path == NULL) { - status = CAIRO_INT_STATUS_UNSUPPORTED; - goto CLEANUP; - } - - if ((info & CAIRO_SCALED_GLYPH_INFO_META_SURFACE) != 0 && - scaled_glyph->meta_surface == NULL) { - status = CAIRO_INT_STATUS_UNSUPPORTED; - goto CLEANUP; - } - } - - CLEANUP: - if (status) { - /* It's not an error for the backend to not support the info we want. */ - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - status = _cairo_scaled_font_set_error (scaled_font, status); - *scaled_glyph_ret = NULL; - } else { - *scaled_glyph_ret = scaled_glyph; - } - - return status; -} - -double -_cairo_scaled_font_get_max_scale (cairo_scaled_font_t *scaled_font) -{ - return scaled_font->max_scale; -} - - -/** - * cairo_scaled_font_get_font_face: - * @scaled_font: a #cairo_scaled_font_t - * - * Gets the font face that this scaled font was created for. - * - * Return value: The #cairo_font_face_t with which @scaled_font was - * created. - * - * Since: 1.2 - **/ -cairo_font_face_t * -cairo_scaled_font_get_font_face (cairo_scaled_font_t *scaled_font) -{ - if (scaled_font->status) - return (cairo_font_face_t*) &_cairo_font_face_nil; - - return scaled_font->font_face; -} -slim_hidden_def (cairo_scaled_font_get_font_face); - -/** - * cairo_scaled_font_get_font_matrix: - * @scaled_font: a #cairo_scaled_font_t - * @font_matrix: return value for the matrix - * - * Stores the font matrix with which @scaled_font was created into - * @matrix. - * - * Since: 1.2 - **/ -void -cairo_scaled_font_get_font_matrix (cairo_scaled_font_t *scaled_font, - cairo_matrix_t *font_matrix) -{ - if (scaled_font->status) { - cairo_matrix_init_identity (font_matrix); - return; - } - - *font_matrix = scaled_font->font_matrix; -} -slim_hidden_def (cairo_scaled_font_get_font_matrix); - -/** - * cairo_scaled_font_get_ctm: - * @scaled_font: a #cairo_scaled_font_t - * @ctm: return value for the CTM - * - * Stores the CTM with which @scaled_font was created into @ctm. - * - * Since: 1.2 - **/ -void -cairo_scaled_font_get_ctm (cairo_scaled_font_t *scaled_font, - cairo_matrix_t *ctm) -{ - if (scaled_font->status) { - cairo_matrix_init_identity (ctm); - return; - } - - *ctm = scaled_font->ctm; -} -slim_hidden_def (cairo_scaled_font_get_ctm); - -/** - * cairo_scaled_font_get_scale_matrix: - * @scaled_font: a #cairo_scaled_font_t - * @scale_matrix: return value for the matrix - * - * Stores the scale matrix of @scaled_font into @matrix. - * The scale matrix is product of the font matrix and the ctm - * associated with the scaled font, and hence is the matrix mapping from - * font space to device space. - * - * Since: 1.8 - **/ -void -cairo_scaled_font_get_scale_matrix (cairo_scaled_font_t *scaled_font, - cairo_matrix_t *scale_matrix) -{ - if (scaled_font->status) { - cairo_matrix_init_identity (scale_matrix); - return; - } - - *scale_matrix = scaled_font->scale; -} - -/** - * cairo_scaled_font_get_font_options: - * @scaled_font: a #cairo_scaled_font_t - * @options: return value for the font options - * - * Stores the font options with which @scaled_font was created into - * @options. - * - * Since: 1.2 - **/ -void -cairo_scaled_font_get_font_options (cairo_scaled_font_t *scaled_font, - cairo_font_options_t *options) -{ - if (cairo_font_options_status (options)) - return; - - if (scaled_font->status) { - _cairo_font_options_init_default (options); - return; - } - - _cairo_font_options_init_copy (options, &scaled_font->options); -} -slim_hidden_def (cairo_scaled_font_get_font_options); diff --git a/uppdev/plugin/cairo/lib/cairo-skiplist-private.h b/uppdev/plugin/cairo/lib/cairo-skiplist-private.h deleted file mode 100644 index 3a948afce..000000000 --- a/uppdev/plugin/cairo/lib/cairo-skiplist-private.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright © 2006 Keith Packard - * Copyright © 2006 Carl Worth - * - * 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 the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS 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. - */ - -#ifndef SKIPLIST_H -#define SKIPLIST_H - -#include "cairoint.h" - -/* - * Skip lists are described in detail here: - * - * http://citeseer.ist.psu.edu/pugh90skip.html - */ - -/* Note that random_level() called from alloc_node_for_level() depends on - * this being not more than 16. - */ -#define MAX_LEVEL 15 - -/* Returns the index of the free-list to use for a node at level 'level' */ -#define FREELIST_FOR_LEVEL(level) (((level) - 1) / 2) - -/* Returns the maximum level that uses the same free-list as 'level' does */ -#define FREELIST_MAX_LEVEL_FOR(level) (((level) + 1) & ~1) - -#define MAX_FREELIST_LEVEL (FREELIST_FOR_LEVEL (MAX_LEVEL - 1) + 1) - -/* - * Skip list element. In order to use the skip list, the caller must - * generate a structure for list elements that has as its final member - * a skip_elt_t, (which will be allocated with variable size). - * - * The caller must also pass the size of the structure to - * _cairo_skip_list_init. - */ -typedef struct _skip_elt { - int prev_index; - struct _skip_elt *prev; - struct _skip_elt *next[1]; -} skip_elt_t; - -#define SKIP_LIST_ELT_TO_DATA(type, elt) ((type *) ((char *) (elt) - (sizeof (type) - sizeof (skip_elt_t)))) - -typedef int -(*cairo_skip_list_compare_t) (void *list, void *a, void *b); - -typedef struct _skip_list { - cairo_skip_list_compare_t compare; - size_t elt_size; - size_t data_size; - skip_elt_t *chains[MAX_LEVEL]; - skip_elt_t *freelists[MAX_FREELIST_LEVEL]; - int max_level; -} cairo_skip_list_t; - -/* Initialize a new skip list. The compare function accepts a pointer - * to the list as well as pointers to two elements. The function must - * return a value greater than zero, zero, or less then 0 if the first - * element is considered respectively greater than, equal to, or less - * than the second element. The size of each object, (as computed by - * sizeof) is passed for elt_size. Note that the structure used for - * list elements must have as its final member a skip_elt_t - */ -cairo_private void -_cairo_skip_list_init (cairo_skip_list_t *list, - cairo_skip_list_compare_t compare, - size_t elt_size); - - -/* Deallocate resources associated with a skip list and all elements - * in it. (XXX: currently this simply deletes all elements.) - */ -cairo_private void -_cairo_skip_list_fini (cairo_skip_list_t *list); - -/* Insert a new element into the list at the correct sort order as - * determined by compare. If unique is true, then duplicate elements - * are ignored and the already inserted element is returned. - * Otherwise data will be copied (elt_size bytes from via - * memcpy) and the new element is returned. */ -cairo_private void * -_cairo_skip_list_insert (cairo_skip_list_t *list, void *data, int unique); - -/* Find an element which compare considers equal to */ -cairo_private void * -_cairo_skip_list_find (cairo_skip_list_t *list, void *data); - -/* Delete an element which compare considers equal to */ -cairo_private void -_cairo_skip_list_delete (cairo_skip_list_t *list, void *data); - -/* Delete the given element from the list. */ -cairo_private void -_cairo_skip_list_delete_given (cairo_skip_list_t *list, skip_elt_t *given); - -#endif diff --git a/uppdev/plugin/cairo/lib/cairo-skiplist.c b/uppdev/plugin/cairo/lib/cairo-skiplist.c deleted file mode 100644 index e2b793e15..000000000 --- a/uppdev/plugin/cairo/lib/cairo-skiplist.c +++ /dev/null @@ -1,485 +0,0 @@ -/* - * Copyright © 2006 Keith Packard - * Copyright © 2006 Carl Worth - * - * 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 the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS 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-skiplist-private.h" - -#define ELT_DATA(elt) (void *) ((char*) (elt) - list->data_size) -#define NEXT_TO_ELT(next) (skip_elt_t *) ((char *) (next) - offsetof (skip_elt_t, next)) - -/* Four 256 element lookup tables back to back implementing a linear - * feedback shift register of degree 32. */ -static unsigned const _cairo_lfsr_random_lut[1024] = { - 0x00000000, 0x9a795537, 0xae8bff59, 0x34f2aa6e, 0xc76eab85, 0x5d17feb2, - 0x69e554dc, 0xf39c01eb, 0x14a4023d, 0x8edd570a, 0xba2ffd64, 0x2056a853, - 0xd3caa9b8, 0x49b3fc8f, 0x7d4156e1, 0xe73803d6, 0x2948047a, 0xb331514d, - 0x87c3fb23, 0x1dbaae14, 0xee26afff, 0x745ffac8, 0x40ad50a6, 0xdad40591, - 0x3dec0647, 0xa7955370, 0x9367f91e, 0x091eac29, 0xfa82adc2, 0x60fbf8f5, - 0x5409529b, 0xce7007ac, 0x529008f4, 0xc8e95dc3, 0xfc1bf7ad, 0x6662a29a, - 0x95fea371, 0x0f87f646, 0x3b755c28, 0xa10c091f, 0x46340ac9, 0xdc4d5ffe, - 0xe8bff590, 0x72c6a0a7, 0x815aa14c, 0x1b23f47b, 0x2fd15e15, 0xb5a80b22, - 0x7bd80c8e, 0xe1a159b9, 0xd553f3d7, 0x4f2aa6e0, 0xbcb6a70b, 0x26cff23c, - 0x123d5852, 0x88440d65, 0x6f7c0eb3, 0xf5055b84, 0xc1f7f1ea, 0x5b8ea4dd, - 0xa812a536, 0x326bf001, 0x06995a6f, 0x9ce00f58, 0xa52011e8, 0x3f5944df, - 0x0babeeb1, 0x91d2bb86, 0x624eba6d, 0xf837ef5a, 0xccc54534, 0x56bc1003, - 0xb18413d5, 0x2bfd46e2, 0x1f0fec8c, 0x8576b9bb, 0x76eab850, 0xec93ed67, - 0xd8614709, 0x4218123e, 0x8c681592, 0x161140a5, 0x22e3eacb, 0xb89abffc, - 0x4b06be17, 0xd17feb20, 0xe58d414e, 0x7ff41479, 0x98cc17af, 0x02b54298, - 0x3647e8f6, 0xac3ebdc1, 0x5fa2bc2a, 0xc5dbe91d, 0xf1294373, 0x6b501644, - 0xf7b0191c, 0x6dc94c2b, 0x593be645, 0xc342b372, 0x30deb299, 0xaaa7e7ae, - 0x9e554dc0, 0x042c18f7, 0xe3141b21, 0x796d4e16, 0x4d9fe478, 0xd7e6b14f, - 0x247ab0a4, 0xbe03e593, 0x8af14ffd, 0x10881aca, 0xdef81d66, 0x44814851, - 0x7073e23f, 0xea0ab708, 0x1996b6e3, 0x83efe3d4, 0xb71d49ba, 0x2d641c8d, - 0xca5c1f5b, 0x50254a6c, 0x64d7e002, 0xfeaeb535, 0x0d32b4de, 0x974be1e9, - 0xa3b94b87, 0x39c01eb0, 0xd03976e7, 0x4a4023d0, 0x7eb289be, 0xe4cbdc89, - 0x1757dd62, 0x8d2e8855, 0xb9dc223b, 0x23a5770c, 0xc49d74da, 0x5ee421ed, - 0x6a168b83, 0xf06fdeb4, 0x03f3df5f, 0x998a8a68, 0xad782006, 0x37017531, - 0xf971729d, 0x630827aa, 0x57fa8dc4, 0xcd83d8f3, 0x3e1fd918, 0xa4668c2f, - 0x90942641, 0x0aed7376, 0xedd570a0, 0x77ac2597, 0x435e8ff9, 0xd927dace, - 0x2abbdb25, 0xb0c28e12, 0x8430247c, 0x1e49714b, 0x82a97e13, 0x18d02b24, - 0x2c22814a, 0xb65bd47d, 0x45c7d596, 0xdfbe80a1, 0xeb4c2acf, 0x71357ff8, - 0x960d7c2e, 0x0c742919, 0x38868377, 0xa2ffd640, 0x5163d7ab, 0xcb1a829c, - 0xffe828f2, 0x65917dc5, 0xabe17a69, 0x31982f5e, 0x056a8530, 0x9f13d007, - 0x6c8fd1ec, 0xf6f684db, 0xc2042eb5, 0x587d7b82, 0xbf457854, 0x253c2d63, - 0x11ce870d, 0x8bb7d23a, 0x782bd3d1, 0xe25286e6, 0xd6a02c88, 0x4cd979bf, - 0x7519670f, 0xef603238, 0xdb929856, 0x41ebcd61, 0xb277cc8a, 0x280e99bd, - 0x1cfc33d3, 0x868566e4, 0x61bd6532, 0xfbc43005, 0xcf369a6b, 0x554fcf5c, - 0xa6d3ceb7, 0x3caa9b80, 0x085831ee, 0x922164d9, 0x5c516375, 0xc6283642, - 0xf2da9c2c, 0x68a3c91b, 0x9b3fc8f0, 0x01469dc7, 0x35b437a9, 0xafcd629e, - 0x48f56148, 0xd28c347f, 0xe67e9e11, 0x7c07cb26, 0x8f9bcacd, 0x15e29ffa, - 0x21103594, 0xbb6960a3, 0x27896ffb, 0xbdf03acc, 0x890290a2, 0x137bc595, - 0xe0e7c47e, 0x7a9e9149, 0x4e6c3b27, 0xd4156e10, 0x332d6dc6, 0xa95438f1, - 0x9da6929f, 0x07dfc7a8, 0xf443c643, 0x6e3a9374, 0x5ac8391a, 0xc0b16c2d, - 0x0ec16b81, 0x94b83eb6, 0xa04a94d8, 0x3a33c1ef, 0xc9afc004, 0x53d69533, - 0x67243f5d, 0xfd5d6a6a, 0x1a6569bc, 0x801c3c8b, 0xb4ee96e5, 0x2e97c3d2, - 0xdd0bc239, 0x4772970e, 0x73803d60, 0xe9f96857, 0x00000000, 0x3a0bb8f9, - 0x741771f2, 0x4e1cc90b, 0xe82ee3e4, 0xd2255b1d, 0x9c399216, 0xa6322aef, - 0x4a2492ff, 0x702f2a06, 0x3e33e30d, 0x04385bf4, 0xa20a711b, 0x9801c9e2, - 0xd61d00e9, 0xec16b810, 0x944925fe, 0xae429d07, 0xe05e540c, 0xda55ecf5, - 0x7c67c61a, 0x466c7ee3, 0x0870b7e8, 0x327b0f11, 0xde6db701, 0xe4660ff8, - 0xaa7ac6f3, 0x90717e0a, 0x364354e5, 0x0c48ec1c, 0x42542517, 0x785f9dee, - 0xb2eb1ecb, 0x88e0a632, 0xc6fc6f39, 0xfcf7d7c0, 0x5ac5fd2f, 0x60ce45d6, - 0x2ed28cdd, 0x14d93424, 0xf8cf8c34, 0xc2c434cd, 0x8cd8fdc6, 0xb6d3453f, - 0x10e16fd0, 0x2aead729, 0x64f61e22, 0x5efda6db, 0x26a23b35, 0x1ca983cc, - 0x52b54ac7, 0x68bef23e, 0xce8cd8d1, 0xf4876028, 0xba9ba923, 0x809011da, - 0x6c86a9ca, 0x568d1133, 0x1891d838, 0x229a60c1, 0x84a84a2e, 0xbea3f2d7, - 0xf0bf3bdc, 0xcab48325, 0xffaf68a1, 0xc5a4d058, 0x8bb81953, 0xb1b3a1aa, - 0x17818b45, 0x2d8a33bc, 0x6396fab7, 0x599d424e, 0xb58bfa5e, 0x8f8042a7, - 0xc19c8bac, 0xfb973355, 0x5da519ba, 0x67aea143, 0x29b26848, 0x13b9d0b1, - 0x6be64d5f, 0x51edf5a6, 0x1ff13cad, 0x25fa8454, 0x83c8aebb, 0xb9c31642, - 0xf7dfdf49, 0xcdd467b0, 0x21c2dfa0, 0x1bc96759, 0x55d5ae52, 0x6fde16ab, - 0xc9ec3c44, 0xf3e784bd, 0xbdfb4db6, 0x87f0f54f, 0x4d44766a, 0x774fce93, - 0x39530798, 0x0358bf61, 0xa56a958e, 0x9f612d77, 0xd17de47c, 0xeb765c85, - 0x0760e495, 0x3d6b5c6c, 0x73779567, 0x497c2d9e, 0xef4e0771, 0xd545bf88, - 0x9b597683, 0xa152ce7a, 0xd90d5394, 0xe306eb6d, 0xad1a2266, 0x97119a9f, - 0x3123b070, 0x0b280889, 0x4534c182, 0x7f3f797b, 0x9329c16b, 0xa9227992, - 0xe73eb099, 0xdd350860, 0x7b07228f, 0x410c9a76, 0x0f10537d, 0x351beb84, - 0x65278475, 0x5f2c3c8c, 0x1130f587, 0x2b3b4d7e, 0x8d096791, 0xb702df68, - 0xf91e1663, 0xc315ae9a, 0x2f03168a, 0x1508ae73, 0x5b146778, 0x611fdf81, - 0xc72df56e, 0xfd264d97, 0xb33a849c, 0x89313c65, 0xf16ea18b, 0xcb651972, - 0x8579d079, 0xbf726880, 0x1940426f, 0x234bfa96, 0x6d57339d, 0x575c8b64, - 0xbb4a3374, 0x81418b8d, 0xcf5d4286, 0xf556fa7f, 0x5364d090, 0x696f6869, - 0x2773a162, 0x1d78199b, 0xd7cc9abe, 0xedc72247, 0xa3dbeb4c, 0x99d053b5, - 0x3fe2795a, 0x05e9c1a3, 0x4bf508a8, 0x71feb051, 0x9de80841, 0xa7e3b0b8, - 0xe9ff79b3, 0xd3f4c14a, 0x75c6eba5, 0x4fcd535c, 0x01d19a57, 0x3bda22ae, - 0x4385bf40, 0x798e07b9, 0x3792ceb2, 0x0d99764b, 0xabab5ca4, 0x91a0e45d, - 0xdfbc2d56, 0xe5b795af, 0x09a12dbf, 0x33aa9546, 0x7db65c4d, 0x47bde4b4, - 0xe18fce5b, 0xdb8476a2, 0x9598bfa9, 0xaf930750, 0x9a88ecd4, 0xa083542d, - 0xee9f9d26, 0xd49425df, 0x72a60f30, 0x48adb7c9, 0x06b17ec2, 0x3cbac63b, - 0xd0ac7e2b, 0xeaa7c6d2, 0xa4bb0fd9, 0x9eb0b720, 0x38829dcf, 0x02892536, - 0x4c95ec3d, 0x769e54c4, 0x0ec1c92a, 0x34ca71d3, 0x7ad6b8d8, 0x40dd0021, - 0xe6ef2ace, 0xdce49237, 0x92f85b3c, 0xa8f3e3c5, 0x44e55bd5, 0x7eeee32c, - 0x30f22a27, 0x0af992de, 0xaccbb831, 0x96c000c8, 0xd8dcc9c3, 0xe2d7713a, - 0x2863f21f, 0x12684ae6, 0x5c7483ed, 0x667f3b14, 0xc04d11fb, 0xfa46a902, - 0xb45a6009, 0x8e51d8f0, 0x624760e0, 0x584cd819, 0x16501112, 0x2c5ba9eb, - 0x8a698304, 0xb0623bfd, 0xfe7ef2f6, 0xc4754a0f, 0xbc2ad7e1, 0x86216f18, - 0xc83da613, 0xf2361eea, 0x54043405, 0x6e0f8cfc, 0x201345f7, 0x1a18fd0e, - 0xf60e451e, 0xcc05fde7, 0x821934ec, 0xb8128c15, 0x1e20a6fa, 0x242b1e03, - 0x6a37d708, 0x503c6ff1, 0x00000000, 0xca4f08ea, 0x0ee744e3, 0xc4a84c09, - 0x1dce89c6, 0xd781812c, 0x1329cd25, 0xd966c5cf, 0x3b9d138c, 0xf1d21b66, - 0x357a576f, 0xff355f85, 0x26539a4a, 0xec1c92a0, 0x28b4dea9, 0xe2fbd643, - 0x773a2718, 0xbd752ff2, 0x79dd63fb, 0xb3926b11, 0x6af4aede, 0xa0bba634, - 0x6413ea3d, 0xae5ce2d7, 0x4ca73494, 0x86e83c7e, 0x42407077, 0x880f789d, - 0x5169bd52, 0x9b26b5b8, 0x5f8ef9b1, 0x95c1f15b, 0xee744e30, 0x243b46da, - 0xe0930ad3, 0x2adc0239, 0xf3bac7f6, 0x39f5cf1c, 0xfd5d8315, 0x37128bff, - 0xd5e95dbc, 0x1fa65556, 0xdb0e195f, 0x114111b5, 0xc827d47a, 0x0268dc90, - 0xc6c09099, 0x0c8f9873, 0x994e6928, 0x530161c2, 0x97a92dcb, 0x5de62521, - 0x8480e0ee, 0x4ecfe804, 0x8a67a40d, 0x4028ace7, 0xa2d37aa4, 0x689c724e, - 0xac343e47, 0x667b36ad, 0xbf1df362, 0x7552fb88, 0xb1fab781, 0x7bb5bf6b, - 0x4691c957, 0x8cdec1bd, 0x48768db4, 0x8239855e, 0x5b5f4091, 0x9110487b, - 0x55b80472, 0x9ff70c98, 0x7d0cdadb, 0xb743d231, 0x73eb9e38, 0xb9a496d2, - 0x60c2531d, 0xaa8d5bf7, 0x6e2517fe, 0xa46a1f14, 0x31abee4f, 0xfbe4e6a5, - 0x3f4caaac, 0xf503a246, 0x2c656789, 0xe62a6f63, 0x2282236a, 0xe8cd2b80, - 0x0a36fdc3, 0xc079f529, 0x04d1b920, 0xce9eb1ca, 0x17f87405, 0xddb77cef, - 0x191f30e6, 0xd350380c, 0xa8e58767, 0x62aa8f8d, 0xa602c384, 0x6c4dcb6e, - 0xb52b0ea1, 0x7f64064b, 0xbbcc4a42, 0x718342a8, 0x937894eb, 0x59379c01, - 0x9d9fd008, 0x57d0d8e2, 0x8eb61d2d, 0x44f915c7, 0x805159ce, 0x4a1e5124, - 0xdfdfa07f, 0x1590a895, 0xd138e49c, 0x1b77ec76, 0xc21129b9, 0x085e2153, - 0xccf66d5a, 0x06b965b0, 0xe442b3f3, 0x2e0dbb19, 0xeaa5f710, 0x20eafffa, - 0xf98c3a35, 0x33c332df, 0xf76b7ed6, 0x3d24763c, 0x8d2392ae, 0x476c9a44, - 0x83c4d64d, 0x498bdea7, 0x90ed1b68, 0x5aa21382, 0x9e0a5f8b, 0x54455761, - 0xb6be8122, 0x7cf189c8, 0xb859c5c1, 0x7216cd2b, 0xab7008e4, 0x613f000e, - 0xa5974c07, 0x6fd844ed, 0xfa19b5b6, 0x3056bd5c, 0xf4fef155, 0x3eb1f9bf, - 0xe7d73c70, 0x2d98349a, 0xe9307893, 0x237f7079, 0xc184a63a, 0x0bcbaed0, - 0xcf63e2d9, 0x052cea33, 0xdc4a2ffc, 0x16052716, 0xd2ad6b1f, 0x18e263f5, - 0x6357dc9e, 0xa918d474, 0x6db0987d, 0xa7ff9097, 0x7e995558, 0xb4d65db2, - 0x707e11bb, 0xba311951, 0x58cacf12, 0x9285c7f8, 0x562d8bf1, 0x9c62831b, - 0x450446d4, 0x8f4b4e3e, 0x4be30237, 0x81ac0add, 0x146dfb86, 0xde22f36c, - 0x1a8abf65, 0xd0c5b78f, 0x09a37240, 0xc3ec7aaa, 0x074436a3, 0xcd0b3e49, - 0x2ff0e80a, 0xe5bfe0e0, 0x2117ace9, 0xeb58a403, 0x323e61cc, 0xf8716926, - 0x3cd9252f, 0xf6962dc5, 0xcbb25bf9, 0x01fd5313, 0xc5551f1a, 0x0f1a17f0, - 0xd67cd23f, 0x1c33dad5, 0xd89b96dc, 0x12d49e36, 0xf02f4875, 0x3a60409f, - 0xfec80c96, 0x3487047c, 0xede1c1b3, 0x27aec959, 0xe3068550, 0x29498dba, - 0xbc887ce1, 0x76c7740b, 0xb26f3802, 0x782030e8, 0xa146f527, 0x6b09fdcd, - 0xafa1b1c4, 0x65eeb92e, 0x87156f6d, 0x4d5a6787, 0x89f22b8e, 0x43bd2364, - 0x9adbe6ab, 0x5094ee41, 0x943ca248, 0x5e73aaa2, 0x25c615c9, 0xef891d23, - 0x2b21512a, 0xe16e59c0, 0x38089c0f, 0xf24794e5, 0x36efd8ec, 0xfca0d006, - 0x1e5b0645, 0xd4140eaf, 0x10bc42a6, 0xdaf34a4c, 0x03958f83, 0xc9da8769, - 0x0d72cb60, 0xc73dc38a, 0x52fc32d1, 0x98b33a3b, 0x5c1b7632, 0x96547ed8, - 0x4f32bb17, 0x857db3fd, 0x41d5fff4, 0x8b9af71e, 0x6961215d, 0xa32e29b7, - 0x678665be, 0xadc96d54, 0x74afa89b, 0xbee0a071, 0x7a48ec78, 0xb007e492, - 0x00000000, 0x803e706b, 0x9a05b5e1, 0x1a3bc58a, 0xae723ef5, 0x2e4c4e9e, - 0x34778b14, 0xb449fb7f, 0xc69d28dd, 0x46a358b6, 0x5c989d3c, 0xdca6ed57, - 0x68ef1628, 0xe8d16643, 0xf2eaa3c9, 0x72d4d3a2, 0x1743048d, 0x977d74e6, - 0x8d46b16c, 0x0d78c107, 0xb9313a78, 0x390f4a13, 0x23348f99, 0xa30afff2, - 0xd1de2c50, 0x51e05c3b, 0x4bdb99b1, 0xcbe5e9da, 0x7fac12a5, 0xff9262ce, - 0xe5a9a744, 0x6597d72f, 0x2e86091a, 0xaeb87971, 0xb483bcfb, 0x34bdcc90, - 0x80f437ef, 0x00ca4784, 0x1af1820e, 0x9acff265, 0xe81b21c7, 0x682551ac, - 0x721e9426, 0xf220e44d, 0x46691f32, 0xc6576f59, 0xdc6caad3, 0x5c52dab8, - 0x39c50d97, 0xb9fb7dfc, 0xa3c0b876, 0x23fec81d, 0x97b73362, 0x17894309, - 0x0db28683, 0x8d8cf6e8, 0xff58254a, 0x7f665521, 0x655d90ab, 0xe563e0c0, - 0x512a1bbf, 0xd1146bd4, 0xcb2fae5e, 0x4b11de35, 0x5d0c1234, 0xdd32625f, - 0xc709a7d5, 0x4737d7be, 0xf37e2cc1, 0x73405caa, 0x697b9920, 0xe945e94b, - 0x9b913ae9, 0x1baf4a82, 0x01948f08, 0x81aaff63, 0x35e3041c, 0xb5dd7477, - 0xafe6b1fd, 0x2fd8c196, 0x4a4f16b9, 0xca7166d2, 0xd04aa358, 0x5074d333, - 0xe43d284c, 0x64035827, 0x7e389dad, 0xfe06edc6, 0x8cd23e64, 0x0cec4e0f, - 0x16d78b85, 0x96e9fbee, 0x22a00091, 0xa29e70fa, 0xb8a5b570, 0x389bc51b, - 0x738a1b2e, 0xf3b46b45, 0xe98faecf, 0x69b1dea4, 0xddf825db, 0x5dc655b0, - 0x47fd903a, 0xc7c3e051, 0xb51733f3, 0x35294398, 0x2f128612, 0xaf2cf679, - 0x1b650d06, 0x9b5b7d6d, 0x8160b8e7, 0x015ec88c, 0x64c91fa3, 0xe4f76fc8, - 0xfeccaa42, 0x7ef2da29, 0xcabb2156, 0x4a85513d, 0x50be94b7, 0xd080e4dc, - 0xa254377e, 0x226a4715, 0x3851829f, 0xb86ff2f4, 0x0c26098b, 0x8c1879e0, - 0x9623bc6a, 0x161dcc01, 0xba182468, 0x3a265403, 0x201d9189, 0xa023e1e2, - 0x146a1a9d, 0x94546af6, 0x8e6faf7c, 0x0e51df17, 0x7c850cb5, 0xfcbb7cde, - 0xe680b954, 0x66bec93f, 0xd2f73240, 0x52c9422b, 0x48f287a1, 0xc8ccf7ca, - 0xad5b20e5, 0x2d65508e, 0x375e9504, 0xb760e56f, 0x03291e10, 0x83176e7b, - 0x992cabf1, 0x1912db9a, 0x6bc60838, 0xebf87853, 0xf1c3bdd9, 0x71fdcdb2, - 0xc5b436cd, 0x458a46a6, 0x5fb1832c, 0xdf8ff347, 0x949e2d72, 0x14a05d19, - 0x0e9b9893, 0x8ea5e8f8, 0x3aec1387, 0xbad263ec, 0xa0e9a666, 0x20d7d60d, - 0x520305af, 0xd23d75c4, 0xc806b04e, 0x4838c025, 0xfc713b5a, 0x7c4f4b31, - 0x66748ebb, 0xe64afed0, 0x83dd29ff, 0x03e35994, 0x19d89c1e, 0x99e6ec75, - 0x2daf170a, 0xad916761, 0xb7aaa2eb, 0x3794d280, 0x45400122, 0xc57e7149, - 0xdf45b4c3, 0x5f7bc4a8, 0xeb323fd7, 0x6b0c4fbc, 0x71378a36, 0xf109fa5d, - 0xe714365c, 0x672a4637, 0x7d1183bd, 0xfd2ff3d6, 0x496608a9, 0xc95878c2, - 0xd363bd48, 0x535dcd23, 0x21891e81, 0xa1b76eea, 0xbb8cab60, 0x3bb2db0b, - 0x8ffb2074, 0x0fc5501f, 0x15fe9595, 0x95c0e5fe, 0xf05732d1, 0x706942ba, - 0x6a528730, 0xea6cf75b, 0x5e250c24, 0xde1b7c4f, 0xc420b9c5, 0x441ec9ae, - 0x36ca1a0c, 0xb6f46a67, 0xaccfafed, 0x2cf1df86, 0x98b824f9, 0x18865492, - 0x02bd9118, 0x8283e173, 0xc9923f46, 0x49ac4f2d, 0x53978aa7, 0xd3a9facc, - 0x67e001b3, 0xe7de71d8, 0xfde5b452, 0x7ddbc439, 0x0f0f179b, 0x8f3167f0, - 0x950aa27a, 0x1534d211, 0xa17d296e, 0x21435905, 0x3b789c8f, 0xbb46ece4, - 0xded13bcb, 0x5eef4ba0, 0x44d48e2a, 0xc4eafe41, 0x70a3053e, 0xf09d7555, - 0xeaa6b0df, 0x6a98c0b4, 0x184c1316, 0x9872637d, 0x8249a6f7, 0x0277d69c, - 0xb63e2de3, 0x36005d88, 0x2c3b9802, 0xac05e869}; - -static unsigned _cairo_lfsr_random_state = 0x12345678; - -static unsigned -lfsr_random(void) -{ - unsigned next; - next = _cairo_lfsr_random_lut[((_cairo_lfsr_random_state>> 0) & 0xFF) + 0*256]; - next ^= _cairo_lfsr_random_lut[((_cairo_lfsr_random_state>> 8) & 0xFF) + 1*256]; - next ^= _cairo_lfsr_random_lut[((_cairo_lfsr_random_state>>16) & 0xFF) + 2*256]; - next ^= _cairo_lfsr_random_lut[((_cairo_lfsr_random_state>>24) & 0xFF) + 3*256]; - return _cairo_lfsr_random_state = next; -} - -/* - * Initialize an empty skip list - */ -void -_cairo_skip_list_init (cairo_skip_list_t *list, - cairo_skip_list_compare_t compare, - size_t elt_size) -{ - int i; - - list->compare = compare; - list->elt_size = elt_size; - list->data_size = elt_size - sizeof (skip_elt_t); - - for (i = 0; i < MAX_LEVEL; i++) { - list->chains[i] = NULL; - } - - for (i = 0; i < MAX_FREELIST_LEVEL; i++) { - list->freelists[i] = NULL; - } - - list->max_level = 0; -} - -void -_cairo_skip_list_fini (cairo_skip_list_t *list) -{ - skip_elt_t *elt; - int i; - - while ((elt = list->chains[0])) { - _cairo_skip_list_delete_given (list, elt); - } - for (i=0; ifreelists[i]; - while (elt) { - skip_elt_t *nextfree = elt->prev; - free (ELT_DATA(elt)); - elt = nextfree; - } - } -} - -/* - * Generate a random level number, distributed - * so that each level is 1/4 as likely as the one before - * - * Note that level numbers run 1 <= level < MAX_LEVEL - */ -static int -random_level (void) -{ - int level = 0; - /* tricky bit -- each bit is '1' 75% of the time. - * This works because we only use the lower MAX_LEVEL - * bits, and MAX_LEVEL < 16 */ - long int bits = lfsr_random(); - bits |= bits >> 16; - - while (++level < MAX_LEVEL) - { - if (bits & 1) - break; - bits >>= 1; - } - return level; -} - -static void * -alloc_node_for_level (cairo_skip_list_t *list, unsigned level) -{ - int freelist_level = FREELIST_FOR_LEVEL (level); - if (list->freelists[freelist_level]) { - skip_elt_t *elt = list->freelists[freelist_level]; - list->freelists[freelist_level] = elt->prev; - return ELT_DATA(elt); - } - return malloc (list->elt_size - + (FREELIST_MAX_LEVEL_FOR (level) - 1) * sizeof (skip_elt_t *)); -} - -static void -free_elt (cairo_skip_list_t *list, skip_elt_t *elt) -{ - int level = elt->prev_index + 1; - int freelist_level = FREELIST_FOR_LEVEL (level); - elt->prev = list->freelists[freelist_level]; - list->freelists[freelist_level] = elt; -} - -/* - * Insert 'data' into the list - */ -void * -_cairo_skip_list_insert (cairo_skip_list_t *list, void *data, int unique) -{ - skip_elt_t **update[MAX_LEVEL]; - skip_elt_t *prev[MAX_LEVEL]; - char *data_and_elt; - skip_elt_t *elt, **next; - int i, level, prev_index; - - /* - * Find links along each chain - */ - elt = NULL; - next = list->chains; - for (i = list->max_level; --i >= 0; ) - { - if (elt != next[i]) - { - for (; (elt = next[i]); next = elt->next) - { - int cmp = list->compare (list, ELT_DATA(elt), data); - if (unique && 0 == cmp) - return ELT_DATA(elt); - if (cmp > 0) - break; - } - } - update[i] = next; - if (next != list->chains) - prev[i] = NEXT_TO_ELT (next); - else - prev[i] = NULL; - } - level = random_level (); - prev_index = level - 1; - - /* - * Create new list element - */ - if (level > list->max_level) - { - level = list->max_level + 1; - prev_index = level - 1; - prev[prev_index] = NULL; - update[list->max_level] = list->chains; - list->max_level = level; - } - - data_and_elt = alloc_node_for_level (list, level); - if (data_and_elt == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return NULL; - } - - memcpy (data_and_elt, data, list->data_size); - elt = (skip_elt_t *) (data_and_elt + list->data_size); - - elt->prev_index = prev_index; - elt->prev = prev[prev_index]; - - /* - * Insert into all chains - */ - for (i = 0; i < level; i++) - { - elt->next[i] = update[i][i]; - if (elt->next[i] && elt->next[i]->prev_index == i) - elt->next[i]->prev = elt; - update[i][i] = elt; - } - - return data_and_elt; -} - -void * -_cairo_skip_list_find (cairo_skip_list_t *list, void *data) -{ - int i; - skip_elt_t **next = list->chains; - skip_elt_t *elt; - - /* - * Walk chain pointers one level at a time - */ - for (i = list->max_level; --i >= 0;) - while (next[i] && list->compare (list, data, ELT_DATA(next[i])) > 0) - { - next = next[i]->next; - } - /* - * Here we are - */ - elt = next[0]; - if (elt && list->compare (list, data, ELT_DATA (elt)) == 0) - return ELT_DATA (elt); - - return NULL; -} - -void -_cairo_skip_list_delete (cairo_skip_list_t *list, void *data) -{ - skip_elt_t **update[MAX_LEVEL], *prev[MAX_LEVEL]; - skip_elt_t *elt, **next; - int i; - - /* - * Find links along each chain - */ - next = list->chains; - for (i = list->max_level; --i >= 0; ) - { - for (; (elt = next[i]); next = elt->next) - { - if (list->compare (list, ELT_DATA (elt), data) >= 0) - break; - } - update[i] = &next[i]; - if (next == list->chains) - prev[i] = NULL; - else - prev[i] = NEXT_TO_ELT (next); - } - elt = next[0]; - assert (list->compare (list, ELT_DATA (elt), data) == 0); - for (i = 0; i < list->max_level && *update[i] == elt; i++) { - *update[i] = elt->next[i]; - if (elt->next[i] && elt->next[i]->prev_index == i) - elt->next[i]->prev = prev[i]; - } - while (list->max_level > 0 && list->chains[list->max_level - 1] == NULL) - list->max_level--; - free_elt (list, elt); -} - -void -_cairo_skip_list_delete_given (cairo_skip_list_t *list, skip_elt_t *given) -{ - skip_elt_t **update[MAX_LEVEL], *prev[MAX_LEVEL]; - skip_elt_t *elt, **next; - int i; - - /* - * Find links along each chain - */ - if (given->prev) - next = given->prev->next; - else - next = list->chains; - for (i = given->prev_index + 1; --i >= 0; ) - { - for (; (elt = next[i]); next = elt->next) - { - if (elt == given) - break; - } - update[i] = &next[i]; - if (next == list->chains) - prev[i] = NULL; - else - prev[i] = NEXT_TO_ELT (next); - } - elt = next[0]; - assert (elt == given); - for (i = 0; i < (given->prev_index + 1) && *update[i] == elt; i++) { - *update[i] = elt->next[i]; - if (elt->next[i] && elt->next[i]->prev_index == i) - elt->next[i]->prev = prev[i]; - } - while (list->max_level > 0 && list->chains[list->max_level - 1] == NULL) - list->max_level--; - free_elt (list, elt); -} diff --git a/uppdev/plugin/cairo/lib/cairo-slope.c b/uppdev/plugin/cairo/lib/cairo-slope.c deleted file mode 100644 index 35c537221..000000000 --- a/uppdev/plugin/cairo/lib/cairo-slope.c +++ /dev/null @@ -1,108 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - */ - -#include "cairoint.h" - -void -_cairo_slope_init (cairo_slope_t *slope, - const cairo_point_t *a, - const cairo_point_t *b) -{ - slope->dx = b->x - a->x; - slope->dy = b->y - a->y; -} - -/* Compare two slopes. Slope angles begin at 0 in the direction of the - positive X axis and increase in the direction of the positive Y - axis. - - This function always compares the slope vectors based on the - smaller angular difference between them, (that is based on an - angular difference that is strictly less than pi). To break ties - when comparing slope vectors with an angular difference of exactly - pi, the vector with a positive dx (or positive dy if dx's are zero) - is considered to be more positive than the other. - - Also, all slope vectors with both dx==0 and dy==0 are considered - equal and more positive than any non-zero vector. - - < 0 => a less positive than b - == 0 => a equal to b - > 0 => a more positive than b -*/ -int -_cairo_slope_compare (const cairo_slope_t *a, const cairo_slope_t *b) -{ - cairo_int64_t ady_bdx = _cairo_int32x32_64_mul (a->dy, b->dx); - cairo_int64_t bdy_adx = _cairo_int32x32_64_mul (b->dy, a->dx); - int cmp; - - cmp = _cairo_int64_cmp (ady_bdx, bdy_adx); - if (cmp) - return cmp; - - /* special-case zero vectors. the intended logic here is: - * zero vectors all compare equal, and more positive than any - * non-zero vector. - */ - if (a->dx == 0 && a->dy == 0 && b->dx == 0 && b->dy ==0) - return 0; - if (a->dx == 0 && a->dy == 0) - return 1; - if (b->dx == 0 && b->dy ==0) - return -1; - - /* Finally, we're looking at two vectors that are either equal or - * that differ by exactly pi. We can identify the "differ by pi" - * case by looking for a change in sign in either dx or dy between - * a and b. - * - * And in these cases, we eliminate the ambiguity by reducing the angle - * of b by an infinitesimally small amount, (that is, 'a' will - * always be considered less than 'b'). - */ - if (((a->dx > 0) != (b->dx > 0)) || - ((a->dy > 0) != (b->dy > 0))) - { - if (a->dx > 0 || (a->dx == 0 && a->dy > 0)) - return +1; - else - return -1; - } - - /* Finally, for identical slopes, we obviously return 0. */ - return 0; -} diff --git a/uppdev/plugin/cairo/lib/cairo-spline.c b/uppdev/plugin/cairo/lib/cairo-spline.c deleted file mode 100644 index b39257e25..000000000 --- a/uppdev/plugin/cairo/lib/cairo-spline.c +++ /dev/null @@ -1,287 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - */ - -#include "cairoint.h" - -static cairo_status_t -_cairo_spline_grow (cairo_spline_t *spline); - -static cairo_status_t -_cairo_spline_add_point (cairo_spline_t *spline, const cairo_point_t *point); - -static void -_lerp_half (const cairo_point_t *a, const cairo_point_t *b, cairo_point_t *result); - -static void -_de_casteljau (cairo_spline_knots_t *s1, cairo_spline_knots_t *s2); - -static double -_cairo_spline_error_squared (const cairo_spline_knots_t *spline); - -static cairo_status_t -_cairo_spline_decompose_into (cairo_spline_knots_t *spline, double tolerance_squared, cairo_spline_t *result); - -cairo_int_status_t -_cairo_spline_init (cairo_spline_t *spline, - const cairo_point_t *a, const cairo_point_t *b, - const cairo_point_t *c, const cairo_point_t *d) -{ - spline->knots.a = *a; - spline->knots.b = *b; - spline->knots.c = *c; - spline->knots.d = *d; - - if (a->x != b->x || a->y != b->y) - _cairo_slope_init (&spline->initial_slope, &spline->knots.a, &spline->knots.b); - else if (a->x != c->x || a->y != c->y) - _cairo_slope_init (&spline->initial_slope, &spline->knots.a, &spline->knots.c); - else if (a->x != d->x || a->y != d->y) - _cairo_slope_init (&spline->initial_slope, &spline->knots.a, &spline->knots.d); - else - return CAIRO_INT_STATUS_DEGENERATE; - - if (c->x != d->x || c->y != d->y) - _cairo_slope_init (&spline->final_slope, &spline->knots.c, &spline->knots.d); - else if (b->x != d->x || b->y != d->y) - _cairo_slope_init (&spline->final_slope, &spline->knots.b, &spline->knots.d); - else - _cairo_slope_init (&spline->final_slope, &spline->knots.a, &spline->knots.d); - - spline->points = spline->points_embedded; - spline->points_size = ARRAY_LENGTH (spline->points_embedded); - spline->num_points = 0; - - return CAIRO_STATUS_SUCCESS; -} - -void -_cairo_spline_fini (cairo_spline_t *spline) -{ - if (spline->points != spline->points_embedded) - free (spline->points); - - spline->points = spline->points_embedded; - spline->points_size = ARRAY_LENGTH (spline->points_embedded); - spline->num_points = 0; -} - -/* make room for at least one more point */ -static cairo_status_t -_cairo_spline_grow (cairo_spline_t *spline) -{ - cairo_point_t *new_points; - int old_size = spline->points_size; - int new_size = 2 * MAX (old_size, 16); - - assert (spline->num_points <= spline->points_size); - - if (spline->points == spline->points_embedded) { - new_points = _cairo_malloc_ab (new_size, sizeof (cairo_point_t)); - if (new_points) - memcpy (new_points, spline->points, old_size * sizeof (cairo_point_t)); - } else { - new_points = _cairo_realloc_ab (spline->points, - new_size, sizeof (cairo_point_t)); - } - - if (new_points == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - spline->points = new_points; - spline->points_size = new_size; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_spline_add_point (cairo_spline_t *spline, const cairo_point_t *point) -{ - cairo_status_t status; - cairo_point_t *prev; - - if (spline->num_points) { - prev = &spline->points[spline->num_points - 1]; - if (prev->x == point->x && prev->y == point->y) - return CAIRO_STATUS_SUCCESS; - } - - if (spline->num_points >= spline->points_size) { - status = _cairo_spline_grow (spline); - if (status) - return status; - } - - spline->points[spline->num_points] = *point; - spline->num_points++; - - return CAIRO_STATUS_SUCCESS; -} - -static void -_lerp_half (const cairo_point_t *a, const cairo_point_t *b, cairo_point_t *result) -{ - result->x = a->x + ((b->x - a->x) >> 1); - result->y = a->y + ((b->y - a->y) >> 1); -} - -static void -_de_casteljau (cairo_spline_knots_t *s1, cairo_spline_knots_t *s2) -{ - cairo_point_t ab, bc, cd; - cairo_point_t abbc, bccd; - cairo_point_t final; - - _lerp_half (&s1->a, &s1->b, &ab); - _lerp_half (&s1->b, &s1->c, &bc); - _lerp_half (&s1->c, &s1->d, &cd); - _lerp_half (&ab, &bc, &abbc); - _lerp_half (&bc, &cd, &bccd); - _lerp_half (&abbc, &bccd, &final); - - s2->a = final; - s2->b = bccd; - s2->c = cd; - s2->d = s1->d; - - s1->b = ab; - s1->c = abbc; - s1->d = final; -} - -/* Return an upper bound on the error (squared) that could result from - * approximating a spline as a line segment connecting the two endpoints. */ -static double -_cairo_spline_error_squared (const cairo_spline_knots_t *knots) -{ - double bdx, bdy, berr; - double cdx, cdy, cerr; - - /* Intersection point (px): - * px = p1 + u(p2 - p1) - * (p - px) ∙ (p2 - p1) = 0 - * Thus: - * u = ((p - p1) ∙ (p2 - p1)) / ∥p2 - p1∥²; - */ - bdx = _cairo_fixed_to_double (knots->b.x - knots->a.x); - bdy = _cairo_fixed_to_double (knots->b.y - knots->a.y); - - cdx = _cairo_fixed_to_double (knots->c.x - knots->a.x); - cdy = _cairo_fixed_to_double (knots->c.y - knots->a.y); - - if (knots->a.x != knots->d.x || knots->a.y != knots->d.y) { - double dx, dy, u, v; - - dx = _cairo_fixed_to_double (knots->d.x - knots->a.x); - dy = _cairo_fixed_to_double (knots->d.y - knots->a.y); - v = dx * dx + dy * dy; - - u = bdx * dx + bdy * dy; - if (u <= 0) { - /* bdx -= 0; - * bdy -= 0; - */ - } else if (u >= v) { - bdx -= dx; - bdy -= dy; - } else { - bdx -= u/v * dx; - bdy -= u/v * dy; - } - - u = cdx * dx + cdy * dy; - if (u <= 0) { - /* cdx -= 0; - * cdy -= 0; - */ - } else if (u >= v) { - cdx -= dx; - cdy -= dy; - } else { - cdx -= u/v * dx; - cdy -= u/v * dy; - } - } - - berr = bdx * bdx + bdy * bdy; - cerr = cdx * cdx + cdy * cdy; - if (berr > cerr) - return berr; - else - return cerr; -} - -static cairo_status_t -_cairo_spline_decompose_into (cairo_spline_knots_t *s1, double tolerance_squared, cairo_spline_t *result) -{ - cairo_spline_knots_t s2; - cairo_status_t status; - - if (_cairo_spline_error_squared (s1) < tolerance_squared) - return _cairo_spline_add_point (result, &s1->a); - - _de_casteljau (s1, &s2); - - status = _cairo_spline_decompose_into (s1, tolerance_squared, result); - if (status) - return status; - - status = _cairo_spline_decompose_into (&s2, tolerance_squared, result); - if (status) - return status; - - return CAIRO_STATUS_SUCCESS; -} - -cairo_status_t -_cairo_spline_decompose (cairo_spline_t *spline, double tolerance) -{ - cairo_status_t status; - cairo_spline_knots_t s1; - - /* reset the spline, but keep the buffer */ - spline->num_points = 0; - - s1 = spline->knots; - status = _cairo_spline_decompose_into (&s1, tolerance * tolerance, spline); - if (status) - return status; - - status = _cairo_spline_add_point (spline, &spline->knots.d); - if (status) - return status; - - return CAIRO_STATUS_SUCCESS; -} diff --git a/uppdev/plugin/cairo/lib/cairo-stroke-style.c b/uppdev/plugin/cairo/lib/cairo-stroke-style.c deleted file mode 100644 index 3bc234e90..000000000 --- a/uppdev/plugin/cairo/lib/cairo-stroke-style.c +++ /dev/null @@ -1,103 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Carl Worth - */ - -#include "cairoint.h" - -void -_cairo_stroke_style_init (cairo_stroke_style_t *style) -{ - style->line_width = CAIRO_GSTATE_LINE_WIDTH_DEFAULT; - style->line_cap = CAIRO_GSTATE_LINE_CAP_DEFAULT; - style->line_join = CAIRO_GSTATE_LINE_JOIN_DEFAULT; - style->miter_limit = CAIRO_GSTATE_MITER_LIMIT_DEFAULT; - - style->dash = NULL; - style->num_dashes = 0; - style->dash_offset = 0.0; -} - -cairo_status_t -_cairo_stroke_style_init_copy (cairo_stroke_style_t *style, - cairo_stroke_style_t *other) -{ - style->line_width = other->line_width; - style->line_cap = other->line_cap; - style->line_join = other->line_join; - style->miter_limit = other->miter_limit; - - style->num_dashes = other->num_dashes; - - if (other->dash == NULL) { - style->dash = NULL; - } else { - style->dash = _cairo_malloc_ab (style->num_dashes, sizeof (double)); - if (style->dash == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - memcpy (style->dash, other->dash, - style->num_dashes * sizeof (double)); - } - - style->dash_offset = other->dash_offset; - - return CAIRO_STATUS_SUCCESS; -} - -void -_cairo_stroke_style_fini (cairo_stroke_style_t *style) -{ - if (style->dash) { - free (style->dash); - style->dash = NULL; - } - style->num_dashes = 0; -} - -/* - * For a stroke in the given style, compute the maximum distance - * from the path that vertices could be generated. In the case - * of rotation in the ctm, the distance will not be exact. - */ -void -_cairo_stroke_style_max_distance_from_path (const cairo_stroke_style_t *style, - const cairo_matrix_t *ctm, - double *dx, double *dy) -{ - double style_expansion = MAX(style->line_cap == CAIRO_LINE_CAP_SQUARE ? M_SQRT1_2 : 0.5, - style->line_join == CAIRO_LINE_JOIN_MITER ? style->miter_limit : 0.5); - - *dx = style->line_width * style_expansion * (fabs(ctm->xx) + fabs(ctm->xy)); - *dy = style->line_width * style_expansion * (fabs(ctm->yy) + fabs(ctm->yx)); -} diff --git a/uppdev/plugin/cairo/lib/cairo-supported-features.h b/uppdev/plugin/cairo/lib/cairo-supported-features.h deleted file mode 100644 index 93f44b812..000000000 --- a/uppdev/plugin/cairo/lib/cairo-supported-features.h +++ /dev/null @@ -1,21 +0,0 @@ -/* Generated by configure. Do not edit. */ -#ifndef CAIRO_SUPPORTED_FEATURES_H -#define CAIRO_SUPPORTED_FEATURES_H - -/* This is a dummy header, to trick gtk-doc only */ - -#define CAIRO_HAS_XLIB_SURFACE 1 -#define CAIRO_HAS_XLIB_XRENDER_SURFACE 1 -#define CAIRO_HAS_QUARTZ_SURFACE 1 -#define CAIRO_HAS_QUARTZ_FONT 1 -#define CAIRO_HAS_WIN32_SURFACE 1 -#define CAIRO_HAS_WIN32_FONT 1 -#define CAIRO_HAS_PNG_FUNCTIONS 1 -#define CAIRO_HAS_FT_FONT 1 -#define CAIRO_HAS_PS_SURFACE 1 -#define CAIRO_HAS_PDF_SURFACE 1 -#define CAIRO_HAS_SVG_SURFACE 1 -#define CAIRO_HAS_IMAGE_SURFACE 1 -#define CAIRO_HAS_USER_FONT 1 - -#endif diff --git a/uppdev/plugin/cairo/lib/cairo-surface-fallback-private.h b/uppdev/plugin/cairo/lib/cairo-surface-fallback-private.h deleted file mode 100644 index 2e10241c2..000000000 --- a/uppdev/plugin/cairo/lib/cairo-surface-fallback-private.h +++ /dev/null @@ -1,131 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - */ - -#ifndef CAIRO_SURFACE_FALLBACK_PRIVATE_H -#define CAIRO_SURFACE_FALLBACK_PRIVATE_H - -#include "cairoint.h" - -cairo_private cairo_status_t -_cairo_surface_fallback_paint (cairo_surface_t *surface, - cairo_operator_t op, - cairo_pattern_t *source); -cairo_private cairo_status_t -_cairo_surface_fallback_mask (cairo_surface_t *surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_pattern_t *mask); - -cairo_private cairo_status_t -_cairo_surface_fallback_stroke (cairo_surface_t *surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_path_fixed_t *path, - cairo_stroke_style_t *stroke_style, - cairo_matrix_t *ctm, - cairo_matrix_t *ctm_inverse, - double tolerance, - cairo_antialias_t antialias); - -cairo_private cairo_status_t -_cairo_surface_fallback_fill (cairo_surface_t *surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias); - -cairo_private cairo_status_t -_cairo_surface_fallback_show_glyphs (cairo_surface_t *surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font); - -cairo_private cairo_surface_t * -_cairo_surface_fallback_snapshot (cairo_surface_t *surface); - -cairo_private cairo_status_t -_cairo_surface_fallback_composite (cairo_operator_t op, - cairo_pattern_t *src, - cairo_pattern_t *mask, - cairo_surface_t *dst, - 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_private cairo_status_t -_cairo_surface_fallback_fill_rectangles (cairo_surface_t *surface, - cairo_operator_t op, - const cairo_color_t *color, - cairo_rectangle_int_t *rects, - int num_rects); - -cairo_private cairo_status_t -_cairo_surface_fallback_composite_trapezoids (cairo_operator_t op, - cairo_pattern_t *pattern, - cairo_surface_t *dst, - cairo_antialias_t antialias, - int src_x, - int src_y, - int dst_x, - int dst_y, - unsigned int width, - unsigned int height, - cairo_trapezoid_t *traps, - int num_traps); - -cairo_private cairo_status_t -_cairo_surface_fallback_clone_similar (cairo_surface_t *surface, - cairo_surface_t *src, - int src_x, - int src_y, - int width, - int height, - int *clone_offset_x, - int *clone_offset_y, - cairo_surface_t **clone_out); - -#endif diff --git a/uppdev/plugin/cairo/lib/cairo-surface-fallback.c b/uppdev/plugin/cairo/lib/cairo-surface-fallback.c deleted file mode 100644 index 5b9c99a64..000000000 --- a/uppdev/plugin/cairo/lib/cairo-surface-fallback.c +++ /dev/null @@ -1,1301 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - */ - -#include "cairoint.h" - -#include "cairo-surface-fallback-private.h" -#include "cairo-clip-private.h" - -typedef struct { - cairo_surface_t *dst; - cairo_rectangle_int_t extents; - cairo_image_surface_t *image; - cairo_rectangle_int_t image_rect; - void *image_extra; -} fallback_state_t; - -/** - * _fallback_init: - * - * Acquire destination image surface needed for an image-based - * fallback. - * - * Return value: %CAIRO_INT_STATUS_NOTHING_TO_DO if the extents are not - * visible, %CAIRO_STATUS_SUCCESS if some portion is visible and all - * went well, or some error status otherwise. - **/ -static cairo_int_status_t -_fallback_init (fallback_state_t *state, - cairo_surface_t *dst, - int x, - int y, - int width, - int height) -{ - cairo_status_t status; - - state->extents.x = x; - state->extents.y = y; - state->extents.width = width; - state->extents.height = height; - - state->dst = dst; - - status = _cairo_surface_acquire_dest_image (dst, &state->extents, - &state->image, &state->image_rect, - &state->image_extra); - if (status) - return status; - - /* XXX: This NULL value tucked away in state->image is a rather - * ugly interface. Cleaner would be to push the - * CAIRO_INT_STATUS_NOTHING_TO_DO value down into - * _cairo_surface_acquire_dest_image and its backend - * counterparts. */ - if (state->image == NULL) - return CAIRO_INT_STATUS_NOTHING_TO_DO; - - return CAIRO_STATUS_SUCCESS; -} - -static void -_fallback_fini (fallback_state_t *state) -{ - _cairo_surface_release_dest_image (state->dst, &state->extents, - state->image, &state->image_rect, - state->image_extra); -} - -typedef cairo_status_t (*cairo_draw_func_t) (void *closure, - cairo_operator_t op, - cairo_pattern_t *src, - cairo_surface_t *dst, - int dst_x, - int dst_y, - const cairo_rectangle_int_t *extents); - -static cairo_status_t -_create_composite_mask_pattern (cairo_surface_pattern_t *mask_pattern, - cairo_clip_t *clip, - cairo_draw_func_t draw_func, - void *draw_closure, - cairo_surface_t *dst, - const cairo_rectangle_int_t *extents) -{ - cairo_surface_t *mask; - cairo_status_t status; - - mask = cairo_surface_create_similar (dst, - CAIRO_CONTENT_ALPHA, - extents->width, - extents->height); - if (mask->status) - return mask->status; - - status = (*draw_func) (draw_closure, CAIRO_OPERATOR_ADD, - NULL, mask, - extents->x, extents->y, - extents); - if (status) - goto CLEANUP_SURFACE; - - if (clip && clip->surface) - status = _cairo_clip_combine_to_surface (clip, CAIRO_OPERATOR_IN, - mask, - extents->x, extents->y, - extents); - if (status) - goto CLEANUP_SURFACE; - - _cairo_pattern_init_for_surface (mask_pattern, mask); - - CLEANUP_SURFACE: - cairo_surface_destroy (mask); - - return status; -} - -/* Handles compositing with a clip surface when the operator allows - * us to combine the clip with the mask - */ -static cairo_status_t -_clip_and_composite_with_mask (cairo_clip_t *clip, - cairo_operator_t op, - cairo_pattern_t *src, - cairo_draw_func_t draw_func, - void *draw_closure, - cairo_surface_t *dst, - const cairo_rectangle_int_t *extents) -{ - cairo_surface_pattern_t mask_pattern; - cairo_status_t status; - - status = _create_composite_mask_pattern (&mask_pattern, - clip, - draw_func, draw_closure, - dst, extents); - if (status) - return status; - - status = _cairo_surface_composite (op, - src, &mask_pattern.base, dst, - extents->x, extents->y, - 0, 0, - extents->x, extents->y, - extents->width, extents->height); - - _cairo_pattern_fini (&mask_pattern.base); - - return status; -} - -/* Handles compositing with a clip surface when we have to do the operation - * in two pieces and combine them together. - */ -static cairo_status_t -_clip_and_composite_combine (cairo_clip_t *clip, - cairo_operator_t op, - cairo_pattern_t *src, - cairo_draw_func_t draw_func, - void *draw_closure, - cairo_surface_t *dst, - const cairo_rectangle_int_t *extents) -{ - cairo_surface_t *intermediate; - cairo_surface_pattern_t dst_pattern; - cairo_surface_pattern_t intermediate_pattern; - cairo_status_t status; - - /* We'd be better off here creating a surface identical in format - * to dst, but we have no way of getting that information. - * A CAIRO_CONTENT_CLONE or something might be useful. - * cairo_surface_create_similar() also unnecessarily clears the surface. - */ - intermediate = cairo_surface_create_similar (dst, - CAIRO_CONTENT_COLOR_ALPHA, - extents->width, - extents->height); - if (intermediate->status) - return intermediate->status; - - /* Initialize the intermediate surface from the destination surface - */ - _cairo_pattern_init_for_surface (&dst_pattern, dst); - - status = _cairo_surface_composite (CAIRO_OPERATOR_SOURCE, - &dst_pattern.base, NULL, intermediate, - extents->x, extents->y, - 0, 0, - 0, 0, - extents->width, extents->height); - - _cairo_pattern_fini (&dst_pattern.base); - - if (status) - goto CLEANUP_SURFACE; - - status = (*draw_func) (draw_closure, op, - src, intermediate, - extents->x, extents->y, - extents); - if (status) - goto CLEANUP_SURFACE; - - /* Combine that with the clip - */ - status = _cairo_clip_combine_to_surface (clip, CAIRO_OPERATOR_DEST_IN, - intermediate, - extents->x, extents->y, - extents); - if (status) - goto CLEANUP_SURFACE; - - /* Punch the clip out of the destination - */ - status = _cairo_clip_combine_to_surface (clip, CAIRO_OPERATOR_DEST_OUT, - dst, - 0, 0, - extents); - if (status) - goto CLEANUP_SURFACE; - - /* Now add the two results together - */ - _cairo_pattern_init_for_surface (&intermediate_pattern, intermediate); - - status = _cairo_surface_composite (CAIRO_OPERATOR_ADD, - &intermediate_pattern.base, NULL, dst, - 0, 0, - 0, 0, - extents->x, extents->y, - extents->width, extents->height); - - _cairo_pattern_fini (&intermediate_pattern.base); - - CLEANUP_SURFACE: - cairo_surface_destroy (intermediate); - - return status; -} - -/* Handles compositing for %CAIRO_OPERATOR_SOURCE, which is special; it's - * defined as (src IN mask IN clip) ADD (dst OUT (mask IN clip)) - */ -static cairo_status_t -_clip_and_composite_source (cairo_clip_t *clip, - cairo_pattern_t *src, - cairo_draw_func_t draw_func, - void *draw_closure, - cairo_surface_t *dst, - const cairo_rectangle_int_t *extents) -{ - cairo_surface_pattern_t mask_pattern; - cairo_status_t status; - - /* Create a surface that is mask IN clip - */ - status = _create_composite_mask_pattern (&mask_pattern, - clip, - draw_func, draw_closure, - dst, extents); - if (status) - return status; - - /* Compute dest' = dest OUT (mask IN clip) - */ - status = _cairo_surface_composite (CAIRO_OPERATOR_DEST_OUT, - &mask_pattern.base, NULL, dst, - 0, 0, - 0, 0, - extents->x, extents->y, - extents->width, extents->height); - - if (status) - goto CLEANUP_MASK_PATTERN; - - /* Now compute (src IN (mask IN clip)) ADD dest' - */ - status = _cairo_surface_composite (CAIRO_OPERATOR_ADD, - src, &mask_pattern.base, dst, - extents->x, extents->y, - 0, 0, - extents->x, extents->y, - extents->width, extents->height); - - CLEANUP_MASK_PATTERN: - _cairo_pattern_fini (&mask_pattern.base); - return status; -} - -static int -_cairo_rectangle_empty (const cairo_rectangle_int_t *rect) -{ - return rect->width == 0 || rect->height == 0; -} - -/** - * _clip_and_composite: - * @clip: a #cairo_clip_t - * @op: the operator to draw with - * @src: source pattern - * @draw_func: function that can be called to draw with the mask onto a surface. - * @draw_closure: data to pass to @draw_func. - * @dst: destination surface - * @extents: rectangle holding a bounding box for the operation; this - * rectangle will be used as the size for the temporary - * surface. - * - * When there is a surface clip, we typically need to create an intermediate - * surface. This function handles the logic of creating a temporary surface - * drawing to it, then compositing the result onto the target surface. - * - * @draw_func is to called to draw the mask; it will be called no more - * than once. - * - * Return value: %CAIRO_STATUS_SUCCESS if the drawing succeeded. - **/ -static cairo_status_t -_clip_and_composite (cairo_clip_t *clip, - cairo_operator_t op, - cairo_pattern_t *src, - cairo_draw_func_t draw_func, - void *draw_closure, - cairo_surface_t *dst, - const cairo_rectangle_int_t *extents) -{ - cairo_solid_pattern_t solid_pattern; - cairo_status_t status; - - if (_cairo_rectangle_empty (extents)) - /* Nothing to do */ - return CAIRO_STATUS_SUCCESS; - - if (op == CAIRO_OPERATOR_CLEAR) { - _cairo_pattern_init_solid (&solid_pattern, CAIRO_COLOR_WHITE, - CAIRO_CONTENT_COLOR); - src = &solid_pattern.base; - op = CAIRO_OPERATOR_DEST_OUT; - } - - if ((clip && clip->surface) || op == CAIRO_OPERATOR_SOURCE) - { - if (op == CAIRO_OPERATOR_SOURCE) - status = _clip_and_composite_source (clip, - src, - draw_func, draw_closure, - dst, extents); - else if (_cairo_operator_bounded_by_mask (op)) - status = _clip_and_composite_with_mask (clip, op, - src, - draw_func, draw_closure, - dst, extents); - else - status = _clip_and_composite_combine (clip, op, - src, - draw_func, draw_closure, - dst, extents); - } - else - { - status = (*draw_func) (draw_closure, op, - src, dst, - 0, 0, - extents); - } - - if (src == &solid_pattern.base) - _cairo_pattern_fini (&solid_pattern.base); - - return status; -} - -/* Composites a region representing a set of trapezoids. - */ -static cairo_status_t -_composite_trap_region (cairo_clip_t *clip, - cairo_pattern_t *src, - cairo_operator_t op, - cairo_surface_t *dst, - cairo_region_t *trap_region, - cairo_rectangle_int_t *extents) -{ - cairo_status_t status; - cairo_solid_pattern_t solid_pattern; - cairo_surface_pattern_t mask; - int num_rects = _cairo_region_num_boxes (trap_region); - unsigned int clip_serial; - cairo_surface_t *clip_surface = clip ? clip->surface : NULL; - - if (clip_surface && op == CAIRO_OPERATOR_CLEAR) { - _cairo_pattern_init_solid (&solid_pattern, CAIRO_COLOR_WHITE, - CAIRO_CONTENT_COLOR); - src = &solid_pattern.base; - op = CAIRO_OPERATOR_DEST_OUT; - } - - if (num_rects == 0) - return CAIRO_STATUS_SUCCESS; - - if (num_rects > 1) { - if (_cairo_surface_get_clip_mode (dst) != CAIRO_CLIP_MODE_REGION) - return CAIRO_INT_STATUS_UNSUPPORTED; - - clip_serial = _cairo_surface_allocate_clip_serial (dst); - status = _cairo_surface_set_clip_region (dst, - trap_region, - clip_serial); - if (status) - return status; - } - - if (clip_surface) - _cairo_pattern_init_for_surface (&mask, clip_surface); - - status = _cairo_surface_composite (op, - src, - clip_surface ? &mask.base : NULL, - dst, - extents->x, extents->y, - extents->x - (clip_surface ? clip->surface_rect.x : 0), - extents->y - (clip_surface ? clip->surface_rect.y : 0), - extents->x, extents->y, - extents->width, extents->height); - - /* Restore the original clip if we modified it temporarily. */ - if (num_rects > 1) { - cairo_status_t status2 = _cairo_surface_set_clip (dst, clip); - if (status == CAIRO_STATUS_SUCCESS) - status = status2; - } - - if (clip_surface) - _cairo_pattern_fini (&mask.base); - - if (src == &solid_pattern.base) - _cairo_pattern_fini (&solid_pattern.base); - - return status; -} - -typedef struct { - cairo_traps_t *traps; - cairo_antialias_t antialias; -} cairo_composite_traps_info_t; - -static cairo_status_t -_composite_traps_draw_func (void *closure, - cairo_operator_t op, - cairo_pattern_t *src, - cairo_surface_t *dst, - int dst_x, - int dst_y, - const cairo_rectangle_int_t *extents) -{ - cairo_composite_traps_info_t *info = closure; - cairo_solid_pattern_t pattern; - cairo_status_t status; - - if (dst_x != 0 || dst_y != 0) - _cairo_traps_translate (info->traps, - dst_x, - dst_y); - - _cairo_pattern_init_solid (&pattern, CAIRO_COLOR_WHITE, - CAIRO_CONTENT_COLOR); - if (!src) - src = &pattern.base; - - status = _cairo_surface_composite_trapezoids (op, - src, dst, info->antialias, - extents->x, extents->y, - extents->x - dst_x, extents->y - dst_y, - extents->width, extents->height, - info->traps->traps, - info->traps->num_traps); - _cairo_pattern_fini (&pattern.base); - - return status; -} - -/* Warning: This call modifies the coordinates of traps */ -static cairo_status_t -_clip_and_composite_trapezoids (cairo_pattern_t *src, - cairo_operator_t op, - cairo_surface_t *dst, - cairo_traps_t *traps, - cairo_clip_t *clip, - cairo_antialias_t antialias) -{ - cairo_status_t status; - cairo_region_t trap_region; - cairo_region_t clear_region; - cairo_bool_t has_trap_region = FALSE; - cairo_bool_t has_clear_region = FALSE; - cairo_rectangle_int_t extents; - cairo_composite_traps_info_t traps_info; - - if (_cairo_operator_bounded_by_mask (op) && traps->num_traps == 0) - return CAIRO_STATUS_SUCCESS; - - status = _cairo_surface_get_extents (dst, &extents); - if (status) - return status; - - status = _cairo_traps_extract_region (traps, &trap_region); - if (CAIRO_INT_STATUS_UNSUPPORTED == status) { - has_trap_region = FALSE; - } else if (status) { - return status; - } else { - has_trap_region = TRUE; - } - - if (_cairo_operator_bounded_by_mask (op)) { - cairo_rectangle_int_t trap_extents; - - if (has_trap_region) { - status = _cairo_clip_intersect_to_region (clip, &trap_region); - if (status) - goto out; - - _cairo_region_get_extents (&trap_region, &trap_extents); - } else { - cairo_box_t trap_box; - _cairo_traps_extents (traps, &trap_box); - _cairo_box_round_to_rectangle (&trap_box, &trap_extents); - } - - if (! _cairo_rectangle_intersect (&extents, &trap_extents)) { - status = CAIRO_STATUS_SUCCESS; - goto out; - } - - status = _cairo_clip_intersect_to_rectangle (clip, &extents); - if (status) - goto out; - } else { - cairo_surface_t *clip_surface = clip ? clip->surface : NULL; - - if (has_trap_region && !clip_surface) { - /* If we optimize drawing with an unbounded operator to - * _cairo_surface_fill_rectangles() or to drawing with a - * clip region, then we have an additional region to clear. - */ - _cairo_region_init_rect (&clear_region, &extents); - - has_clear_region = TRUE; - status = _cairo_clip_intersect_to_region (clip, &clear_region); - - if (status) - goto out; - - _cairo_region_get_extents (&clear_region, &extents); - - status = _cairo_region_subtract (&clear_region, &clear_region, &trap_region); - if (status) - goto out; - - if (!_cairo_region_not_empty (&clear_region)) { - _cairo_region_fini (&clear_region); - has_clear_region = FALSE; - } - } else { - status = _cairo_clip_intersect_to_rectangle (clip, &extents); - } - } - - if (status) - goto out; - - if (has_trap_region) { - cairo_surface_t *clip_surface = clip ? clip->surface : NULL; - - if ((src->type == CAIRO_PATTERN_TYPE_SOLID || - op == CAIRO_OPERATOR_CLEAR) && !clip_surface) { - const cairo_color_t *color; - - if (op == CAIRO_OPERATOR_CLEAR) { - color = CAIRO_COLOR_TRANSPARENT; - } else { - color = &((cairo_solid_pattern_t *)src)->color; - } - - /* Solid rectangles special case */ - status = _cairo_surface_fill_region (dst, op, color, &trap_region); - - if (!status && has_clear_region) - status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR, - CAIRO_COLOR_TRANSPARENT, - &clear_region); - - goto out; - } - - if ((_cairo_operator_bounded_by_mask (op) && - op != CAIRO_OPERATOR_SOURCE) || !clip_surface) { - /* For a simple rectangle, we can just use composite(), for more - * rectangles, we have to set a clip region. The cost of rasterizing - * trapezoids is pretty high for most backends currently, so it's - * worthwhile even if a region is needed. - * - * If we have a clip surface, we set it as the mask; this only works - * for bounded operators other than SOURCE; for unbounded operators, - * clip and mask cannot be interchanged. For SOURCE, the operator - * as implemented by the backends is different in it's handling - * of the mask then what we want. - * - * CAIRO_INT_STATUS_UNSUPPORTED will be returned if the region has - * more than rectangle and the destination doesn't support clip - * regions. In that case, we fall through. - */ - status = _composite_trap_region (clip, src, op, dst, - &trap_region, &extents); - - if (status != CAIRO_INT_STATUS_UNSUPPORTED) { - if (!status && has_clear_region) - status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR, - CAIRO_COLOR_TRANSPARENT, - &clear_region); - goto out; - } - } - } - - traps_info.traps = traps; - traps_info.antialias = antialias; - - status = _clip_and_composite (clip, op, src, - _composite_traps_draw_func, - &traps_info, dst, &extents); - -out: - if (has_trap_region) - _cairo_region_fini (&trap_region); - if (has_clear_region) - _cairo_region_fini (&clear_region); - - return status; -} - -cairo_status_t -_cairo_surface_fallback_paint (cairo_surface_t *surface, - cairo_operator_t op, - cairo_pattern_t *source) -{ - cairo_status_t status; - cairo_rectangle_int_t extents; - cairo_box_t box; - cairo_traps_t traps; - - status = _cairo_surface_get_extents (surface, &extents); - if (status) - return status; - - if (_cairo_operator_bounded_by_source (op)) { - cairo_rectangle_int_t source_extents; - status = _cairo_pattern_get_extents (source, &source_extents); - if (status) - return status; - - if (! _cairo_rectangle_intersect (&extents, &source_extents)) - return CAIRO_STATUS_SUCCESS; - } - - status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents); - if (status) - return status; - - _cairo_box_from_rectangle (&box, &extents); - - _cairo_traps_init_box (&traps, &box); - - status = _clip_and_composite_trapezoids (source, - op, - surface, - &traps, - surface->clip, - CAIRO_ANTIALIAS_NONE); - - _cairo_traps_fini (&traps); - - return status; -} - -static cairo_status_t -_cairo_surface_mask_draw_func (void *closure, - cairo_operator_t op, - cairo_pattern_t *src, - cairo_surface_t *dst, - int dst_x, - int dst_y, - const cairo_rectangle_int_t *extents) -{ - cairo_pattern_t *mask = closure; - - if (src) - return _cairo_surface_composite (op, - src, mask, dst, - extents->x, extents->y, - extents->x, extents->y, - extents->x - dst_x, extents->y - dst_y, - extents->width, extents->height); - else - return _cairo_surface_composite (op, - mask, NULL, dst, - extents->x, extents->y, - 0, 0, /* unused */ - extents->x - dst_x, extents->y - dst_y, - extents->width, extents->height); -} - -cairo_status_t -_cairo_surface_fallback_mask (cairo_surface_t *surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_pattern_t *mask) -{ - cairo_status_t status; - cairo_rectangle_int_t extents, source_extents, mask_extents; - - status = _cairo_surface_get_extents (surface, &extents); - if (status) - return status; - - if (_cairo_operator_bounded_by_source (op)) { - status = _cairo_pattern_get_extents (source, &source_extents); - if (status) - return status; - - if (! _cairo_rectangle_intersect (&extents, &source_extents)) - return CAIRO_STATUS_SUCCESS; - } - - if (_cairo_operator_bounded_by_mask (op)) { - status = _cairo_pattern_get_extents (mask, &mask_extents); - if (status) - return status; - - if (! _cairo_rectangle_intersect (&extents, &mask_extents)) - return CAIRO_STATUS_SUCCESS; - } - - status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents); - if (status) - return status; - - status = _clip_and_composite (surface->clip, op, - source, - _cairo_surface_mask_draw_func, - mask, - surface, - &extents); - - return status; -} - -cairo_status_t -_cairo_surface_fallback_stroke (cairo_surface_t *surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_path_fixed_t *path, - cairo_stroke_style_t *stroke_style, - cairo_matrix_t *ctm, - cairo_matrix_t *ctm_inverse, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_status_t status; - cairo_traps_t traps; - cairo_box_t box; - cairo_rectangle_int_t extents; - - status = _cairo_surface_get_extents (surface, &extents); - if (status) - return status; - - if (_cairo_operator_bounded_by_source (op)) { - cairo_rectangle_int_t source_extents; - status = _cairo_pattern_get_extents (source, &source_extents); - if (status) - return status; - - if (! _cairo_rectangle_intersect (&extents, &source_extents)) - return CAIRO_STATUS_SUCCESS; - } - - status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents); - if (status) - return status; - - if (extents.width == 0 || extents.height == 0) - return CAIRO_STATUS_SUCCESS; - - _cairo_box_from_rectangle (&box, &extents); - - _cairo_traps_init (&traps); - _cairo_traps_limit (&traps, &box); - - status = _cairo_path_fixed_stroke_to_traps (path, - stroke_style, - ctm, ctm_inverse, - tolerance, - &traps); - if (status) - goto FAIL; - - status = _clip_and_composite_trapezoids (source, - op, - surface, - &traps, - surface->clip, - antialias); - -FAIL: - _cairo_traps_fini (&traps); - - return status; -} - -cairo_status_t -_cairo_surface_fallback_fill (cairo_surface_t *surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_status_t status; - cairo_traps_t traps; - cairo_box_t box; - cairo_rectangle_int_t extents; - - status = _cairo_surface_get_extents (surface, &extents); - if (status) - return status; - - if (_cairo_operator_bounded_by_source (op)) { - cairo_rectangle_int_t source_extents; - - status = _cairo_pattern_get_extents (source, &source_extents); - if (status) - return status; - - if (! _cairo_rectangle_intersect (&extents, &source_extents)) - return CAIRO_STATUS_SUCCESS; - } - - status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents); - if (status) - return status; - - if (extents.width == 0 || extents.height == 0) - return CAIRO_STATUS_SUCCESS; - - _cairo_box_from_rectangle (&box, &extents); - - _cairo_traps_init (&traps); - _cairo_traps_limit (&traps, &box); - - status = _cairo_path_fixed_fill_to_traps (path, - fill_rule, - tolerance, - &traps); - if (status) { - _cairo_traps_fini (&traps); - return status; - } - - status = _clip_and_composite_trapezoids (source, - op, - surface, - &traps, - surface->clip, - antialias); - - _cairo_traps_fini (&traps); - - return status; -} - -typedef struct { - cairo_scaled_font_t *font; - cairo_glyph_t *glyphs; - int num_glyphs; -} cairo_show_glyphs_info_t; - -static cairo_status_t -_cairo_surface_old_show_glyphs_draw_func (void *closure, - cairo_operator_t op, - cairo_pattern_t *src, - cairo_surface_t *dst, - int dst_x, - int dst_y, - const cairo_rectangle_int_t *extents) -{ - cairo_show_glyphs_info_t *glyph_info = closure; - cairo_solid_pattern_t pattern; - cairo_status_t status; - - /* Modifying the glyph array is fine because we know that this function - * will be called only once, and we've already made a copy of the - * glyphs in the wrapper. - */ - if (dst_x != 0 || dst_y != 0) { - int i; - - for (i = 0; i < glyph_info->num_glyphs; ++i) - { - ((cairo_glyph_t *) glyph_info->glyphs)[i].x -= dst_x; - ((cairo_glyph_t *) glyph_info->glyphs)[i].y -= dst_y; - } - } - - _cairo_pattern_init_solid (&pattern, CAIRO_COLOR_WHITE, - CAIRO_CONTENT_COLOR); - if (!src) - src = &pattern.base; - - status = _cairo_surface_old_show_glyphs (glyph_info->font, op, src, - dst, - extents->x, extents->y, - extents->x - dst_x, - extents->y - dst_y, - extents->width, - extents->height, - glyph_info->glyphs, - glyph_info->num_glyphs); - - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - - status = _cairo_scaled_font_show_glyphs (glyph_info->font, - op, - src, dst, - extents->x, extents->y, - extents->x - dst_x, - extents->y - dst_y, - extents->width, extents->height, - glyph_info->glyphs, - glyph_info->num_glyphs); - - if (src == &pattern.base) - _cairo_pattern_fini (&pattern.base); - - return status; -} - -cairo_status_t -_cairo_surface_fallback_show_glyphs (cairo_surface_t *surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font) -{ - cairo_status_t status; - cairo_rectangle_int_t extents; - cairo_show_glyphs_info_t glyph_info; - - status = _cairo_surface_get_extents (surface, &extents); - if (status) - return status; - - if (_cairo_operator_bounded_by_mask (op)) { - cairo_rectangle_int_t glyph_extents; - - status = _cairo_scaled_font_glyph_device_extents (scaled_font, - glyphs, - num_glyphs, - &glyph_extents); - if (status) - return status; - - if (! _cairo_rectangle_intersect (&extents, &glyph_extents)) - return CAIRO_STATUS_SUCCESS; - } - - status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents); - if (status) - return status; - - glyph_info.font = scaled_font; - glyph_info.glyphs = glyphs; - glyph_info.num_glyphs = num_glyphs; - - status = _clip_and_composite (surface->clip, - op, - source, - _cairo_surface_old_show_glyphs_draw_func, - &glyph_info, - surface, - &extents); - - return status; -} - -cairo_surface_t * -_cairo_surface_fallback_snapshot (cairo_surface_t *surface) -{ - cairo_surface_t *snapshot; - cairo_status_t status; - cairo_surface_pattern_t pattern; - cairo_image_surface_t *image; - void *image_extra; - - status = _cairo_surface_acquire_source_image (surface, - &image, &image_extra); - if (status) - return _cairo_surface_create_in_error (status); - - snapshot = cairo_image_surface_create (image->format, - image->width, - image->height); - if (cairo_surface_status (snapshot)) { - _cairo_surface_release_source_image (surface, - image, image_extra); - return snapshot; - } - - _cairo_pattern_init_for_surface (&pattern, &image->base); - - status = _cairo_surface_composite (CAIRO_OPERATOR_SOURCE, - &pattern.base, - NULL, - snapshot, - 0, 0, - 0, 0, - 0, 0, - image->width, - image->height); - - _cairo_pattern_fini (&pattern.base); - _cairo_surface_release_source_image (surface, - image, image_extra); - - if (status) { - cairo_surface_destroy (snapshot); - return _cairo_surface_create_in_error (status); - } - - snapshot->device_transform = surface->device_transform; - snapshot->device_transform_inverse = surface->device_transform_inverse; - - snapshot->is_snapshot = TRUE; - - return snapshot; -} - -cairo_status_t -_cairo_surface_fallback_composite (cairo_operator_t op, - cairo_pattern_t *src, - cairo_pattern_t *mask, - cairo_surface_t *dst, - int src_x, - int src_y, - int mask_x, - int mask_y, - int dst_x, - int dst_y, - unsigned int width, - unsigned int height) -{ - fallback_state_t state; - cairo_status_t status; - - status = _fallback_init (&state, dst, dst_x, dst_y, width, height); - if (status) { - if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) - return CAIRO_STATUS_SUCCESS; - return status; - } - - /* We know this will never fail with the image backend; but - * instead of calling into it directly, we call - * _cairo_surface_composite so that we get the correct device - * offset handling. - */ - status = _cairo_surface_composite (op, src, mask, - &state.image->base, - src_x, src_y, mask_x, mask_y, - dst_x - state.image_rect.x, - dst_y - state.image_rect.y, - width, height); - _fallback_fini (&state); - - return status; -} - -cairo_status_t -_cairo_surface_fallback_fill_rectangles (cairo_surface_t *surface, - cairo_operator_t op, - const cairo_color_t *color, - cairo_rectangle_int_t *rects, - int num_rects) -{ - fallback_state_t state; - cairo_rectangle_int_t *offset_rects = NULL; - cairo_status_t status; - int x1, y1, x2, y2; - int i; - - assert (! surface->is_snapshot); - - if (num_rects <= 0) - return CAIRO_STATUS_SUCCESS; - - /* Compute the bounds of the rectangles, so that we know what area of the - * destination surface to fetch - */ - x1 = rects[0].x; - y1 = rects[0].y; - x2 = rects[0].x + rects[0].width; - y2 = rects[0].y + rects[0].height; - - for (i = 1; i < num_rects; i++) { - if (rects[i].x < x1) - x1 = rects[i].x; - if (rects[i].y < y1) - y1 = rects[i].y; - - if ((int) (rects[i].x + rects[i].width) > x2) - x2 = rects[i].x + rects[i].width; - if ((int) (rects[i].y + rects[i].height) > y2) - y2 = rects[i].y + rects[i].height; - } - - status = _fallback_init (&state, surface, x1, y1, x2 - x1, y2 - y1); - if (status) { - if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) - return CAIRO_STATUS_SUCCESS; - return status; - } - - /* If the fetched image isn't at 0,0, we need to offset the rectangles */ - - if (state.image_rect.x != 0 || state.image_rect.y != 0) { - offset_rects = _cairo_malloc_ab (num_rects, sizeof (cairo_rectangle_int_t)); - if (offset_rects == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto DONE; - } - - for (i = 0; i < num_rects; i++) { - offset_rects[i].x = rects[i].x - state.image_rect.x; - offset_rects[i].y = rects[i].y - state.image_rect.y; - offset_rects[i].width = rects[i].width; - offset_rects[i].height = rects[i].height; - } - - rects = offset_rects; - } - - status = _cairo_surface_fill_rectangles (&state.image->base, - op, color, - rects, num_rects); - - free (offset_rects); - - DONE: - _fallback_fini (&state); - - return status; -} - -cairo_status_t -_cairo_surface_fallback_composite_trapezoids (cairo_operator_t op, - cairo_pattern_t *pattern, - cairo_surface_t *dst, - cairo_antialias_t antialias, - int src_x, - int src_y, - int dst_x, - int dst_y, - unsigned int width, - unsigned int height, - cairo_trapezoid_t *traps, - int num_traps) -{ - fallback_state_t state; - cairo_trapezoid_t *offset_traps = NULL; - cairo_status_t status; - - status = _fallback_init (&state, dst, dst_x, dst_y, width, height); - if (status) { - if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) - return CAIRO_STATUS_SUCCESS; - return status; - } - - /* If the destination image isn't at 0,0, we need to offset the trapezoids */ - - if (state.image_rect.x != 0 || state.image_rect.y != 0) { - offset_traps = _cairo_malloc_ab (num_traps, sizeof (cairo_trapezoid_t)); - if (!offset_traps) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto DONE; - } - - _cairo_trapezoid_array_translate_and_scale (offset_traps, traps, num_traps, - - state.image_rect.x, - state.image_rect.y, - 1.0, 1.0); - traps = offset_traps; - } - - status = _cairo_surface_composite_trapezoids (op, pattern, - &state.image->base, - antialias, - src_x, src_y, - dst_x - state.image_rect.x, - dst_y - state.image_rect.y, - width, height, - traps, num_traps); - if (offset_traps) - free (offset_traps); - - DONE: - _fallback_fini (&state); - - return status; -} - -cairo_status_t -_cairo_surface_fallback_clone_similar (cairo_surface_t *surface, - cairo_surface_t *src, - int src_x, - int src_y, - int width, - int height, - int *clone_offset_x, - int *clone_offset_y, - cairo_surface_t **clone_out) -{ - cairo_status_t status; - cairo_surface_t *new_surface = NULL; - cairo_t *cr; - - new_surface = _cairo_surface_create_similar_scratch (surface, - cairo_surface_get_content (src), - width, height); - if (new_surface->status) - return new_surface->status; - - /* We have to copy these here, so that the coordinate spaces are correct */ - new_surface->device_transform = src->device_transform; - new_surface->device_transform_inverse = src->device_transform_inverse; - - /* We can't use _cairo_composite directly, because backends that - * implement the "high-level" API may not have it implemented. - * (For example, SVG.) We can fix this by either checking if the - * destination supports composite first, or we can make clone a - * required "high-level" operation. - */ - cr = cairo_create (new_surface); - cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); - cairo_set_source_surface (cr, src, -src_x, -src_y); - cairo_paint (cr); - status = cairo_status (cr); - cairo_destroy (cr); - - if (status == CAIRO_STATUS_SUCCESS) { - *clone_offset_x = src_x; - *clone_offset_y = src_y; - *clone_out = new_surface; - } else - cairo_surface_destroy (new_surface); - - return status; -} diff --git a/uppdev/plugin/cairo/lib/cairo-surface-private.h b/uppdev/plugin/cairo/lib/cairo-surface-private.h deleted file mode 100644 index efd4365eb..000000000 --- a/uppdev/plugin/cairo/lib/cairo-surface-private.h +++ /dev/null @@ -1,105 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - */ - -#ifndef CAIRO_SURFACE_PRIVATE_H -#define CAIRO_SURFACE_PRIVATE_H - -#include "cairo.h" - -#include "cairo-types-private.h" -#include "cairo-reference-count-private.h" - -struct _cairo_surface { - const cairo_surface_backend_t *backend; - - /* We allow surfaces to override the backend->type by shoving something - * else into surface->type. This is for "wrapper" surfaces that want to - * hide their internal type from the user-level API. */ - cairo_surface_type_t type; - - cairo_content_t content; - - cairo_reference_count_t ref_count; - cairo_status_t status; - cairo_bool_t finished; - cairo_user_data_array_t user_data; - - cairo_matrix_t device_transform; - cairo_matrix_t device_transform_inverse; - - /* The actual resolution of the device, in dots per inch. */ - double x_resolution; - double y_resolution; - - /* The resolution that should be used when generating image-based - * fallback; generally only used by the analysis/paginated - * surfaces - */ - double x_fallback_resolution; - double y_fallback_resolution; - - cairo_clip_t *clip; - - /* - * Each time a clip region is modified, it gets the next value in this - * sequence. This means that clip regions for this surface are uniquely - * identified and updates to the clip can be readily identified - */ - unsigned int next_clip_serial; - /* - * The serial number of the current clip. This is set when - * the surface clipping is set. The gstate can then cheaply - * check whether the surface clipping is already correct before - * performing a rendering operation. - * - * The special value '0' is reserved for the unclipped case. - */ - unsigned int current_clip_serial; - - /* A "snapshot" surface is immutable. See _cairo_surface_snapshot. */ - cairo_bool_t is_snapshot; - - /* - * Surface font options, falling back to backend's default options, - * and set using _cairo_surface_set_font_options(), and propagated by - * cairo_surface_create_similar(). - */ - cairo_bool_t has_font_options; - cairo_font_options_t font_options; -}; - -#endif /* CAIRO_SURFACE_PRIVATE_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-surface.c b/uppdev/plugin/cairo/lib/cairo-surface.c deleted file mode 100644 index 609a0e05a..000000000 --- a/uppdev/plugin/cairo/lib/cairo-surface.c +++ /dev/null @@ -1,2697 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - */ - -#include "cairoint.h" - -#include "cairo-surface-fallback-private.h" -#include "cairo-clip-private.h" - -#define DEFINE_NIL_SURFACE(status, name) \ -const cairo_surface_t name = { \ - &_cairo_image_surface_backend, /* backend */ \ - CAIRO_SURFACE_TYPE_IMAGE, \ - CAIRO_CONTENT_COLOR, \ - CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */ \ - status, /* status */ \ - FALSE, /* finished */ \ - { 0, /* size */ \ - 0, /* num_elements */ \ - 0, /* element_size */ \ - NULL, /* elements */ \ - }, /* user_data */ \ - { 1.0, 0.0, \ - 0.0, 1.0, \ - 0.0, 0.0 \ - }, /* device_transform */ \ - { 1.0, 0.0, \ - 0.0, 1.0, \ - 0.0, 0.0 \ - }, /* device_transform_inverse */ \ - 0.0, /* x_resolution */ \ - 0.0, /* y_resolution */ \ - 0.0, /* x_fallback_resolution */ \ - 0.0, /* y_fallback_resolution */ \ - NULL, /* clip */ \ - 0, /* next_clip_serial */ \ - 0, /* current_clip_serial */ \ - FALSE, /* is_snapshot */ \ - FALSE, /* has_font_options */ \ - { CAIRO_ANTIALIAS_DEFAULT, /* antialias */ \ - CAIRO_SUBPIXEL_ORDER_DEFAULT, /* subpixel_order */ \ - CAIRO_HINT_STYLE_DEFAULT, /* hint_style */ \ - CAIRO_HINT_METRICS_DEFAULT /* hint_metrics */ \ - } /* font_options */ \ -} - -static DEFINE_NIL_SURFACE(CAIRO_STATUS_NO_MEMORY, _cairo_surface_nil); -static DEFINE_NIL_SURFACE(CAIRO_STATUS_INVALID_CONTENT, _cairo_surface_nil_invalid_content); -static DEFINE_NIL_SURFACE(CAIRO_STATUS_INVALID_FORMAT, _cairo_surface_nil_invalid_format); -static DEFINE_NIL_SURFACE(CAIRO_STATUS_INVALID_VISUAL, _cairo_surface_nil_invalid_visual); -static DEFINE_NIL_SURFACE(CAIRO_STATUS_FILE_NOT_FOUND, _cairo_surface_nil_file_not_found); -static DEFINE_NIL_SURFACE(CAIRO_STATUS_TEMP_FILE_ERROR, _cairo_surface_nil_temp_file_error); -static DEFINE_NIL_SURFACE(CAIRO_STATUS_READ_ERROR, _cairo_surface_nil_read_error); -static DEFINE_NIL_SURFACE(CAIRO_STATUS_WRITE_ERROR, _cairo_surface_nil_write_error); -static DEFINE_NIL_SURFACE(CAIRO_STATUS_INVALID_STRIDE, _cairo_surface_nil_invalid_stride); - -static cairo_status_t -_cairo_surface_copy_pattern_for_destination (const cairo_pattern_t *pattern, - cairo_surface_t *destination, - cairo_pattern_t **pattern_out); - -/** - * _cairo_surface_set_error: - * @surface: a surface - * @status: a status value indicating an error - * - * Atomically sets surface->status to @status and calls _cairo_error; - * Does nothing if status is %CAIRO_STATUS_SUCCESS or any of the internal - * status values. - * - * All assignments of an error status to surface->status should happen - * through _cairo_surface_set_error(). Note that due to the nature of - * the atomic operation, it is not safe to call this function on the - * nil objects. - * - * The purpose of this function is to allow the user to set a - * breakpoint in _cairo_error() to generate a stack trace for when the - * user causes cairo to detect an error. - * - * Return value: the error status. - **/ -cairo_status_t -_cairo_surface_set_error (cairo_surface_t *surface, - cairo_status_t status) -{ - if (status == CAIRO_STATUS_SUCCESS || status >= CAIRO_INT_STATUS_UNSUPPORTED) - return status; - - /* Don't overwrite an existing error. This preserves the first - * error, which is the most significant. */ - _cairo_status_set_error (&surface->status, status); - - return _cairo_error (status); -} - -/** - * cairo_surface_get_type: - * @surface: a #cairo_surface_t - * - * This function returns the type of the backend used to create - * a surface. See #cairo_surface_type_t for available types. - * - * Return value: The type of @surface. - * - * Since: 1.2 - **/ -cairo_surface_type_t -cairo_surface_get_type (cairo_surface_t *surface) -{ - /* We don't use surface->backend->type here so that some of the - * special "wrapper" surfaces such as cairo_paginated_surface_t - * can override surface->type with the type of the "child" - * surface. */ - return surface->type; -} -slim_hidden_def (cairo_surface_get_type); - -/** - * cairo_surface_get_content: - * @surface: a #cairo_surface_t - * - * This function returns the content type of @surface which indicates - * whether the surface contains color and/or alpha information. See - * #cairo_content_t. - * - * Return value: The content type of @surface. - * - * Since: 1.2 - **/ -cairo_content_t -cairo_surface_get_content (cairo_surface_t *surface) -{ - return surface->content; -} -slim_hidden_def(cairo_surface_get_content); - -/** - * cairo_surface_status: - * @surface: a #cairo_surface_t - * - * Checks whether an error has previously occurred for this - * surface. - * - * Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_STATUS_NULL_POINTER, - * %CAIRO_STATUS_NO_MEMORY, %CAIRO_STATUS_READ_ERROR, - * %CAIRO_STATUS_INVALID_CONTENT, %CAIRO_STATUS_INVALID_FORMAT, or - * %CAIRO_STATUS_INVALID_VISUAL. - **/ -cairo_status_t -cairo_surface_status (cairo_surface_t *surface) -{ - return surface->status; -} -slim_hidden_def (cairo_surface_status); - -void -_cairo_surface_init (cairo_surface_t *surface, - const cairo_surface_backend_t *backend, - cairo_content_t content) -{ - CAIRO_MUTEX_INITIALIZE (); - - surface->backend = backend; - surface->content = content; - surface->type = backend->type; - - CAIRO_REFERENCE_COUNT_INIT (&surface->ref_count, 1); - surface->status = CAIRO_STATUS_SUCCESS; - surface->finished = FALSE; - - _cairo_user_data_array_init (&surface->user_data); - - cairo_matrix_init_identity (&surface->device_transform); - cairo_matrix_init_identity (&surface->device_transform_inverse); - - surface->x_resolution = CAIRO_SURFACE_RESOLUTION_DEFAULT; - surface->y_resolution = CAIRO_SURFACE_RESOLUTION_DEFAULT; - - surface->x_fallback_resolution = CAIRO_SURFACE_FALLBACK_RESOLUTION_DEFAULT; - surface->y_fallback_resolution = CAIRO_SURFACE_FALLBACK_RESOLUTION_DEFAULT; - - surface->clip = NULL; - surface->next_clip_serial = 0; - surface->current_clip_serial = 0; - - surface->is_snapshot = FALSE; - - surface->has_font_options = FALSE; -} - -cairo_surface_t * -_cairo_surface_create_similar_scratch (cairo_surface_t *other, - cairo_content_t content, - int width, - int height) -{ - cairo_surface_t *surface = NULL; - cairo_font_options_t options; - - cairo_format_t format = _cairo_format_from_content (content); - - if (other->status) - return _cairo_surface_create_in_error (other->status); - - if (other->backend->create_similar) { - surface = other->backend->create_similar (other, content, width, height); - if (surface != NULL && surface->status) - return surface; - } - - if (surface == NULL) - surface = cairo_image_surface_create (format, width, height); - - /* If any error occurred, then return the nil surface we received. */ - if (surface->status) - return surface; - - cairo_surface_get_font_options (other, &options); - _cairo_surface_set_font_options (surface, &options); - - cairo_surface_set_fallback_resolution (surface, - other->x_fallback_resolution, - other->y_fallback_resolution); - - return surface; -} - -/** - * cairo_surface_create_similar: - * @other: an existing surface used to select the backend of the new surface - * @content: the content for the new surface - * @width: width of the new surface, (in device-space units) - * @height: height of the new surface (in device-space units) - * - * Create a new surface that is as compatible as possible with an - * existing surface. For example the new surface will have the same - * fallback resolution and font options as @other. Generally, the new - * surface will also use the same backend as @other, unless that is - * not possible for some reason. The type of the returned surface may - * be examined with cairo_surface_get_type(). - * - * Initially the surface contents are all 0 (transparent if contents - * have transparency, black otherwise.) - * - * Return value: a pointer to the newly allocated surface. The caller - * owns the surface and should call cairo_surface_destroy() when done - * with it. - * - * This function always returns a valid pointer, but it will return a - * pointer to a "nil" surface if @other is already in an error state - * or any other error occurs. - **/ -cairo_surface_t * -cairo_surface_create_similar (cairo_surface_t *other, - cairo_content_t content, - int width, - int height) -{ - if (other->status) - return _cairo_surface_create_in_error (other->status); - - if (! CAIRO_CONTENT_VALID (content)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_CONTENT)); - - return _cairo_surface_create_similar_solid (other, content, - width, height, - CAIRO_COLOR_TRANSPARENT); -} -slim_hidden_def (cairo_surface_create_similar); - -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_status_t status; - cairo_surface_t *surface; - cairo_solid_pattern_t solid_pattern; - - surface = _cairo_surface_create_similar_scratch (other, content, - width, height); - if (surface->status) - return surface; - - _cairo_pattern_init_solid (&solid_pattern, color, content); - - status = _cairo_surface_paint (surface, - color == CAIRO_COLOR_TRANSPARENT ? - CAIRO_OPERATOR_CLEAR : CAIRO_OPERATOR_SOURCE, - &solid_pattern.base); - - _cairo_pattern_fini (&solid_pattern.base); - - if (status) { - cairo_surface_destroy (surface); - return _cairo_surface_create_in_error (status); - } - - return surface; -} - -cairo_surface_t * -_cairo_surface_create_solid_pattern_surface (cairo_surface_t *other, - cairo_solid_pattern_t *solid_pattern) -{ - cairo_surface_t *surface; - - if (other->backend->create_solid_pattern_surface) { - surface = other->backend->create_solid_pattern_surface (other, solid_pattern); - if (surface) - return surface; - } - - surface = _cairo_surface_create_similar_solid (other, - solid_pattern->content, - 1, 1, - &solid_pattern->color); - return surface; -} - -cairo_int_status_t -_cairo_surface_repaint_solid_pattern_surface (cairo_surface_t *other, - cairo_surface_t *solid_surface, - cairo_solid_pattern_t *solid_pattern) -{ - if (other->backend->create_solid_pattern_surface) - /* Solid pattern surface for this backend are not trivial to make. - * Skip repainting. - * - * This does not work optimally with things like analysis surface that - * are proxies. But returning UNSUPPORTED is *safe* as it only - * disables some caching. - */ - return CAIRO_INT_STATUS_UNSUPPORTED; - - return _cairo_surface_paint (solid_surface, CAIRO_OPERATOR_SOURCE, &solid_pattern->base); -} - -cairo_clip_mode_t -_cairo_surface_get_clip_mode (cairo_surface_t *surface) -{ - if (surface->backend->intersect_clip_path != NULL) - return CAIRO_CLIP_MODE_PATH; - else if (surface->backend->set_clip_region != NULL) - return CAIRO_CLIP_MODE_REGION; - else - return CAIRO_CLIP_MODE_MASK; -} - -/** - * cairo_surface_reference: - * @surface: a #cairo_surface_t - * - * Increases the reference count on @surface by one. This prevents - * @surface from being destroyed until a matching call to - * cairo_surface_destroy() is made. - * - * The number of references to a #cairo_surface_t can be get using - * cairo_surface_get_reference_count(). - * - * Return value: the referenced #cairo_surface_t. - **/ -cairo_surface_t * -cairo_surface_reference (cairo_surface_t *surface) -{ - if (surface == NULL || - CAIRO_REFERENCE_COUNT_IS_INVALID (&surface->ref_count)) - return surface; - - assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&surface->ref_count)); - - _cairo_reference_count_inc (&surface->ref_count); - - return surface; -} -slim_hidden_def (cairo_surface_reference); - -/** - * cairo_surface_destroy: - * @surface: a #cairo_surface_t - * - * Decreases the reference count on @surface by one. If the result is - * zero, then @surface and all associated resources are freed. See - * cairo_surface_reference(). - **/ -void -cairo_surface_destroy (cairo_surface_t *surface) -{ - if (surface == NULL || - CAIRO_REFERENCE_COUNT_IS_INVALID (&surface->ref_count)) - return; - - assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&surface->ref_count)); - - if (! _cairo_reference_count_dec_and_test (&surface->ref_count)) - return; - - if (! surface->finished) - cairo_surface_finish (surface); - - _cairo_user_data_array_fini (&surface->user_data); - - free (surface); -} -slim_hidden_def(cairo_surface_destroy); - -/** - * _cairo_surface_reset: - * @surface: a #cairo_surface_t - * - * Resets the surface back to defaults such that it may be reused in lieu - * of creating a new surface. - **/ -cairo_status_t -_cairo_surface_reset (cairo_surface_t *surface) -{ - if (surface == NULL || - CAIRO_REFERENCE_COUNT_IS_INVALID (&surface->ref_count)) - return CAIRO_STATUS_SUCCESS; - - assert (CAIRO_REFERENCE_COUNT_GET_VALUE (&surface->ref_count) == 1); - - _cairo_user_data_array_fini (&surface->user_data); - - if (surface->backend->reset != NULL) { - cairo_status_t status = surface->backend->reset (surface); - if (status) - return _cairo_surface_set_error (surface, status); - } - - _cairo_surface_init (surface, surface->backend, surface->content); - - return CAIRO_STATUS_SUCCESS; -} - -/** - * cairo_surface_get_reference_count: - * @surface: a #cairo_surface_t - * - * Returns the current reference count of @surface. - * - * Return value: the current reference count of @surface. If the - * object is a nil object, 0 will be returned. - * - * Since: 1.4 - **/ -unsigned int -cairo_surface_get_reference_count (cairo_surface_t *surface) -{ - if (surface == NULL || - CAIRO_REFERENCE_COUNT_IS_INVALID (&surface->ref_count)) - return 0; - - return CAIRO_REFERENCE_COUNT_GET_VALUE (&surface->ref_count); -} - -/** - * cairo_surface_finish: - * @surface: the #cairo_surface_t to finish - * - * This function finishes the surface and drops all references to - * external resources. For example, for the Xlib backend it means - * that cairo will no longer access the drawable, which can be freed. - * After calling cairo_surface_finish() the only valid operations on a - * surface are getting and setting user, referencing and - * destroying, and flushing and finishing it. - * Further drawing to the surface will not affect the - * surface but will instead trigger a %CAIRO_STATUS_SURFACE_FINISHED - * error. - * - * When the last call to cairo_surface_destroy() decreases the - * reference count to zero, cairo will call cairo_surface_finish() if - * it hasn't been called already, before freeing the resources - * associated with the surface. - **/ -void -cairo_surface_finish (cairo_surface_t *surface) -{ - cairo_status_t status; - - if (surface == NULL) - return; - - if (CAIRO_REFERENCE_COUNT_IS_INVALID (&surface->ref_count)) - return; - - if (surface->finished) - return; - - cairo_surface_flush (surface); - - /* call finish even if in error mode */ - if (surface->backend->finish) { - status = surface->backend->finish (surface); - if (status) - status = _cairo_surface_set_error (surface, status); - } - - surface->finished = TRUE; -} -slim_hidden_def (cairo_surface_finish); - -/** - * cairo_surface_get_user_data: - * @surface: a #cairo_surface_t - * @key: the address of the #cairo_user_data_key_t the user data was - * attached to - * - * Return user data previously attached to @surface using the specified - * key. If no user data has been attached with the given key this - * function returns %NULL. - * - * Return value: the user data previously attached or %NULL. - **/ -void * -cairo_surface_get_user_data (cairo_surface_t *surface, - const cairo_user_data_key_t *key) -{ - return _cairo_user_data_array_get_data (&surface->user_data, - key); -} - -/** - * cairo_surface_set_user_data: - * @surface: a #cairo_surface_t - * @key: the address of a #cairo_user_data_key_t to attach the user data to - * @user_data: the user data to attach to the surface - * @destroy: a #cairo_destroy_func_t which will be called when the - * surface is destroyed or when new user data is attached using the - * same key. - * - * Attach user data to @surface. To remove user data from a surface, - * call this function with the key that was used to set it and %NULL - * for @data. - * - * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a - * slot could not be allocated for the user data. - **/ -cairo_status_t -cairo_surface_set_user_data (cairo_surface_t *surface, - const cairo_user_data_key_t *key, - void *user_data, - cairo_destroy_func_t destroy) -{ - if (CAIRO_REFERENCE_COUNT_IS_INVALID (&surface->ref_count)) - return surface->status; - - return _cairo_user_data_array_set_data (&surface->user_data, - key, user_data, destroy); -} - -/** - * _cairo_surface_set_font_options: - * @surface: a #cairo_surface_t - * @options: a #cairo_font_options_t object that contains the - * options to use for this surface instead of backend's default - * font options. - * - * Sets the default font rendering options for the surface. - * This is useful to correctly propagate default font options when - * falling back to an image surface in a backend implementation. - * This affects the options returned in cairo_surface_get_font_options(). - * - * If @options is %NULL the surface options are reset to those of - * the backend default. - **/ -void -_cairo_surface_set_font_options (cairo_surface_t *surface, - cairo_font_options_t *options) -{ - cairo_status_t status; - - if (surface->status) - return; - - assert (! surface->is_snapshot); - - if (surface->finished) { - status = _cairo_surface_set_error (surface, - CAIRO_STATUS_SURFACE_FINISHED); - return; - } - - if (options) { - surface->has_font_options = TRUE; - _cairo_font_options_init_copy (&surface->font_options, options); - } else { - surface->has_font_options = FALSE; - } -} - -/** - * cairo_surface_get_font_options: - * @surface: a #cairo_surface_t - * @options: a #cairo_font_options_t object into which to store - * the retrieved options. All existing values are overwritten - * - * Retrieves the default font rendering options for the surface. - * This allows display surfaces to report the correct subpixel order - * for rendering on them, print surfaces to disable hinting of - * metrics and so forth. The result can then be used with - * cairo_scaled_font_create(). - **/ -void -cairo_surface_get_font_options (cairo_surface_t *surface, - cairo_font_options_t *options) -{ - if (cairo_font_options_status (options)) - return; - - if (surface->status) { - _cairo_font_options_init_default (options); - return; - } - - if (! surface->has_font_options) { - surface->has_font_options = TRUE; - - _cairo_font_options_init_default (&surface->font_options); - - if (!surface->finished && surface->backend->get_font_options) { - surface->backend->get_font_options (surface, &surface->font_options); - } - } - - _cairo_font_options_init_copy (options, &surface->font_options); -} -slim_hidden_def (cairo_surface_get_font_options); - -/** - * cairo_surface_flush: - * @surface: a #cairo_surface_t - * - * Do any pending drawing for the surface and also restore any - * temporary modification's cairo has made to the surface's - * state. This function must be called before switching from - * drawing on the surface with cairo to drawing on it directly - * with native APIs. If the surface doesn't support direct access, - * then this function does nothing. - **/ -void -cairo_surface_flush (cairo_surface_t *surface) -{ - cairo_status_t status; - - if (surface->status) - return; - - if (surface->finished) - return; - - if (surface->backend->flush) { - status = surface->backend->flush (surface); - if (status) - status = _cairo_surface_set_error (surface, status); - } -} -slim_hidden_def (cairo_surface_flush); - -/** - * cairo_surface_mark_dirty: - * @surface: a #cairo_surface_t - * - * Tells cairo that drawing has been done to surface using means other - * than cairo, and that cairo should reread any cached areas. Note - * that you must call cairo_surface_flush() before doing such drawing. - */ -void -cairo_surface_mark_dirty (cairo_surface_t *surface) -{ - if (surface->status) - return; - - assert (! surface->is_snapshot); - - cairo_surface_mark_dirty_rectangle (surface, 0, 0, -1, -1); -} - -/** - * cairo_surface_mark_dirty_rectangle: - * @surface: a #cairo_surface_t - * @x: X coordinate of dirty rectangle - * @y: Y coordinate of dirty rectangle - * @width: width of dirty rectangle - * @height: height of dirty rectangle - * - * Like cairo_surface_mark_dirty(), but drawing has been done only to - * the specified rectangle, so that cairo can retain cached contents - * for other parts of the surface. - * - * Any cached clip set on the surface will be reset by this function, - * to make sure that future cairo calls have the clip set that they - * expect. - */ -void -cairo_surface_mark_dirty_rectangle (cairo_surface_t *surface, - int x, - int y, - int width, - int height) -{ - cairo_status_t status; - - if (surface->status) - return; - - assert (! surface->is_snapshot); - - if (surface->finished) { - status = _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED); - return; - } - - /* Always reset the clip here, to avoid having external calls to - * clip manipulation functions of the underlying device clip result - * in a desync between the cairo clip and the backend clip, due to - * the clip caching. - */ - surface->current_clip_serial = -1; - - if (surface->backend->mark_dirty_rectangle) { - /* XXX: FRAGILE: We're ignoring the scaling component of - * device_transform here. I don't know what the right thing to - * do would actually be if there were some scaling here, but - * we avoid this since device_transfom scaling is not exported - * publicly and mark_dirty is not used internally. */ - status = surface->backend->mark_dirty_rectangle (surface, - x + surface->device_transform.x0, - y + surface->device_transform.y0, - width, height); - - if (status) - status = _cairo_surface_set_error (surface, status); - } -} -slim_hidden_def (cairo_surface_mark_dirty_rectangle); - -/** - * _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 - * meta surface to an image fallback intended for an eventual - * vector-oriented backend. Since the meta 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. - **/ -void -_cairo_surface_set_device_scale (cairo_surface_t *surface, - double sx, - double sy) -{ - cairo_status_t status; - - if (surface->status) - return; - - assert (! surface->is_snapshot); - - if (surface->finished) { - status = _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED); - return; - } - - surface->device_transform.xx = sx; - surface->device_transform.yy = sy; - surface->device_transform.xy = 0.0; - surface->device_transform.yx = 0.0; - - surface->device_transform_inverse = surface->device_transform; - status = cairo_matrix_invert (&surface->device_transform_inverse); - /* should always be invertible unless given pathological input */ - assert (status == CAIRO_STATUS_SUCCESS); -} - -/** - * cairo_surface_set_device_offset: - * @surface: a #cairo_surface_t - * @x_offset: the offset in the X direction, in device units - * @y_offset: the offset in the Y direction, in device units - * - * Sets an offset that is added to the device coordinates determined - * by the CTM when drawing to @surface. One use case for this function - * is when we want to create a #cairo_surface_t that redirects drawing - * for a portion of an onscreen surface to an offscreen surface in a - * way that is completely invisible to the user of the cairo - * API. Setting a transformation via cairo_translate() isn't - * sufficient to do this, since functions like - * cairo_device_to_user() will expose the hidden offset. - * - * Note that the offset affects drawing to the surface as well as - * using the surface in a source pattern. - **/ -void -cairo_surface_set_device_offset (cairo_surface_t *surface, - double x_offset, - double y_offset) -{ - cairo_status_t status; - - if (surface->status) - return; - - assert (! surface->is_snapshot); - - if (surface->finished) { - status = _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED); - return; - } - - surface->device_transform.x0 = x_offset; - surface->device_transform.y0 = y_offset; - - surface->device_transform_inverse = surface->device_transform; - status = cairo_matrix_invert (&surface->device_transform_inverse); - /* should always be invertible unless given pathological input */ - assert (status == CAIRO_STATUS_SUCCESS); -} -slim_hidden_def (cairo_surface_set_device_offset); - -/** - * cairo_surface_get_device_offset: - * @surface: a #cairo_surface_t - * @x_offset: the offset in the X direction, in device units - * @y_offset: the offset in the Y direction, in device units - * - * This function returns the previous device offset set by - * cairo_surface_set_device_offset(). - * - * Since: 1.2 - **/ -void -cairo_surface_get_device_offset (cairo_surface_t *surface, - double *x_offset, - double *y_offset) -{ - if (x_offset) - *x_offset = surface->device_transform.x0; - if (y_offset) - *y_offset = surface->device_transform.y0; -} -slim_hidden_def (cairo_surface_get_device_offset); - -/** - * cairo_surface_set_fallback_resolution: - * @surface: a #cairo_surface_t - * @x_pixels_per_inch: horizontal setting for pixels per inch - * @y_pixels_per_inch: vertical setting for pixels per inch - * - * Set the horizontal and vertical resolution for image fallbacks. - * - * When certain operations aren't supported natively by a backend, - * cairo will fallback by rendering operations to an image and then - * overlaying that image onto the output. For backends that are - * natively vector-oriented, this function can be used to set the - * resolution used for these image fallbacks, (larger values will - * result in more detailed images, but also larger file sizes). - * - * Some examples of natively vector-oriented backends are the ps, pdf, - * and svg backends. - * - * For backends that are natively raster-oriented, image fallbacks are - * still possible, but they are always performed at the native - * device resolution. So this function has no effect on those - * backends. - * - * Note: The fallback resolution only takes effect at the time of - * completing a page (with cairo_show_page() or cairo_copy_page()) so - * there is currently no way to have more than one fallback resolution - * in effect on a single page. - * - * The default fallback resoultion is 300 pixels per inch in both - * dimensions. - * - * Since: 1.2 - **/ -void -cairo_surface_set_fallback_resolution (cairo_surface_t *surface, - double x_pixels_per_inch, - double y_pixels_per_inch) -{ - cairo_status_t status; - - if (surface->status) - return; - - assert (! surface->is_snapshot); - - if (surface->finished) { - status = _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED); - return; - } - - surface->x_fallback_resolution = x_pixels_per_inch; - surface->y_fallback_resolution = y_pixels_per_inch; -} -slim_hidden_def (cairo_surface_set_fallback_resolution); - -/** - * cairo_surface_get_fallback_resolution: - * @surface: a #cairo_surface_t - * @x_pixels_per_inch: horizontal pixels per inch - * @y_pixels_per_inch: vertical pixels per inch - * - * This function returns the previous fallback resolution set by - * cairo_surface_set_fallback_resolution(), or default fallback - * resolution if never set. - * - * Since: 1.8 - **/ -void -cairo_surface_get_fallback_resolution (cairo_surface_t *surface, - double *x_pixels_per_inch, - double *y_pixels_per_inch) -{ - if (x_pixels_per_inch) - *x_pixels_per_inch = surface->x_fallback_resolution; - if (y_pixels_per_inch) - *y_pixels_per_inch = surface->y_fallback_resolution; -} - -cairo_bool_t -_cairo_surface_has_device_transform (cairo_surface_t *surface) -{ - return ! _cairo_matrix_is_identity (&surface->device_transform); -} - -/** - * _cairo_surface_acquire_source_image: - * @surface: a #cairo_surface_t - * @image_out: location to store a pointer to an image surface that - * has identical contents to @surface. This surface could be @surface - * itself, a surface held internal to @surface, or it could be a new - * surface with a copy of the relevant portion of @surface. - * @image_extra: location to store image specific backend data - * - * Gets an image surface to use when drawing as a fallback when drawing with - * @surface as a source. _cairo_surface_release_source_image() must be called - * when finished. - * - * Return value: %CAIRO_STATUS_SUCCESS if an image was stored in @image_out. - * %CAIRO_INT_STATUS_UNSUPPORTED if an image cannot be retrieved for the specified - * surface. Or %CAIRO_STATUS_NO_MEMORY. - **/ -cairo_status_t -_cairo_surface_acquire_source_image (cairo_surface_t *surface, - cairo_image_surface_t **image_out, - void **image_extra) -{ - if (surface->status) - return surface->status; - - assert (!surface->finished); - - if (surface->backend->acquire_source_image == NULL) - return CAIRO_INT_STATUS_UNSUPPORTED; - - return _cairo_surface_set_error (surface, - surface->backend->acquire_source_image (surface, - image_out, image_extra)); -} - -/** - * _cairo_surface_release_source_image: - * @surface: a #cairo_surface_t - * @image_extra: same as return from the matching _cairo_surface_acquire_source_image() - * - * Releases any resources obtained with _cairo_surface_acquire_source_image() - **/ -void -_cairo_surface_release_source_image (cairo_surface_t *surface, - cairo_image_surface_t *image, - void *image_extra) -{ - assert (!surface->finished); - - if (surface->backend->release_source_image) - surface->backend->release_source_image (surface, image, image_extra); -} - -/** - * _cairo_surface_acquire_dest_image: - * @surface: a #cairo_surface_t - * @interest_rect: area of @surface for which fallback drawing is being done. - * A value of %NULL indicates that the entire surface is desired. - * XXXX I'd like to get rid of being able to pass %NULL here (nothing seems to) - * @image_out: location to store a pointer to an image surface that includes at least - * the intersection of @interest_rect with the visible area of @surface. - * This surface could be @surface itself, a surface held internal to @surface, - * or it could be a new surface with a copy of the relevant portion of @surface. - * If a new surface is created, it should have the same channels and depth - * as @surface so that copying to and from it is exact. - * @image_rect: location to store area of the original surface occupied - * by the surface stored in @image. - * @image_extra: location to store image specific backend data - * - * Retrieves a local image for a surface for implementing a fallback drawing - * operation. After calling this function, the implementation of the fallback - * drawing operation draws the primitive to the surface stored in @image_out - * then calls _cairo_surface_release_dest_image(), - * which, if a temporary surface was created, copies the bits back to the - * main surface and frees the temporary surface. - * - * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY. - * %CAIRO_INT_STATUS_UNSUPPORTED can be returned but this will mean that - * the backend can't draw with fallbacks. It's possible for the routine - * to store %NULL in @local_out and return %CAIRO_STATUS_SUCCESS; - * that indicates that no part of @interest_rect is visible, so no drawing - * is necessary. _cairo_surface_release_dest_image() should not be called in that - * case. - **/ -cairo_status_t -_cairo_surface_acquire_dest_image (cairo_surface_t *surface, - cairo_rectangle_int_t *interest_rect, - cairo_image_surface_t **image_out, - cairo_rectangle_int_t *image_rect, - void **image_extra) -{ - if (surface->status) - return surface->status; - - assert (!surface->finished); - - if (surface->backend->acquire_dest_image == NULL) - return CAIRO_INT_STATUS_UNSUPPORTED; - - return _cairo_surface_set_error (surface, - surface->backend->acquire_dest_image (surface, - interest_rect, - image_out, - image_rect, - image_extra)); -} - -/** - * _cairo_surface_release_dest_image: - * @surface: a #cairo_surface_t - * @interest_rect: same as passed to the matching _cairo_surface_acquire_dest_image() - * @image: same as returned from the matching _cairo_surface_acquire_dest_image() - * @image_rect: same as returned from the matching _cairo_surface_acquire_dest_image() - * @image_extra: same as return from the matching _cairo_surface_acquire_dest_image() - * - * Finishes the operation started with _cairo_surface_acquire_dest_image(), by, if - * necessary, copying the image from @image back to @surface and freeing any - * resources that were allocated. - **/ -void -_cairo_surface_release_dest_image (cairo_surface_t *surface, - cairo_rectangle_int_t *interest_rect, - cairo_image_surface_t *image, - cairo_rectangle_int_t *image_rect, - void *image_extra) -{ - assert (!surface->finished); - - if (surface->backend->release_dest_image) - surface->backend->release_dest_image (surface, interest_rect, - image, image_rect, image_extra); -} - -/** - * _cairo_surface_clone_similar: - * @surface: a #cairo_surface_t - * @src: the source image - * @src_x: extent for the rectangle in src we actually care about - * @src_y: extent for the rectangle in src we actually care about - * @width: extent for the rectangle in src we actually care about - * @height: extent for the rectangle in src we actually care about - * @clone_out: location to store a surface compatible with @surface - * and with contents identical to @src. The caller must call - * cairo_surface_destroy() on the result. - * - * Creates a surface with contents identical to @src but that - * can be used efficiently with @surface. If @surface and @src are - * already compatible then it may return a new reference to @src. - * - * Return value: %CAIRO_STATUS_SUCCESS if a surface was created and stored - * in @clone_out. Otherwise %CAIRO_INT_STATUS_UNSUPPORTED or another - * error like %CAIRO_STATUS_NO_MEMORY. - **/ -cairo_status_t -_cairo_surface_clone_similar (cairo_surface_t *surface, - cairo_surface_t *src, - int src_x, - int src_y, - int width, - int height, - int *clone_offset_x, - int *clone_offset_y, - cairo_surface_t **clone_out) -{ - cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED; - cairo_image_surface_t *image; - void *image_extra; - - if (surface->status) - return surface->status; - - if (surface->finished) - return _cairo_error (CAIRO_STATUS_SURFACE_FINISHED); - - if (surface->backend->clone_similar) { - status = surface->backend->clone_similar (surface, src, - src_x, src_y, - width, height, - clone_offset_x, - clone_offset_y, - clone_out); - - if (status == CAIRO_INT_STATUS_UNSUPPORTED) { - /* If we failed, try again with an image surface */ - status = _cairo_surface_acquire_source_image (src, &image, &image_extra); - if (status == CAIRO_STATUS_SUCCESS) { - status = - surface->backend->clone_similar (surface, &image->base, - src_x, src_y, - width, height, - clone_offset_x, - clone_offset_y, - clone_out); - - _cairo_surface_release_source_image (src, image, image_extra); - } - } - } - - /* If we're still unsupported, hit our fallback path to get a clone */ - if (status == CAIRO_INT_STATUS_UNSUPPORTED) - status = - _cairo_surface_fallback_clone_similar (surface, src, - src_x, src_y, - width, height, - clone_offset_x, - clone_offset_y, - clone_out); - - /* We should never get UNSUPPORTED here, so if we have an error, bail. */ - if (status) - return status; - - /* Update the clone's device_transform (which the underlying surface - * backend knows nothing about) */ - if (*clone_out != src) { - (*clone_out)->device_transform = src->device_transform; - (*clone_out)->device_transform_inverse = src->device_transform_inverse; - } - - return status; -} - -/* XXX: Shouldn't really need to do this here. */ -#include "cairo-meta-surface-private.h" - -/** - * _cairo_surface_snapshot - * @surface: a #cairo_surface_t - * - * Make an immutable copy of @surface. It is an error to call a - * surface-modifying function on the result of this function. - * - * The caller owns the return value and should call - * cairo_surface_destroy() when finished with it. This function will not - * return %NULL, but will return a nil surface instead. - * - * Return value: The snapshot surface. Note that the return surface - * may not necessarily be of the same type as @surface. - **/ -cairo_surface_t * -_cairo_surface_snapshot (cairo_surface_t *surface) -{ - if (surface->status) - return _cairo_surface_create_in_error (surface->status); - - if (surface->finished) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_FINISHED)); - - if (surface->backend->snapshot) - return surface->backend->snapshot (surface); - - return _cairo_surface_fallback_snapshot (surface); -} - -/** - * _cairo_surface_is_similar - * @surface_a: a #cairo_surface_t - * @surface_b: a #cairo_surface_t - * @content: a #cairo_content_t - * - * Find out whether the given surfaces share the same backend, - * and if so, whether they can be considered similar. - * - * The definition of "similar" depends on the backend. In - * general, it means that the surface is equivalent to one - * that would have been generated by a call to cairo_surface_create_similar(). - * - * Return value: %TRUE if the surfaces are similar. - **/ -cairo_bool_t -_cairo_surface_is_similar (cairo_surface_t *surface_a, - cairo_surface_t *surface_b, - cairo_content_t content) -{ - if (surface_a->backend != surface_b->backend) - return FALSE; - - if (surface_a->backend->is_similar != NULL) - return surface_a->backend->is_similar (surface_a, surface_b, content); - - return TRUE; -} - -cairo_status_t -_cairo_surface_composite (cairo_operator_t op, - cairo_pattern_t *src, - cairo_pattern_t *mask, - cairo_surface_t *dst, - 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; - - if (mask) { - /* These operators aren't interpreted the same way by the backends; - * they are implemented in terms of other operators in cairo-gstate.c - */ - assert (op != CAIRO_OPERATOR_SOURCE && op != CAIRO_OPERATOR_CLEAR); - } - - if (dst->status) - return dst->status; - - assert (! dst->is_snapshot); - - if (dst->finished) - return _cairo_surface_set_error (dst, CAIRO_STATUS_SURFACE_FINISHED); - - if (dst->backend->composite) { - status = dst->backend->composite (op, - src, mask, dst, - src_x, src_y, - mask_x, mask_y, - dst_x, dst_y, - width, height); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return _cairo_surface_set_error (dst, status); - } - - return _cairo_surface_set_error (dst, - _cairo_surface_fallback_composite (op, - src, mask, dst, - src_x, src_y, - mask_x, mask_y, - dst_x, dst_y, - width, height)); -} - -/** - * _cairo_surface_fill_rectangle: - * @surface: a #cairo_surface_t - * @op: the operator to apply to the rectangle - * @color: the source color - * @x: X coordinate of rectangle, in backend coordinates - * @y: Y coordinate of rectangle, in backend coordinates - * @width: width of rectangle, in backend coordinates - * @height: height of rectangle, in backend coordinates - * - * Applies an operator to a rectangle using a solid color as the source. - * See _cairo_surface_fill_rectangles() for full details. - * - * Return value: %CAIRO_STATUS_SUCCESS or the error that occurred - **/ -cairo_status_t -_cairo_surface_fill_rectangle (cairo_surface_t *surface, - cairo_operator_t op, - const cairo_color_t *color, - int x, - int y, - int width, - int height) -{ - cairo_rectangle_int_t rect; - - if (surface->status) - return surface->status; - - assert (! surface->is_snapshot); - - if (surface->finished) - return _cairo_surface_set_error (surface,CAIRO_STATUS_SURFACE_FINISHED); - - rect.x = x; - rect.y = y; - rect.width = width; - rect.height = height; - - return _cairo_surface_fill_rectangles (surface, op, color, &rect, 1); -} - -/** - * _cairo_surface_fill_region: - * @surface: a #cairo_surface_t - * @op: the operator to apply to the region - * @color: the source color - * @region: the region to modify, in backend coordinates - * - * Applies an operator to a set of rectangles specified as a - * #cairo_region_t using a solid color as the source. - * See _cairo_surface_fill_rectangles() for full details. - * - * Return value: %CAIRO_STATUS_SUCCESS or the error that occurred - **/ -cairo_status_t -_cairo_surface_fill_region (cairo_surface_t *surface, - cairo_operator_t op, - const cairo_color_t *color, - cairo_region_t *region) -{ - int num_boxes; - cairo_box_int_t *boxes = NULL; - cairo_rectangle_int_t stack_rects[CAIRO_STACK_ARRAY_LENGTH (cairo_rectangle_int_t)]; - cairo_rectangle_int_t *rects = stack_rects; - cairo_status_t status; - int i; - - if (surface->status) - return surface->status; - - assert (! surface->is_snapshot); - - num_boxes = _cairo_region_num_boxes (region); - - if (num_boxes == 0) - return CAIRO_STATUS_SUCCESS; - - /* handle the common case of a single box without allocation */ - if (num_boxes > 1) { - status = _cairo_region_get_boxes (region, &num_boxes, &boxes); - if (status) - return status; - - if (num_boxes > ARRAY_LENGTH (stack_rects)) { - rects = _cairo_malloc_ab (num_boxes, - sizeof (cairo_rectangle_int_t)); - if (!rects) { - _cairo_region_boxes_fini (region, boxes); - return _cairo_surface_set_error (surface, - CAIRO_STATUS_NO_MEMORY); - } - } - - for (i = 0; i < num_boxes; i++) { - rects[i].x = boxes[i].p1.x; - rects[i].y = boxes[i].p1.y; - rects[i].width = boxes[i].p2.x - boxes[i].p1.x; - rects[i].height = boxes[i].p2.y - boxes[i].p1.y; - } - } else - _cairo_region_get_extents (region, &rects[0]); - - status = _cairo_surface_fill_rectangles (surface, op, - color, rects, num_boxes); - - if (boxes != NULL) - _cairo_region_boxes_fini (region, boxes); - - if (rects != stack_rects) - free (rects); - - return _cairo_surface_set_error (surface, status); -} - -/** - * _cairo_surface_fill_rectangles: - * @surface: a #cairo_surface_t - * @op: the operator to apply to the region - * @color: the source color - * @rects: the rectangles to modify, in backend coordinates - * @num_rects: the number of rectangles in @rects - * - * Applies an operator to a set of rectangles using a solid color - * as the source. Note that even if the operator is an unbounded operator - * such as %CAIRO_OPERATOR_IN, only the given set of rectangles - * is affected. This differs from _cairo_surface_composite_trapezoids() - * where the entire destination rectangle is cleared. - * - * Return value: %CAIRO_STATUS_SUCCESS or the error that occurred - **/ -cairo_status_t -_cairo_surface_fill_rectangles (cairo_surface_t *surface, - cairo_operator_t op, - const cairo_color_t *color, - cairo_rectangle_int_t *rects, - int num_rects) -{ - cairo_int_status_t status; - - if (surface->status) - return surface->status; - - assert (! surface->is_snapshot); - - if (surface->finished) - return _cairo_surface_set_error (surface,CAIRO_STATUS_SURFACE_FINISHED); - - if (num_rects == 0) - return CAIRO_STATUS_SUCCESS; - - if (surface->backend->fill_rectangles) { - status = surface->backend->fill_rectangles (surface, op, color, - rects, num_rects); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return _cairo_surface_set_error (surface, status); - } - - return _cairo_surface_set_error (surface, - _cairo_surface_fallback_fill_rectangles (surface, op, color, - rects, num_rects)); -} - -cairo_status_t -_cairo_surface_paint (cairo_surface_t *surface, - cairo_operator_t op, - cairo_pattern_t *source) -{ - cairo_status_t status; - cairo_pattern_t *dev_source; - - if (surface->status) - return surface->status; - - assert (! surface->is_snapshot); - - status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source); - if (status) - return _cairo_surface_set_error (surface, status); - - if (surface->backend->paint) { - status = surface->backend->paint (surface, op, dev_source); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - goto FINISH; - } - - status = _cairo_surface_fallback_paint (surface, op, dev_source); - - FINISH: - cairo_pattern_destroy (dev_source); - - return _cairo_surface_set_error (surface, status); -} - -cairo_status_t -_cairo_surface_mask (cairo_surface_t *surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_pattern_t *mask) -{ - cairo_status_t status; - cairo_pattern_t *dev_source; - cairo_pattern_t *dev_mask; - - if (surface->status) - return surface->status; - - assert (! surface->is_snapshot); - - status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source); - if (status) - goto FINISH; - - status = _cairo_surface_copy_pattern_for_destination (mask, surface, &dev_mask); - if (status) - goto CLEANUP_SOURCE; - - if (surface->backend->mask) { - status = surface->backend->mask (surface, op, dev_source, dev_mask); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - goto CLEANUP_MASK; - } - - status = _cairo_surface_fallback_mask (surface, op, dev_source, dev_mask); - - CLEANUP_MASK: - cairo_pattern_destroy (dev_mask); - CLEANUP_SOURCE: - cairo_pattern_destroy (dev_source); - FINISH: - - return _cairo_surface_set_error (surface, status); -} - -cairo_status_t -_cairo_surface_fill_stroke (cairo_surface_t *surface, - cairo_operator_t fill_op, - cairo_pattern_t *fill_source, - cairo_fill_rule_t fill_rule, - double fill_tolerance, - cairo_antialias_t fill_antialias, - cairo_path_fixed_t *path, - cairo_operator_t stroke_op, - cairo_pattern_t *stroke_source, - cairo_stroke_style_t *stroke_style, - cairo_matrix_t *stroke_ctm, - cairo_matrix_t *stroke_ctm_inverse, - double stroke_tolerance, - cairo_antialias_t stroke_antialias) -{ - cairo_status_t status; - - if (surface->status) - return surface->status; - - if (surface->backend->fill_stroke) { - cairo_pattern_t *dev_stroke_source; - cairo_pattern_t *dev_fill_source; - cairo_matrix_t dev_ctm = *stroke_ctm; - cairo_matrix_t dev_ctm_inverse = *stroke_ctm_inverse; - - status = _cairo_surface_copy_pattern_for_destination (stroke_source, surface, &dev_stroke_source); - if (status) - return _cairo_surface_set_error (surface, status); - - status = _cairo_surface_copy_pattern_for_destination (fill_source, surface, &dev_fill_source); - if (status) { - cairo_pattern_destroy (dev_stroke_source); - return _cairo_surface_set_error (surface, status); - } - - status = surface->backend->fill_stroke (surface, fill_op, dev_fill_source, - fill_rule, fill_tolerance, fill_antialias, - path, stroke_op, dev_stroke_source, stroke_style, - &dev_ctm, &dev_ctm_inverse, stroke_tolerance, - stroke_antialias); - - cairo_pattern_destroy (dev_stroke_source); - cairo_pattern_destroy (dev_fill_source); - - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return _cairo_surface_set_error (surface, status); - } - - status = _cairo_surface_fill (surface, fill_op, fill_source, path, - fill_rule, fill_tolerance, fill_antialias); - if (status) - return _cairo_surface_set_error (surface, status); - - status = _cairo_surface_stroke (surface, stroke_op, stroke_source, path, - stroke_style, stroke_ctm, stroke_ctm_inverse, - stroke_tolerance, stroke_antialias); - if (status) - return _cairo_surface_set_error (surface, status); - - return CAIRO_STATUS_SUCCESS; -} - -cairo_status_t -_cairo_surface_stroke (cairo_surface_t *surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_path_fixed_t *path, - cairo_stroke_style_t *stroke_style, - cairo_matrix_t *ctm, - cairo_matrix_t *ctm_inverse, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_status_t status; - cairo_pattern_t *dev_source; - cairo_path_fixed_t *dev_path = path; - cairo_path_fixed_t real_dev_path; - cairo_matrix_t dev_ctm = *ctm; - cairo_matrix_t dev_ctm_inverse = *ctm_inverse; - - if (surface->status) - return surface->status; - - assert (! surface->is_snapshot); - - status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source); - if (status) - return _cairo_surface_set_error (surface, status); - - if (surface->backend->stroke) { - status = surface->backend->stroke (surface, op, dev_source, - path, stroke_style, - &dev_ctm, &dev_ctm_inverse, - tolerance, antialias); - - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - goto FINISH; - } - - status = _cairo_surface_fallback_stroke (surface, op, dev_source, - path, stroke_style, - &dev_ctm, &dev_ctm_inverse, - tolerance, antialias); - - FINISH: - if (dev_path == &real_dev_path) - _cairo_path_fixed_fini (&real_dev_path); - cairo_pattern_destroy (dev_source); - - return _cairo_surface_set_error (surface, status); -} - -cairo_status_t -_cairo_surface_fill (cairo_surface_t *surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_status_t status; - cairo_pattern_t *dev_source; - - if (surface->status) - return surface->status; - - assert (! surface->is_snapshot); - - status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source); - if (status) - return _cairo_surface_set_error (surface, status); - - if (surface->backend->fill) { - status = surface->backend->fill (surface, op, dev_source, - path, fill_rule, - tolerance, antialias); - - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - goto FINISH; - } - - status = _cairo_surface_fallback_fill (surface, op, dev_source, - path, fill_rule, - tolerance, antialias); - - FINISH: - cairo_pattern_destroy (dev_source); - - return _cairo_surface_set_error (surface, status); -} - -cairo_status_t -_cairo_surface_composite_trapezoids (cairo_operator_t op, - cairo_pattern_t *pattern, - cairo_surface_t *dst, - cairo_antialias_t antialias, - int src_x, - int src_y, - int dst_x, - int dst_y, - unsigned int width, - unsigned int height, - cairo_trapezoid_t *traps, - int num_traps) -{ - cairo_int_status_t status; - - /* These operators aren't interpreted the same way by the backends; - * they are implemented in terms of other operators in cairo-gstate.c - */ - assert (op != CAIRO_OPERATOR_SOURCE && op != CAIRO_OPERATOR_CLEAR); - - if (dst->status) - return dst->status; - - assert (! dst->is_snapshot); - - if (dst->finished) - return _cairo_surface_set_error (dst, CAIRO_STATUS_SURFACE_FINISHED); - - if (dst->backend->composite_trapezoids) { - status = dst->backend->composite_trapezoids (op, - pattern, dst, - antialias, - src_x, src_y, - dst_x, dst_y, - width, height, - traps, num_traps); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return _cairo_surface_set_error (dst, status); - } - - return _cairo_surface_set_error (dst, - _cairo_surface_fallback_composite_trapezoids (op, pattern, dst, - antialias, - src_x, src_y, - dst_x, dst_y, - width, height, - traps, num_traps)); -} - -/** - * cairo_surface_copy_page: - * @surface: a #cairo_surface_t - * - * Emits the current page for backends that support multiple pages, - * but doesn't clear it, so that the contents of the current page will - * be retained for the next page. Use cairo_surface_show_page() if you - * want to get an empty page after the emission. - * - * There is a convenience function for this that takes a #cairo_t, - * namely cairo_copy_page(). - * - * Since: 1.6 - */ -void -cairo_surface_copy_page (cairo_surface_t *surface) -{ - cairo_status_t status_ignored; - - if (surface->status) - return; - - assert (! surface->is_snapshot); - - if (surface->finished) { - status_ignored = _cairo_surface_set_error (surface, - CAIRO_STATUS_SURFACE_FINISHED); - return; - } - - /* It's fine if some backends don't implement copy_page */ - if (surface->backend->copy_page == NULL) - return; - - status_ignored = _cairo_surface_set_error (surface, - surface->backend->copy_page (surface)); -} -slim_hidden_def (cairo_surface_copy_page); - -/** - * cairo_surface_show_page: - * @surface: a #cairo_Surface_t - * - * Emits and clears the current page for backends that support multiple - * pages. Use cairo_surface_copy_page() if you don't want to clear the page. - * - * There is a convenience function for this that takes a #cairo_t, - * namely cairo_show_page(). - * - * Since: 1.6 - **/ -void -cairo_surface_show_page (cairo_surface_t *surface) -{ - cairo_status_t status_ignored; - - if (surface->status) - return; - - assert (! surface->is_snapshot); - - if (surface->finished) { - status_ignored = _cairo_surface_set_error (surface, - CAIRO_STATUS_SURFACE_FINISHED); - return; - } - - /* It's fine if some backends don't implement show_page */ - if (surface->backend->show_page == NULL) - return; - - status_ignored = _cairo_surface_set_error (surface, - surface->backend->show_page (surface)); -} -slim_hidden_def (cairo_surface_show_page); - -/** - * _cairo_surface_get_current_clip_serial: - * @surface: the #cairo_surface_t to return the serial number for - * - * This space left intentionally blank. - * - * Returns: the serial number associated with the current - * clip in the surface. All gstate functions must - * verify that the correct clip is set in the surface before - * invoking any surface drawing function. - */ -unsigned int -_cairo_surface_get_current_clip_serial (cairo_surface_t *surface) -{ - return surface->current_clip_serial; -} - -/** - * _cairo_surface_allocate_clip_serial: - * @surface: the #cairo_surface_t to allocate a serial number from - * - * Each surface has a separate set of clipping serial numbers, and - * this function allocates one from the specified surface. As zero is - * reserved for the special no-clipping case, this function will not - * return that except for an in-error surface, (ie. surface->status != - * %CAIRO_STATUS_SUCCESS). - */ -unsigned int -_cairo_surface_allocate_clip_serial (cairo_surface_t *surface) -{ - unsigned int serial; - - if (surface->status) - return 0; - - if ((serial = ++(surface->next_clip_serial)) == 0) - serial = ++(surface->next_clip_serial); - return serial; -} - -/** - * _cairo_surface_reset_clip: - * @surface: the #cairo_surface_t to reset the clip on - * - * This function sets the clipping for the surface to - * None, which is to say that drawing is entirely - * unclipped. It also sets the clip serial number - * to zero. - */ -cairo_status_t -_cairo_surface_reset_clip (cairo_surface_t *surface) -{ - cairo_status_t status; - - if (surface->status) - return surface->status; - - if (surface->finished) - return _cairo_surface_set_error (surface,CAIRO_STATUS_SURFACE_FINISHED); - - surface->current_clip_serial = 0; - - if (surface->backend->intersect_clip_path) { - status = surface->backend->intersect_clip_path (surface, - NULL, - CAIRO_FILL_RULE_WINDING, - 0, - CAIRO_ANTIALIAS_DEFAULT); - if (status) - return _cairo_surface_set_error (surface, status); - } - - if (surface->backend->set_clip_region != NULL) { - status = surface->backend->set_clip_region (surface, NULL); - if (status) - return _cairo_surface_set_error (surface, status); - } - - return CAIRO_STATUS_SUCCESS; -} - -/** - * _cairo_surface_set_clip_region: - * @surface: the #cairo_surface_t to reset the clip on - * @region: the #cairo_region_t to use for clipping - * @serial: the clip serial number associated with the region - * - * This function sets the clipping for the surface to - * the specified region and sets the surface clipping - * serial number to the associated serial number. - */ -cairo_status_t -_cairo_surface_set_clip_region (cairo_surface_t *surface, - cairo_region_t *region, - unsigned int serial) -{ - cairo_status_t status; - - if (surface->status) - return surface->status; - - assert (surface->backend->set_clip_region != NULL); - - surface->current_clip_serial = serial; - - status = surface->backend->set_clip_region (surface, region); - - return _cairo_surface_set_error (surface, status); -} - -cairo_int_status_t -_cairo_surface_intersect_clip_path (cairo_surface_t *surface, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_path_fixed_t *dev_path = path; - cairo_status_t status; - - if (surface->status) - return surface->status; - - if (surface->finished) - return _cairo_surface_set_error (surface,CAIRO_STATUS_SURFACE_FINISHED); - - assert (surface->backend->intersect_clip_path != NULL); - - status = surface->backend->intersect_clip_path (surface, - dev_path, - fill_rule, - tolerance, - antialias); - - return _cairo_surface_set_error (surface, status); -} - -static cairo_status_t -_cairo_surface_set_clip_path_recursive (cairo_surface_t *surface, - cairo_clip_path_t *clip_path) -{ - cairo_status_t status; - - if (surface->status) - return surface->status; - - if (clip_path == NULL) - return CAIRO_STATUS_SUCCESS; - - status = _cairo_surface_set_clip_path_recursive (surface, clip_path->prev); - if (status) - return status; - - return _cairo_surface_intersect_clip_path (surface, - &clip_path->path, - clip_path->fill_rule, - clip_path->tolerance, - clip_path->antialias); -} - -/** - * _cairo_surface_set_clip_path: - * @surface: the #cairo_surface_t to set the clip on - * @clip_path: the clip path to set - * @serial: the clip serial number associated with the clip path - * - * Sets the given clipping path for the surface and assigns the - * clipping serial to the surface. - **/ -static cairo_status_t -_cairo_surface_set_clip_path (cairo_surface_t *surface, - cairo_clip_path_t *clip_path, - unsigned int serial) -{ - cairo_status_t status; - - if (surface->status) - return surface->status; - - if (surface->finished) - return _cairo_surface_set_error (surface,CAIRO_STATUS_SURFACE_FINISHED); - - assert (surface->backend->intersect_clip_path != NULL); - - status = surface->backend->intersect_clip_path (surface, - NULL, - CAIRO_FILL_RULE_WINDING, - 0, - CAIRO_ANTIALIAS_DEFAULT); - if (status) - return _cairo_surface_set_error (surface, status); - - status = _cairo_surface_set_clip_path_recursive (surface, clip_path); - if (status) - return _cairo_surface_set_error (surface, status); - - surface->current_clip_serial = serial; - - return CAIRO_STATUS_SUCCESS; -} - - -/** - * _cairo_surface_set_empty_clip_path: - * @surface: the #cairo_surface_t to set the clip on - * @serial: the clip serial number associated with the clip path - * - * Create an empty clip path, one that represents the entire surface clipped - * out, and assigns the given clipping serial to the surface. - **/ -static cairo_status_t -_cairo_surface_set_empty_clip_path (cairo_surface_t *surface, - unsigned int serial) -{ - cairo_path_fixed_t path; - cairo_status_t status; - - if (surface->status) - return surface->status; - - _cairo_path_fixed_init (&path); - - status = surface->backend->intersect_clip_path (surface, - &path, - CAIRO_FILL_RULE_WINDING, - 0, - CAIRO_ANTIALIAS_DEFAULT); - - if (status == CAIRO_STATUS_SUCCESS) - surface->current_clip_serial = serial; - - _cairo_path_fixed_fini (&path); - - return _cairo_surface_set_error (surface, status); -} - -cairo_clip_t * -_cairo_surface_get_clip (cairo_surface_t *surface) -{ - return surface->clip; -} - -cairo_status_t -_cairo_surface_set_clip (cairo_surface_t *surface, cairo_clip_t *clip) -{ - unsigned int serial = 0; - - if (surface->status) - return surface->status; - - if (surface->finished) - return _cairo_surface_set_error (surface,CAIRO_STATUS_SURFACE_FINISHED); - - if (clip) { - serial = clip->serial; - if (serial == 0) - clip = NULL; - } - - surface->clip = clip; - - if (serial == _cairo_surface_get_current_clip_serial (surface)) - return CAIRO_STATUS_SUCCESS; - - if (clip) { - if (clip->all_clipped) { - if (surface->backend->intersect_clip_path != NULL) - return _cairo_surface_set_empty_clip_path (surface, - clip->serial); - - if (surface->backend->set_clip_region != NULL) - return _cairo_surface_set_clip_region (surface, - &clip->region, - clip->serial); - } else { - if (clip->path) - return _cairo_surface_set_clip_path (surface, - clip->path, - clip->serial); - - if (clip->has_region) - return _cairo_surface_set_clip_region (surface, - &clip->region, - clip->serial); - } - } - - return _cairo_surface_reset_clip (surface); -} - -/** - * _cairo_surface_get_extents: - * @surface: the #cairo_surface_t to fetch extents for - * - * This function returns a bounding box for the surface. The surface - * bounds are defined as a region beyond which no rendering will - * possibly be recorded, in other words, it is the maximum extent of - * potentially usable coordinates. - * - * For vector surfaces, (PDF, PS, SVG and meta-surfaces), the surface - * might be conceived as unbounded, but we force the user to provide a - * maximum size at the time of surface_create. So get_extents uses - * that size. - * - * Note: The coordinates returned are in "backend" space rather than - * "surface" space. That is, they are relative to the true (0,0) - * origin rather than the device_transform origin. This might seem a - * bit inconsistent with other #cairo_surface_t interfaces, but all - * current callers are within the surface layer where backend space is - * desired. - * - * This behavior would have to be changed is we ever exported a public - * variant of this function. - */ -cairo_int_status_t -_cairo_surface_get_extents (cairo_surface_t *surface, - cairo_rectangle_int_t *extents) -{ - cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED; - - if (surface->status) - return surface->status; - - if (surface->finished) - return _cairo_surface_set_error (surface,CAIRO_STATUS_SURFACE_FINISHED); - - if (surface->backend->get_extents) { - status = _cairo_surface_set_error (surface, - surface->backend->get_extents (surface, extents)); - } - - if (status == CAIRO_INT_STATUS_UNSUPPORTED) { - extents->x = CAIRO_RECT_INT_MIN; - extents->y = CAIRO_RECT_INT_MIN; - extents->width = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN; - extents->height = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN; - } - - return status; -} - -/** - * cairo_surface_has_show_text_glyphs: - * @surface: a #cairo_surface_t - * - * Returns whether the surface supports - * sophisticated cairo_show_text_glyphs() operations. That is, - * whether it actually uses the provided text and cluster data - * to a cairo_show_text_glyphs() call. - * - * Note: Even if this function returns %FALSE, a - * cairo_show_text_glyphs() operation targeted at @surface will - * still succeed. It just will - * act like a cairo_show_glyphs() operation. Users can use this - * function to avoid computing UTF-8 text and cluster mapping if the - * target surface does not use it. - * - * Return value: %TRUE if @surface supports - * cairo_show_text_glyphs(), %FALSE otherwise - * - * Since: 1.8 - **/ -cairo_bool_t -cairo_surface_has_show_text_glyphs (cairo_surface_t *surface) -{ - cairo_status_t status_ignored; - - if (surface->status) - return FALSE; - - if (surface->finished) { - status_ignored = _cairo_surface_set_error (surface, - CAIRO_STATUS_SURFACE_FINISHED); - return FALSE; - } - - if (surface->backend->has_show_text_glyphs) - return surface->backend->has_show_text_glyphs (surface); - else - return surface->backend->show_text_glyphs != NULL; -} -slim_hidden_def (cairo_surface_has_show_text_glyphs); - -/* Note: the backends may modify the contents of the glyph array as long as - * they do not return %CAIRO_INT_STATUS_UNSUPPORTED. This makes it possible to - * avoid copying the array again and again, and edit it in-place. - * Backends are in fact free to use the array as a generic buffer as they - * see fit. - * - * For show_glyphs backend method, and NOT for show_text_glyphs method, - * when they do return UNSUPPORTED, they may adjust remaining_glyphs to notify - * that they have successfully rendered some of the glyphs (from the beginning - * of the array), but not all. If they don't touch remaining_glyphs, it - * defaults to all glyphs. - * - * See commits 5a9642c5746fd677aed35ce620ce90b1029b1a0c and - * 1781e6018c17909311295a9cc74b70500c6b4d0a for the rationale. - */ -cairo_status_t -_cairo_surface_show_text_glyphs (cairo_surface_t *surface, - cairo_operator_t op, - cairo_pattern_t *source, - const char *utf8, - int utf8_len, - cairo_glyph_t *glyphs, - int num_glyphs, - const cairo_text_cluster_t *clusters, - int num_clusters, - cairo_text_cluster_flags_t cluster_flags, - cairo_scaled_font_t *scaled_font) -{ - cairo_status_t status; - cairo_scaled_font_t *dev_scaled_font = scaled_font; - cairo_pattern_t *dev_source; - - if (surface->status) - return surface->status; - - assert (! surface->is_snapshot); - - if (!num_glyphs && !utf8_len) - return CAIRO_STATUS_SUCCESS; - - status = _cairo_surface_copy_pattern_for_destination (source, - surface, - &dev_source); - if (status) - return _cairo_surface_set_error (surface, 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 (status) { - cairo_pattern_destroy (dev_source); - return _cairo_surface_set_error (surface, status); - } - - status = CAIRO_INT_STATUS_UNSUPPORTED; - - /* The logic here is duplicated in _cairo_analysis_surface show_glyphs and - * show_text_glyphs. Keep in synch. */ - if (clusters) { - /* A real show_text_glyphs call. Try show_text_glyphs backend - * method first */ - if (surface->backend->show_text_glyphs) { - status = surface->backend->show_text_glyphs (surface, op, dev_source, - utf8, utf8_len, - glyphs, num_glyphs, - clusters, num_clusters, cluster_flags, - dev_scaled_font); - } - if (status == CAIRO_INT_STATUS_UNSUPPORTED && surface->backend->show_glyphs) { - int remaining_glyphs = num_glyphs; - status = surface->backend->show_glyphs (surface, op, dev_source, - glyphs, num_glyphs, - dev_scaled_font, - &remaining_glyphs); - glyphs += num_glyphs - remaining_glyphs; - num_glyphs = remaining_glyphs; - if (status == CAIRO_INT_STATUS_UNSUPPORTED && remaining_glyphs == 0) - status = CAIRO_STATUS_SUCCESS; - } - } else { - /* A mere show_glyphs call. Try show_glyphs backend method first */ - if (surface->backend->show_glyphs) { - int remaining_glyphs = num_glyphs; - status = surface->backend->show_glyphs (surface, op, dev_source, - glyphs, num_glyphs, - dev_scaled_font, - &remaining_glyphs); - glyphs += num_glyphs - remaining_glyphs; - num_glyphs = remaining_glyphs; - if (status == CAIRO_INT_STATUS_UNSUPPORTED && remaining_glyphs == 0) - status = CAIRO_STATUS_SUCCESS; - } else if (surface->backend->show_text_glyphs) { - /* Intentionally only try show_text_glyphs method for show_glyphs - * calls if backend does not have show_glyphs. If backend has - * both methods implemented, we don't fallback from show_glyphs to - * show_text_glyphs, and hence the backend can assume in its - * show_text_glyphs call that clusters is not NULL (which also - * implies that UTF-8 is not NULL, unless the text is - * zero-length). - */ - status = surface->backend->show_text_glyphs (surface, op, dev_source, - utf8, utf8_len, - glyphs, num_glyphs, - clusters, num_clusters, cluster_flags, - dev_scaled_font); - } - } - - if (status == CAIRO_INT_STATUS_UNSUPPORTED) - status = _cairo_surface_fallback_show_glyphs (surface, op, dev_source, - glyphs, num_glyphs, - dev_scaled_font); - - if (dev_scaled_font != scaled_font) - cairo_scaled_font_destroy (dev_scaled_font); - - cairo_pattern_destroy (dev_source); - - return _cairo_surface_set_error (surface, status); -} - -/* XXX: Previously, we had a function named _cairo_surface_show_glyphs - * with not-so-useful semantics. We've now got a - * _cairo_surface_show_text_glyphs with the proper semantics, and its - * fallback still uses this old function (which still needs to be - * cleaned up in terms of both semantics and naming). */ -cairo_status_t -_cairo_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font, - cairo_operator_t op, - cairo_pattern_t *pattern, - cairo_surface_t *dst, - int source_x, - int source_y, - int dest_x, - int dest_y, - unsigned int width, - unsigned int height, - cairo_glyph_t *glyphs, - int num_glyphs) -{ - cairo_status_t status; - - if (dst->status) - return dst->status; - - assert (! dst->is_snapshot); - - if (dst->finished) - return _cairo_surface_set_error (dst, CAIRO_STATUS_SURFACE_FINISHED); - - if (dst->backend->old_show_glyphs) { - status = dst->backend->old_show_glyphs (scaled_font, - op, pattern, dst, - source_x, source_y, - dest_x, dest_y, - width, height, - glyphs, num_glyphs); - } else - status = CAIRO_INT_STATUS_UNSUPPORTED; - - return _cairo_surface_set_error (dst, status); -} - -static cairo_status_t -_cairo_surface_composite_fixup_unbounded_internal (cairo_surface_t *dst, - cairo_rectangle_int_t *src_rectangle, - cairo_rectangle_int_t *mask_rectangle, - int dst_x, - int dst_y, - unsigned int width, - unsigned int height) -{ - cairo_rectangle_int_t dst_rectangle; - cairo_rectangle_int_t drawn_rectangle; - cairo_bool_t has_drawn_region = FALSE; - cairo_region_t drawn_region; - cairo_region_t clear_region; - cairo_status_t status; - - /* The area that was drawn is the area in the destination rectangle but not within - * the source or the mask. - */ - dst_rectangle.x = dst_x; - dst_rectangle.y = dst_y; - dst_rectangle.width = width; - dst_rectangle.height = height; - _cairo_region_init_rect (&clear_region, &dst_rectangle); - - drawn_rectangle = dst_rectangle; - - if (src_rectangle) { - if (! _cairo_rectangle_intersect (&drawn_rectangle, src_rectangle)) - goto EMPTY; - } - - if (mask_rectangle) { - if (! _cairo_rectangle_intersect (&drawn_rectangle, mask_rectangle)) - goto EMPTY; - } - - /* Now compute the area that is in dst_rectangle but not in drawn_rectangle - */ - _cairo_region_init_rect (&drawn_region, &drawn_rectangle); - has_drawn_region = TRUE; - - status = _cairo_region_subtract (&clear_region, - &clear_region, - &drawn_region); - if (status) - goto CLEANUP_REGIONS; - - EMPTY: - status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_SOURCE, - CAIRO_COLOR_TRANSPARENT, - &clear_region); - - CLEANUP_REGIONS: - if (has_drawn_region) - _cairo_region_fini (&drawn_region); - _cairo_region_fini (&clear_region); - - return _cairo_surface_set_error (dst, status); -} - -/** - * _cairo_surface_composite_fixup_unbounded: - * @dst: the destination surface - * @src_attr: source surface attributes (from _cairo_pattern_acquire_surface()) - * @src_width: width of source surface - * @src_height: height of source surface - * @mask_attr: mask surface attributes or %NULL if no mask - * @mask_width: width of mask surface - * @mask_height: height of mask surface - * @src_x: @src_x from _cairo_surface_composite() - * @src_y: @src_y from _cairo_surface_composite() - * @mask_x: @mask_x from _cairo_surface_composite() - * @mask_y: @mask_y from _cairo_surface_composite() - * @dst_x: @dst_x from _cairo_surface_composite() - * @dst_y: @dst_y from _cairo_surface_composite() - * @width: @width from _cairo_surface_composite() - * @height: @height_x from _cairo_surface_composite() - * - * Eeek! Too many parameters! This is a helper function to take care of fixing - * up for bugs in libpixman and RENDER where, when asked to composite an - * untransformed surface with an unbounded operator (like CLEAR or SOURCE) - * only the region inside both the source and the mask is affected. - * This function clears the region that should have been drawn but was wasn't. - **/ -cairo_status_t -_cairo_surface_composite_fixup_unbounded (cairo_surface_t *dst, - cairo_surface_attributes_t *src_attr, - int src_width, - int src_height, - cairo_surface_attributes_t *mask_attr, - int mask_width, - int mask_height, - 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_rectangle_int_t src_tmp, mask_tmp; - cairo_rectangle_int_t *src_rectangle = NULL; - cairo_rectangle_int_t *mask_rectangle = NULL; - - if (dst->status) - return dst->status; - - assert (! dst->is_snapshot); - - /* The RENDER/libpixman operators are clipped to the bounds of the untransformed, - * non-repeating sources and masks. Other sources and masks can be ignored. - */ - if (_cairo_matrix_is_integer_translation (&src_attr->matrix, NULL, NULL) && - src_attr->extend == CAIRO_EXTEND_NONE) - { - src_tmp.x = (dst_x - (src_x + src_attr->x_offset)); - src_tmp.y = (dst_y - (src_y + src_attr->y_offset)); - src_tmp.width = src_width; - src_tmp.height = src_height; - - src_rectangle = &src_tmp; - } - - if (mask_attr && - _cairo_matrix_is_integer_translation (&mask_attr->matrix, NULL, NULL) && - mask_attr->extend == CAIRO_EXTEND_NONE) - { - mask_tmp.x = (dst_x - (mask_x + mask_attr->x_offset)); - mask_tmp.y = (dst_y - (mask_y + mask_attr->y_offset)); - mask_tmp.width = mask_width; - mask_tmp.height = mask_height; - - mask_rectangle = &mask_tmp; - } - - return _cairo_surface_composite_fixup_unbounded_internal (dst, src_rectangle, mask_rectangle, - dst_x, dst_y, width, height); -} - -/** - * _cairo_surface_composite_shape_fixup_unbounded: - * @dst: the destination surface - * @src_attr: source surface attributes (from _cairo_pattern_acquire_surface()) - * @src_width: width of source surface - * @src_height: height of source surface - * @mask_width: width of mask surface - * @mask_height: height of mask surface - * @src_x: @src_x from _cairo_surface_composite() - * @src_y: @src_y from _cairo_surface_composite() - * @mask_x: @mask_x from _cairo_surface_composite() - * @mask_y: @mask_y from _cairo_surface_composite() - * @dst_x: @dst_x from _cairo_surface_composite() - * @dst_y: @dst_y from _cairo_surface_composite() - * @width: @width from _cairo_surface_composite() - * @height: @height_x from _cairo_surface_composite() - * - * Like _cairo_surface_composite_fixup_unbounded(), but instead of - * handling the case where we have a source pattern and a mask - * pattern, handle the case where we are compositing a source pattern - * using a mask we create ourselves, as in - * _cairo_surface_composite_glyphs() or _cairo_surface_composite_trapezoids() - **/ -cairo_status_t -_cairo_surface_composite_shape_fixup_unbounded (cairo_surface_t *dst, - cairo_surface_attributes_t *src_attr, - int src_width, - int src_height, - int mask_width, - int mask_height, - 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_rectangle_int_t src_tmp, mask_tmp; - cairo_rectangle_int_t *src_rectangle = NULL; - cairo_rectangle_int_t *mask_rectangle = NULL; - - if (dst->status) - return dst->status; - - assert (! dst->is_snapshot); - - /* The RENDER/libpixman operators are clipped to the bounds of the untransformed, - * non-repeating sources and masks. Other sources and masks can be ignored. - */ - if (_cairo_matrix_is_integer_translation (&src_attr->matrix, NULL, NULL) && - src_attr->extend == CAIRO_EXTEND_NONE) - { - src_tmp.x = (dst_x - (src_x + src_attr->x_offset)); - src_tmp.y = (dst_y - (src_y + src_attr->y_offset)); - src_tmp.width = src_width; - src_tmp.height = src_height; - - src_rectangle = &src_tmp; - } - - mask_tmp.x = dst_x - mask_x; - mask_tmp.y = dst_y - mask_y; - mask_tmp.width = mask_width; - mask_tmp.height = mask_height; - - mask_rectangle = &mask_tmp; - - return _cairo_surface_composite_fixup_unbounded_internal (dst, src_rectangle, mask_rectangle, - dst_x, dst_y, width, height); -} - -/** - * _cairo_surface_copy_pattern_for_destination - * @pattern: the pattern to copy - * @destination: the destination surface for which the pattern is being copied - * @pattern_out: the location to hold the copy - * - * Copies the given pattern, taking into account device scale and offsets - * of the destination surface. - */ -static cairo_status_t -_cairo_surface_copy_pattern_for_destination (const cairo_pattern_t *pattern, - cairo_surface_t *destination, - cairo_pattern_t **pattern_out) -{ - cairo_status_t status; - - status = _cairo_pattern_create_copy (pattern_out, pattern); - if (status) - return status; - - if (_cairo_surface_has_device_transform (destination)) { - _cairo_pattern_transform (*pattern_out, - &destination->device_transform_inverse); - } - - return CAIRO_STATUS_SUCCESS; -} - -/** - * _cairo_surface_set_resolution - * @surface: the surface - * @x_res: x resolution, in dpi - * @y_res: y resolution, in dpi - * - * Set the actual surface resolution of @surface to the given x and y DPI. - * Mainly used for correctly computing the scale factor when fallback - * rendering needs to take place in the paginated surface. - */ -void -_cairo_surface_set_resolution (cairo_surface_t *surface, - double x_res, - double y_res) -{ - if (surface->status) - return; - - surface->x_resolution = x_res; - surface->y_resolution = y_res; -} - -cairo_surface_t * -_cairo_surface_create_in_error (cairo_status_t status) -{ - switch (status) { - case CAIRO_STATUS_NO_MEMORY: - return (cairo_surface_t *) &_cairo_surface_nil; - case CAIRO_STATUS_INVALID_CONTENT: - return (cairo_surface_t *) &_cairo_surface_nil_invalid_content; - case CAIRO_STATUS_INVALID_FORMAT: - return (cairo_surface_t *) &_cairo_surface_nil_invalid_format; - case CAIRO_STATUS_INVALID_VISUAL: - return (cairo_surface_t *) &_cairo_surface_nil_invalid_visual; - case CAIRO_STATUS_READ_ERROR: - return (cairo_surface_t *) &_cairo_surface_nil_read_error; - case CAIRO_STATUS_WRITE_ERROR: - return (cairo_surface_t *) &_cairo_surface_nil_write_error; - case CAIRO_STATUS_FILE_NOT_FOUND: - return (cairo_surface_t *) &_cairo_surface_nil_file_not_found; - case CAIRO_STATUS_TEMP_FILE_ERROR: - return (cairo_surface_t *) &_cairo_surface_nil_temp_file_error; - case CAIRO_STATUS_INVALID_STRIDE: - return (cairo_surface_t *) &_cairo_surface_nil_invalid_stride; - case CAIRO_STATUS_SUCCESS: - ASSERT_NOT_REACHED; - /* fall-through */ - case CAIRO_STATUS_INVALID_RESTORE: - case CAIRO_STATUS_INVALID_POP_GROUP: - case CAIRO_STATUS_NO_CURRENT_POINT: - case CAIRO_STATUS_INVALID_MATRIX: - case CAIRO_STATUS_INVALID_STATUS: - case CAIRO_STATUS_NULL_POINTER: - case CAIRO_STATUS_INVALID_STRING: - case CAIRO_STATUS_INVALID_PATH_DATA: - case CAIRO_STATUS_SURFACE_FINISHED: - case CAIRO_STATUS_SURFACE_TYPE_MISMATCH: - case CAIRO_STATUS_PATTERN_TYPE_MISMATCH: - case CAIRO_STATUS_INVALID_DASH: - case CAIRO_STATUS_INVALID_DSC_COMMENT: - case CAIRO_STATUS_INVALID_INDEX: - case CAIRO_STATUS_CLIP_NOT_REPRESENTABLE: - case CAIRO_STATUS_FONT_TYPE_MISMATCH: - case CAIRO_STATUS_USER_FONT_IMMUTABLE: - case CAIRO_STATUS_USER_FONT_ERROR: - case CAIRO_STATUS_NEGATIVE_COUNT: - case CAIRO_STATUS_INVALID_CLUSTERS: - case CAIRO_STATUS_INVALID_SLANT: - case CAIRO_STATUS_INVALID_WEIGHT: - default: - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_surface_t *) &_cairo_surface_nil; - } -} - -/* LocalWords: rasterized - */ diff --git a/uppdev/plugin/cairo/lib/cairo-svg-surface-private.h b/uppdev/plugin/cairo/lib/cairo-svg-surface-private.h deleted file mode 100644 index e7cd4db8c..000000000 --- a/uppdev/plugin/cairo/lib/cairo-svg-surface-private.h +++ /dev/null @@ -1,74 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2004 Red Hat, Inc - * Copyright © 2005-2006 Emmanuel Pacaud - * Copyright © 2006 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Kristian Høgsberg - * Emmanuel Pacaud - * Carl Worth - */ - -#ifndef CAIRO_SVG_SURFACE_PRIVATE_H -#define CAIRO_SVG_SURFACE_PRIVATE_H - -#include "cairo-svg.h" - -#include "cairo-surface-private.h" - -typedef struct cairo_svg_document cairo_svg_document_t; - -typedef struct cairo_svg_surface { - cairo_surface_t base; - - cairo_content_t content; - - unsigned int id; - - double width; - double height; - - cairo_svg_document_t *document; - - cairo_output_stream_t *xml_node; - cairo_array_t page_set; - - unsigned int clip_level; - unsigned int base_clip; - cairo_bool_t is_base_clip_emitted; - - cairo_paginated_mode_t paginated_mode; - - cairo_bool_t force_fallbacks; -} cairo_svg_surface_t; - -#endif /* CAIRO_SVG_SURFACE_PRIVATE_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-svg-surface.c b/uppdev/plugin/cairo/lib/cairo-svg-surface.c deleted file mode 100644 index f392c8ed2..000000000 --- a/uppdev/plugin/cairo/lib/cairo-svg-surface.c +++ /dev/null @@ -1,2611 +0,0 @@ -/* vim: set sw=4 sts=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 © 2004 Red Hat, Inc - * Copyright © 2005-2007 Emmanuel Pacaud - * Copyright © 2006 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Kristian Høgsberg - * Emmanuel Pacaud - * Carl Worth - */ - -#define _BSD_SOURCE /* for snprintf() */ -#include "cairoint.h" -#include "cairo-svg.h" -#include "cairo-analysis-surface-private.h" -#include "cairo-svg-surface-private.h" -#include "cairo-meta-surface-private.h" -#include "cairo-output-stream-private.h" -#include "cairo-path-fixed-private.h" -#include "cairo-paginated-private.h" -#include "cairo-scaled-font-subsets-private.h" - -typedef struct cairo_svg_page cairo_svg_page_t; - -static const int invalid_pattern_id = -1; - -static const cairo_svg_version_t _cairo_svg_versions[] = -{ - CAIRO_SVG_VERSION_1_1, - CAIRO_SVG_VERSION_1_2 -}; - -#define CAIRO_SVG_VERSION_LAST ARRAY_LENGTH (_cairo_svg_versions) - -static cairo_bool_t -_cairo_svg_version_has_page_set_support (cairo_svg_version_t version) -{ - return version > CAIRO_SVG_VERSION_1_1; -} - -static const char * _cairo_svg_version_strings[CAIRO_SVG_VERSION_LAST] = -{ - "SVG 1.1", - "SVG 1.2" -}; - -static const char * _cairo_svg_internal_version_strings[CAIRO_SVG_VERSION_LAST] = -{ - "1.1", - "1.2" -}; - -struct cairo_svg_page { - unsigned int surface_id; - unsigned int clip_level; - cairo_output_stream_t *xml_node; -}; - -struct cairo_svg_document { - cairo_output_stream_t *output_stream; - unsigned long refcount; - cairo_surface_t *owner; - cairo_bool_t finished; - - double width; - double height; - - cairo_output_stream_t *xml_node_defs; - cairo_output_stream_t *xml_node_glyphs; - - unsigned int surface_id; - unsigned int linear_pattern_id; - unsigned int radial_pattern_id; - unsigned int pattern_id; - unsigned int filter_id; - unsigned int clip_id; - unsigned int mask_id; - - cairo_bool_t alpha_filter; - - cairo_array_t meta_snapshots; - - cairo_svg_version_t svg_version; - - cairo_scaled_font_subsets_t *font_subsets; -}; - -typedef struct { - unsigned int id; - cairo_meta_surface_t *meta; -} cairo_meta_snapshot_t; - -static cairo_status_t -_cairo_svg_document_create (cairo_output_stream_t *stream, - double width, - double height, - cairo_svg_version_t version, - cairo_svg_document_t **document_out); - -static cairo_status_t -_cairo_svg_document_destroy (cairo_svg_document_t *document); - -static cairo_status_t -_cairo_svg_document_finish (cairo_svg_document_t *document); - -static cairo_svg_document_t * -_cairo_svg_document_reference (cairo_svg_document_t *document); - -static unsigned int -_cairo_svg_document_allocate_mask_id (cairo_svg_document_t *document); - -static cairo_surface_t * -_cairo_svg_surface_create_for_document (cairo_svg_document_t *document, - cairo_content_t content, - double width, - double height); -static cairo_surface_t * -_cairo_svg_surface_create_for_stream_internal (cairo_output_stream_t *stream, - double width, - double height, - cairo_svg_version_t version); - -static const cairo_surface_backend_t cairo_svg_surface_backend; -static const cairo_paginated_surface_backend_t cairo_svg_surface_paginated_backend; - -/** - * cairo_svg_surface_create_for_stream: - * @write_func: a #cairo_write_func_t to accept the output data, may be %NULL - * to indicate a no-op @write_func. With a no-op @write_func, - * the surface may be queried or used as a source without - * generating any temporary files. - * @closure: the closure argument for @write_func - * @width_in_points: width of the surface, in points (1 point == 1/72.0 inch) - * @height_in_points: height of the surface, in points (1 point == 1/72.0 inch) - * - * Creates a SVG surface of the specified size in points to be written - * incrementally to the stream represented by @write_func and @closure. - * - * Return value: a pointer to the newly created surface. The caller - * owns the surface and should call cairo_surface_destroy() when done - * with it. - * - * This function always returns a valid pointer, but it will return a - * pointer to a "nil" surface if an error such as out of memory - * occurs. You can use cairo_surface_status() to check for this. - * - * Since: 1.2 - */ -cairo_surface_t * -cairo_svg_surface_create_for_stream (cairo_write_func_t write_func, - void *closure, - double width, - double height) -{ - cairo_output_stream_t *stream; - - stream = _cairo_output_stream_create (write_func, NULL, closure); - if (_cairo_output_stream_get_status (stream)) - return _cairo_surface_create_in_error (_cairo_output_stream_destroy (stream)); - - return _cairo_svg_surface_create_for_stream_internal (stream, width, height, CAIRO_SVG_VERSION_1_1); -} - -/** - * cairo_svg_surface_create: - * @filename: a filename for the SVG output (must be writable), %NULL may be - * used to specify no output. This will generate a SVG surface that - * may be queried and used as a source, without generating a - * temporary file. - * @width_in_points: width of the surface, in points (1 point == 1/72.0 inch) - * @height_in_points: height of the surface, in points (1 point == 1/72.0 inch) - * - * Creates a SVG surface of the specified size in points to be written - * to @filename. - * - * Return value: a pointer to the newly created surface. The caller - * owns the surface and should call cairo_surface_destroy() when done - * with it. - * - * This function always returns a valid pointer, but it will return a - * pointer to a "nil" surface if an error such as out of memory - * occurs. You can use cairo_surface_status() to check for this. - * - * Since: 1.2 - **/ -cairo_surface_t * -cairo_svg_surface_create (const char *filename, - double width, - double height) -{ - cairo_output_stream_t *stream; - - stream = _cairo_output_stream_create_for_filename (filename); - if (_cairo_output_stream_get_status (stream)) - return _cairo_surface_create_in_error (_cairo_output_stream_destroy (stream)); - - return _cairo_svg_surface_create_for_stream_internal (stream, width, height, CAIRO_SVG_VERSION_1_1); -} - -static cairo_bool_t -_cairo_surface_is_svg (cairo_surface_t *surface) -{ - return surface->backend == &cairo_svg_surface_backend; -} - -/* If the abstract_surface is a paginated surface, and that paginated - * surface's target is a svg_surface, then set svg_surface to that - * target. Otherwise return %CAIRO_STATUS_SURFACE_TYPE_MISMATCH. - */ -static cairo_status_t -_extract_svg_surface (cairo_surface_t *surface, - cairo_svg_surface_t **svg_surface) -{ - cairo_surface_t *target; - - if (surface->status) - return surface->status; - - if (! _cairo_surface_is_paginated (surface)) - return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - - target = _cairo_paginated_surface_get_target (surface); - if (target->status) - return target->status; - - if (! _cairo_surface_is_svg (target)) - return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - - *svg_surface = (cairo_svg_surface_t *) target; - - return CAIRO_STATUS_SUCCESS; -} - -/** - * cairo_svg_surface_restrict_to_version: - * @surface: a SVG #cairo_surface_t - * @version: SVG version - * - * Restricts the generated SVG file to @version. See cairo_svg_get_versions() - * for a list of available version values that can be used here. - * - * This function should only be called before any drawing operations - * have been performed on the given surface. The simplest way to do - * this is to call this function immediately after creating the - * surface. - * - * Since: 1.2 - **/ -void -cairo_svg_surface_restrict_to_version (cairo_surface_t *abstract_surface, - cairo_svg_version_t version) -{ - cairo_svg_surface_t *surface = NULL; /* hide compiler warning */ - cairo_status_t status; - - status = _extract_svg_surface (abstract_surface, &surface); - if (status) { - status = _cairo_surface_set_error (abstract_surface, status); - return; - } - - if (version < CAIRO_SVG_VERSION_LAST) - surface->document->svg_version = version; -} - -/** - * cairo_svg_get_versions: - * @versions: supported version list - * @num_versions: list length - * - * Used to retrieve the list of supported versions. See - * cairo_svg_surface_restrict_to_version(). - * - * Since: 1.2 - **/ -void -cairo_svg_get_versions (cairo_svg_version_t const **versions, - int *num_versions) -{ - if (versions != NULL) - *versions = _cairo_svg_versions; - - if (num_versions != NULL) - *num_versions = CAIRO_SVG_VERSION_LAST; -} - -/** - * cairo_svg_version_to_string: - * @version: a version id - * - * Get the string representation of the given @version id. This function - * will return %NULL if @version isn't valid. See cairo_svg_get_versions() - * for a way to get the list of valid version ids. - * - * Return value: the string associated to given version. - * - * Since: 1.2 - **/ -const char * -cairo_svg_version_to_string (cairo_svg_version_t version) -{ - if (version >= CAIRO_SVG_VERSION_LAST) - return NULL; - - return _cairo_svg_version_strings[version]; -} - -static cairo_surface_t * -_cairo_svg_surface_create_for_document (cairo_svg_document_t *document, - cairo_content_t content, - double width, - double height) -{ - cairo_svg_surface_t *surface; - cairo_surface_t *paginated; - cairo_status_t status, status_ignored; - - surface = malloc (sizeof (cairo_svg_surface_t)); - if (surface == NULL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - _cairo_surface_init (&surface->base, &cairo_svg_surface_backend, - content); - - surface->width = width; - surface->height = height; - - surface->document = _cairo_svg_document_reference (document); - - surface->clip_level = 0; - - surface->id = document->surface_id++; - surface->base_clip = document->clip_id++; - surface->is_base_clip_emitted = FALSE; - - surface->xml_node = _cairo_memory_stream_create (); - status = _cairo_output_stream_get_status (surface->xml_node); - if (status) - goto CLEANUP; - - _cairo_array_init (&surface->page_set, sizeof (cairo_svg_page_t)); - - if (content == CAIRO_CONTENT_COLOR) { - _cairo_output_stream_printf (surface->xml_node, - "\n", - width, height); - status = _cairo_output_stream_get_status (surface->xml_node); - if (status) - goto CLEANUP; - } - - surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE; - surface->force_fallbacks = FALSE; - surface->content = content; - - paginated = _cairo_paginated_surface_create (&surface->base, - surface->content, - surface->width, - surface->height, - &cairo_svg_surface_paginated_backend); - status = paginated->status; - if (status == CAIRO_STATUS_SUCCESS) { - /* paginated keeps the only reference to surface now, drop ours */ - cairo_surface_destroy (&surface->base); - return paginated; - } - - /* ignore status as we are on the error path */ -CLEANUP: - status_ignored = _cairo_output_stream_destroy (surface->xml_node); - status_ignored = _cairo_svg_document_destroy (document); - - free (surface); - - return _cairo_surface_create_in_error (status); -} - -static cairo_surface_t * -_cairo_svg_surface_create_for_stream_internal (cairo_output_stream_t *stream, - double width, - double height, - cairo_svg_version_t version) -{ - cairo_svg_document_t *document = NULL; /* silence compiler */ - cairo_surface_t *surface; - cairo_status_t status; - - status = _cairo_svg_document_create (stream, - width, height, version, - &document); - if (status) { - surface = _cairo_surface_create_in_error (status); - /* consume the output stream on behalf of caller */ - status = _cairo_output_stream_destroy (stream); - return surface; - } - - surface = _cairo_svg_surface_create_for_document (document, CAIRO_CONTENT_COLOR_ALPHA, - width, height); - if (surface->status) { - status = _cairo_svg_document_destroy (document); - return surface; - } - - document->owner = surface; - status = _cairo_svg_document_destroy (document); - /* the ref count should be 2 at this point */ - assert (status == CAIRO_STATUS_SUCCESS); - - return surface; -} - -static cairo_svg_page_t * -_cairo_svg_surface_store_page (cairo_svg_surface_t *surface) -{ - unsigned int i; - cairo_svg_page_t page; - cairo_output_stream_t *stream; - cairo_status_t status; - - stream = _cairo_memory_stream_create (); - if (_cairo_output_stream_get_status (stream)) { - status = _cairo_output_stream_destroy (stream); - return NULL; - } - - page.surface_id = surface->id; - page.clip_level = surface->clip_level; - page.xml_node = surface->xml_node; - - if (_cairo_array_append (&surface->page_set, &page)) { - status = _cairo_output_stream_destroy (stream); - return NULL; - } - - surface->xml_node = stream; - surface->clip_level = 0; - - for (i = 0; i < page.clip_level; i++) - _cairo_output_stream_printf (page.xml_node, "\n"); - - return _cairo_array_index (&surface->page_set, surface->page_set.num_elements - 1); -} - -static cairo_int_status_t -_cairo_svg_surface_copy_page (void *abstract_surface) -{ - cairo_svg_surface_t *surface = abstract_surface; - cairo_svg_page_t *page; - - page = _cairo_svg_surface_store_page (surface); - if (page == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - _cairo_memory_stream_copy (page->xml_node, surface->xml_node); - surface->clip_level = page->clip_level; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_svg_surface_show_page (void *abstract_surface) -{ - cairo_svg_surface_t *surface = abstract_surface; - - if (_cairo_svg_surface_store_page (surface) == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_svg_surface_emit_transform (cairo_output_stream_t *output, - char const *attribute_str, - const cairo_matrix_t *object_matrix, - const cairo_matrix_t *parent_matrix) -{ - cairo_matrix_t matrix = *object_matrix; - - if (parent_matrix != NULL) - cairo_matrix_multiply (&matrix, &matrix, parent_matrix); - - if (!_cairo_matrix_is_identity (&matrix)) - _cairo_output_stream_printf (output, - "%s=\"matrix(%f,%f,%f,%f,%f,%f)\"", - attribute_str, - matrix.xx, matrix.yx, - matrix.xy, matrix.yy, - matrix.x0, matrix.y0); -} - -typedef struct -{ - cairo_output_stream_t *output; - cairo_matrix_t *ctm_inverse; -} svg_path_info_t; - -static cairo_status_t -_cairo_svg_path_move_to (void *closure, cairo_point_t *point) -{ - svg_path_info_t *info = closure; - double x = _cairo_fixed_to_double (point->x); - double y = _cairo_fixed_to_double (point->y); - - if (info->ctm_inverse) - cairo_matrix_transform_point (info->ctm_inverse, &x, &y); - - _cairo_output_stream_printf (info->output, "M %f %f ", x, y); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_svg_path_line_to (void *closure, cairo_point_t *point) -{ - svg_path_info_t *info = closure; - double x = _cairo_fixed_to_double (point->x); - double y = _cairo_fixed_to_double (point->y); - - if (info->ctm_inverse) - cairo_matrix_transform_point (info->ctm_inverse, &x, &y); - - _cairo_output_stream_printf (info->output, "L %f %f ", x, y); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_svg_path_curve_to (void *closure, - cairo_point_t *b, - cairo_point_t *c, - cairo_point_t *d) -{ - svg_path_info_t *info = closure; - double bx = _cairo_fixed_to_double (b->x); - double by = _cairo_fixed_to_double (b->y); - double cx = _cairo_fixed_to_double (c->x); - double cy = _cairo_fixed_to_double (c->y); - double dx = _cairo_fixed_to_double (d->x); - double dy = _cairo_fixed_to_double (d->y); - - if (info->ctm_inverse) { - cairo_matrix_transform_point (info->ctm_inverse, &bx, &by); - cairo_matrix_transform_point (info->ctm_inverse, &cx, &cy); - cairo_matrix_transform_point (info->ctm_inverse, &dx, &dy); - } - - _cairo_output_stream_printf (info->output, - "C %f %f %f %f %f %f ", - bx, by, cx, cy, dx, dy); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_svg_path_close_path (void *closure) -{ - svg_path_info_t *info = closure; - - _cairo_output_stream_printf (info->output, "Z "); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_svg_surface_emit_path (cairo_output_stream_t *output, - cairo_path_fixed_t *path, - cairo_matrix_t *ctm_inverse) -{ - cairo_status_t status; - svg_path_info_t info; - - _cairo_output_stream_printf (output, "d=\""); - - info.output = output; - info.ctm_inverse = ctm_inverse; - status = _cairo_path_fixed_interpret (path, - CAIRO_DIRECTION_FORWARD, - _cairo_svg_path_move_to, - _cairo_svg_path_line_to, - _cairo_svg_path_curve_to, - _cairo_svg_path_close_path, - &info); - if (status) - return status; - - _cairo_output_stream_printf (output, "\""); - - return status; -} - -static cairo_int_status_t -_cairo_svg_document_emit_outline_glyph_data (cairo_svg_document_t *document, - cairo_scaled_font_t *scaled_font, - unsigned long glyph_index) -{ - cairo_scaled_glyph_t *scaled_glyph; - cairo_int_status_t status; - - status = _cairo_scaled_glyph_lookup (scaled_font, - glyph_index, - CAIRO_SCALED_GLYPH_INFO_METRICS| - CAIRO_SCALED_GLYPH_INFO_PATH, - &scaled_glyph); - if (status) - return status; - - _cairo_output_stream_printf (document->xml_node_glyphs, - "xml_node_glyphs, scaled_glyph->path, NULL); - if (status) - return status; - - _cairo_output_stream_printf (document->xml_node_glyphs, - "/>\n"); - - return status; -} - -static cairo_int_status_t -_cairo_svg_document_emit_bitmap_glyph_data (cairo_svg_document_t *document, - cairo_scaled_font_t *scaled_font, - unsigned long glyph_index) -{ - cairo_image_surface_t *image; - cairo_scaled_glyph_t *scaled_glyph; - cairo_status_t status; - uint8_t *row, *byte; - int rows, cols; - int x, y, bit; - - status = _cairo_scaled_glyph_lookup (scaled_font, - glyph_index, - CAIRO_SCALED_GLYPH_INFO_METRICS| - CAIRO_SCALED_GLYPH_INFO_SURFACE, - &scaled_glyph); - if (status) - return status; - - image = scaled_glyph->surface; - if (image->format != CAIRO_FORMAT_A1) { - image = _cairo_image_surface_clone (image, CAIRO_FORMAT_A1); - if (cairo_surface_status (&image->base)) - return cairo_surface_status (&image->base); - } - - _cairo_output_stream_printf (document->xml_node_glyphs, "xml_node_glyphs, " transform", - &image->base.device_transform_inverse, NULL); - _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--) { - uint8_t output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte); - for (bit = 7; bit >= 0 && x < image->width; bit--, x++) { - if (output_byte & (1 << bit)) { - _cairo_output_stream_printf (document->xml_node_glyphs, - "\n", - x, y); - } - } - } - } - _cairo_output_stream_printf (document->xml_node_glyphs, "\n"); - - if (image != scaled_glyph->surface) - cairo_surface_destroy (&image->base); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_svg_document_emit_glyph (cairo_svg_document_t *document, - cairo_scaled_font_t *scaled_font, - unsigned long scaled_font_glyph_index, - unsigned int font_id, - unsigned int subset_glyph_index) -{ - cairo_status_t status; - - _cairo_output_stream_printf (document->xml_node_glyphs, - "\n", - font_id, - subset_glyph_index); - - status = _cairo_svg_document_emit_outline_glyph_data (document, - scaled_font, - scaled_font_glyph_index); - if (status == CAIRO_INT_STATUS_UNSUPPORTED) - status = _cairo_svg_document_emit_bitmap_glyph_data (document, - scaled_font, - scaled_font_glyph_index); - if (status) - return status; - - _cairo_output_stream_printf (document->xml_node_glyphs, "\n"); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_svg_document_emit_font_subset (cairo_scaled_font_subset_t *font_subset, - void *closure) -{ - cairo_svg_document_t *document = closure; - unsigned int i; - cairo_status_t status = CAIRO_STATUS_SUCCESS; - - _cairo_scaled_font_freeze_cache (font_subset->scaled_font); - for (i = 0; i < font_subset->num_glyphs; i++) { - status = _cairo_svg_document_emit_glyph (document, - font_subset->scaled_font, - font_subset->glyphs[i], - font_subset->font_id, i); - if (status) - break; - } - _cairo_scaled_font_thaw_cache (font_subset->scaled_font); - - return status; -} - -static cairo_status_t -_cairo_svg_document_emit_font_subsets (cairo_svg_document_t *document) -{ - cairo_status_t status; - - status = _cairo_scaled_font_subsets_foreach_scaled (document->font_subsets, - _cairo_svg_document_emit_font_subset, - document); - if (status) - goto FAIL; - - status = _cairo_scaled_font_subsets_foreach_user (document->font_subsets, - _cairo_svg_document_emit_font_subset, - document); - - FAIL: - _cairo_scaled_font_subsets_destroy (document->font_subsets); - document->font_subsets = NULL; - - return status; -} - -static char const * -_cairo_svg_surface_operators[] = { - "clear", - - "src", "src-over", "src-in", - "src-out", "src-atop", - - "dst", "dst-over", "dst-in", - "dst-out", "dst-atop", - - "xor", "plus", - "color-dodge", /* FIXME: saturate ? */ -}; - -static cairo_bool_t -_cairo_svg_surface_analyze_operator (cairo_svg_surface_t *surface, - cairo_operator_t op) -{ - /* guard against newly added operators */ - if (op >= ARRAY_LENGTH (_cairo_svg_surface_operators)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - /* allow operators being NULL if they are unsupported */ - if (_cairo_svg_surface_operators[op] == NULL) - return CAIRO_INT_STATUS_UNSUPPORTED; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_svg_surface_analyze_operation (cairo_svg_surface_t *surface, - cairo_operator_t op, - const cairo_pattern_t *pattern) -{ - cairo_svg_document_t *document = surface->document; - - if (surface->force_fallbacks && - surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - { - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - /* SVG doesn't support extend reflect for image pattern */ - if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE && - pattern->extend == CAIRO_EXTEND_REFLECT) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (document->svg_version >= CAIRO_SVG_VERSION_1_2) - return _cairo_svg_surface_analyze_operator (surface, op); - - if (op == CAIRO_OPERATOR_OVER) - return CAIRO_STATUS_SUCCESS; - - /* The SOURCE operator is only supported if there is nothing - * painted underneath. */ - if (op == CAIRO_OPERATOR_SOURCE) - return CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY; - - return CAIRO_INT_STATUS_UNSUPPORTED; -} - -static cairo_int_status_t -_cairo_svg_surface_operation_supported (cairo_svg_surface_t *surface, - cairo_operator_t op, - const cairo_pattern_t *pattern) -{ - if (_cairo_svg_surface_analyze_operation (surface, op, pattern) - != CAIRO_INT_STATUS_UNSUPPORTED) - { - return TRUE; - } else { - return FALSE; - } -} - -static cairo_surface_t * -_cairo_svg_surface_create_similar (void *abstract_src, - cairo_content_t content, - int width, - int height) -{ - return _cairo_meta_surface_create (content, width, height); -} - -static cairo_status_t -_cairo_svg_surface_finish (void *abstract_surface) -{ - cairo_status_t status, status2; - cairo_svg_surface_t *surface = abstract_surface; - cairo_svg_document_t *document = surface->document; - cairo_svg_page_t *page; - unsigned int i; - - if (_cairo_paginated_surface_get_target (document->owner) == &surface->base) - status = _cairo_svg_document_finish (document); - else - status = CAIRO_STATUS_SUCCESS; - - if (surface->xml_node != NULL) { - status2 = _cairo_output_stream_destroy (surface->xml_node); - if (status == CAIRO_STATUS_SUCCESS) - status = status2; - } - - for (i = 0; i < surface->page_set.num_elements; i++) { - page = _cairo_array_index (&surface->page_set, i); - status2 = _cairo_output_stream_destroy (page->xml_node); - if (status == CAIRO_STATUS_SUCCESS) - status = status2; - } - _cairo_array_fini (&surface->page_set); - - status2 = _cairo_svg_document_destroy (document); - if (status == CAIRO_STATUS_SUCCESS) - status = status2; - - return status; -} - -static void -_cairo_svg_surface_emit_alpha_filter (cairo_svg_document_t *document) -{ - if (document->alpha_filter) - return; - - _cairo_output_stream_printf (document->xml_node_defs, - "\n" - " \n" - "\n"); - - document->alpha_filter = TRUE; -} - -typedef struct { - cairo_output_stream_t *output; - unsigned int in_mem; - unsigned int trailing; - unsigned char src[3]; -} base64_write_closure_t; - -static char const base64_table[64] = -"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -static cairo_status_t -base64_write_func (void *closure, - const unsigned char *data, - unsigned int length) -{ - base64_write_closure_t *info = (base64_write_closure_t *) closure; - unsigned int i; - unsigned char *src; - - src = info->src; - - if (info->in_mem + length < 3) { - for (i = 0; i < length; i++) { - src[i + info->in_mem] = *data++; - } - info->in_mem += length; - return CAIRO_STATUS_SUCCESS; - } - - do { - unsigned char dst[4]; - - for (i = info->in_mem; i < 3; i++) { - src[i] = *data++; - length--; - } - info->in_mem = 0; - - dst[0] = base64_table[src[0] >> 2]; - dst[1] = base64_table[(src[0] & 0x03) << 4 | src[1] >> 4]; - dst[2] = base64_table[(src[1] & 0x0f) << 2 | src[2] >> 6]; - dst[3] = base64_table[src[2] & 0xfc >> 2]; - /* Special case for the last missing bits */ - switch (info->trailing) { - case 2: - dst[2] = '='; - case 1: - dst[3] = '='; - default: - break; - } - _cairo_output_stream_write (info->output, dst, 4); - } while (length >= 3); - - for (i = 0; i < length; i++) { - src[i] = *data++; - } - info->in_mem = length; - - return _cairo_output_stream_get_status (info->output); -} - -static cairo_int_status_t -_cairo_surface_base64_encode (cairo_surface_t *surface, - cairo_output_stream_t *output) -{ - cairo_status_t status; - base64_write_closure_t info; - unsigned int i; - - info.output = output; - info.in_mem = 0; - info.trailing = 0; - - _cairo_output_stream_printf (info.output, "data:image/png;base64,"); - - status = cairo_surface_write_to_png_stream (surface, base64_write_func, - (void *) &info); - - if (status) - return status; - - if (info.in_mem > 0) { - for (i = info.in_mem; i < 3; i++) - info.src[i] = '\x0'; - info.trailing = 3 - info.in_mem; - info.in_mem = 3; - status = base64_write_func (&info, NULL, 0); - } - - return status; -} - -static void -_cairo_svg_surface_emit_operator (cairo_output_stream_t *output, - cairo_svg_surface_t *surface, - cairo_operator_t op) -{ - if (surface->document->svg_version >= CAIRO_SVG_VERSION_1_2 && - op != CAIRO_OPERATOR_OVER) { - _cairo_output_stream_printf (output, " comp-op=\"%s\"", _cairo_svg_surface_operators[op]); - if (!_cairo_operator_bounded_by_source (op)) - _cairo_output_stream_printf (output, " clip-to-self=\"true\""); - } -} - -static void -_cairo_svg_surface_emit_operator_for_style (cairo_output_stream_t *output, - cairo_svg_surface_t *surface, - cairo_operator_t op) -{ - if (surface->document->svg_version >= CAIRO_SVG_VERSION_1_2 && - op != CAIRO_OPERATOR_OVER) { - _cairo_output_stream_printf (output, "comp-op:%s;", _cairo_svg_surface_operators[op]); - if (!_cairo_operator_bounded_by_source (op)) - _cairo_output_stream_printf (output, "clip-to-self:true;"); - } -} - -static cairo_status_t -_cairo_svg_surface_emit_composite_image_pattern (cairo_output_stream_t *output, - cairo_svg_surface_t *svg_surface, - cairo_operator_t op, - cairo_surface_pattern_t *pattern, - int pattern_id, - const cairo_matrix_t *parent_matrix, - const char *extra_attributes) -{ - cairo_rectangle_int_t extents; - cairo_status_t status; - cairo_matrix_t p2u; - - status = _cairo_surface_get_extents (pattern->surface, &extents); - if (status) - return status; - - p2u = pattern->base.matrix; - status = cairo_matrix_invert (&p2u); - /* cairo_pattern_set_matrix ensures the matrix is invertible */ - assert (status == CAIRO_STATUS_SUCCESS); - - if (pattern_id != invalid_pattern_id) { - _cairo_output_stream_printf (output, - "\n"); - } - - _cairo_output_stream_printf (output, - " surface, output); - - _cairo_output_stream_printf (output, "\"/>\n"); - - if (pattern_id != invalid_pattern_id) - _cairo_output_stream_printf (output, "\n"); - - return status; -} - -static cairo_status_t -_cairo_svg_surface_emit_meta_surface (cairo_svg_document_t *document, - cairo_meta_surface_t *surface, - int *id) -{ - cairo_status_t status; - cairo_surface_t *paginated_surface; - cairo_svg_surface_t *svg_surface; - cairo_meta_snapshot_t new_snapshot; - cairo_array_t *page_set; - - cairo_output_stream_t *contents; - cairo_meta_surface_t *meta; - cairo_meta_snapshot_t *snapshot; - unsigned int num_elements; - unsigned int i; - - /* search in already emitted meta snapshots */ - num_elements = document->meta_snapshots.num_elements; - for (i = 0; i < num_elements; i++) { - snapshot = _cairo_array_index (&document->meta_snapshots, i); - meta = snapshot->meta; - if (meta->commands.num_elements == surface->commands.num_elements && - _cairo_array_index (&meta->commands, 0) == _cairo_array_index (&surface->commands, 0)) { - *id = snapshot->id; - return CAIRO_STATUS_SUCCESS; - } - } - - meta = (cairo_meta_surface_t *) _cairo_surface_snapshot (&surface->base); - paginated_surface = _cairo_svg_surface_create_for_document (document, - meta->content, - meta->width_pixels, - meta->height_pixels); - if (paginated_surface->status) { - cairo_surface_destroy (&meta->base); - return paginated_surface->status; - } - - svg_surface = (cairo_svg_surface_t *) _cairo_paginated_surface_get_target (paginated_surface); - cairo_surface_set_fallback_resolution (paginated_surface, - document->owner->x_fallback_resolution, - document->owner->y_fallback_resolution); - - status = _cairo_meta_surface_replay (&meta->base, paginated_surface); - if (status) { - cairo_surface_destroy (&meta->base); - cairo_surface_destroy (paginated_surface); - return status; - } - - cairo_surface_show_page (paginated_surface); - status = cairo_surface_status (paginated_surface); - if (status) { - cairo_surface_destroy (&meta->base); - cairo_surface_destroy (paginated_surface); - return status; - } - - new_snapshot.meta = meta; - new_snapshot.id = svg_surface->id; - status = _cairo_array_append (&document->meta_snapshots, &new_snapshot); - if (status) { - cairo_surface_destroy (&meta->base); - cairo_surface_destroy (paginated_surface); - return status; - } - - if (!svg_surface->is_base_clip_emitted) { - svg_surface->is_base_clip_emitted = TRUE; - _cairo_output_stream_printf (document->xml_node_defs, - "\n" - " \n" - "\n", - svg_surface->base_clip, - svg_surface->width, - svg_surface->height); - } - - if (meta->content == CAIRO_CONTENT_ALPHA) { - _cairo_svg_surface_emit_alpha_filter (document); - _cairo_output_stream_printf (document->xml_node_defs, - "\n", - svg_surface->id, - svg_surface->base_clip); - } else { - _cairo_output_stream_printf (document->xml_node_defs, - "\n", - svg_surface->id, - svg_surface->base_clip); - } - - contents = svg_surface->xml_node; - page_set = &svg_surface->page_set; - - if (_cairo_memory_stream_length (contents) > 0) { - if (_cairo_svg_surface_store_page (svg_surface) == NULL) { - cairo_surface_destroy (paginated_surface); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - } - - if (page_set->num_elements > 0) { - cairo_svg_page_t *page; - - page = _cairo_array_index (page_set, page_set->num_elements - 1); - _cairo_memory_stream_copy (page->xml_node, document->xml_node_defs); - } - - _cairo_output_stream_printf (document->xml_node_defs, "\n"); - - *id = new_snapshot.id; - - status = cairo_surface_status (paginated_surface); - cairo_surface_destroy (paginated_surface); - - /* FIXME: cairo_paginated_surface doesn't take a ref to the - * passed in target surface so we can't call destroy here. - * cairo_paginated_surface should be fixed, but for now just - * work around it. */ - - /* cairo_surface_destroy (svg_surface); */ - - return status; -} - -static cairo_status_t -_cairo_svg_surface_emit_composite_meta_pattern (cairo_output_stream_t *output, - cairo_svg_surface_t *surface, - cairo_operator_t op, - cairo_surface_pattern_t *pattern, - int pattern_id, - const cairo_matrix_t *parent_matrix, - const char *extra_attributes) -{ - cairo_svg_document_t *document = surface->document; - cairo_meta_surface_t *meta_surface; - cairo_matrix_t p2u; - cairo_status_t status; - int id = 0; - - p2u = pattern->base.matrix; - status = cairo_matrix_invert (&p2u); - /* cairo_pattern_set_matrix ensures the matrix is invertible */ - assert (status == CAIRO_STATUS_SUCCESS); - - meta_surface = (cairo_meta_surface_t *) pattern->surface; - - status = _cairo_svg_surface_emit_meta_surface (document, meta_surface, &id); - if (status) - return status; - - if (pattern_id != invalid_pattern_id) { - _cairo_output_stream_printf (output, - "width_pixels, - meta_surface->height_pixels); - _cairo_svg_surface_emit_transform (output, " patternTransform", &p2u, parent_matrix); - _cairo_output_stream_printf (output, ">\n"); - } - - _cairo_output_stream_printf (output, - "\n"); - - if (pattern_id != invalid_pattern_id) - _cairo_output_stream_printf (output, "\n"); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_svg_surface_emit_composite_pattern (cairo_output_stream_t *output, - cairo_svg_surface_t *surface, - cairo_operator_t op, - cairo_surface_pattern_t *pattern, - int pattern_id, - const cairo_matrix_t *parent_matrix, - const char *extra_attributes) -{ - - if (_cairo_surface_is_meta (pattern->surface)) { - return _cairo_svg_surface_emit_composite_meta_pattern (output, surface, op, pattern, - pattern_id, parent_matrix, extra_attributes); - } - - return _cairo_svg_surface_emit_composite_image_pattern (output, surface, op, pattern, - pattern_id, parent_matrix, extra_attributes); -} - -static cairo_status_t -_cairo_svg_surface_emit_solid_pattern (cairo_svg_surface_t *surface, - cairo_solid_pattern_t *pattern, - cairo_output_stream_t *style, - cairo_bool_t is_stroke) -{ - _cairo_output_stream_printf (style, is_stroke ? - "stroke:rgb(%f%%,%f%%,%f%%);stroke-opacity:%f;": - "fill:rgb(%f%%,%f%%,%f%%);fill-opacity:%f;", - pattern->color.red * 100.0, - pattern->color.green * 100.0, - pattern->color.blue * 100.0, - pattern->color.alpha); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_svg_surface_emit_surface_pattern (cairo_svg_surface_t *surface, - cairo_surface_pattern_t *pattern, - cairo_output_stream_t *style, - cairo_bool_t is_stroke, - const cairo_matrix_t *parent_matrix) -{ - cairo_svg_document_t *document = surface->document; - cairo_status_t status; - int pattern_id; - - pattern_id = document->pattern_id++; - status = _cairo_svg_surface_emit_composite_pattern (document->xml_node_defs, - surface, CAIRO_OPERATOR_SOURCE, pattern, - pattern_id, parent_matrix, NULL); - if (status) - return status; - - _cairo_output_stream_printf (style, - "%s:url(#pattern%d);", - is_stroke ? "stroke" : "fill", - pattern_id); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output, - cairo_gradient_pattern_t const *pattern, - double start_offset, - cairo_bool_t reverse_stops, - cairo_bool_t emulate_reflect) -{ - cairo_gradient_stop_t *stops; - double offset; - unsigned int n_stops; - unsigned int i; - - if (pattern->n_stops < 1) - return CAIRO_STATUS_SUCCESS; - - if (pattern->n_stops == 1) { - _cairo_output_stream_printf (output, - "\n", - pattern->stops[0].offset, - pattern->stops[0].color.red * 100.0, - pattern->stops[0].color.green * 100.0, - pattern->stops[0].color.blue * 100.0, - pattern->stops[0].color.alpha); - return CAIRO_STATUS_SUCCESS; - } - - if (emulate_reflect || reverse_stops) { - n_stops = emulate_reflect ? pattern->n_stops * 2 - 2: pattern->n_stops; - stops = _cairo_malloc_ab (n_stops, sizeof (cairo_gradient_stop_t)); - if (stops == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - for (i = 0; i < pattern->n_stops; i++) { - if (reverse_stops) { - stops[i] = pattern->stops[pattern->n_stops - i - 1]; - stops[i].offset = 1.0 - stops[i].offset; - } else - stops[i] = pattern->stops[i]; - if (emulate_reflect) { - stops[i].offset /= 2; - if (i > 0 && i < (pattern->n_stops - 1)) { - if (reverse_stops) { - stops[i + pattern->n_stops - 1] = pattern->stops[i]; - stops[i + pattern->n_stops - 1].offset = - 0.5 + 0.5 * stops[i + pattern->n_stops - 1].offset; - } else { - stops[i + pattern->n_stops - 1] = pattern->stops[pattern->n_stops - i - 1]; - stops[i + pattern->n_stops - 1].offset = - 1 - 0.5 * stops[i + pattern->n_stops - 1].offset; - } - } - } - } - } else { - n_stops = pattern->n_stops; - stops = pattern->stops; - } - - if (start_offset >= 0.0) - for (i = 0; i < n_stops; i++) { - offset = start_offset + (1 - start_offset ) * stops[i].offset; - _cairo_output_stream_printf (output, - "\n", - offset, - stops[i].color.red * 100.0, - stops[i].color.green * 100.0, - stops[i].color.blue * 100.0, - stops[i].color.alpha); - } - else { - cairo_bool_t found = FALSE; - unsigned int offset_index; - cairo_color_t offset_color_start, offset_color_stop; - - for (i = 0; i < n_stops; i++) { - if (stops[i].offset >= -start_offset) { - if (i > 0) { - if (stops[i].offset != stops[i-1].offset) { - double x0, x1; - cairo_color_t *color0, *color1; - - x0 = stops[i-1].offset; - x1 = stops[i].offset; - color0 = &stops[i-1].color; - color1 = &stops[i].color; - offset_color_start.red = color0->red + (color1->red - color0->red) - * (-start_offset - x0) / (x1 - x0); - offset_color_start.green = color0->green + (color1->green - color0->green) - * (-start_offset - x0) / (x1 - x0); - offset_color_start.blue = color0->blue + (color1->blue - color0->blue) - * (-start_offset - x0) / (x1 - x0); - offset_color_start.alpha = color0->alpha + (color1->alpha - color0->alpha) - * (-start_offset - x0) / (x1 - x0); - offset_color_stop = offset_color_start; - } else { - offset_color_stop = stops[i-1].color; - offset_color_start = stops[i].color; - } - } else - offset_color_stop = offset_color_start = stops[i].color; - offset_index = i; - found = TRUE; - break; - } - } - - if (!found) { - offset_index = n_stops - 1; - offset_color_stop = offset_color_start = stops[offset_index].color; - } - - _cairo_output_stream_printf (output, - "\n", - offset_color_start.red * 100.0, - offset_color_start.green * 100.0, - offset_color_start.blue * 100.0, - offset_color_start.alpha); - for (i = offset_index; i < n_stops; i++) { - _cairo_output_stream_printf (output, - "\n", - stops[i].offset + start_offset, - stops[i].color.red * 100.0, - stops[i].color.green * 100.0, - stops[i].color.blue * 100.0, - stops[i].color.alpha); - } - for (i = 0; i < offset_index; i++) { - _cairo_output_stream_printf (output, - "\n", - 1.0 + stops[i].offset + start_offset, - stops[i].color.red * 100.0, - stops[i].color.green * 100.0, - stops[i].color.blue * 100.0, - stops[i].color.alpha); - } - - _cairo_output_stream_printf (output, - "\n", - offset_color_stop.red * 100.0, - offset_color_stop.green * 100.0, - offset_color_stop.blue * 100.0, - offset_color_stop.alpha); - - } - - if (reverse_stops || emulate_reflect) - free (stops); - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_svg_surface_emit_pattern_extend (cairo_output_stream_t *output, - cairo_pattern_t *pattern) -{ - switch (pattern->extend) { - case CAIRO_EXTEND_REPEAT: - _cairo_output_stream_printf (output, "spreadMethod=\"repeat\" "); - break; - case CAIRO_EXTEND_REFLECT: - _cairo_output_stream_printf (output, "spreadMethod=\"reflect\" "); - break; - case CAIRO_EXTEND_NONE: - case CAIRO_EXTEND_PAD: - break; - } -} - -static cairo_status_t -_cairo_svg_surface_emit_linear_pattern (cairo_svg_surface_t *surface, - cairo_linear_pattern_t *pattern, - cairo_output_stream_t *style, - cairo_bool_t is_stroke, - const cairo_matrix_t *parent_matrix) -{ - cairo_svg_document_t *document = surface->document; - double x0, y0, x1, y1; - cairo_matrix_t p2u; - cairo_status_t status; - - p2u = pattern->base.base.matrix; - status = cairo_matrix_invert (&p2u); - /* cairo_pattern_set_matrix ensures the matrix is invertible */ - assert (status == CAIRO_STATUS_SUCCESS); - - x0 = _cairo_fixed_to_double (pattern->p1.x); - y0 = _cairo_fixed_to_double (pattern->p1.y); - x1 = _cairo_fixed_to_double (pattern->p2.x); - y1 = _cairo_fixed_to_double (pattern->p2.y); - - _cairo_output_stream_printf (document->xml_node_defs, - "linear_pattern_id, - x0, y0, x1, y1); - - _cairo_svg_surface_emit_pattern_extend (document->xml_node_defs, &pattern->base.base), - _cairo_svg_surface_emit_transform (document->xml_node_defs, "gradientTransform", &p2u, parent_matrix); - _cairo_output_stream_printf (document->xml_node_defs, ">\n"); - - status = _cairo_svg_surface_emit_pattern_stops (document->xml_node_defs, - &pattern->base, 0.0, - FALSE, FALSE); - if (status) - return status; - - _cairo_output_stream_printf (document->xml_node_defs, - "\n"); - - _cairo_output_stream_printf (style, - "%s:url(#linear%d);", - is_stroke ? "stroke" : "fill", - document->linear_pattern_id); - - document->linear_pattern_id++; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface, - cairo_radial_pattern_t *pattern, - cairo_output_stream_t *style, - cairo_bool_t is_stroke, - const cairo_matrix_t *parent_matrix) -{ - cairo_svg_document_t *document = surface->document; - cairo_matrix_t p2u; - cairo_extend_t extend; - double x0, y0, x1, y1, r0, r1; - double fx, fy; - cairo_bool_t reverse_stops; - cairo_status_t status; - cairo_point_t *c0, *c1; - cairo_fixed_t radius0, radius1; - - extend = pattern->base.base.extend; - - if (pattern->r1 < pattern->r2) { - c0 = &pattern->c1; - c1 = &pattern->c2; - radius0 = pattern->r1; - radius1 = pattern->r2; - reverse_stops = FALSE; - } else { - c0 = &pattern->c2; - c1 = &pattern->c1; - radius0 = pattern->r2; - radius1 = pattern->r1; - reverse_stops = TRUE; - } - - x0 = _cairo_fixed_to_double (c0->x); - y0 = _cairo_fixed_to_double (c0->y); - r0 = _cairo_fixed_to_double (radius0); - x1 = _cairo_fixed_to_double (c1->x); - y1 = _cairo_fixed_to_double (c1->y); - r1 = _cairo_fixed_to_double (radius1); - - p2u = pattern->base.base.matrix; - status = cairo_matrix_invert (&p2u); - /* cairo_pattern_set_matrix ensures the matrix is invertible */ - assert (status == CAIRO_STATUS_SUCCESS); - - if (pattern->r1 == pattern->r2) { - unsigned int n_stops = pattern->base.n_stops; - - _cairo_output_stream_printf (document->xml_node_defs, - "radial_pattern_id, - x1, y1, - x1, y1, r1); - _cairo_svg_surface_emit_transform (document->xml_node_defs, "gradientTransform", &p2u, parent_matrix); - _cairo_output_stream_printf (document->xml_node_defs, ">\n"); - - if (extend == CAIRO_EXTEND_NONE || n_stops < 1) - _cairo_output_stream_printf (document->xml_node_defs, - "\n"); - else { - _cairo_output_stream_printf (document->xml_node_defs, - "\n", - pattern->base.stops[0].color.red * 100.0, - pattern->base.stops[0].color.green * 100.0, - pattern->base.stops[0].color.blue * 100.0, - pattern->base.stops[0].color.alpha); - if (n_stops > 1) - _cairo_output_stream_printf (document->xml_node_defs, - "\n", - pattern->base.stops[n_stops - 1].color.red * 100.0, - pattern->base.stops[n_stops - 1].color.green * 100.0, - pattern->base.stops[n_stops - 1].color.blue * 100.0, - pattern->base.stops[n_stops - 1].color.alpha); - } - - } else { - double offset, r, x, y; - cairo_bool_t emulate_reflect = FALSE; - - fx = (r1 * x0 - r0 * x1) / (r1 - r0); - fy = (r1 * y0 - r0 * y1) / (r1 - r0); - - /* SVG doesn't support the inner circle and use instead a gradient focal. - * That means we need to emulate the cairo behaviour by processing the - * cairo gradient stops. - * The CAIRO_EXTENT_NONE and CAIRO_EXTENT_PAD modes are quite easy to handle, - * it's just a matter of stop position translation and calculation of - * the corresponding SVG radial gradient focal. - * The CAIRO_EXTENT_REFLECT and CAIRO_EXTEND_REPEAT modes require to compute a new - * radial gradient, with an new outer circle, equal to r1 - r0 in the CAIRO_EXTEND_REPEAT - * case, and 2 * (r1 - r0) in the CAIRO_EXTENT_REFLECT case, and a new gradient stop - * list that maps to the original cairo stop list. - */ - if ((extend == CAIRO_EXTEND_REFLECT - || extend == CAIRO_EXTEND_REPEAT) - && r0 > 0.0) { - double r_org = r1; - - if (extend == CAIRO_EXTEND_REFLECT) { - r1 = 2 * r1 - r0; - emulate_reflect = TRUE; - } - - offset = fmod (r1, r1 - r0) / (r1 - r0) - 1.0; - r = r1 - r0; - - /* New position of outer circle. */ - x = r * (x1 - fx) / r_org + fx; - y = r * (y1 - fy) / r_org + fy; - - x1 = x; - y1 = y; - r1 = r; - r0 = 0.0; - } else { - offset = r0 / r1; - } - - _cairo_output_stream_printf (document->xml_node_defs, - "radial_pattern_id, - x1, y1, - fx, fy, r1); - - if (emulate_reflect) - _cairo_output_stream_printf (document->xml_node_defs, "spreadMethod=\"repeat\" "); - else - _cairo_svg_surface_emit_pattern_extend (document->xml_node_defs, &pattern->base.base); - _cairo_svg_surface_emit_transform (document->xml_node_defs, "gradientTransform", &p2u, parent_matrix); - _cairo_output_stream_printf (document->xml_node_defs, ">\n"); - - /* To support cairo's EXTEND_NONE, (for which SVG has no similar - * notion), we add transparent color stops on either end of the - * user-provided stops. */ - if (extend == CAIRO_EXTEND_NONE) { - _cairo_output_stream_printf (document->xml_node_defs, - "\n"); - if (r0 != 0.0) - _cairo_output_stream_printf (document->xml_node_defs, - "\n", - r0 / r1); - } - status = _cairo_svg_surface_emit_pattern_stops (document->xml_node_defs, - &pattern->base, offset, - reverse_stops, - emulate_reflect); - if (status) - return status; - - if (pattern->base.base.extend == CAIRO_EXTEND_NONE) - _cairo_output_stream_printf (document->xml_node_defs, - "\n"); - } - - _cairo_output_stream_printf (document->xml_node_defs, - "\n"); - - _cairo_output_stream_printf (style, - "%s:url(#radial%d);", - is_stroke ? "stroke" : "fill", - document->radial_pattern_id); - - document->radial_pattern_id++; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_svg_surface_emit_pattern (cairo_svg_surface_t *surface, - cairo_pattern_t *pattern, - cairo_output_stream_t *output, - cairo_bool_t is_stroke, - const cairo_matrix_t *parent_matrix) -{ - switch (pattern->type) { - case CAIRO_PATTERN_TYPE_SOLID: - return _cairo_svg_surface_emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern, - output, is_stroke); - - case CAIRO_PATTERN_TYPE_SURFACE: - return _cairo_svg_surface_emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern, - output, is_stroke, parent_matrix); - - case CAIRO_PATTERN_TYPE_LINEAR: - return _cairo_svg_surface_emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern, - output, is_stroke, parent_matrix); - - case CAIRO_PATTERN_TYPE_RADIAL: - return _cairo_svg_surface_emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern, - output, is_stroke, parent_matrix); - } - return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH); -} - -static cairo_status_t -_cairo_svg_surface_emit_fill_style (cairo_output_stream_t *output, - cairo_svg_surface_t *surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_fill_rule_t fill_rule, - cairo_matrix_t *parent_matrix) -{ - _cairo_output_stream_printf (output, - "fill-rule:%s;", - fill_rule == CAIRO_FILL_RULE_EVEN_ODD ? - "evenodd" : "nonzero"); - _cairo_svg_surface_emit_operator_for_style (output, surface, op); - return _cairo_svg_surface_emit_pattern (surface, source, output, FALSE, parent_matrix); -} - -static cairo_status_t -_cairo_svg_surface_emit_stroke_style (cairo_output_stream_t *output, - cairo_svg_surface_t *surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_stroke_style_t *stroke_style, - cairo_matrix_t *parent_matrix) -{ - cairo_status_t status; - const char *line_cap, *line_join; - unsigned int i; - - switch (stroke_style->line_cap) { - case CAIRO_LINE_CAP_BUTT: - line_cap = "butt"; - break; - case CAIRO_LINE_CAP_ROUND: - line_cap = "round"; - break; - case CAIRO_LINE_CAP_SQUARE: - line_cap = "square"; - break; - default: - ASSERT_NOT_REACHED; - } - - switch (stroke_style->line_join) { - case CAIRO_LINE_JOIN_MITER: - line_join = "miter"; - break; - case CAIRO_LINE_JOIN_ROUND: - line_join = "round"; - break; - case CAIRO_LINE_JOIN_BEVEL: - line_join = "bevel"; - break; - default: - ASSERT_NOT_REACHED; - } - - _cairo_output_stream_printf (output, - "stroke-width:%f;" - "stroke-linecap:%s;" - "stroke-linejoin:%s;", - stroke_style->line_width, - line_cap, - line_join); - - status = _cairo_svg_surface_emit_pattern (surface, source, output, TRUE, parent_matrix); - if (status) - return status; - - _cairo_svg_surface_emit_operator_for_style (output, surface, op); - - if (stroke_style->num_dashes > 0) { - _cairo_output_stream_printf (output, "stroke-dasharray:"); - for (i = 0; i < stroke_style->num_dashes; i++) { - _cairo_output_stream_printf (output, "%f", - stroke_style->dash[i]); - if (i + 1 < stroke_style->num_dashes) - _cairo_output_stream_printf (output, ","); - else - _cairo_output_stream_printf (output, ";"); - } - if (stroke_style->dash_offset != 0.0) { - _cairo_output_stream_printf (output, - "stroke-dashoffset:%f;", - stroke_style->dash_offset); - } - } - - _cairo_output_stream_printf (output, - "stroke-miterlimit:%f;", - stroke_style->miter_limit); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_svg_surface_fill_stroke (void *abstract_surface, - cairo_operator_t fill_op, - cairo_pattern_t *fill_source, - cairo_fill_rule_t fill_rule, - double fill_tolerance, - cairo_antialias_t fill_antialias, - cairo_path_fixed_t *path, - cairo_operator_t stroke_op, - cairo_pattern_t *stroke_source, - cairo_stroke_style_t *stroke_style, - cairo_matrix_t *stroke_ctm, - cairo_matrix_t *stroke_ctm_inverse, - double stroke_tolerance, - cairo_antialias_t stroke_antialias) -{ - cairo_svg_surface_t *surface = abstract_surface; - cairo_status_t status; - - _cairo_output_stream_printf (surface->xml_node, "xml_node, surface, fill_op, - fill_source, fill_rule, stroke_ctm_inverse); - if (status) - return status; - - status = _cairo_svg_surface_emit_stroke_style (surface->xml_node, surface, stroke_op, - stroke_source, stroke_style, stroke_ctm_inverse); - if (status) - return status; - - _cairo_output_stream_printf (surface->xml_node, "\" "); - - status = _cairo_svg_surface_emit_path (surface->xml_node, path, stroke_ctm_inverse); - if (status) - return status; - - _cairo_svg_surface_emit_transform (surface->xml_node, " transform", stroke_ctm, NULL); - _cairo_output_stream_printf (surface->xml_node, "/>\n"); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_svg_surface_fill (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_svg_surface_t *surface = abstract_surface; - cairo_status_t status; - - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return _cairo_svg_surface_analyze_operation (surface, op, source); - - assert (_cairo_svg_surface_operation_supported (surface, op, source)); - - _cairo_output_stream_printf (surface->xml_node, "xml_node, surface, op, source, fill_rule, NULL); - if (status) - return status; - - _cairo_output_stream_printf (surface->xml_node, "\" "); - - status = _cairo_svg_surface_emit_path (surface->xml_node, path, NULL); - if (status) - return status; - - _cairo_output_stream_printf (surface->xml_node, "/>\n"); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_svg_surface_get_extents (void *abstract_surface, - cairo_rectangle_int_t *rectangle) -{ - cairo_svg_surface_t *surface = abstract_surface; - - rectangle->x = 0; - rectangle->y = 0; - - /* XXX: The conversion to integers here is pretty bogus, (not to - * mention the aribitray limitation of width to a short(!). We - * may need to come up with a better interface for get_size. - */ - rectangle->width = (int) ceil (surface->width); - rectangle->height = (int) ceil (surface->height); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_svg_surface_emit_paint (cairo_output_stream_t *output, - cairo_svg_surface_t *surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_pattern_t *mask_source, - const char *extra_attributes) -{ - cairo_status_t status; - - if (source->type == CAIRO_PATTERN_TYPE_SURFACE && - source->extend == CAIRO_EXTEND_NONE) - return _cairo_svg_surface_emit_composite_pattern (output, - surface, - op, - (cairo_surface_pattern_t *) source, - invalid_pattern_id, - mask_source ? &mask_source->matrix :NULL, - extra_attributes); - - _cairo_output_stream_printf (output, - "width, surface->height); - _cairo_svg_surface_emit_operator_for_style (output, surface, op); - status = _cairo_svg_surface_emit_pattern (surface, source, output, FALSE, NULL); - if (status) - return status; - - _cairo_output_stream_printf (output, "stroke:none;\""); - - if (extra_attributes) - _cairo_output_stream_printf (output, " %s", extra_attributes); - - _cairo_output_stream_printf (output, "/>\n"); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_svg_surface_paint (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source) -{ - cairo_status_t status; - cairo_svg_surface_t *surface = abstract_surface; - - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return _cairo_svg_surface_analyze_operation (surface, op, source); - - assert (_cairo_svg_surface_operation_supported (surface, op, source)); - - /* Emulation of clear and source operators, when no clipping region - * is defined. We just delete existing content of surface root node, - * and exit early if operator is clear. - * XXX: optimization of SOURCE operator doesn't work, since analyze - * above always return FALSE. In order to make it work, we need a way - * to know if there's an active clipping path. - * Optimization of CLEAR works because of a test in paginated surface, - * and an optimization in meta surface. */ - if (surface->clip_level == 0 && op == CAIRO_OPERATOR_CLEAR) { - status = _cairo_output_stream_destroy (surface->xml_node); - if (status) { - surface->xml_node = NULL; - return status; - } - - surface->xml_node = _cairo_memory_stream_create (); - if (_cairo_output_stream_get_status (surface->xml_node)) { - status = _cairo_output_stream_destroy (surface->xml_node); - surface->xml_node = NULL; - return status; - } - - if (op == CAIRO_OPERATOR_CLEAR) { - if (surface->content == CAIRO_CONTENT_COLOR) { - _cairo_output_stream_printf (surface->xml_node, - "\n", - surface->width, surface->height); - } - return CAIRO_STATUS_SUCCESS; - } - } - - return _cairo_svg_surface_emit_paint (surface->xml_node, - surface, op, source, 0, NULL); -} - -static cairo_int_status_t -_cairo_svg_surface_mask (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_pattern_t *mask) -{ - cairo_status_t status; - cairo_svg_surface_t *surface = abstract_surface; - cairo_svg_document_t *document = surface->document; - cairo_output_stream_t *mask_stream; - char buffer[64]; - cairo_bool_t discard_filter = FALSE; - unsigned int mask_id; - - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { - cairo_status_t source_status, mask_status; - - source_status = _cairo_svg_surface_analyze_operation (surface, op, source); - if (_cairo_status_is_error (source_status)) - return source_status; - - mask_status = _cairo_svg_surface_analyze_operation (surface, op, mask); - if (_cairo_status_is_error (mask_status)) - return mask_status; - - return _cairo_analysis_surface_merge_status (source_status, - mask_status); - } - - assert (_cairo_svg_surface_operation_supported (surface, op, source)); - assert (_cairo_svg_surface_operation_supported (surface, CAIRO_OPERATOR_OVER, mask)); - - if (cairo_pattern_get_type (mask) == CAIRO_PATTERN_TYPE_SURFACE) { - cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t*) mask; - cairo_content_t content = cairo_surface_get_content (surface_pattern->surface); - if (content == CAIRO_CONTENT_ALPHA) - discard_filter = TRUE; - } - - if (!discard_filter) - _cairo_svg_surface_emit_alpha_filter (document); - - /* _cairo_svg_surface_emit_paint() will output a pattern definition to - * document->xml_node_defs so we need to write the mask element to - * a temporary stream and then copy that to xml_node_defs. */ - mask_stream = _cairo_memory_stream_create (); - if (_cairo_output_stream_get_status (mask_stream)) - return _cairo_output_stream_destroy (mask_stream); - - mask_id = _cairo_svg_document_allocate_mask_id (document); - - _cairo_output_stream_printf (mask_stream, - "\n" - "%s", - mask_id, - discard_filter ? "" : " \n"); - status = _cairo_svg_surface_emit_paint (mask_stream, surface, CAIRO_OPERATOR_OVER, mask, source, NULL); - if (status) { - cairo_status_t ignore = _cairo_output_stream_destroy (mask_stream); - return status; - (void) ignore; - } - - _cairo_output_stream_printf (mask_stream, - "%s" - "\n", - discard_filter ? "" : " \n"); - _cairo_memory_stream_copy (mask_stream, document->xml_node_defs); - - status = _cairo_output_stream_destroy (mask_stream); - if (status) - return status; - - snprintf (buffer, sizeof buffer, "mask=\"url(#mask%d)\"", - mask_id); - status = _cairo_svg_surface_emit_paint (surface->xml_node, surface, op, source, 0, buffer); - if (status) - return status; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_svg_surface_stroke (void *abstract_dst, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_path_fixed_t *path, - cairo_stroke_style_t *stroke_style, - cairo_matrix_t *ctm, - cairo_matrix_t *ctm_inverse, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_svg_surface_t *surface = abstract_dst; - cairo_status_t status; - - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return _cairo_svg_surface_analyze_operation (surface, op, source); - - assert (_cairo_svg_surface_operation_supported (surface, op, source)); - - _cairo_output_stream_printf (surface->xml_node, "xml_node, surface, op, - source, stroke_style, ctm_inverse); - if (status) - return status; - - _cairo_output_stream_printf (surface->xml_node, "\" "); - - status = _cairo_svg_surface_emit_path (surface->xml_node, path, ctm_inverse); - if (status) - return status; - - _cairo_svg_surface_emit_transform (surface->xml_node, " transform", ctm, NULL); - _cairo_output_stream_printf (surface->xml_node, "/>\n"); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_svg_surface_show_glyphs (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *pattern, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font, - int *remaining_glyphs) -{ - cairo_svg_surface_t *surface = abstract_surface; - cairo_svg_document_t *document = surface->document; - cairo_path_fixed_t path; - cairo_status_t status; - cairo_scaled_font_subsets_glyph_t subset_glyph; - int i; - - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return _cairo_svg_surface_analyze_operation (surface, op, pattern); - - assert (_cairo_svg_surface_operation_supported (surface, op, pattern)); - - if (num_glyphs <= 0) - return CAIRO_STATUS_SUCCESS; - - /* FIXME it's probably possible to apply a pattern of a gradient to - * a group of symbols, but I don't know how yet. Gradients or patterns - * are translated by x and y properties of use element. */ - if (pattern->type != CAIRO_PATTERN_TYPE_SOLID) - goto FALLBACK; - - _cairo_output_stream_printf (surface->xml_node, "xml_node, FALSE, NULL); - if (status) - return status; - - _cairo_svg_surface_emit_operator_for_style (surface->xml_node, surface, op); - - _cairo_output_stream_printf (surface->xml_node, "\">\n"); - - for (i = 0; i < num_glyphs; i++) { - status = _cairo_scaled_font_subsets_map_glyph (document->font_subsets, - scaled_font, glyphs[i].index, - NULL, 0, - &subset_glyph); - if (status == CAIRO_INT_STATUS_UNSUPPORTED) { - _cairo_output_stream_printf (surface->xml_node, "\n"); - - glyphs += i; - num_glyphs -= i; - goto FALLBACK; - } - - if (status) - return status; - - _cairo_output_stream_printf (surface->xml_node, - " \n", - subset_glyph.font_id, - subset_glyph.subset_glyph_index, - glyphs[i].x, glyphs[i].y); - } - - _cairo_output_stream_printf (surface->xml_node, "\n"); - - return CAIRO_STATUS_SUCCESS; - -FALLBACK: - _cairo_path_fixed_init (&path); - - status = _cairo_scaled_font_glyph_path (scaled_font,(cairo_glyph_t *) glyphs, num_glyphs, &path); - - if (status) { - _cairo_path_fixed_fini (&path); - return status; - } - - status = _cairo_svg_surface_fill (abstract_surface, op, pattern, - &path, CAIRO_FILL_RULE_WINDING, 0.0, CAIRO_ANTIALIAS_SUBPIXEL); - - _cairo_path_fixed_fini (&path); - - return status; -} - -static cairo_int_status_t -_cairo_svg_surface_intersect_clip_path (void *dst, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_svg_surface_t *surface = dst; - cairo_svg_document_t *document = surface->document; - cairo_status_t status; - unsigned int i; - - if (path == NULL) { - for (i = 0; i < surface->clip_level; i++) - _cairo_output_stream_printf (surface->xml_node, "\n"); - - surface->clip_level = 0; - return CAIRO_STATUS_SUCCESS; - } - - _cairo_output_stream_printf (document->xml_node_defs, - "\n" - " clip_id); - status = _cairo_svg_surface_emit_path (document->xml_node_defs, path, NULL); - if (status) - return status; - - _cairo_output_stream_printf (document->xml_node_defs, - "/>\n" - "\n"); - - _cairo_output_stream_printf (surface->xml_node, - "\n", - document->clip_id, - fill_rule == CAIRO_FILL_RULE_EVEN_ODD ? - "evenodd" : "nonzero"); - - document->clip_id++; - surface->clip_level++; - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_svg_surface_get_font_options (void *abstract_surface, - cairo_font_options_t *options) -{ - _cairo_font_options_init_default (options); - - cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_NONE); - cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF); - cairo_font_options_set_antialias (options, CAIRO_ANTIALIAS_GRAY); -} - -static const cairo_surface_backend_t cairo_svg_surface_backend = { - CAIRO_SURFACE_TYPE_SVG, - _cairo_svg_surface_create_similar, - _cairo_svg_surface_finish, - NULL, /* acquire_source_image */ - NULL, /* release_source_image */ - NULL, /* acquire_dest_image */ - NULL, /* release_dest_image */ - NULL, /* clone_similar */ - NULL, /* _cairo_svg_surface_composite, */ - NULL, /* _cairo_svg_surface_fill_rectangles, */ - NULL, /* _cairo_svg_surface_composite_trapezoids,*/ - _cairo_svg_surface_copy_page, - _cairo_svg_surface_show_page, - NULL, /* set_clip_region */ - _cairo_svg_surface_intersect_clip_path, - _cairo_svg_surface_get_extents, - NULL, /* _cairo_svg_surface_old_show_glyphs, */ - _cairo_svg_surface_get_font_options, - NULL, /* flush */ - NULL, /* mark dirty rectangle */ - NULL, /* scaled font fini */ - NULL, /* scaled glyph fini */ - _cairo_svg_surface_paint, - _cairo_svg_surface_mask, - _cairo_svg_surface_stroke, - _cairo_svg_surface_fill, - _cairo_svg_surface_show_glyphs, - NULL, /* snapshot */ - NULL, /* is_similar */ - NULL, /* reset */ - _cairo_svg_surface_fill_stroke -}; - -static cairo_status_t -_cairo_svg_document_create (cairo_output_stream_t *output_stream, - double width, - double height, - cairo_svg_version_t version, - cairo_svg_document_t **document_out) -{ - cairo_svg_document_t *document; - cairo_status_t status, status_ignored; - - if (output_stream->status) - return output_stream->status; - - document = malloc (sizeof (cairo_svg_document_t)); - if (document == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - /* The use of defs for font glyphs imposes no per-subset limit. */ - document->font_subsets = _cairo_scaled_font_subsets_create_scaled (); - if (document->font_subsets == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto CLEANUP_DOCUMENT; - } - - document->output_stream = output_stream; - document->refcount = 1; - document->owner = NULL; - document->finished = FALSE; - document->width = width; - document->height = height; - - document->surface_id = 0; - document->linear_pattern_id = 0; - document->radial_pattern_id = 0; - document->pattern_id = 0; - document->filter_id = 0; - document->clip_id = 0; - document->mask_id = 0; - - document->xml_node_defs = _cairo_memory_stream_create (); - status = _cairo_output_stream_get_status (document->xml_node_defs); - if (status) - goto CLEANUP_NODE_DEFS; - - document->xml_node_glyphs = _cairo_memory_stream_create (); - status = _cairo_output_stream_get_status (document->xml_node_glyphs); - if (status) - goto CLEANUP_NODE_GLYPHS; - - document->alpha_filter = FALSE; - - _cairo_array_init (&document->meta_snapshots, - sizeof (cairo_meta_snapshot_t)); - - document->svg_version = version; - - *document_out = document; - return CAIRO_STATUS_SUCCESS; - - CLEANUP_NODE_GLYPHS: - status_ignored = _cairo_output_stream_destroy (document->xml_node_glyphs); - CLEANUP_NODE_DEFS: - status_ignored = _cairo_output_stream_destroy (document->xml_node_defs); - _cairo_scaled_font_subsets_destroy (document->font_subsets); - CLEANUP_DOCUMENT: - free (document); - return status; -} - -static cairo_svg_document_t * -_cairo_svg_document_reference (cairo_svg_document_t *document) -{ - document->refcount++; - - return document; -} - -static unsigned int -_cairo_svg_document_allocate_mask_id (cairo_svg_document_t *document) -{ - return document->mask_id++; -} - -static cairo_status_t -_cairo_svg_document_destroy (cairo_svg_document_t *document) -{ - cairo_status_t status; - - document->refcount--; - if (document->refcount > 0) - return CAIRO_STATUS_SUCCESS; - - status = _cairo_svg_document_finish (document); - - free (document); - - return status; -} - -static cairo_status_t -_cairo_svg_document_finish (cairo_svg_document_t *document) -{ - cairo_status_t status, status2; - cairo_output_stream_t *output = document->output_stream; - cairo_meta_snapshot_t *snapshot; - cairo_svg_page_t *page; - unsigned int i; - - if (document->finished) - return CAIRO_STATUS_SUCCESS; - - /* - * Should we add DOCTYPE? - * - * Google says no. - * - * http://tech.groups.yahoo.com/group/svg-developers/message/48562: - * There's a bunch of issues, but just to pick a few: - * - they'll give false positives. - * - they'll give false negatives. - * - they're namespace-unaware. - * - they don't wildcard. - * So when they say OK they really haven't checked anything, when - * they say NOT OK they might be on crack, and like all - * namespace-unaware things they're a dead branch of the XML tree. - * - * http://jwatt.org/svg/authoring/: - * Unfortunately the SVG DTDs are a source of so many issues that the - * SVG WG has decided not to write one for the upcoming SVG 1.2 - * standard. In fact SVG WG members are even telling people not to use - * a DOCTYPE declaration in SVG 1.0 and 1.1 documents. - */ - - _cairo_output_stream_printf (output, - "\n" - "\n", - document->width, document->height, - document->width, document->height, - _cairo_svg_internal_version_strings [document->svg_version]); - - status = _cairo_svg_document_emit_font_subsets (document); - - if (_cairo_memory_stream_length (document->xml_node_glyphs) > 0 || - _cairo_memory_stream_length (document->xml_node_defs) > 0) { - _cairo_output_stream_printf (output, "\n"); - if (_cairo_memory_stream_length (document->xml_node_glyphs) > 0) { - _cairo_output_stream_printf (output, "\n"); - _cairo_memory_stream_copy (document->xml_node_glyphs, output); - _cairo_output_stream_printf (output, "\n"); - } - _cairo_memory_stream_copy (document->xml_node_defs, output); - _cairo_output_stream_printf (output, "\n"); - } - - if (document->owner != NULL) { - cairo_svg_surface_t *surface; - - surface = (cairo_svg_surface_t *) _cairo_paginated_surface_get_target (document->owner); - if (surface->xml_node != NULL && - _cairo_memory_stream_length (surface->xml_node) > 0) { - if (_cairo_svg_surface_store_page (surface) == NULL) { - if (status == CAIRO_STATUS_SUCCESS) - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - } - - if (surface->page_set.num_elements > 1 && - _cairo_svg_version_has_page_set_support (document->svg_version)) { - _cairo_output_stream_printf (output, "\n"); - for (i = 0; i < surface->page_set.num_elements; i++) { - page = _cairo_array_index (&surface->page_set, i); - _cairo_output_stream_printf (output, "\n"); - _cairo_output_stream_printf (output, - "\n", - page->surface_id); - _cairo_memory_stream_copy (page->xml_node, output); - _cairo_output_stream_printf (output, "\n\n"); - } - _cairo_output_stream_printf (output, "\n"); - } else if (surface->page_set.num_elements > 0) { - page = _cairo_array_index (&surface->page_set, surface->page_set.num_elements - 1); - _cairo_output_stream_printf (output, - "\n", - page->surface_id); - _cairo_memory_stream_copy (page->xml_node, output); - _cairo_output_stream_printf (output, "\n"); - } - } - - _cairo_output_stream_printf (output, "\n"); - - status2 = _cairo_output_stream_destroy (document->xml_node_glyphs); - if (status == CAIRO_STATUS_SUCCESS) - status = status2; - - status2 = _cairo_output_stream_destroy (document->xml_node_defs); - if (status == CAIRO_STATUS_SUCCESS) - status = status2; - - status2 = _cairo_output_stream_destroy (output); - if (status == CAIRO_STATUS_SUCCESS) - status = status2; - - for (i = 0; i < document->meta_snapshots.num_elements; i++) { - snapshot = _cairo_array_index (&document->meta_snapshots, i); - status2 = cairo_surface_status (&snapshot->meta->base); - cairo_surface_destroy (&snapshot->meta->base); - if (status == CAIRO_STATUS_SUCCESS) - status = status2; - } - _cairo_array_fini (&document->meta_snapshots); - - document->finished = TRUE; - - return status; -} - -static void -_cairo_svg_surface_set_paginated_mode (void *abstract_surface, - cairo_paginated_mode_t paginated_mode) -{ - cairo_svg_surface_t *surface = abstract_surface; - - surface->paginated_mode = paginated_mode; -} - -static cairo_bool_t -_cairo_svg_surface_supports_fine_grained_fallbacks (void *abstract_surface) -{ - cairo_svg_surface_t *surface = abstract_surface; - cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED; - - if (surface->document->svg_version >= CAIRO_SVG_VERSION_1_2) { - status = _cairo_svg_surface_analyze_operator (surface, - CAIRO_OPERATOR_SOURCE); - } - - return status == CAIRO_STATUS_SUCCESS; -} - -static const cairo_paginated_surface_backend_t cairo_svg_surface_paginated_backend = { - NULL /*_cairo_svg_surface_start_page*/, - _cairo_svg_surface_set_paginated_mode, - NULL, /* _cairo_svg_surface_set_bounding_box */ - NULL, /* _cairo_svg_surface_set_fallback_images_required */ - _cairo_svg_surface_supports_fine_grained_fallbacks, - -}; diff --git a/uppdev/plugin/cairo/lib/cairo-svg.h b/uppdev/plugin/cairo/lib/cairo-svg.h deleted file mode 100644 index 785133813..000000000 --- a/uppdev/plugin/cairo/lib/cairo-svg.h +++ /dev/null @@ -1,82 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * cairo-svg.h - * - * Copyright © 2005 Emmanuel Pacaud - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - */ - -#ifndef CAIRO_SVG_H -#define CAIRO_SVG_H - -#include "cairo.h" - -#if CAIRO_HAS_SVG_SURFACE - -CAIRO_BEGIN_DECLS - -/** - * cairo_svg_version_t: - * @CAIRO_SVG_VERSION_1_1: The version 1.1 of the SVG specification. - * @CAIRO_SVG_VERSION_1_2: The version 1.2 of the SVG specification. - * - * #cairo_svg_version_t is used to describe the version number of the SVG - * specification that a generated SVG file will conform to. - */ -typedef enum _cairo_svg_version { - CAIRO_SVG_VERSION_1_1, - CAIRO_SVG_VERSION_1_2 -} cairo_svg_version_t; - -cairo_public cairo_surface_t * -cairo_svg_surface_create (const char *filename, - double width_in_points, - double height_in_points); - -cairo_public cairo_surface_t * -cairo_svg_surface_create_for_stream (cairo_write_func_t write_func, - void *closure, - double width_in_points, - double height_in_points); - -cairo_public void -cairo_svg_surface_restrict_to_version (cairo_surface_t *surface, - cairo_svg_version_t version); - -cairo_public void -cairo_svg_get_versions (cairo_svg_version_t const **versions, - int *num_versions); - -cairo_public const char * -cairo_svg_version_to_string (cairo_svg_version_t version); - -CAIRO_END_DECLS - -#else /* CAIRO_HAS_SVG_SURFACE */ -# error Cairo was not compiled with support for the svg backend -#endif /* CAIRO_HAS_SVG_SURFACE */ - -#endif /* CAIRO_SVG_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-system.c b/uppdev/plugin/cairo/lib/cairo-system.c deleted file mode 100644 index 85c74876e..000000000 --- a/uppdev/plugin/cairo/lib/cairo-system.c +++ /dev/null @@ -1,97 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* Cairo - a vector graphics library with display and print output - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Owen Taylor - * Stuart Parmenter - * Vladimir Vukicevic - */ - -/* This file should include code that is system-specific, not - * feature-specific. For example, the DLL initialization/finalization - * code on Win32 or OS/2 must live here (not in cairo-whatever-surface.c). - * Same about possible ELF-specific code. - * - * And no other function should live here. - */ - - -#include "cairoint.h" - - - -#if CAIRO_MUTEX_IMPL_WIN32 -#if !CAIRO_WIN32_STATIC_BUILD - -#define WIN32_LEAN_AND_MEAN -/* We require Windows 2000 features such as ETO_PDY */ -#if !defined(WINVER) || (WINVER < 0x0500) -# define WINVER 0x0500 -#endif -#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500) -# define _WIN32_WINNT 0x0500 -#endif - -#include "cairo-clip-private.h" -#include "cairo-paginated-private.h" -#include "cairo-win32-private.h" -#include "cairo-scaled-font-subsets-private.h" - -#include - -/* declare to avoid "no previous prototype for 'DllMain'" warning */ -BOOL WINAPI -DllMain (HINSTANCE hinstDLL, - DWORD fdwReason, - LPVOID lpvReserved); - -BOOL WINAPI -DllMain (HINSTANCE hinstDLL, - DWORD fdwReason, - LPVOID lpvReserved) -{ - switch (fdwReason) { - case DLL_PROCESS_ATTACH: - CAIRO_MUTEX_INITIALIZE (); - break; - - case DLL_PROCESS_DETACH: - CAIRO_MUTEX_FINALIZE (); - break; - } - - return TRUE; -} - -#endif -#endif - diff --git a/uppdev/plugin/cairo/lib/cairo-traps.c b/uppdev/plugin/cairo/lib/cairo-traps.c deleted file mode 100644 index b76e9089c..000000000 --- a/uppdev/plugin/cairo/lib/cairo-traps.c +++ /dev/null @@ -1,713 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* - * Copyright © 2002 Keith Packard - * Copyright © 2007 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Keith Packard - * - * Contributor(s): - * Keith R. Packard - * Carl D. Worth - * - * 2002-07-15: Converted from XRenderCompositeDoublePoly to #cairo_trap_t. Carl D. Worth - */ - -#include "cairoint.h" - -/* private functions */ - -static int -_compare_point_fixed_by_y (const void *av, const void *bv); - -void -_cairo_traps_init (cairo_traps_t *traps) -{ - traps->status = CAIRO_STATUS_SUCCESS; - - traps->num_traps = 0; - - traps->traps_size = ARRAY_LENGTH (traps->traps_embedded); - traps->traps = traps->traps_embedded; - traps->extents.p1.x = traps->extents.p1.y = INT32_MAX; - traps->extents.p2.x = traps->extents.p2.y = INT32_MIN; - - traps->has_limits = FALSE; -} - -void -_cairo_traps_limit (cairo_traps_t *traps, - cairo_box_t *limits) -{ - traps->has_limits = TRUE; - - traps->limits = *limits; -} - -cairo_bool_t -_cairo_traps_get_limit (cairo_traps_t *traps, - cairo_box_t *limits) -{ - *limits = traps->limits; - return traps->has_limits; -} - -void -_cairo_traps_clear (cairo_traps_t *traps) -{ - traps->status = CAIRO_STATUS_SUCCESS; - - traps->num_traps = 0; - traps->extents.p1.x = traps->extents.p1.y = INT32_MAX; - traps->extents.p2.x = traps->extents.p2.y = INT32_MIN; -} - -void -_cairo_traps_fini (cairo_traps_t *traps) -{ - if (traps->traps != traps->traps_embedded) - free (traps->traps); -} - -/** - * _cairo_traps_init_box: - * @traps: a #cairo_traps_t - * @box: a box that will be converted to a single trapezoid - * to store in @traps. - * - * Initializes a #cairo_traps_t to contain a single rectangular - * trapezoid. - **/ -void -_cairo_traps_init_box (cairo_traps_t *traps, - const cairo_box_t *box) -{ - _cairo_traps_init (traps); - - assert (traps->traps_size >= 1); - - traps->num_traps = 1; - - traps->traps[0].top = box->p1.y; - traps->traps[0].bottom = box->p2.y; - traps->traps[0].left.p1 = box->p1; - traps->traps[0].left.p2.x = box->p1.x; - traps->traps[0].left.p2.y = box->p2.y; - traps->traps[0].right.p1.x = box->p2.x; - traps->traps[0].right.p1.y = box->p1.y; - traps->traps[0].right.p2 = box->p2; - - traps->extents = *box; -} - -/* make room for at least one more trap */ -static cairo_bool_t -_cairo_traps_grow (cairo_traps_t *traps) -{ - cairo_trapezoid_t *new_traps; - int new_size = 2 * MAX (traps->traps_size, 16); - - if (traps->traps == traps->traps_embedded) { - new_traps = _cairo_malloc_ab (new_size, sizeof (cairo_trapezoid_t)); - if (new_traps != NULL) - memcpy (new_traps, traps->traps, sizeof (traps->traps_embedded)); - } else { - new_traps = _cairo_realloc_ab (traps->traps, - new_size, sizeof (cairo_trapezoid_t)); - } - - if (new_traps == NULL) { - traps->status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - return FALSE; - } - - traps->traps = new_traps; - traps->traps_size = new_size; - return TRUE; -} - -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) -{ - cairo_trapezoid_t *trap; - - /* Note: With the goofy trapezoid specification, (where an - * arbitrary two points on the lines can specified for the left - * and right edges), these limit checks would not work in - * general. For example, one can imagine a trapezoid entirely - * within the limits, but with two points used to specify the left - * edge entirely to the right of the limits. Fortunately, for our - * purposes, cairo will never generate such a crazy - * trapezoid. Instead, cairo always uses for its points the - * extreme positions of the edge that are visible on at least some - * trapezoid. With this constraint, it's impossible for both - * points to be outside the limits while the relevant edge is - * entirely inside the limits. - */ - if (traps->has_limits) { - /* Trivially reject if trapezoid is entirely to the right or - * to the left of the limits. */ - if (left->p1.x >= traps->limits.p2.x && - left->p2.x >= traps->limits.p2.x) - { - return; - } - - if (right->p1.x <= traps->limits.p1.x && - right->p2.x <= traps->limits.p1.x) - { - return; - } - - /* And reject if the trapezoid is entirely above or below */ - if (top > traps->limits.p2.y || bottom < traps->limits.p1.y) - return; - - /* Otherwise, clip the trapezoid to the limits. We only clip - * where an edge is entirely outside the limits. If we wanted - * to be more clever, we could handle cases where a trapezoid - * edge intersects the edge of the limits, but that would - * require slicing this trapezoid into multiple trapezoids, - * and I'm not sure the effort would be worth it. */ - if (top < traps->limits.p1.y) - top = traps->limits.p1.y; - - if (bottom > traps->limits.p2.y) - bottom = traps->limits.p2.y; - - if (left->p1.x <= traps->limits.p1.x && - left->p2.x <= traps->limits.p1.x) - { - left->p1.x = traps->limits.p1.x; - left->p2.x = traps->limits.p1.x; - } - - if (right->p1.x >= traps->limits.p2.x && - right->p2.x >= traps->limits.p2.x) - { - right->p1.x = traps->limits.p2.x; - right->p2.x = traps->limits.p2.x; - } - } - - /* Trivial discards for empty trapezoids that are likely to be produced - * by our tessellators (most notably convex_quad when given a simple - * rectangle). - */ - if (top >= bottom) - return; - /* cheap colinearity check */ - if (right->p1.x <= left->p1.x && right->p1.y == left->p1.y && - right->p2.x <= left->p2.x && right->p2.y == left->p2.y) - return; - - if (traps->num_traps == traps->traps_size) { - if (! _cairo_traps_grow (traps)) - return; - } - - trap = &traps->traps[traps->num_traps]; - trap->top = top; - trap->bottom = bottom; - trap->left = *left; - trap->right = *right; - - if (top < traps->extents.p1.y) - traps->extents.p1.y = top; - if (bottom > traps->extents.p2.y) - traps->extents.p2.y = bottom; - /* - * This isn't generally accurate, but it is close enough for - * this purpose. Assuming that the left and right segments always - * contain the trapezoid vertical extents, these compares will - * yield a containing box. Assuming that the points all come from - * the same figure which will eventually be completely drawn, then - * the compares will yield the correct overall extents - */ - if (left->p1.x < traps->extents.p1.x) - traps->extents.p1.x = left->p1.x; - if (left->p2.x < traps->extents.p1.x) - traps->extents.p1.x = left->p2.x; - - if (right->p1.x > traps->extents.p2.x) - traps->extents.p2.x = right->p1.x; - if (right->p2.x > traps->extents.p2.x) - traps->extents.p2.x = right->p2.x; - - traps->num_traps++; -} - -static int -_compare_point_fixed_by_y (const void *av, const void *bv) -{ - const cairo_point_t *a = av, *b = bv; - - int ret = a->y - b->y; - if (ret == 0) { - ret = a->x - b->x; - } - return ret; -} - -void -_cairo_traps_translate (cairo_traps_t *traps, int x, int y) -{ - cairo_fixed_t xoff, yoff; - cairo_trapezoid_t *t; - int i; - - /* Ugh. The cairo_composite/(Render) interface doesn't allow - an offset for the trapezoids. Need to manually shift all - the coordinates to align with the offset origin of the - intermediate surface. */ - - xoff = _cairo_fixed_from_int (x); - yoff = _cairo_fixed_from_int (y); - - for (i = 0, t = traps->traps; i < traps->num_traps; i++, t++) { - t->top += yoff; - t->bottom += yoff; - t->left.p1.x += xoff; - t->left.p1.y += yoff; - t->left.p2.x += xoff; - t->left.p2.y += yoff; - t->right.p1.x += xoff; - t->right.p1.y += yoff; - t->right.p2.x += xoff; - t->right.p2.y += yoff; - } -} - -void -_cairo_trapezoid_array_translate_and_scale (cairo_trapezoid_t *offset_traps, - cairo_trapezoid_t *src_traps, - int num_traps, - double tx, double ty, - double sx, double sy) -{ - int i; - cairo_fixed_t xoff = _cairo_fixed_from_double (tx); - cairo_fixed_t yoff = _cairo_fixed_from_double (ty); - - if (sx == 1.0 && sy == 1.0) { - for (i = 0; i < num_traps; i++) { - offset_traps[i].top = src_traps[i].top + yoff; - offset_traps[i].bottom = src_traps[i].bottom + yoff; - offset_traps[i].left.p1.x = src_traps[i].left.p1.x + xoff; - offset_traps[i].left.p1.y = src_traps[i].left.p1.y + yoff; - offset_traps[i].left.p2.x = src_traps[i].left.p2.x + xoff; - offset_traps[i].left.p2.y = src_traps[i].left.p2.y + yoff; - offset_traps[i].right.p1.x = src_traps[i].right.p1.x + xoff; - offset_traps[i].right.p1.y = src_traps[i].right.p1.y + yoff; - offset_traps[i].right.p2.x = src_traps[i].right.p2.x + xoff; - offset_traps[i].right.p2.y = src_traps[i].right.p2.y + yoff; - } - } else { - cairo_fixed_t xsc = _cairo_fixed_from_double (sx); - cairo_fixed_t ysc = _cairo_fixed_from_double (sy); - - for (i = 0; i < num_traps; i++) { - offset_traps[i].top = _cairo_fixed_mul (src_traps[i].top + yoff, ysc); - offset_traps[i].bottom = _cairo_fixed_mul (src_traps[i].bottom + yoff, ysc); - offset_traps[i].left.p1.x = _cairo_fixed_mul (src_traps[i].left.p1.x + xoff, xsc); - offset_traps[i].left.p1.y = _cairo_fixed_mul (src_traps[i].left.p1.y + yoff, ysc); - offset_traps[i].left.p2.x = _cairo_fixed_mul (src_traps[i].left.p2.x + xoff, xsc); - offset_traps[i].left.p2.y = _cairo_fixed_mul (src_traps[i].left.p2.y + yoff, ysc); - offset_traps[i].right.p1.x = _cairo_fixed_mul (src_traps[i].right.p1.x + xoff, xsc); - offset_traps[i].right.p1.y = _cairo_fixed_mul (src_traps[i].right.p1.y + yoff, ysc); - offset_traps[i].right.p2.x = _cairo_fixed_mul (src_traps[i].right.p2.x + xoff, xsc); - offset_traps[i].right.p2.y = _cairo_fixed_mul (src_traps[i].right.p2.y + yoff, ysc); - } - } -} - -/* 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. */ -cairo_status_t -_cairo_traps_tessellate_triangle (cairo_traps_t *traps, - const cairo_point_t t[3]) -{ - cairo_point_t quad[4]; - - quad[0] = t[0]; - quad[1] = t[0]; - quad[2] = t[1]; - quad[3] = t[2]; - - return _cairo_traps_tessellate_convex_quad (traps, quad); -} - -cairo_status_t -_cairo_traps_tessellate_rectangle (cairo_traps_t *traps, - const cairo_point_t *top_left, - const cairo_point_t *bottom_right) -{ - cairo_line_t left; - cairo_line_t right; - - left.p1.x = left.p2.x = top_left->x; - left.p1.y = right.p1.y = top_left->y; - right.p1.x = right.p2.x = bottom_right->x; - left.p2.y = right.p2.y = bottom_right->y; - - _cairo_traps_add_trap (traps, top_left->y, bottom_right->y, &left, &right); - - return traps->status; -} - -cairo_status_t -_cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, - const cairo_point_t q[4]) -{ - int a, b, c, d; - int i; - cairo_slope_t ab, ad; - cairo_bool_t b_left_of_d; - cairo_line_t left; - cairo_line_t right; - - /* Choose a as a point with minimal y */ - a = 0; - for (i = 1; i < 4; i++) - if (_compare_point_fixed_by_y (&q[i], &q[a]) < 0) - a = i; - - /* b and d are adjacent to a, while c is opposite */ - b = (a + 1) % 4; - c = (a + 2) % 4; - d = (a + 3) % 4; - - /* Choose between b and d so that b.y is less than d.y */ - if (_compare_point_fixed_by_y (&q[d], &q[b]) < 0) { - b = (a + 3) % 4; - d = (a + 1) % 4; - } - - /* Without freedom left to choose anything else, we have four - * cases to tessellate. - * - * First, we have to determine the Y-axis sort of the four - * vertices, (either abcd or abdc). After that we need to detemine - * which edges will be "left" and which will be "right" in the - * resulting trapezoids. This can be determined by computing a - * slope comparison of ab and ad to determine if b is left of d or - * not. - * - * Note that "left of" here is in the sense of which edges should - * be the left vs. right edges of the trapezoid. In particular, b - * left of d does *not* mean that b.x is less than d.x. - * - * This should hopefully be made clear in the lame ASCII art - * below. Since the same slope comparison is used in all cases, we - * compute it before testing for the Y-value sort. */ - - /* Note: If a == b then the ab slope doesn't give us any - * information. In that case, we can replace it with the ac (or - * equivalenly the bc) slope which gives us exactly the same - * information we need. At worst the names of the identifiers ab - * and b_left_of_d are inaccurate in this case, (would be ac, and - * c_left_of_d). */ - if (q[a].x == q[b].x && q[a].y == q[b].y) - _cairo_slope_init (&ab, &q[a], &q[c]); - else - _cairo_slope_init (&ab, &q[a], &q[b]); - - _cairo_slope_init (&ad, &q[a], &q[d]); - - b_left_of_d = (_cairo_slope_compare (&ab, &ad) > 0); - - if (q[c].y <= q[d].y) { - if (b_left_of_d) { - /* Y-sort is abcd and b is left of d, (slope(ab) > slope (ad)) - * - * top bot left right - * _a a a - * / / /| |\ a.y b.y ab ad - * b / b | b \ - * / / | | \ \ b.y c.y bc ad - * c / c | c \ - * | / \| \ \ c.y d.y cd ad - * d d d - */ - left.p1 = q[a]; left.p2 = q[b]; - right.p1 = q[a]; right.p2 = q[d]; - _cairo_traps_add_trap (traps, q[a].y, q[b].y, &left, &right); - left.p1 = q[b]; left.p2 = q[c]; - _cairo_traps_add_trap (traps, q[b].y, q[c].y, &left, &right); - left.p1 = q[c]; left.p2 = q[d]; - _cairo_traps_add_trap (traps, q[c].y, q[d].y, &left, &right); - } else { - /* Y-sort is abcd and b is right of d, (slope(ab) <= slope (ad)) - * - * a a a_ - * /| |\ \ \ a.y b.y ad ab - * / b | b \ b - * / / | | \ \ b.y c.y ad bc - * / c | c \ c - * / / |/ \ | c.y d.y ad cd - * d d d - */ - left.p1 = q[a]; left.p2 = q[d]; - right.p1 = q[a]; right.p2 = q[b]; - _cairo_traps_add_trap (traps, q[a].y, q[b].y, &left, &right); - right.p1 = q[b]; right.p2 = q[c]; - _cairo_traps_add_trap (traps, q[b].y, q[c].y, &left, &right); - right.p1 = q[c]; right.p2 = q[d]; - _cairo_traps_add_trap (traps, q[c].y, q[d].y, &left, &right); - } - } else { - if (b_left_of_d) { - /* Y-sort is abdc and b is left of d, (slope (ab) > slope (ad)) - * - * a a a - * // / \ |\ a.y b.y ab ad - * /b/ b \ b \ - * / / \ \ \ \ b.y d.y bc ad - * /d/ \ d \ d - * // \ / \| d.y c.y bc dc - * c c c - */ - left.p1 = q[a]; left.p2 = q[b]; - right.p1 = q[a]; right.p2 = q[d]; - _cairo_traps_add_trap (traps, q[a].y, q[b].y, &left, &right); - left.p1 = q[b]; left.p2 = q[c]; - _cairo_traps_add_trap (traps, q[b].y, q[d].y, &left, &right); - right.p1 = q[d]; right.p2 = q[c]; - _cairo_traps_add_trap (traps, q[d].y, q[c].y, &left, &right); - } else { - /* Y-sort is abdc and b is right of d, (slope (ab) <= slope (ad)) - * - * a a a - * /| / \ \\ a.y b.y ad ab - * / b / b \b\ - * / / / / \ \ b.y d.y ad bc - * d / d / \d\ - * |/ \ / \\ d.y c.y dc bc - * c c c - */ - left.p1 = q[a]; left.p2 = q[d]; - right.p1 = q[a]; right.p2 = q[b]; - _cairo_traps_add_trap (traps, q[a].y, q[b].y, &left, &right); - right.p1 = q[b]; right.p2 = q[c]; - _cairo_traps_add_trap (traps, q[b].y, q[d].y, &left, &right); - left.p1 = q[d]; left.p2 = q[c]; - _cairo_traps_add_trap (traps, q[d].y, q[c].y, &left, &right); - } - } - - return traps->status; -} - -static cairo_bool_t -_cairo_trap_contains (cairo_trapezoid_t *t, cairo_point_t *pt) -{ - cairo_slope_t slope_left, slope_pt, slope_right; - - if (t->top > pt->y) - return FALSE; - if (t->bottom < pt->y) - return FALSE; - - _cairo_slope_init (&slope_left, &t->left.p1, &t->left.p2); - _cairo_slope_init (&slope_pt, &t->left.p1, pt); - - if (_cairo_slope_compare (&slope_left, &slope_pt) < 0) - return FALSE; - - _cairo_slope_init (&slope_right, &t->right.p1, &t->right.p2); - _cairo_slope_init (&slope_pt, &t->right.p1, pt); - - if (_cairo_slope_compare (&slope_pt, &slope_right) < 0) - return FALSE; - - return TRUE; -} - -cairo_bool_t -_cairo_traps_contain (const cairo_traps_t *traps, - double x, double y) -{ - int i; - cairo_point_t point; - - point.x = _cairo_fixed_from_double (x); - point.y = _cairo_fixed_from_double (y); - - for (i = 0; i < traps->num_traps; i++) { - if (_cairo_trap_contains (&traps->traps[i], &point)) - return TRUE; - } - - return FALSE; -} - -void -_cairo_traps_extents (const cairo_traps_t *traps, - cairo_box_t *extents) -{ - if (traps->num_traps == 0) { - extents->p1.x = extents->p1.y = _cairo_fixed_from_int (0); - extents->p2.x = extents->p2.y = _cairo_fixed_from_int (0); - } else { - *extents = traps->extents; - if (traps->has_limits) { - /* clip the traps to the imposed limits */ - if (extents->p1.x < traps->limits.p1.x) - extents->p1.x = traps->limits.p1.x; - if (extents->p2.x > traps->limits.p2.x) - extents->p2.x = traps->limits.p2.x; - - if (extents->p1.y < traps->limits.p1.y) - extents->p1.y = traps->limits.p1.y; - if (extents->p2.y > traps->limits.p2.y) - extents->p2.y = traps->limits.p2.y; - } - } -} - -/** - * _cairo_traps_extract_region: - * @traps: a #cairo_traps_t - * @region: a #cairo_region_t - * - * Determines if a set of trapezoids are exactly representable as a - * cairo region. If so, the passed-in region is initialized to - * the area representing the given traps. It should be finalized - * with _cairo_region_fini(). If not, %CAIRO_INT_STATUS_UNSUPPORTED - * is returned. - * - * Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_INT_STATUS_UNSUPPORTED - * or %CAIRO_STATUS_NO_MEMORY - **/ -cairo_int_status_t -_cairo_traps_extract_region (const cairo_traps_t *traps, - cairo_region_t *region) -{ - cairo_box_int_t stack_boxes[CAIRO_STACK_ARRAY_LENGTH (cairo_box_int_t)]; - cairo_box_int_t *boxes = stack_boxes; - int i, box_count; - cairo_int_status_t status; - - for (i = 0; i < traps->num_traps; i++) - if (!(traps->traps[i].left.p1.x == traps->traps[i].left.p2.x - && traps->traps[i].right.p1.x == traps->traps[i].right.p2.x - && _cairo_fixed_is_integer(traps->traps[i].top) - && _cairo_fixed_is_integer(traps->traps[i].bottom) - && _cairo_fixed_is_integer(traps->traps[i].left.p1.x) - && _cairo_fixed_is_integer(traps->traps[i].right.p1.x))) { - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - if (traps->num_traps > ARRAY_LENGTH(stack_boxes)) { - boxes = _cairo_malloc_ab (traps->num_traps, sizeof(cairo_box_int_t)); - - if (boxes == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - box_count = 0; - - for (i = 0; i < traps->num_traps; i++) { - int x1 = _cairo_fixed_integer_part(traps->traps[i].left.p1.x); - int y1 = _cairo_fixed_integer_part(traps->traps[i].top); - int x2 = _cairo_fixed_integer_part(traps->traps[i].right.p1.x); - int y2 = _cairo_fixed_integer_part(traps->traps[i].bottom); - - /* XXX: Sometimes we get degenerate trapezoids from the tesellator; - * skip these. - */ - if (x1 == x2 || y1 == y2) - continue; - - boxes[box_count].p1.x = x1; - boxes[box_count].p1.y = y1; - boxes[box_count].p2.x = x2; - boxes[box_count].p2.y = y2; - - box_count++; - } - - status = _cairo_region_init_boxes (region, boxes, box_count); - - if (boxes != stack_boxes) - free (boxes); - - if (status) - _cairo_region_fini (region); - - return status; -} - -/* moves trap points such that they become the actual corners of the trapezoid */ -static void -_sanitize_trap (cairo_trapezoid_t *t) -{ - cairo_trapezoid_t s = *t; - -#define FIX(lr, tb, p) \ - if (t->lr.p.y != t->tb) { \ - t->lr.p.x = s.lr.p2.x + _cairo_fixed_mul_div (s.lr.p1.x - s.lr.p2.x, s.tb - s.lr.p2.y, s.lr.p1.y - s.lr.p2.y); \ - t->lr.p.y = s.tb; \ - } - FIX (left, top, p1); - FIX (left, bottom, p2); - FIX (right, top, p1); - FIX (right, bottom, p2); -} - -cairo_private cairo_status_t -_cairo_traps_path (const cairo_traps_t *traps, - cairo_path_fixed_t *path) -{ - int i; - - for (i = 0; i < traps->num_traps; i++) { - cairo_status_t status; - cairo_trapezoid_t trap = traps->traps[i]; - - if (trap.top == trap.bottom) - continue; - - _sanitize_trap (&trap); - - status = _cairo_path_fixed_move_to (path, trap.left.p1.x, trap.top); - if (status) return status; - status = _cairo_path_fixed_line_to (path, trap.right.p1.x, trap.top); - if (status) return status; - status = _cairo_path_fixed_line_to (path, trap.right.p2.x, trap.bottom); - if (status) return status; - status = _cairo_path_fixed_line_to (path, trap.left.p2.x, trap.bottom); - if (status) return status; - status = _cairo_path_fixed_close_path (path); - if (status) return status; - } - - return CAIRO_STATUS_SUCCESS; -} diff --git a/uppdev/plugin/cairo/lib/cairo-truetype-subset-private.h b/uppdev/plugin/cairo/lib/cairo-truetype-subset-private.h deleted file mode 100644 index 397a9f389..000000000 --- a/uppdev/plugin/cairo/lib/cairo-truetype-subset-private.h +++ /dev/null @@ -1,199 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2006 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Kristian Høgsberg - * Adrian Johnson - */ - -#ifndef CAIRO_TRUETYPE_SUBSET_PRIVATE_H -#define CAIRO_TRUETYPE_SUBSET_PRIVATE_H - -#include "cairoint.h" - -#if CAIRO_HAS_FONT_SUBSET - -/* The structs defined here should strictly follow the TrueType - * specification and not be padded. We use only 16-bit integer - * in their definition to guarantee that. The fields of type - * "FIXED" in the TT spec are broken into two *_1 and *_2 16-bit - * parts, and 64-bit members are broken into four. - * - * The test truetype-tables in the test suite makes sure that - * these tables have the right size. Please update that test - * if you add new tables/structs that should be packed. - */ - -#define MAKE_TT_TAG(a, b, c, d) (a<<24 | b<<16 | c<<8 | d) -#define TT_TAG_CFF MAKE_TT_TAG('C','F','F',' ') -#define TT_TAG_cmap MAKE_TT_TAG('c','m','a','p') -#define TT_TAG_cvt MAKE_TT_TAG('c','v','t',' ') -#define TT_TAG_fpgm MAKE_TT_TAG('f','p','g','m') -#define TT_TAG_glyf MAKE_TT_TAG('g','l','y','f') -#define TT_TAG_head MAKE_TT_TAG('h','e','a','d') -#define TT_TAG_hhea MAKE_TT_TAG('h','h','e','a') -#define TT_TAG_hmtx MAKE_TT_TAG('h','m','t','x') -#define TT_TAG_loca MAKE_TT_TAG('l','o','c','a') -#define TT_TAG_maxp MAKE_TT_TAG('m','a','x','p') -#define TT_TAG_name MAKE_TT_TAG('n','a','m','e') -#define TT_TAG_post MAKE_TT_TAG('p','o','s','t') -#define TT_TAG_prep MAKE_TT_TAG('p','r','e','p') - -/* All tt_* structs are big-endian */ -typedef struct _tt_cmap_index { - uint16_t platform; - uint16_t encoding; - uint32_t offset; -} tt_cmap_index_t; - -typedef struct _tt_cmap { - uint16_t version; - uint16_t num_tables; - tt_cmap_index_t index[1]; -} tt_cmap_t; - -typedef struct _segment_map { - uint16_t format; - uint16_t length; - uint16_t version; - uint16_t segCountX2; - uint16_t searchRange; - uint16_t entrySelector; - uint16_t rangeShift; - uint16_t endCount[1]; -} tt_segment_map_t; - -typedef struct _tt_head { - int16_t version_1; - int16_t version_2; - int16_t revision_1; - int16_t revision_2; - uint16_t checksum_1; - uint16_t checksum_2; - uint16_t magic_1; - uint16_t magic_2; - uint16_t flags; - uint16_t units_per_em; - int16_t created_1; - int16_t created_2; - int16_t created_3; - int16_t created_4; - int16_t modified_1; - int16_t modified_2; - int16_t modified_3; - int16_t modified_4; - int16_t x_min; /* FWORD */ - int16_t y_min; /* FWORD */ - int16_t x_max; /* FWORD */ - int16_t y_max; /* FWORD */ - uint16_t mac_style; - uint16_t lowest_rec_pppem; - int16_t font_direction_hint; - int16_t index_to_loc_format; - int16_t glyph_data_format; -} tt_head_t; - -typedef struct _tt_hhea { - int16_t version_1; - int16_t version_2; - int16_t ascender; /* FWORD */ - int16_t descender; /* FWORD */ - int16_t line_gap; /* FWORD */ - uint16_t advance_max_width; /* UFWORD */ - int16_t min_left_side_bearing; /* FWORD */ - int16_t min_right_side_bearing; /* FWORD */ - int16_t x_max_extent; /* FWORD */ - int16_t caret_slope_rise; - int16_t caret_slope_run; - int16_t reserved[5]; - int16_t metric_data_format; - uint16_t num_hmetrics; -} tt_hhea_t; - -typedef struct _tt_maxp { - int16_t version_1; - int16_t version_2; - uint16_t num_glyphs; - uint16_t max_points; - uint16_t max_contours; - uint16_t max_composite_points; - uint16_t max_composite_contours; - uint16_t max_zones; - uint16_t max_twilight_points; - uint16_t max_storage; - uint16_t max_function_defs; - uint16_t max_instruction_defs; - uint16_t max_stack_elements; - uint16_t max_size_of_instructions; - uint16_t max_component_elements; - uint16_t max_component_depth; -} tt_maxp_t; - -typedef struct _tt_name_record { - uint16_t platform; - uint16_t encoding; - uint16_t language; - uint16_t name; - uint16_t length; - uint16_t offset; -} tt_name_record_t; - -typedef struct _tt_name { - uint16_t format; - uint16_t num_records; - uint16_t strings_offset; - tt_name_record_t records[1]; -} tt_name_t; - - - -/* composite_glyph_t flags */ -#define TT_ARG_1_AND_2_ARE_WORDS 0x0001 -#define TT_WE_HAVE_A_SCALE 0x0008 -#define TT_MORE_COMPONENTS 0x0020 -#define TT_WE_HAVE_AN_X_AND_Y_SCALE 0x0040 -#define TT_WE_HAVE_A_TWO_BY_TWO 0x0080 - -typedef struct _tt_composite_glyph { - uint16_t flags; - uint16_t index; - uint16_t args[7]; /* 1 to 7 arguments depending on value of flags */ -} tt_composite_glyph_t; - -typedef struct _tt_glyph_data { - int16_t num_contours; - int8_t data[8]; - tt_composite_glyph_t glyph; -} tt_glyph_data_t; - -#endif /* CAIRO_HAS_FONT_SUBSET */ - -#endif /* CAIRO_TRUETYPE_SUBSET_PRIVATE_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-truetype-subset.c b/uppdev/plugin/cairo/lib/cairo-truetype-subset.c deleted file mode 100644 index e8be4b444..000000000 --- a/uppdev/plugin/cairo/lib/cairo-truetype-subset.c +++ /dev/null @@ -1,1338 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2004 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Kristian Høgsberg - * Adrian Johnson - */ - -/* - * Useful links: - * http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6.html - * http://www.microsoft.com/typography/specs/default.htm - */ - -#define _BSD_SOURCE /* for snprintf(), strdup() */ -#include "cairoint.h" - -#if CAIRO_HAS_FONT_SUBSET - -#include "cairo-scaled-font-subsets-private.h" -#include "cairo-truetype-subset-private.h" - - -typedef struct subset_glyph subset_glyph_t; -struct subset_glyph { - int parent_index; - unsigned long location; -}; - -typedef struct _cairo_truetype_font cairo_truetype_font_t; - -typedef struct table table_t; -struct table { - unsigned long tag; - cairo_status_t (*write) (cairo_truetype_font_t *font, unsigned long tag); - int pos; /* position in the font directory */ -}; - -struct _cairo_truetype_font { - - cairo_scaled_font_subset_t *scaled_font_subset; - - table_t truetype_tables[10]; - int num_tables; - - struct { - char *base_font; - unsigned int num_glyphs; - int *widths; - long x_min, y_min, x_max, y_max; - long ascent, descent; - int units_per_em; - } base; - - subset_glyph_t *glyphs; - const cairo_scaled_font_backend_t *backend; - int num_glyphs_in_face; - int checksum_index; - cairo_array_t output; - cairo_array_t string_offsets; - unsigned long last_offset; - unsigned long last_boundary; - int *parent_to_subset; - cairo_status_t status; - -}; - -static cairo_status_t -cairo_truetype_font_use_glyph (cairo_truetype_font_t *font, - unsigned short glyph, - unsigned short *out); - -#define SFNT_VERSION 0x00010000 -#define SFNT_STRING_MAX_LENGTH 65535 - -static cairo_status_t -_cairo_truetype_font_set_error (cairo_truetype_font_t *font, - cairo_status_t status) -{ - if (status == CAIRO_STATUS_SUCCESS || status == CAIRO_INT_STATUS_UNSUPPORTED) - return status; - - _cairo_status_set_error (&font->status, status); - - return _cairo_error (status); -} - -static cairo_status_t -_cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset, - cairo_truetype_font_t **font_return) -{ - cairo_status_t status; - cairo_truetype_font_t *font; - const cairo_scaled_font_backend_t *backend; - tt_head_t head; - tt_hhea_t hhea; - tt_maxp_t maxp; - tt_name_t *name; - tt_name_record_t *record; - unsigned long size; - int i, j; - - backend = scaled_font_subset->scaled_font->backend; - if (!backend->load_truetype_table) - return CAIRO_INT_STATUS_UNSUPPORTED; - - /* FIXME: We should either support subsetting vertical fonts, or fail on - * vertical. Currently font_options_t doesn't have vertical flag, but - * it should be added in the future. For now, the freetype backend - * returns UNSUPPORTED in load_truetype_table if the font is vertical. - * - * if (cairo_font_options_get_vertical_layout (scaled_font_subset->scaled_font)) - * return CAIRO_INT_STATUS_UNSUPPORTED; - */ - - size = sizeof (tt_head_t); - status = backend->load_truetype_table (scaled_font_subset->scaled_font, - TT_TAG_head, 0, - (unsigned char *) &head, - &size); - if (status) - return status; - - size = sizeof (tt_maxp_t); - status = backend->load_truetype_table (scaled_font_subset->scaled_font, - TT_TAG_maxp, 0, - (unsigned char *) &maxp, - &size); - if (status) - return status; - - size = sizeof (tt_hhea_t); - status = backend->load_truetype_table (scaled_font_subset->scaled_font, - TT_TAG_hhea, 0, - (unsigned char *) &hhea, - &size); - if (status) - return status; - - size = 0; - status = backend->load_truetype_table (scaled_font_subset->scaled_font, - TT_TAG_name, 0, - NULL, - &size); - if (status) - return status; - - name = malloc(size); - if (name == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - status = backend->load_truetype_table (scaled_font_subset->scaled_font, - TT_TAG_name, 0, - (unsigned char *) name, - &size); - if (status) - goto fail0; - - font = malloc (sizeof (cairo_truetype_font_t)); - if (font == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto fail0; - } - - font->backend = backend; - font->num_glyphs_in_face = be16_to_cpu (maxp.num_glyphs); - font->scaled_font_subset = scaled_font_subset; - - font->last_offset = 0; - font->last_boundary = 0; - _cairo_array_init (&font->output, sizeof (char)); - status = _cairo_array_grow_by (&font->output, 4096); - if (status) - goto fail1; - - font->glyphs = calloc (font->num_glyphs_in_face + 1, sizeof (subset_glyph_t)); - if (font->glyphs == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto fail1; - } - - font->parent_to_subset = calloc (font->num_glyphs_in_face, sizeof (int)); - if (font->parent_to_subset == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto fail2; - } - - font->base.num_glyphs = 0; - font->base.x_min = (int16_t) be16_to_cpu (head.x_min); - font->base.y_min = (int16_t) be16_to_cpu (head.y_min); - font->base.x_max = (int16_t) be16_to_cpu (head.x_max); - font->base.y_max = (int16_t) be16_to_cpu (head.y_max); - font->base.ascent = (int16_t) be16_to_cpu (hhea.ascender); - font->base.descent = (int16_t) be16_to_cpu (hhea.descender); - font->base.units_per_em = (int16_t) be16_to_cpu (head.units_per_em); - if (font->base.units_per_em == 0) - font->base.units_per_em = 2048; - - /* Extract the font name from the name table. At present this - * just looks for the Mac platform/Roman encoded font name. It - * should be extended to use any suitable font name in the - * name table. If the mac/roman font name is not found a - * CairoFont-x-y name is created. - */ - font->base.base_font = NULL; - for (i = 0; i < be16_to_cpu(name->num_records); i++) { - record = &(name->records[i]); - if ((be16_to_cpu (record->platform) == 1) && - (be16_to_cpu (record->encoding) == 0) && - (be16_to_cpu (record->name) == 4)) { - font->base.base_font = malloc (be16_to_cpu(record->length) + 1); - if (font->base.base_font) { - strncpy(font->base.base_font, - ((char*)name) + be16_to_cpu (name->strings_offset) + be16_to_cpu (record->offset), - be16_to_cpu (record->length)); - font->base.base_font[be16_to_cpu (record->length)] = 0; - } - break; - } - } - - free (name); - name = NULL; - - if (font->base.base_font == NULL) { - font->base.base_font = malloc (30); - if (font->base.base_font == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto fail3; - } - - snprintf(font->base.base_font, 30, "CairoFont-%u-%u", - scaled_font_subset->font_id, - scaled_font_subset->subset_id); - } - - for (i = 0, j = 0; font->base.base_font[j]; j++) { - if (font->base.base_font[j] == ' ') - continue; - font->base.base_font[i++] = font->base.base_font[j]; - } - font->base.base_font[i] = '\0'; - - font->base.widths = calloc (font->num_glyphs_in_face, sizeof (int)); - if (font->base.widths == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto fail4; - } - - _cairo_array_init (&font->string_offsets, sizeof (unsigned long)); - status = _cairo_array_grow_by (&font->string_offsets, 10); - if (status) - goto fail5; - - font->status = CAIRO_STATUS_SUCCESS; - - *font_return = font; - - return CAIRO_STATUS_SUCCESS; - - fail5: - _cairo_array_fini (&font->string_offsets); - free (font->base.widths); - fail4: - free (font->base.base_font); - fail3: - free (font->parent_to_subset); - fail2: - free (font->glyphs); - fail1: - _cairo_array_fini (&font->output); - free (font); - fail0: - if (name) - free (name); - - return status; -} - -static void -cairo_truetype_font_destroy (cairo_truetype_font_t *font) -{ - _cairo_array_fini (&font->string_offsets); - free (font->base.widths); - free (font->base.base_font); - free (font->parent_to_subset); - free (font->glyphs); - _cairo_array_fini (&font->output); - free (font); -} - -static cairo_status_t -cairo_truetype_font_allocate_write_buffer (cairo_truetype_font_t *font, - size_t length, - unsigned char **buffer) -{ - cairo_status_t status; - - if (font->status) - return font->status; - - status = _cairo_array_allocate (&font->output, length, (void **) buffer); - if (status) - return _cairo_truetype_font_set_error (font, status); - - return CAIRO_STATUS_SUCCESS; -} - -static void -cairo_truetype_font_write (cairo_truetype_font_t *font, - const void *data, - size_t length) -{ - cairo_status_t status; - - if (font->status) - return; - - status = _cairo_array_append_multiple (&font->output, data, length); - if (status) - status = _cairo_truetype_font_set_error (font, status); -} - -static void -cairo_truetype_font_write_be16 (cairo_truetype_font_t *font, - uint16_t value) -{ - uint16_t be16_value; - - if (font->status) - return; - - be16_value = cpu_to_be16 (value); - cairo_truetype_font_write (font, &be16_value, sizeof be16_value); -} - -static void -cairo_truetype_font_write_be32 (cairo_truetype_font_t *font, - uint32_t value) -{ - uint32_t be32_value; - - if (font->status) - return; - - be32_value = cpu_to_be32 (value); - cairo_truetype_font_write (font, &be32_value, sizeof be32_value); -} - -static cairo_status_t -cairo_truetype_font_align_output (cairo_truetype_font_t *font, - unsigned long *aligned) -{ - int length, pad; - unsigned char *padding; - - length = _cairo_array_num_elements (&font->output); - *aligned = (length + 3) & ~3; - pad = *aligned - length; - - if (pad) { - cairo_status_t status; - - status = cairo_truetype_font_allocate_write_buffer (font, pad, - &padding); - if (status) - return status; - - memset (padding, 0, pad); - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -cairo_truetype_font_check_boundary (cairo_truetype_font_t *font, - unsigned long boundary) -{ - cairo_status_t status; - - if (font->status) - return font->status; - - if (boundary - font->last_offset > SFNT_STRING_MAX_LENGTH) - { - status = _cairo_array_append (&font->string_offsets, - &font->last_boundary); - if (status) - return _cairo_truetype_font_set_error (font, status); - - font->last_offset = font->last_boundary; - } - font->last_boundary = boundary; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -cairo_truetype_font_write_cmap_table (cairo_truetype_font_t *font, - unsigned long tag) -{ - unsigned int i; - - cairo_truetype_font_write_be16 (font, 0); /* Table version */ - cairo_truetype_font_write_be16 (font, 2); /* Num tables */ - - cairo_truetype_font_write_be16 (font, 3); /* Platform */ - cairo_truetype_font_write_be16 (font, 0); /* Encoding */ - cairo_truetype_font_write_be32 (font, 20); /* Offset to start of table */ - - cairo_truetype_font_write_be16 (font, 1); /* Platform */ - cairo_truetype_font_write_be16 (font, 0); /* Encoding */ - cairo_truetype_font_write_be32 (font, 52); /* Offset to start of table */ - - /* Output a format 4 encoding table. */ - - cairo_truetype_font_write_be16 (font, 4); /* Format */ - cairo_truetype_font_write_be16 (font, 32); /* Length */ - cairo_truetype_font_write_be16 (font, 0); /* Version */ - cairo_truetype_font_write_be16 (font, 4); /* 2*segcount */ - cairo_truetype_font_write_be16 (font, 4); /* searchrange */ - cairo_truetype_font_write_be16 (font, 1); /* entry selector */ - cairo_truetype_font_write_be16 (font, 0); /* rangeshift */ - cairo_truetype_font_write_be16 (font, 0xf000 + font->base.num_glyphs - 1); /* end count[0] */ - cairo_truetype_font_write_be16 (font, 0xffff); /* end count[1] */ - cairo_truetype_font_write_be16 (font, 0); /* reserved */ - cairo_truetype_font_write_be16 (font, 0xf000); /* startCode[0] */ - cairo_truetype_font_write_be16 (font, 0xffff); /* startCode[1] */ - cairo_truetype_font_write_be16 (font, 0x1000); /* delta[0] */ - cairo_truetype_font_write_be16 (font, 1); /* delta[1] */ - cairo_truetype_font_write_be16 (font, 0); /* rangeOffset[0] */ - cairo_truetype_font_write_be16 (font, 0); /* rangeOffset[1] */ - - /* Output a format 6 encoding table. */ - - cairo_truetype_font_write_be16 (font, 6); - cairo_truetype_font_write_be16 (font, 10 + 2 * font->base.num_glyphs); - cairo_truetype_font_write_be16 (font, 0); - cairo_truetype_font_write_be16 (font, 0); /* First character */ - cairo_truetype_font_write_be16 (font, font->base.num_glyphs); - for (i = 0; i < font->base.num_glyphs; i++) - cairo_truetype_font_write_be16 (font, i); - - return font->status; -} - -static cairo_status_t -cairo_truetype_font_write_generic_table (cairo_truetype_font_t *font, - unsigned long tag) -{ - cairo_status_t status; - unsigned char *buffer; - unsigned long size; - - if (font->status) - return font->status; - - size = 0; - status = font->backend->load_truetype_table(font->scaled_font_subset->scaled_font, - tag, 0, NULL, &size); - if (status) - return _cairo_truetype_font_set_error (font, status); - - status = cairo_truetype_font_allocate_write_buffer (font, size, &buffer); - if (status) - return _cairo_truetype_font_set_error (font, status); - - status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, - tag, 0, buffer, &size); - if (status) - return _cairo_truetype_font_set_error (font, status); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -cairo_truetype_font_remap_composite_glyph (cairo_truetype_font_t *font, - unsigned char *buffer, - unsigned long size) -{ - tt_glyph_data_t *glyph_data; - tt_composite_glyph_t *composite_glyph; - int num_args; - int has_more_components; - unsigned short flags; - unsigned short index; - cairo_status_t status; - unsigned char *end = buffer + size; - - if (font->status) - return font->status; - - glyph_data = (tt_glyph_data_t *) buffer; - if ((unsigned char *)(&glyph_data->data) >= end) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if ((int16_t)be16_to_cpu (glyph_data->num_contours) >= 0) - return CAIRO_STATUS_SUCCESS; - - composite_glyph = &glyph_data->glyph; - do { - if ((unsigned char *)(&composite_glyph->args[1]) >= end) - return CAIRO_INT_STATUS_UNSUPPORTED; - - flags = be16_to_cpu (composite_glyph->flags); - has_more_components = flags & TT_MORE_COMPONENTS; - status = cairo_truetype_font_use_glyph (font, be16_to_cpu (composite_glyph->index), &index); - if (status) - return status; - - composite_glyph->index = cpu_to_be16 (index); - num_args = 1; - if (flags & TT_ARG_1_AND_2_ARE_WORDS) - num_args += 1; - if (flags & TT_WE_HAVE_A_SCALE) - num_args += 1; - else if (flags & TT_WE_HAVE_AN_X_AND_Y_SCALE) - num_args += 2; - else if (flags & TT_WE_HAVE_A_TWO_BY_TWO) - num_args += 3; - composite_glyph = (tt_composite_glyph_t *) &(composite_glyph->args[num_args]); - } while (has_more_components); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -cairo_truetype_font_write_glyf_table (cairo_truetype_font_t *font, - unsigned long tag) -{ - unsigned long start_offset, index, size, next; - tt_head_t header; - unsigned long begin, end; - unsigned char *buffer; - unsigned int i; - union { - unsigned char *bytes; - uint16_t *short_offsets; - uint32_t *long_offsets; - } u; - cairo_status_t status; - - if (font->status) - return font->status; - - size = sizeof (tt_head_t); - status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, - TT_TAG_head, 0, - (unsigned char*) &header, &size); - if (status) - return _cairo_truetype_font_set_error (font, status); - - if (be16_to_cpu (header.index_to_loc_format) == 0) - size = sizeof (int16_t) * (font->num_glyphs_in_face + 1); - else - size = sizeof (int32_t) * (font->num_glyphs_in_face + 1); - - u.bytes = malloc (size); - if (u.bytes == NULL) - return _cairo_truetype_font_set_error (font, CAIRO_STATUS_NO_MEMORY); - - status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, - TT_TAG_loca, 0, u.bytes, &size); - if (status) - return _cairo_truetype_font_set_error (font, status); - - start_offset = _cairo_array_num_elements (&font->output); - for (i = 0; i < font->base.num_glyphs; i++) { - index = font->glyphs[i].parent_index; - if (be16_to_cpu (header.index_to_loc_format) == 0) { - begin = be16_to_cpu (u.short_offsets[index]) * 2; - end = be16_to_cpu (u.short_offsets[index + 1]) * 2; - } - else { - begin = be32_to_cpu (u.long_offsets[index]); - end = be32_to_cpu (u.long_offsets[index + 1]); - } - - /* quick sanity check... */ - if (end < begin) { - status = CAIRO_INT_STATUS_UNSUPPORTED; - goto FAIL; - } - - size = end - begin; - status = cairo_truetype_font_align_output (font, &next); - if (status) - goto FAIL; - - status = cairo_truetype_font_check_boundary (font, next); - if (status) - goto FAIL; - - font->glyphs[i].location = next - start_offset; - - status = cairo_truetype_font_allocate_write_buffer (font, size, &buffer); - if (status) - goto FAIL; - - if (size != 0) { - status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, - TT_TAG_glyf, begin, buffer, &size); - if (status) - goto FAIL; - - status = cairo_truetype_font_remap_composite_glyph (font, buffer, size); - if (status) - goto FAIL; - } - } - - status = cairo_truetype_font_align_output (font, &next); - if (status) - goto FAIL; - - font->glyphs[i].location = next - start_offset; - - status = font->status; -FAIL: - free (u.bytes); - - return _cairo_truetype_font_set_error (font, status); -} - -static cairo_status_t -cairo_truetype_font_write_head_table (cairo_truetype_font_t *font, - unsigned long tag) -{ - unsigned char *buffer; - unsigned long size; - cairo_status_t status; - - if (font->status) - return font->status; - - size = 0; - status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, - tag, 0, NULL, &size); - if (status) - return _cairo_truetype_font_set_error (font, status); - - font->checksum_index = _cairo_array_num_elements (&font->output) + 8; - status = cairo_truetype_font_allocate_write_buffer (font, size, &buffer); - if (status) - return _cairo_truetype_font_set_error (font, status); - - status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, - tag, 0, buffer, &size); - if (status) - return _cairo_truetype_font_set_error (font, status); - - /* set checkSumAdjustment to 0 for table checksum calcualtion */ - *(uint32_t *)(buffer + 8) = 0; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -cairo_truetype_font_write_hhea_table (cairo_truetype_font_t *font, unsigned long tag) -{ - tt_hhea_t *hhea; - unsigned long size; - cairo_status_t status; - - if (font->status) - return font->status; - - size = sizeof (tt_hhea_t); - status = cairo_truetype_font_allocate_write_buffer (font, size, (unsigned char **) &hhea); - if (status) - return _cairo_truetype_font_set_error (font, status); - - status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, - tag, 0, (unsigned char *) hhea, &size); - if (status) - return _cairo_truetype_font_set_error (font, status); - - hhea->num_hmetrics = cpu_to_be16 ((uint16_t)(font->base.num_glyphs)); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -cairo_truetype_font_write_hmtx_table (cairo_truetype_font_t *font, - unsigned long tag) -{ - unsigned long size; - unsigned long long_entry_size; - unsigned long short_entry_size; - short *p; - unsigned int i; - tt_hhea_t hhea; - int num_hmetrics; - cairo_status_t status; - - if (font->status) - return font->status; - - size = sizeof (tt_hhea_t); - status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, - TT_TAG_hhea, 0, - (unsigned char*) &hhea, &size); - if (status) - return _cairo_truetype_font_set_error (font, status); - - num_hmetrics = be16_to_cpu(hhea.num_hmetrics); - - for (i = 0; i < font->base.num_glyphs; i++) { - long_entry_size = 2 * sizeof (int16_t); - short_entry_size = sizeof (int16_t); - status = cairo_truetype_font_allocate_write_buffer (font, - long_entry_size, - (unsigned char **) &p); - if (status) - return _cairo_truetype_font_set_error (font, status); - - if (font->glyphs[i].parent_index < num_hmetrics) { - status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, - TT_TAG_hmtx, - font->glyphs[i].parent_index * long_entry_size, - (unsigned char *) p, &long_entry_size); - if (status) - return _cairo_truetype_font_set_error (font, status); - } - else - { - status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, - TT_TAG_hmtx, - (num_hmetrics - 1) * long_entry_size, - (unsigned char *) p, &short_entry_size); - if (status) - return _cairo_truetype_font_set_error (font, status); - - status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, - TT_TAG_hmtx, - num_hmetrics * long_entry_size + - (font->glyphs[i].parent_index - num_hmetrics) * short_entry_size, - (unsigned char *) (p + 1), &short_entry_size); - if (status) - return _cairo_truetype_font_set_error (font, status); - } - font->base.widths[i] = be16_to_cpu (p[0]); - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -cairo_truetype_font_write_loca_table (cairo_truetype_font_t *font, - unsigned long tag) -{ - unsigned int i; - tt_head_t header; - unsigned long size; - cairo_status_t status; - - if (font->status) - return font->status; - - size = sizeof(tt_head_t); - status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, - TT_TAG_head, 0, - (unsigned char*) &header, &size); - if (status) - return _cairo_truetype_font_set_error (font, status); - - if (be16_to_cpu (header.index_to_loc_format) == 0) - { - for (i = 0; i < font->base.num_glyphs + 1; i++) - cairo_truetype_font_write_be16 (font, font->glyphs[i].location / 2); - } else { - for (i = 0; i < font->base.num_glyphs + 1; i++) - cairo_truetype_font_write_be32 (font, font->glyphs[i].location); - } - - return font->status; -} - -static cairo_status_t -cairo_truetype_font_write_maxp_table (cairo_truetype_font_t *font, - unsigned long tag) -{ - tt_maxp_t *maxp; - unsigned long size; - cairo_status_t status; - - if (font->status) - return font->status; - - size = sizeof (tt_maxp_t); - status = cairo_truetype_font_allocate_write_buffer (font, size, (unsigned char **) &maxp); - if (status) - return _cairo_truetype_font_set_error (font, status); - - status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, - tag, 0, (unsigned char *) maxp, &size); - if (status) - return _cairo_truetype_font_set_error (font, status); - - maxp->num_glyphs = cpu_to_be16 (font->base.num_glyphs); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -cairo_truetype_font_write_offset_table (cairo_truetype_font_t *font) -{ - cairo_status_t status; - unsigned char *table_buffer; - size_t table_buffer_length; - unsigned short search_range, entry_selector, range_shift; - - if (font->status) - return font->status; - - search_range = 1; - entry_selector = 0; - while (search_range * 2 <= font->num_tables) { - search_range *= 2; - entry_selector++; - } - search_range *= 16; - range_shift = font->num_tables * 16 - search_range; - - cairo_truetype_font_write_be32 (font, SFNT_VERSION); - cairo_truetype_font_write_be16 (font, font->num_tables); - cairo_truetype_font_write_be16 (font, search_range); - cairo_truetype_font_write_be16 (font, entry_selector); - cairo_truetype_font_write_be16 (font, range_shift); - - /* Allocate space for the table directory. Each directory entry - * will be filled in by cairo_truetype_font_update_entry() after - * the table is written. */ - table_buffer_length = font->num_tables * 16; - status = cairo_truetype_font_allocate_write_buffer (font, table_buffer_length, - &table_buffer); - if (status) - return _cairo_truetype_font_set_error (font, status); - - return CAIRO_STATUS_SUCCESS; -} - -static uint32_t -cairo_truetype_font_calculate_checksum (cairo_truetype_font_t *font, - unsigned long start, - unsigned long end) -{ - uint32_t *padded_end; - uint32_t *p; - uint32_t checksum; - char *data; - - checksum = 0; - data = _cairo_array_index (&font->output, 0); - p = (uint32_t *) (data + start); - padded_end = (uint32_t *) (data + ((end + 3) & ~3)); - while (p < padded_end) - checksum += be32_to_cpu(*p++); - - return checksum; -} - -static void -cairo_truetype_font_update_entry (cairo_truetype_font_t *font, - int index, - unsigned long tag, - unsigned long start, - unsigned long end) -{ - uint32_t *entry; - - entry = _cairo_array_index (&font->output, 12 + 16 * index); - entry[0] = cpu_to_be32 ((uint32_t)tag); - entry[1] = cpu_to_be32 (cairo_truetype_font_calculate_checksum (font, start, end)); - entry[2] = cpu_to_be32 ((uint32_t)start); - entry[3] = cpu_to_be32 ((uint32_t)(end - start)); -} - -static cairo_status_t -cairo_truetype_font_generate (cairo_truetype_font_t *font, - const char **data, - unsigned long *length, - const unsigned long **string_offsets, - unsigned long *num_strings) -{ - cairo_status_t status; - unsigned long start, end, next; - uint32_t checksum, *checksum_location; - int i; - - if (font->status) - return font->status; - - status = cairo_truetype_font_write_offset_table (font); - if (status) - goto FAIL; - - status = cairo_truetype_font_align_output (font, &start); - if (status) - goto FAIL; - - end = 0; - for (i = 0; i < font->num_tables; i++) { - status = font->truetype_tables[i].write (font, font->truetype_tables[i].tag); - if (status) - goto FAIL; - - end = _cairo_array_num_elements (&font->output); - status = cairo_truetype_font_align_output (font, &next); - if (status) - goto FAIL; - - cairo_truetype_font_update_entry (font, font->truetype_tables[i].pos, - font->truetype_tables[i].tag, start, end); - status = cairo_truetype_font_check_boundary (font, next); - if (status) - goto FAIL; - - start = next; - } - - checksum = - 0xb1b0afba - cairo_truetype_font_calculate_checksum (font, 0, end); - checksum_location = _cairo_array_index (&font->output, font->checksum_index); - *checksum_location = cpu_to_be32 (checksum); - - *data = _cairo_array_index (&font->output, 0); - *length = _cairo_array_num_elements (&font->output); - *num_strings = _cairo_array_num_elements (&font->string_offsets); - if (*num_strings != 0) - *string_offsets = _cairo_array_index (&font->string_offsets, 0); - else - *string_offsets = NULL; - - FAIL: - return _cairo_truetype_font_set_error (font, status); -} - -static cairo_status_t -cairo_truetype_font_use_glyph (cairo_truetype_font_t *font, - unsigned short glyph, - unsigned short *out) -{ - if (glyph >= font->num_glyphs_in_face) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (font->parent_to_subset[glyph] == 0) { - font->parent_to_subset[glyph] = font->base.num_glyphs; - font->glyphs[font->base.num_glyphs].parent_index = glyph; - font->base.num_glyphs++; - } - - *out = font->parent_to_subset[glyph]; - return CAIRO_STATUS_SUCCESS; -} - -static void -cairo_truetype_font_add_truetype_table (cairo_truetype_font_t *font, - unsigned long tag, - cairo_status_t (*write) (cairo_truetype_font_t *font, unsigned long tag), - int pos) -{ - font->truetype_tables[font->num_tables].tag = tag; - font->truetype_tables[font->num_tables].write = write; - font->truetype_tables[font->num_tables].pos = pos; - font->num_tables++; -} - -/* cairo_truetype_font_create_truetype_table_list() builds the list of - * truetype tables to be embedded in the subsetted font. Each call to - * cairo_truetype_font_add_truetype_table() adds a table, the callback - * for generating the table, and the position in the table directory - * to the truetype_tables array. - * - * As we write out the glyf table we remap composite glyphs. - * Remapping composite glyphs will reference the sub glyphs the - * composite glyph is made up of. The "glyf" table callback needs to - * be called first so we have all the glyphs in the subset before - * going further. - * - * The order in which tables are added to the truetype_table array - * using cairo_truetype_font_add_truetype_table() specifies the order - * in which the callback functions will be called. - * - * The tables in the table directory must be listed in alphabetical - * order. The "cvt", "fpgm", and "prep" are optional tables. They - * will only be embedded in the subset if they exist in the source - * font. The pos parameter of cairo_truetype_font_add_truetype_table() - * specifies the position of the table in the table directory. - */ -static void -cairo_truetype_font_create_truetype_table_list (cairo_truetype_font_t *font) -{ - cairo_bool_t has_cvt = FALSE; - cairo_bool_t has_fpgm = FALSE; - cairo_bool_t has_prep = FALSE; - unsigned long size; - int pos; - - size = 0; - if (font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, - TT_TAG_cvt, 0, NULL, - &size) == CAIRO_STATUS_SUCCESS) - has_cvt = TRUE; - - size = 0; - if (font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, - TT_TAG_fpgm, 0, NULL, - &size) == CAIRO_STATUS_SUCCESS) - has_fpgm = TRUE; - - size = 0; - if (font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, - TT_TAG_prep, 0, NULL, - &size) == CAIRO_STATUS_SUCCESS) - has_prep = TRUE; - - font->num_tables = 0; - pos = 1; - if (has_cvt) - pos++; - if (has_fpgm) - pos++; - cairo_truetype_font_add_truetype_table (font, TT_TAG_glyf, cairo_truetype_font_write_glyf_table, pos); - - pos = 0; - cairo_truetype_font_add_truetype_table (font, TT_TAG_cmap, cairo_truetype_font_write_cmap_table, pos++); - if (has_cvt) - cairo_truetype_font_add_truetype_table (font, TT_TAG_cvt, cairo_truetype_font_write_generic_table, pos++); - if (has_fpgm) - cairo_truetype_font_add_truetype_table (font, TT_TAG_fpgm, cairo_truetype_font_write_generic_table, pos++); - pos++; - cairo_truetype_font_add_truetype_table (font, TT_TAG_head, cairo_truetype_font_write_head_table, pos++); - cairo_truetype_font_add_truetype_table (font, TT_TAG_hhea, cairo_truetype_font_write_hhea_table, pos++); - cairo_truetype_font_add_truetype_table (font, TT_TAG_hmtx, cairo_truetype_font_write_hmtx_table, pos++); - cairo_truetype_font_add_truetype_table (font, TT_TAG_loca, cairo_truetype_font_write_loca_table, pos++); - cairo_truetype_font_add_truetype_table (font, TT_TAG_maxp, cairo_truetype_font_write_maxp_table, pos++); - if (has_prep) - cairo_truetype_font_add_truetype_table (font, TT_TAG_prep, cairo_truetype_font_write_generic_table, pos); -} - -cairo_status_t -_cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset, - cairo_scaled_font_subset_t *font_subset) -{ - cairo_truetype_font_t *font = NULL; - cairo_status_t status; - const char *data = NULL; /* squelch bogus compiler warning */ - unsigned long length = 0; /* squelch bogus compiler warning */ - unsigned long offsets_length; - unsigned int i; - const unsigned long *string_offsets = NULL; - unsigned long num_strings = 0; - - status = _cairo_truetype_font_create (font_subset, &font); - if (status) - return status; - - for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) { - unsigned short parent_glyph = font->scaled_font_subset->glyphs[i]; - status = cairo_truetype_font_use_glyph (font, parent_glyph, &parent_glyph); - if (status) - goto fail1; - } - - cairo_truetype_font_create_truetype_table_list (font); - status = cairo_truetype_font_generate (font, &data, &length, - &string_offsets, &num_strings); - if (status) - goto fail1; - - truetype_subset->base_font = strdup (font->base.base_font); - if (truetype_subset->base_font == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto fail1; - } - - /* The widths array returned must contain only widths for the - * glyphs in font_subset. Any subglyphs appended after - * font_subset->num_glyphs are omitted. */ - truetype_subset->widths = calloc (sizeof (double), - font->scaled_font_subset->num_glyphs); - if (truetype_subset->widths == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto fail2; - } - for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) - truetype_subset->widths[i] = (double)font->base.widths[i]/font->base.units_per_em; - - truetype_subset->x_min = (double)font->base.x_min/font->base.units_per_em; - truetype_subset->y_min = (double)font->base.y_min/font->base.units_per_em; - truetype_subset->x_max = (double)font->base.x_max/font->base.units_per_em; - truetype_subset->y_max = (double)font->base.y_max/font->base.units_per_em; - truetype_subset->ascent = (double)font->base.ascent/font->base.units_per_em; - truetype_subset->descent = (double)font->base.descent/font->base.units_per_em; - - if (length) { - truetype_subset->data = malloc (length); - if (truetype_subset->data == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto fail3; - } - - memcpy (truetype_subset->data, data, length); - } else - truetype_subset->data = NULL; - truetype_subset->data_length = length; - - if (num_strings) { - offsets_length = num_strings * sizeof (unsigned long); - truetype_subset->string_offsets = malloc (offsets_length); - if (truetype_subset->string_offsets == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto fail4; - } - - memcpy (truetype_subset->string_offsets, string_offsets, offsets_length); - truetype_subset->num_string_offsets = num_strings; - } else { - truetype_subset->string_offsets = NULL; - truetype_subset->num_string_offsets = 0; - } - - cairo_truetype_font_destroy (font); - - return CAIRO_STATUS_SUCCESS; - - fail4: - free (truetype_subset->data); - fail3: - free (truetype_subset->widths); - fail2: - free (truetype_subset->base_font); - fail1: - cairo_truetype_font_destroy (font); - - return status; -} - -void -_cairo_truetype_subset_fini (cairo_truetype_subset_t *subset) -{ - free (subset->base_font); - free (subset->widths); - free (subset->data); - free (subset->string_offsets); -} - -static cairo_int_status_t -_cairo_truetype_reverse_cmap (cairo_scaled_font_t *scaled_font, - unsigned long table_offset, - unsigned long index, - uint32_t *ucs4) -{ - cairo_status_t status; - const cairo_scaled_font_backend_t *backend; - tt_segment_map_t *map; - char buf[4]; - unsigned int num_segments, i; - unsigned long size; - uint16_t *start_code; - uint16_t *end_code; - uint16_t *delta; - uint16_t *range_offset; - uint16_t *glyph_array; - uint16_t c; - - backend = scaled_font->backend; - size = 4; - status = backend->load_truetype_table (scaled_font, - TT_TAG_cmap, table_offset, - (unsigned char *) &buf, - &size); - if (status) - return status; - - /* All table formats have the same first two words */ - map = (tt_segment_map_t *) buf; - if (be16_to_cpu (map->format) != 4) - return CAIRO_INT_STATUS_UNSUPPORTED; - - size = be16_to_cpu (map->length); - map = malloc (size); - if (map == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - status = backend->load_truetype_table (scaled_font, - TT_TAG_cmap, table_offset, - (unsigned char *) map, - &size); - if (status) - goto fail; - - num_segments = be16_to_cpu (map->segCountX2)/2; - - /* A Format 4 cmap contains 8 uint16_t numbers and 4 arrays of - * uint16_t each num_segments long. */ - if (size < (8 + 4*num_segments)*sizeof(uint16_t)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - end_code = map->endCount; - start_code = &(end_code[num_segments + 1]); - delta = &(start_code[num_segments]); - range_offset = &(delta[num_segments]); - glyph_array = &(range_offset[num_segments]); - - /* search for glyph in segments with rangeOffset=0 */ - for (i = 0; i < num_segments; i++) { - c = index - be16_to_cpu (delta[i]); - if (range_offset[i] == 0 && - c >= be16_to_cpu (start_code[i]) && - c <= be16_to_cpu (end_code[i])) - { - *ucs4 = c; - goto found; - } - } - - /* search for glyph in segments with rangeOffset=1 */ - for (i = 0; i < num_segments; i++) { - if (range_offset[i] != 0) { - uint16_t *glyph_ids = &range_offset[i] + be16_to_cpu (range_offset[i])/2; - int range_size = be16_to_cpu (end_code[i]) - be16_to_cpu (start_code[i]) + 1; - uint16_t g_id_be = cpu_to_be16 (index); - int j; - - if (range_size > 0) { - if ((char*)glyph_ids + 2*range_size > (char*)map + size) - return CAIRO_INT_STATUS_UNSUPPORTED; - - for (j = 0; j < range_size; j++) { - if (glyph_ids[j] == g_id_be) { - *ucs4 = be16_to_cpu (start_code[i]) + j; - goto found; - } - } - } - } - } - - /* glyph not found */ - *ucs4 = -1; - -found: - status = CAIRO_STATUS_SUCCESS; - -fail: - free (map); - - return status; -} - -cairo_int_status_t -_cairo_truetype_index_to_ucs4 (cairo_scaled_font_t *scaled_font, - unsigned long index, - uint32_t *ucs4) -{ - cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED; - const cairo_scaled_font_backend_t *backend; - tt_cmap_t *cmap; - char buf[4]; - int num_tables, i; - unsigned long size; - - backend = scaled_font->backend; - if (!backend->load_truetype_table) - return CAIRO_INT_STATUS_UNSUPPORTED; - - size = 4; - status = backend->load_truetype_table (scaled_font, - TT_TAG_cmap, 0, - (unsigned char *) &buf, - &size); - if (status) - return status; - - cmap = (tt_cmap_t *) buf; - num_tables = be16_to_cpu (cmap->num_tables); - size = 4 + num_tables*sizeof(tt_cmap_index_t); - cmap = _cairo_malloc_ab_plus_c (num_tables, sizeof (tt_cmap_index_t), 4); - if (cmap == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - status = backend->load_truetype_table (scaled_font, - TT_TAG_cmap, 0, - (unsigned char *) cmap, - &size); - if (status) - goto cleanup; - - /* Find a table with Unicode mapping */ - for (i = 0; i < num_tables; i++) { - if (be16_to_cpu (cmap->index[i].platform) == 3 && - be16_to_cpu (cmap->index[i].encoding) == 1) { - status = _cairo_truetype_reverse_cmap (scaled_font, - be32_to_cpu (cmap->index[i].offset), - index, - ucs4); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - break; - } - } - -cleanup: - free (cmap); - - return status; -} - -#endif /* CAIRO_HAS_FONT_SUBSET */ diff --git a/uppdev/plugin/cairo/lib/cairo-type1-fallback.c b/uppdev/plugin/cairo/lib/cairo-type1-fallback.c deleted file mode 100644 index 83ddc448a..000000000 --- a/uppdev/plugin/cairo/lib/cairo-type1-fallback.c +++ /dev/null @@ -1,887 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2006 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Adrian Johnson - */ - -#define _BSD_SOURCE /* for snprintf(), strdup() */ -#include "cairoint.h" - -#if CAIRO_HAS_FONT_SUBSET - -#include "cairo-type1-private.h" -#include "cairo-scaled-font-subsets-private.h" -#include "cairo-path-fixed-private.h" -#include "cairo-output-stream-private.h" - -typedef enum { - CAIRO_CHARSTRING_TYPE1, - CAIRO_CHARSTRING_TYPE2 -} cairo_charstring_type_t; - -typedef struct _cairo_type1_font { - int *widths; - - cairo_scaled_font_subset_t *scaled_font_subset; - cairo_scaled_font_t *type1_scaled_font; - - cairo_array_t contents; - - double x_min, y_min, x_max, y_max; - - const char *data; - unsigned long header_size; - unsigned long data_size; - unsigned long trailer_size; - int bbox_position; - int bbox_max_chars; - - cairo_output_stream_t *output; - - unsigned short eexec_key; - cairo_bool_t hex_encode; - int hex_column; -} cairo_type1_font_t; - -static cairo_status_t -cairo_type1_font_create (cairo_scaled_font_subset_t *scaled_font_subset, - cairo_type1_font_t **subset_return, - cairo_bool_t hex_encode) -{ - cairo_type1_font_t *font; - cairo_font_face_t *font_face; - cairo_matrix_t font_matrix; - cairo_matrix_t ctm; - cairo_font_options_t font_options; - cairo_status_t status; - - font = calloc (1, sizeof (cairo_type1_font_t)); - if (font == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - font->widths = calloc (scaled_font_subset->num_glyphs, - sizeof (int)); - if (font->widths == NULL) { - free (font); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - font->scaled_font_subset = scaled_font_subset; - font->hex_encode = hex_encode; - - font_face = cairo_scaled_font_get_font_face (scaled_font_subset->scaled_font); - - cairo_matrix_init_scale (&font_matrix, 1000, -1000); - cairo_matrix_init_identity (&ctm); - - _cairo_font_options_init_default (&font_options); - cairo_font_options_set_hint_style (&font_options, CAIRO_HINT_STYLE_NONE); - cairo_font_options_set_hint_metrics (&font_options, CAIRO_HINT_METRICS_OFF); - - font->type1_scaled_font = cairo_scaled_font_create (font_face, - &font_matrix, - &ctm, - &font_options); - status = font->type1_scaled_font->status; - if (status) - goto fail; - - _cairo_array_init (&font->contents, sizeof (unsigned char)); - font->output = NULL; - - *subset_return = font; - - return CAIRO_STATUS_SUCCESS; - -fail: - free (font->widths); - free (font); - - return status; -} - -/* Charstring commands. If the high byte is 0 the command is encoded - * with a single byte. */ -#define CHARSTRING_sbw 0x0c07 -#define CHARSTRING_rmoveto 0x0015 -#define CHARSTRING_rlineto 0x0005 -#define CHARSTRING_rcurveto 0x0008 -#define CHARSTRING_closepath 0x0009 -#define CHARSTRING_endchar 0x000e - -/* Before calling this function, the caller must allocate sufficient - * space in data (see _cairo_array_grow_by). The maximum number of - * bytes that will be used is 2. - */ -static void -charstring_encode_command (cairo_array_t *data, int command) -{ - cairo_status_t status; - int orig_size; - unsigned char buf[5]; - unsigned char *p = buf; - - if (command & 0xff00) - *p++ = command >> 8; - *p++ = command & 0x00ff; - - /* Ensure the array doesn't grow, which allows this function to - * have no possibility of failure. */ - orig_size = _cairo_array_size (data); - status = _cairo_array_append_multiple (data, buf, p - buf); - - assert (status == CAIRO_STATUS_SUCCESS); - assert (_cairo_array_size (data) == orig_size); -} - -/* Before calling this function, the caller must allocate sufficient - * space in data (see _cairo_array_grow_by). The maximum number of - * bytes that will be used is 5. - */ -static void -charstring_encode_integer (cairo_array_t *data, - int i, - cairo_charstring_type_t type) -{ - cairo_status_t status; - int orig_size; - unsigned char buf[10]; - unsigned char *p = buf; - - if (i >= -107 && i <= 107) { - *p++ = i + 139; - } else if (i >= 108 && i <= 1131) { - i -= 108; - *p++ = (i >> 8)+ 247; - *p++ = i & 0xff; - } else if (i >= -1131 && i <= -108) { - i = -i - 108; - *p++ = (i >> 8)+ 251; - *p++ = i & 0xff; - } else { - if (type == CAIRO_CHARSTRING_TYPE1) { - *p++ = 0xff; - *p++ = i >> 24; - *p++ = (i >> 16) & 0xff; - *p++ = (i >> 8) & 0xff; - *p++ = i & 0xff; - } else { - *p++ = 0xff; - *p++ = (i >> 8) & 0xff; - *p++ = i & 0xff; - *p++ = 0; - *p++ = 0; - } - } - - /* Ensure the array doesn't grow, which allows this function to - * have no possibility of failure. */ - orig_size = _cairo_array_size (data); - status = _cairo_array_append_multiple (data, buf, p - buf); - - assert (status == CAIRO_STATUS_SUCCESS); - assert (_cairo_array_size (data) == orig_size); -} - -typedef struct _ps_path_info { - cairo_array_t *data; - int current_x, current_y; - cairo_charstring_type_t type; -} t1_path_info_t; - -static cairo_status_t -_charstring_move_to (void *closure, - cairo_point_t *point) -{ - t1_path_info_t *path_info = (t1_path_info_t *) closure; - int dx, dy; - cairo_status_t status; - - status = _cairo_array_grow_by (path_info->data, 12); - if (status) - return status; - - dx = _cairo_fixed_integer_part (point->x) - path_info->current_x; - dy = _cairo_fixed_integer_part (point->y) - path_info->current_y; - charstring_encode_integer (path_info->data, dx, path_info->type); - charstring_encode_integer (path_info->data, dy, path_info->type); - path_info->current_x += dx; - path_info->current_y += dy; - - charstring_encode_command (path_info->data, CHARSTRING_rmoveto); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_charstring_line_to (void *closure, - cairo_point_t *point) -{ - t1_path_info_t *path_info = (t1_path_info_t *) closure; - int dx, dy; - cairo_status_t status; - - status = _cairo_array_grow_by (path_info->data, 12); - if (status) - return status; - - dx = _cairo_fixed_integer_part (point->x) - path_info->current_x; - dy = _cairo_fixed_integer_part (point->y) - path_info->current_y; - charstring_encode_integer (path_info->data, dx, path_info->type); - charstring_encode_integer (path_info->data, dy, path_info->type); - path_info->current_x += dx; - path_info->current_y += dy; - - charstring_encode_command (path_info->data, CHARSTRING_rlineto); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_charstring_curve_to (void *closure, - cairo_point_t *point1, - cairo_point_t *point2, - cairo_point_t *point3) -{ - t1_path_info_t *path_info = (t1_path_info_t *) closure; - int dx1, dy1, dx2, dy2, dx3, dy3; - cairo_status_t status; - - status = _cairo_array_grow_by (path_info->data, 32); - if (status) - return status; - - dx1 = _cairo_fixed_integer_part (point1->x) - path_info->current_x; - dy1 = _cairo_fixed_integer_part (point1->y) - path_info->current_y; - dx2 = _cairo_fixed_integer_part (point2->x) - path_info->current_x - dx1; - dy2 = _cairo_fixed_integer_part (point2->y) - path_info->current_y - dy1; - dx3 = _cairo_fixed_integer_part (point3->x) - path_info->current_x - dx1 - dx2; - dy3 = _cairo_fixed_integer_part (point3->y) - path_info->current_y - dy1 - dy2; - charstring_encode_integer (path_info->data, dx1, path_info->type); - charstring_encode_integer (path_info->data, dy1, path_info->type); - charstring_encode_integer (path_info->data, dx2, path_info->type); - charstring_encode_integer (path_info->data, dy2, path_info->type); - charstring_encode_integer (path_info->data, dx3, path_info->type); - charstring_encode_integer (path_info->data, dy3, path_info->type); - path_info->current_x += dx1 + dx2 + dx3; - path_info->current_y += dy1 + dy2 + dy3; - charstring_encode_command (path_info->data, CHARSTRING_rcurveto); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_charstring_close_path (void *closure) -{ - cairo_status_t status; - t1_path_info_t *path_info = (t1_path_info_t *) closure; - - if (path_info->type == CAIRO_CHARSTRING_TYPE2) - return CAIRO_STATUS_SUCCESS; - - status = _cairo_array_grow_by (path_info->data, 2); - if (status) - return status; - - charstring_encode_command (path_info->data, CHARSTRING_closepath); - - return CAIRO_STATUS_SUCCESS; -} - -static void -charstring_encrypt (cairo_array_t *data) -{ - unsigned char *d, *end; - uint16_t c, p, r; - - r = CAIRO_TYPE1_CHARSTRING_KEY; - d = (unsigned char *) _cairo_array_index (data, 0); - end = d + _cairo_array_num_elements (data); - while (d < end) { - p = *d; - c = p ^ (r >> 8); - r = (c + r) * CAIRO_TYPE1_ENCRYPT_C1 + CAIRO_TYPE1_ENCRYPT_C2; - *d++ = c; - } -} - -static cairo_int_status_t -cairo_type1_font_create_charstring (cairo_type1_font_t *font, - int subset_index, - int glyph_index, - cairo_charstring_type_t type, - cairo_array_t *data) -{ - cairo_int_status_t status; - cairo_scaled_glyph_t *scaled_glyph; - t1_path_info_t path_info; - cairo_text_extents_t *metrics; - cairo_bool_t emit_path = TRUE; - - /* This call may return CAIRO_INT_STATUS_UNSUPPORTED for bitmap fonts. */ - status = _cairo_scaled_glyph_lookup (font->type1_scaled_font, - glyph_index, - CAIRO_SCALED_GLYPH_INFO_METRICS| - CAIRO_SCALED_GLYPH_INFO_PATH, - &scaled_glyph); - - /* It is ok for the .notdef glyph to not have a path available. We - * just need the metrics to emit an empty glyph. */ - if (glyph_index == 0 && status == CAIRO_INT_STATUS_UNSUPPORTED) { - emit_path = FALSE; - status = _cairo_scaled_glyph_lookup (font->type1_scaled_font, - glyph_index, - CAIRO_SCALED_GLYPH_INFO_METRICS, - &scaled_glyph); - } - if (status) - return status; - - metrics = &scaled_glyph->metrics; - if (subset_index == 0) { - font->x_min = metrics->x_bearing; - font->y_min = metrics->y_bearing; - font->x_max = metrics->x_bearing + metrics->width; - font->y_max = metrics->y_bearing + metrics->height; - } else { - if (metrics->x_bearing < font->x_min) - font->x_min = metrics->x_bearing; - if (metrics->y_bearing < font->y_min) - font->y_min = metrics->y_bearing; - if (metrics->x_bearing + metrics->width > font->x_max) - font->x_max = metrics->x_bearing + metrics->width; - if (metrics->y_bearing + metrics->height > font->y_max) - font->y_max = metrics->y_bearing + metrics->height; - } - font->widths[subset_index] = metrics->x_advance; - - status = _cairo_array_grow_by (data, 30); - if (status) - return status; - - if (type == CAIRO_CHARSTRING_TYPE1) { - charstring_encode_integer (data, (int) scaled_glyph->metrics.x_bearing, type); - charstring_encode_integer (data, (int) scaled_glyph->metrics.y_bearing, type); - charstring_encode_integer (data, (int) scaled_glyph->metrics.x_advance, type); - charstring_encode_integer (data, (int) scaled_glyph->metrics.y_advance, type); - charstring_encode_command (data, CHARSTRING_sbw); - - path_info.current_x = (int) scaled_glyph->metrics.x_bearing; - path_info.current_y = (int) scaled_glyph->metrics.y_bearing; - } else { - charstring_encode_integer (data, (int) scaled_glyph->metrics.x_advance, type); - - path_info.current_x = 0; - path_info.current_y = 0; - } - path_info.data = data; - path_info.type = type; - if (emit_path) { - status = _cairo_path_fixed_interpret (scaled_glyph->path, - CAIRO_DIRECTION_FORWARD, - _charstring_move_to, - _charstring_line_to, - _charstring_curve_to, - _charstring_close_path, - &path_info); - if (status) - return status; - } - - status = _cairo_array_grow_by (data, 1); - if (status) - return status; - charstring_encode_command (path_info.data, CHARSTRING_endchar); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -cairo_type1_font_write_charstrings (cairo_type1_font_t *font, - cairo_output_stream_t *encrypted_output) -{ - cairo_status_t status; - unsigned char zeros[] = { 0, 0, 0, 0 }; - cairo_array_t data; - unsigned int i; - int length; - - _cairo_array_init (&data, sizeof (unsigned char)); - status = _cairo_array_grow_by (&data, 1024); - if (status) - goto fail; - - _cairo_output_stream_printf (encrypted_output, - "2 index /CharStrings %d dict dup begin\n", - font->scaled_font_subset->num_glyphs + 1); - - _cairo_scaled_font_freeze_cache (font->type1_scaled_font); - for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) { - _cairo_array_truncate (&data, 0); - /* four "random" bytes required by encryption algorithm */ - status = _cairo_array_append_multiple (&data, zeros, 4); - if (status) - goto fail; - - status = cairo_type1_font_create_charstring (font, i, - font->scaled_font_subset->glyphs[i], - CAIRO_CHARSTRING_TYPE1, - &data); - if (status) - goto fail; - - charstring_encrypt (&data); - length = _cairo_array_num_elements (&data); - if (font->scaled_font_subset->glyph_names != NULL) { - _cairo_output_stream_printf (encrypted_output, "/%s %d RD ", - font->scaled_font_subset->glyph_names[i], - length); - } else if (i == 0) { - _cairo_output_stream_printf (encrypted_output, "/.notdef %d RD ", length); - } else { - _cairo_output_stream_printf (encrypted_output, "/g%d %d RD ", i, length); - } - _cairo_output_stream_write (encrypted_output, - _cairo_array_index (&data, 0), - length); - _cairo_output_stream_printf (encrypted_output, " ND\n"); - } - -fail: - _cairo_scaled_font_thaw_cache (font->type1_scaled_font); - _cairo_array_fini (&data); - return status; -} - -static void -cairo_type1_font_write_header (cairo_type1_font_t *font, - const char *name) -{ - unsigned int i; - const char spaces[50] = " "; - - _cairo_output_stream_printf (font->output, - "%%!FontType1-1.1 %s 1.0\n" - "11 dict begin\n" - "/FontName /%s def\n" - "/PaintType 0 def\n" - "/FontType 1 def\n" - "/FontMatrix [0.001 0 0 0.001 0 0] readonly def\n", - name, - name); - - /* We don't know the bbox values until after the charstrings have - * been generated. Reserve some space and fill in the bbox - * later. */ - - /* Worst case for four signed ints with spaces between each number */ - font->bbox_max_chars = 50; - - _cairo_output_stream_printf (font->output, "/FontBBox {"); - font->bbox_position = _cairo_output_stream_get_position (font->output); - _cairo_output_stream_write (font->output, spaces, font->bbox_max_chars); - - _cairo_output_stream_printf (font->output, - "} readonly def\n" - "/Encoding 256 array\n" - "0 1 255 {1 index exch /.notdef put} for\n"); - for (i = 1; i < font->scaled_font_subset->num_glyphs; i++) { - if (font->scaled_font_subset->glyph_names != NULL) { - _cairo_output_stream_printf (font->output, "dup %d /%s put\n", - i, font->scaled_font_subset->glyph_names[i]); - } else { - _cairo_output_stream_printf (font->output, "dup %d /g%d put\n", i, i); - } - } - _cairo_output_stream_printf (font->output, - "readonly def\n" - "currentdict end\n" - "currentfile eexec\n"); -} - -static cairo_status_t -cairo_type1_write_stream_encrypted (void *closure, - const unsigned char *data, - unsigned int length) -{ - const unsigned char *in, *end; - uint16_t c, p; - static const char hex_digits[16] = "0123456789abcdef"; - char digits[3]; - cairo_type1_font_t *font = closure; - - in = (const unsigned char *) data; - end = (const unsigned char *) data + length; - while (in < end) { - p = *in++; - c = p ^ (font->eexec_key >> 8); - font->eexec_key = (c + font->eexec_key) * CAIRO_TYPE1_ENCRYPT_C1 + CAIRO_TYPE1_ENCRYPT_C2; - - if (font->hex_encode) { - digits[0] = hex_digits[c >> 4]; - digits[1] = hex_digits[c & 0x0f]; - digits[2] = '\n'; - font->hex_column += 2; - - if (font->hex_column == 78) { - _cairo_output_stream_write (font->output, digits, 3); - font->hex_column = 0; - } else { - _cairo_output_stream_write (font->output, digits, 2); - } - } else { - digits[0] = c; - _cairo_output_stream_write (font->output, digits, 1); - } - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -cairo_type1_font_write_private_dict (cairo_type1_font_t *font, - const char *name) -{ - cairo_int_status_t status; - cairo_status_t status2; - cairo_output_stream_t *encrypted_output; - - font->eexec_key = CAIRO_TYPE1_PRIVATE_DICT_KEY; - font->hex_column = 0; - encrypted_output = _cairo_output_stream_create ( - cairo_type1_write_stream_encrypted, - NULL, - font); - if (_cairo_output_stream_get_status (encrypted_output)) - return _cairo_output_stream_destroy (encrypted_output); - - /* Note: the first four spaces at the start of this private dict - * are the four "random" bytes of plaintext required by the - * encryption algorithm */ - _cairo_output_stream_printf (encrypted_output, - " dup /Private 9 dict dup begin\n" - "/RD {string currentfile exch readstring pop}" - " executeonly def\n" - "/ND {noaccess def} executeonly def\n" - "/NP {noaccess put} executeonly def\n" - "/BlueValues [] def\n" - "/MinFeature {16 16} def\n" - "/lenIV 4 def\n" - "/password 5839 def\n"); - - status = cairo_type1_font_write_charstrings (font, encrypted_output); - if (status) - goto fail; - - _cairo_output_stream_printf (encrypted_output, - "end\n" - "end\n" - "readonly put\n" - "noaccess put\n" - "dup /FontName get exch definefont pop\n" - "mark currentfile closefile\n"); - - fail: - status2 = _cairo_output_stream_destroy (encrypted_output); - if (status == CAIRO_STATUS_SUCCESS) - status = status2; - - return status; -} - -static void -cairo_type1_font_write_trailer(cairo_type1_font_t *font) -{ - int i; - static const char zeros[65] = - "0000000000000000000000000000000000000000000000000000000000000000\n"; - - for (i = 0; i < 8; i++) - _cairo_output_stream_write (font->output, zeros, sizeof zeros); - - _cairo_output_stream_printf (font->output, "cleartomark\n"); -} - -static cairo_status_t -cairo_type1_write_stream (void *closure, - const unsigned char *data, - unsigned int length) -{ - cairo_type1_font_t *font = closure; - - return _cairo_array_append_multiple (&font->contents, data, length); -} - -static cairo_int_status_t -cairo_type1_font_write (cairo_type1_font_t *font, - const char *name) -{ - cairo_int_status_t status; - - cairo_type1_font_write_header (font, name); - font->header_size = _cairo_output_stream_get_position (font->output); - - status = cairo_type1_font_write_private_dict (font, name); - if (status) - return status; - - font->data_size = _cairo_output_stream_get_position (font->output) - - font->header_size; - - cairo_type1_font_write_trailer (font); - font->trailer_size = - _cairo_output_stream_get_position (font->output) - - font->header_size - font->data_size; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -cairo_type1_font_generate (cairo_type1_font_t *font, const char *name) -{ - cairo_int_status_t status; - - status = _cairo_array_grow_by (&font->contents, 4096); - if (status) - return status; - - font->output = _cairo_output_stream_create (cairo_type1_write_stream, NULL, font); - if (_cairo_output_stream_get_status (font->output)) - return _cairo_output_stream_destroy (font->output); - - status = cairo_type1_font_write (font, name); - if (status) - return status; - - font->data = _cairo_array_index (&font->contents, 0); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -cairo_type1_font_destroy (cairo_type1_font_t *font) -{ - cairo_status_t status = CAIRO_STATUS_SUCCESS; - - free (font->widths); - cairo_scaled_font_destroy (font->type1_scaled_font); - _cairo_array_fini (&font->contents); - if (font->output) - status = _cairo_output_stream_destroy (font->output); - free (font); - - return status; -} - -static cairo_status_t -_cairo_type1_fallback_init_internal (cairo_type1_subset_t *type1_subset, - const char *name, - cairo_scaled_font_subset_t *scaled_font_subset, - cairo_bool_t hex_encode) -{ - cairo_type1_font_t *font; - cairo_status_t status; - unsigned long length; - unsigned int i, len; - - status = cairo_type1_font_create (scaled_font_subset, &font, hex_encode); - if (status) - return status; - - status = cairo_type1_font_generate (font, name); - if (status) - goto fail1; - - type1_subset->base_font = strdup (name); - if (type1_subset->base_font == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto fail1; - } - - type1_subset->widths = calloc (sizeof (int), font->scaled_font_subset->num_glyphs); - if (type1_subset->widths == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto fail2; - } - for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) - type1_subset->widths[i] = font->widths[i]; - - type1_subset->x_min = (int) font->x_min; - type1_subset->y_min = (int) font->y_min; - type1_subset->x_max = (int) font->x_max; - type1_subset->y_max = (int) font->y_max; - type1_subset->ascent = (int) font->y_max; - type1_subset->descent = (int) font->y_min; - - length = font->header_size + font->data_size + - font->trailer_size; - type1_subset->data = malloc (length); - if (type1_subset->data == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto fail3; - } - memcpy (type1_subset->data, - _cairo_array_index (&font->contents, 0), length); - - len = snprintf(type1_subset->data + font->bbox_position, - font->bbox_max_chars, - "%d %d %d %d", - (int)type1_subset->x_min, - (int)type1_subset->y_min, - (int)type1_subset->x_max, - (int)type1_subset->y_max); - type1_subset->data[font->bbox_position + len] = ' '; - - type1_subset->header_length = font->header_size; - type1_subset->data_length = font->data_size; - type1_subset->trailer_length = font->trailer_size; - - return cairo_type1_font_destroy (font); - - fail3: - free (type1_subset->widths); - fail2: - free (type1_subset->base_font); - fail1: - /* status is already set, ignore further errors */ - cairo_type1_font_destroy (font); - - return status; -} - -cairo_status_t -_cairo_type1_fallback_init_binary (cairo_type1_subset_t *type1_subset, - const char *name, - cairo_scaled_font_subset_t *scaled_font_subset) -{ - return _cairo_type1_fallback_init_internal (type1_subset, - name, - scaled_font_subset, FALSE); -} - -cairo_status_t -_cairo_type1_fallback_init_hex (cairo_type1_subset_t *type1_subset, - const char *name, - cairo_scaled_font_subset_t *scaled_font_subset) -{ - return _cairo_type1_fallback_init_internal (type1_subset, - name, - scaled_font_subset, TRUE); -} - -void -_cairo_type1_fallback_fini (cairo_type1_subset_t *subset) -{ - free (subset->base_font); - free (subset->widths); - free (subset->data); -} - -cairo_status_t -_cairo_type2_charstrings_init (cairo_type2_charstrings_t *type2_subset, - cairo_scaled_font_subset_t *scaled_font_subset) -{ - cairo_type1_font_t *font; - cairo_status_t status; - unsigned int i; - cairo_array_t charstring; - - status = cairo_type1_font_create (scaled_font_subset, &font, FALSE); - if (status) - return status; - - _cairo_array_init (&type2_subset->charstrings, sizeof (cairo_array_t)); - - type2_subset->widths = calloc (sizeof (int), font->scaled_font_subset->num_glyphs); - if (type2_subset->widths == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto fail1; - } - - _cairo_scaled_font_freeze_cache (font->type1_scaled_font); - for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) { - _cairo_array_init (&charstring, sizeof (unsigned char)); - status = _cairo_array_grow_by (&charstring, 32); - if (status) - goto fail2; - - status = cairo_type1_font_create_charstring (font, i, - font->scaled_font_subset->glyphs[i], - CAIRO_CHARSTRING_TYPE2, - &charstring); - if (status) - goto fail2; - - status = _cairo_array_append (&type2_subset->charstrings, &charstring); - if (status) - goto fail2; - } - _cairo_scaled_font_thaw_cache (font->type1_scaled_font); - - for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) - type2_subset->widths[i] = font->widths[i]; - - type2_subset->x_min = (int) font->x_min; - type2_subset->y_min = (int) font->y_min; - type2_subset->x_max = (int) font->x_max; - type2_subset->y_max = (int) font->y_max; - type2_subset->ascent = (int) font->y_max; - type2_subset->descent = (int) font->y_min; - - return cairo_type1_font_destroy (font); - -fail2: - _cairo_scaled_font_thaw_cache (font->type1_scaled_font); - _cairo_array_fini (&charstring); - _cairo_type2_charstrings_fini (type2_subset); -fail1: - cairo_type1_font_destroy (font); - return status; -} - -void -_cairo_type2_charstrings_fini (cairo_type2_charstrings_t *type2_subset) -{ - unsigned int i, num_charstrings; - cairo_array_t *charstring; - - num_charstrings = _cairo_array_num_elements (&type2_subset->charstrings); - for (i = 0; i < num_charstrings; i++) { - charstring = _cairo_array_index (&type2_subset->charstrings, i); - _cairo_array_fini (charstring); - } - _cairo_array_fini (&type2_subset->charstrings); - - free (type2_subset->widths); -} - -#endif /* CAIRO_HAS_FONT_SUBSET */ diff --git a/uppdev/plugin/cairo/lib/cairo-type1-private.h b/uppdev/plugin/cairo/lib/cairo-type1-private.h deleted file mode 100644 index 171c22490..000000000 --- a/uppdev/plugin/cairo/lib/cairo-type1-private.h +++ /dev/null @@ -1,51 +0,0 @@ -/* Cairo - a vector graphics library with display and print output - * - * Copyright © 2007 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Adrian Johnson - */ - -#ifndef CAIRO_TYPE1_PRIVATE_H -#define CAIRO_TYPE1_PRIVATE_H - -#include "cairoint.h" - -#if CAIRO_HAS_FONT_SUBSET - -/* Magic constants for the type1 eexec encryption */ -#define CAIRO_TYPE1_ENCRYPT_C1 ((unsigned short) 52845) -#define CAIRO_TYPE1_ENCRYPT_C2 ((unsigned short) 22719) -#define CAIRO_TYPE1_PRIVATE_DICT_KEY ((unsigned short) 55665) -#define CAIRO_TYPE1_CHARSTRING_KEY ((unsigned short) 4330) - -#endif /* CAIRO_HAS_FONT_SUBSET */ - -#endif /* CAIRO_TYPE1_PRIVATE_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-type1-subset.c b/uppdev/plugin/cairo/lib/cairo-type1-subset.c deleted file mode 100644 index bbff33d92..000000000 --- a/uppdev/plugin/cairo/lib/cairo-type1-subset.c +++ /dev/null @@ -1,1405 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2006 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Kristian Høgsberg - */ - -/* - * Useful links: - * http://partners.adobe.com/public/developer/en/font/T1_SPEC.PDF - */ - - -#define _BSD_SOURCE /* for snprintf(), strdup() */ -#include "cairoint.h" - -#if CAIRO_HAS_FONT_SUBSET - -#include "cairo-type1-private.h" -#include "cairo-scaled-font-subsets-private.h" -#include "cairo-output-stream-private.h" - -/* XXX: Eventually, we need to handle other font backends */ -#if CAIRO_HAS_FT_FONT - -#include "cairo-ft-private.h" - -#include -#include FT_FREETYPE_H -#include FT_OUTLINE_H -#include FT_TYPE1_TABLES_H - -#include - -typedef struct _cairo_type1_font_subset { - cairo_scaled_font_subset_t *scaled_font_subset; - - struct { - cairo_unscaled_font_t *unscaled_font; - unsigned int font_id; - char *base_font; - unsigned int num_glyphs; - long x_min, y_min, x_max, y_max; - long ascent, descent; - - const char *data; - unsigned long header_size; - unsigned long data_size; - unsigned long trailer_size; - } base; - - FT_Face face; - int num_glyphs; - - struct { - int subset_index; - int width; - char *name; - } *glyphs; - - cairo_output_stream_t *output; - cairo_array_t contents; - - const char *rd, *nd; - - char *type1_data; - unsigned int type1_length; - char *type1_end; - - char *header_segment; - int header_segment_size; - char *eexec_segment; - int eexec_segment_size; - cairo_bool_t eexec_segment_is_ascii; - - char *cleartext; - char *cleartext_end; - - int header_size; - - unsigned short eexec_key; - cairo_bool_t hex_encode; - int hex_column; -} cairo_type1_font_subset_t; - - -static cairo_status_t -_cairo_type1_font_subset_init (cairo_type1_font_subset_t *font, - cairo_unscaled_font_t *unscaled_font, - cairo_bool_t hex_encode) -{ - cairo_ft_unscaled_font_t *ft_unscaled_font; - cairo_status_t status; - FT_Face face; - PS_FontInfoRec font_info; - int i, j; - - ft_unscaled_font = (cairo_ft_unscaled_font_t *) unscaled_font; - - face = _cairo_ft_unscaled_font_lock_face (ft_unscaled_font); - if (face == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - if (FT_Get_PS_Font_Info(face, &font_info) != 0) { - status = CAIRO_INT_STATUS_UNSUPPORTED; - goto fail1; - } - - /* OpenType/CFF fonts also have a PS_FontInfoRec */ -#if HAVE_FT_LOAD_SFNT_TABLE - if (FT_IS_SFNT (face)) { - status = CAIRO_INT_STATUS_UNSUPPORTED; - goto fail1; - } -#endif - - memset (font, 0, sizeof (font)); - font->base.unscaled_font = _cairo_unscaled_font_reference (unscaled_font); - font->base.num_glyphs = face->num_glyphs; - font->base.x_min = face->bbox.xMin; - font->base.y_min = face->bbox.yMin; - font->base.x_max = face->bbox.xMax; - font->base.y_max = face->bbox.yMax; - font->base.ascent = face->ascender; - font->base.descent = face->descender; - - if (face->family_name) { - font->base.base_font = strdup (face->family_name); - if (font->base.base_font == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto fail2; - } - for (i = 0, j = 0; font->base.base_font[j]; j++) { - if (font->base.base_font[j] == ' ') - continue; - font->base.base_font[i++] = font->base.base_font[j]; - } - font->base.base_font[i] = '\0'; - } - - font->glyphs = calloc (face->num_glyphs, sizeof font->glyphs[0]); - if (font->glyphs == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto fail3; - } - - font->hex_encode = hex_encode; - font->num_glyphs = 0; - for (i = 0; i < face->num_glyphs; i++) - font->glyphs[i].subset_index = -1; - - _cairo_array_init (&font->contents, sizeof (char)); - - _cairo_ft_unscaled_font_unlock_face (ft_unscaled_font); - - return CAIRO_STATUS_SUCCESS; - - fail3: - if (font->base.base_font) - free (font->base.base_font); - fail2: - _cairo_unscaled_font_destroy (unscaled_font); - fail1: - _cairo_ft_unscaled_font_unlock_face (ft_unscaled_font); - - return status; -} - -static void -cairo_type1_font_subset_use_glyph (cairo_type1_font_subset_t *font, int glyph) -{ - if (font->glyphs[glyph].subset_index >= 0) - return; - - font->glyphs[glyph].subset_index = font->num_glyphs++; -} - -static cairo_bool_t -is_ps_delimiter(int c) -{ - static const char delimiters[] = "()[]{}<>/% \t\r\n"; - - return strchr (delimiters, c) != NULL; -} - -static const char * -find_token (const char *buffer, const char *end, const char *token) -{ - int i, length; - /* FIXME: find substring really must be find_token */ - - if (buffer == NULL) - return NULL; - - length = strlen (token); - for (i = 0; buffer + i < end - length + 1; i++) - if (memcmp (buffer + i, token, length) == 0) - if ((i == 0 || token[0] == '/' || is_ps_delimiter(buffer[i - 1])) && - (buffer + i == end - length || is_ps_delimiter(buffer[i + length]))) - return buffer + i; - - return NULL; -} - -static cairo_status_t -cairo_type1_font_subset_find_segments (cairo_type1_font_subset_t *font) -{ - unsigned char *p; - const char *eexec_token; - int size; - - p = (unsigned char *) font->type1_data; - font->type1_end = font->type1_data + font->type1_length; - if (p[0] == 0x80 && p[1] == 0x01) { - font->header_segment_size = - p[2] | (p[3] << 8) | (p[4] << 16) | (p[5] << 24); - font->header_segment = (char *) p + 6; - - p += 6 + font->header_segment_size; - font->eexec_segment_size = - p[2] | (p[3] << 8) | (p[4] << 16) | (p[5] << 24); - font->eexec_segment = (char *) p + 6; - font->eexec_segment_is_ascii = (p[1] == 1); - - p += 6 + font->eexec_segment_size; - while (p < (unsigned char *) (font->type1_end) && p[1] != 0x03) { - size = p[2] | (p[3] << 8) | (p[4] << 16) | (p[5] << 24); - p += 6 + size; - } - font->type1_end = (char *) p; - } else { - eexec_token = find_token ((char *) p, font->type1_end, "eexec"); - if (eexec_token == NULL) - return CAIRO_INT_STATUS_UNSUPPORTED; - - font->header_segment_size = eexec_token - (char *) p + strlen ("eexec\n"); - font->header_segment = (char *) p; - font->eexec_segment_size = font->type1_length - font->header_segment_size; - font->eexec_segment = (char *) p + font->header_segment_size; - font->eexec_segment_is_ascii = TRUE; - } - - return CAIRO_STATUS_SUCCESS; -} - -/* Search for the definition of key and erase it by overwriting with spaces. - * This function is looks for definitions of the form: - * - * /key1 1234 def - * /key2 [12 34 56] def - * - * ie a key defined as an integer or array of integers. - * - */ -static void -cairo_type1_font_erase_dict_key (cairo_type1_font_subset_t *font, - const char *key) -{ - const char *start, *p, *segment_end; - - segment_end = font->header_segment + font->header_segment_size; - - start = font->header_segment; - do { - start = find_token (start, segment_end, key); - if (start) { - p = start + strlen(key); - /* skip integers or array of integers */ - while (p < segment_end && - (isspace(*p) || - isdigit(*p) || - *p == '[' || - *p == ']')) - { - p++; - } - - if (p + 3 < segment_end && memcmp(p, "def", 3) == 0) { - /* erase definition of the key */ - memset((char *) start, ' ', p + 3 - start); - } - start += strlen(key); - } - } while (start); -} - -static cairo_status_t -cairo_type1_font_subset_write_header (cairo_type1_font_subset_t *font, - const char *name) -{ - const char *start, *end, *segment_end; - unsigned int i; - - /* FIXME: - * This function assumes that /FontName always appears - * before /Encoding. This appears to always be the case with Type1 - * fonts. - * - * The more recently added code for removing the UniqueID and XUID - * keys can not make any assumptions about the position of the - * keys in the dictionary so it is implemented by overwriting the - * key definition with spaces before we start copying the font to - * the output. - * - * This code should be rewritten to not make any assumptions about - * the order of dictionary keys. This will allow UniqueID to be - * stripped out instead of leaving a bunch of spaces in the - * output. - */ - cairo_type1_font_erase_dict_key (font, "/UniqueID"); - cairo_type1_font_erase_dict_key (font, "/XUID"); - - segment_end = font->header_segment + font->header_segment_size; - - /* Type 1 fonts created by Fontforge have some PostScript code at - * the start of the font that skips the font if the printer has a - * cached copy of the font with the same unique id. This breaks - * our subsetted font so we disable it by searching for the - * PostScript operator "known" when used to check for the - * "/UniqueID" dictionary key. We append " pop false " after it to - * pop the result of this check off the stack and replace it with - * "false" to make the PostScript code think "/UniqueID" does not - * exist. - */ - end = font->header_segment; - start = find_token (font->header_segment, segment_end, "/UniqueID"); - if (start) { - start += 9; - while (start < segment_end && isspace (*start)) - start++; - if (start + 5 < segment_end && memcmp(start, "known", 5) == 0) { - _cairo_output_stream_write (font->output, font->header_segment, - start + 5 - font->header_segment); - _cairo_output_stream_printf (font->output, " pop false "); - end = start + 5; - } - } - - start = find_token (end, segment_end, "/FontName"); - if (start == NULL) - return CAIRO_INT_STATUS_UNSUPPORTED; - - _cairo_output_stream_write (font->output, end, - start - end); - - _cairo_output_stream_printf (font->output, "/FontName /%s def", name); - - end = find_token (start, segment_end, "def"); - if (end == NULL) - return CAIRO_INT_STATUS_UNSUPPORTED; - end += 3; - - start = find_token (end, segment_end, "/Encoding"); - if (start == NULL) - return CAIRO_INT_STATUS_UNSUPPORTED; - _cairo_output_stream_write (font->output, end, start - end); - - _cairo_output_stream_printf (font->output, - "/Encoding 256 array\n" - "0 1 255 {1 index exch /.notdef put} for\n"); - for (i = 1; i < font->base.num_glyphs; i++) { - if (font->glyphs[i].subset_index < 0) - continue; - _cairo_output_stream_printf (font->output, - "dup %d /%s put\n", - font->glyphs[i].subset_index, - font->glyphs[i].name); - } - _cairo_output_stream_printf (font->output, "readonly def"); - - end = find_token (start, segment_end, "def"); - if (end == NULL) - return CAIRO_INT_STATUS_UNSUPPORTED; - end += 3; - - _cairo_output_stream_write (font->output, end, segment_end - end); - - return font->output->status; -} - -static int -hex_to_int (int ch) -{ - if (ch <= '9') - return ch - '0'; - else if (ch <= 'F') - return ch - 'A' + 10; - else - return ch - 'a' + 10; -} - -static cairo_status_t -cairo_type1_font_subset_write_encrypted (cairo_type1_font_subset_t *font, - const char *data, unsigned int length) -{ - const unsigned char *in, *end; - int c, p; - static const char hex_digits[16] = "0123456789abcdef"; - char digits[3]; - - in = (const unsigned char *) data; - end = (const unsigned char *) data + length; - while (in < end) { - p = *in++; - c = p ^ (font->eexec_key >> 8); - font->eexec_key = (c + font->eexec_key) * CAIRO_TYPE1_ENCRYPT_C1 + CAIRO_TYPE1_ENCRYPT_C2; - - if (font->hex_encode) { - digits[0] = hex_digits[c >> 4]; - digits[1] = hex_digits[c & 0x0f]; - digits[2] = '\n'; - font->hex_column += 2; - - if (font->hex_column == 78) { - _cairo_output_stream_write (font->output, digits, 3); - font->hex_column = 0; - } else { - _cairo_output_stream_write (font->output, digits, 2); - } - } else { - digits[0] = c; - _cairo_output_stream_write (font->output, digits, 1); - } - } - - return font->output->status; -} - -static cairo_status_t -cairo_type1_font_subset_decrypt_eexec_segment (cairo_type1_font_subset_t *font) -{ - unsigned short r = CAIRO_TYPE1_PRIVATE_DICT_KEY; - unsigned char *in, *end; - char *out; - int c, p; - int i; - - in = (unsigned char *) font->eexec_segment; - end = (unsigned char *) in + font->eexec_segment_size; - - font->cleartext = malloc (font->eexec_segment_size); - if (font->cleartext == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - out = font->cleartext; - while (in < end) { - if (font->eexec_segment_is_ascii) { - c = *in++; - if (isspace (c)) - continue; - c = (hex_to_int (c) << 4) | hex_to_int (*in++); - } else { - c = *in++; - } - p = c ^ (r >> 8); - r = (c + r) * CAIRO_TYPE1_ENCRYPT_C1 + CAIRO_TYPE1_ENCRYPT_C2; - - *out++ = p; - } - font->cleartext_end = out; - - /* Overwrite random bytes with spaces. - * - * The first 4 bytes of the cleartext are the random bytes - * required by the encryption algorithm. When encrypting the - * cleartext, the first ciphertext byte must not be a white space - * character and the first 4 bytes must not be an ASCII Hex - * character. Some fonts do not check that their randomly chosen - * bytes results in ciphertext that complies with this - * restriction. This may cause problems for some PDF consumers. By - * replacing the random bytes with spaces, the first four bytes of - * ciphertext will always be 0xf9, 0x83, 0xef, 0x00 which complies - * with this restriction. Using spaces also means we don't have to - * skip over the random bytes when parsing the cleartext. - */ - for (i = 0; i < 4 && i < font->eexec_segment_size; i++) - font->cleartext[i] = ' '; - - return CAIRO_STATUS_SUCCESS; -} - -static const char * -skip_token (const char *p, const char *end) -{ - while (p < end && isspace(*p)) - p++; - - while (p < end && !isspace(*p)) - p++; - - if (p == end) - return NULL; - - return p; -} - -static int -cairo_type1_font_subset_lookup_glyph (cairo_type1_font_subset_t *font, - const char *glyph_name, int length) -{ - unsigned int i; - - for (i = 0; i < font->base.num_glyphs; i++) { - if (font->glyphs[i].name && - strncmp (font->glyphs[i].name, glyph_name, length) == 0 && - font->glyphs[i].name[length] == '\0') - return i; - } - - return -1; -} - -static cairo_status_t -cairo_type1_font_subset_get_glyph_names_and_widths (cairo_type1_font_subset_t *font) -{ - unsigned int i; - char buffer[256]; - FT_Error error; - - /* Get glyph names and width using the freetype API */ - for (i = 0; i < font->base.num_glyphs; i++) { - if (font->glyphs[i].name != NULL) - continue; - - error = FT_Load_Glyph (font->face, i, - FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING | - FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM); - if (error != 0) - return CAIRO_INT_STATUS_UNSUPPORTED; - - font->glyphs[i].width = font->face->glyph->metrics.horiAdvance; - - error = FT_Get_Glyph_Name(font->face, i, buffer, sizeof buffer); - if (error != 0) - return CAIRO_INT_STATUS_UNSUPPORTED; - - font->glyphs[i].name = strdup (buffer); - if (font->glyphs[i].name == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - return CAIRO_STATUS_SUCCESS; -} - -static void -cairo_type1_font_subset_decrypt_charstring (const unsigned char *in, int size, unsigned char *out) -{ - unsigned short r = CAIRO_TYPE1_CHARSTRING_KEY; - int c, p, i; - - for (i = 0; i < size; i++) { - c = *in++; - p = c ^ (r >> 8); - r = (c + r) * CAIRO_TYPE1_ENCRYPT_C1 + CAIRO_TYPE1_ENCRYPT_C2; - *out++ = p; - } -} - -static const unsigned char * -cairo_type1_font_subset_decode_integer (const unsigned char *p, int *integer) -{ - if (*p <= 246) { - *integer = *p++ - 139; - } else if (*p <= 250) { - *integer = (p[0] - 247) * 256 + p[1] + 108; - p += 2; - } else if (*p <= 254) { - *integer = -(p[0] - 251) * 256 - p[1] - 108; - p += 2; - } else { - *integer = (p[1] << 24) | (p[2] << 16) | (p[3] << 8) | p[4]; - p += 5; - } - - return p; -} - -#if 0 -/* - * The two tables that follow are generated using this perl code: - */ - -@encoding = ( - /* 0 */ - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - /* 16 */ - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - /* 32 */ - "space", "exclam", "quotedbl", "numbersign", - "dollar", "percent", "ampersand", "quoteright", - "parenleft", "parenright", "asterisk", "plus", - "comma", "hyphen", "period", "slash", - /* 48 */ - "zero", "one", "two", "three", - "four", "five", "six", "seven", - "eight", "nine", "colon", "semicolon", - "less", "equal", "greater", "question", - /* 64 */ - "at", "A", "B", "C", - "D", "E", "F", "G", - "H", "I", "J", "K", - "L", "M", "N", "O", - /* 80 */ - "P", "Q", "R", "S", - "T", "U", "V", "W", - "X", "Y", "Z", "bracketleft", - "backslash", "bracketright", "asciicircum", "underscore", - /* 96 */ - "quoteleft", "a", "b", "c", - "d", "e", "f", "g", - "h", "i", "j", "k", - "l", "m", "n", "o", - /* 112 */ - "p", "q", "r", "s", - "t", "u", "v", "w", - "x", "y", "z", "braceleft", - "bar", "braceright", "asciitilde", NULL, - /* 128 */ - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - /* 144 */ - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - /* 160 */ - NULL, "exclamdown", "cent", "sterling", - "fraction", "yen", "florin", "section", - "currency", "quotesingle", "quotedblleft", "guillemotleft", - "guilsinglleft","guilsinglright","fi", "fl", - /* 176 */ - NULL, "endash", "dagger", "daggerdbl", - "periodcentered",NULL, "paragraph", "bullet", - "quotesinglbase","quotedblbase","quotedblright","guillemotright", - "ellipsis", "perthousand", NULL, "questiondown", - /* 192 */ - NULL, "grave", "acute", "circumflex", - "tilde", "macron", "breve", "dotaccent", - "dieresis", NULL, "ring", "cedilla", - NULL, "hungarumlaut", "ogonek", "caron", - /* 208 */ - "emdash", NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - /* 224 */ - NULL, "AE", NULL, "ordfeminine", - NULL, NULL, NULL, NULL, - "Lslash", "Oslash", "OE", "ordmasculine", - NULL, NULL, NULL, NULL, - /* 240 */ - NULL, "ae", NULL, NULL, - NULL, "dotlessi", NULL, NULL, - "lslash", "oslash", "oe", "germandbls", - NULL, NULL, NULL, NULL - ); - -print "static const char ps_standard_encoding_symbol[] = {\n"; -$s = qq( "\\0"); -for $sym (@encoding) { - if (! ($sym eq NULL)) { - $ss = qq( "$sym\\0"); - if (length($s) + length($ss) > 78) { - print qq( $s\n); - $s = ""; - } - $s .= $ss; - } -} -print qq( $s\n); -print "};\n\n"; -print "static const int16_t ps_standard_encoding_offset[256] = {\n"; -$offset = 1; -$s = qq(); -for $sym (@encoding) { - if (! ($sym eq NULL)) { - $ss = qq( $offset/*$sym*/,); - $offset += length($sym) + 1; - } else { - $ss = qq( 0,); - } - if (length($s) + length($ss) > 78) { - print qq( $s\n); - $s = ""; - } - $s .= $ss; -} -print qq( $s\n); -print "};\n"; -exit; -#endif - -static const char ps_standard_encoding_symbol[] = { - "\0" "space\0" "exclam\0" "quotedbl\0" "numbersign\0" "dollar\0" "percent\0" - "ampersand\0" "quoteright\0" "parenleft\0" "parenright\0" "asterisk\0" - "plus\0" "comma\0" "hyphen\0" "period\0" "slash\0" "zero\0" "one\0" "two\0" - "three\0" "four\0" "five\0" "six\0" "seven\0" "eight\0" "nine\0" "colon\0" - "semicolon\0" "less\0" "equal\0" "greater\0" "question\0" "at\0" "A\0" "B\0" - "C\0" "D\0" "E\0" "F\0" "G\0" "H\0" "I\0" "J\0" "K\0" "L\0" "M\0" "N\0" "O\0" - "P\0" "Q\0" "R\0" "S\0" "T\0" "U\0" "V\0" "W\0" "X\0" "Y\0" "Z\0" - "bracketleft\0" "backslash\0" "bracketright\0" "asciicircum\0" "underscore\0" - "quoteleft\0" "a\0" "b\0" "c\0" "d\0" "e\0" "f\0" "g\0" "h\0" "i\0" "j\0" - "k\0" "l\0" "m\0" "n\0" "o\0" "p\0" "q\0" "r\0" "s\0" "t\0" "u\0" "v\0" "w\0" - "x\0" "y\0" "z\0" "braceleft\0" "bar\0" "braceright\0" "asciitilde\0" - "exclamdown\0" "cent\0" "sterling\0" "fraction\0" "yen\0" "florin\0" - "section\0" "currency\0" "quotesingle\0" "quotedblleft\0" "guillemotleft\0" - "guilsinglleft\0" "guilsinglright\0" "fi\0" "fl\0" "endash\0" "dagger\0" - "daggerdbl\0" "periodcentered\0" "paragraph\0" "bullet\0" "quotesinglbase\0" - "quotedblbase\0" "quotedblright\0" "guillemotright\0" "ellipsis\0" - "perthousand\0" "questiondown\0" "grave\0" "acute\0" "circumflex\0" "tilde\0" - "macron\0" "breve\0" "dotaccent\0" "dieresis\0" "ring\0" "cedilla\0" - "hungarumlaut\0" "ogonek\0" "caron\0" "emdash\0" "AE\0" "ordfeminine\0" - "Lslash\0" "Oslash\0" "OE\0" "ordmasculine\0" "ae\0" "dotlessi\0" "lslash\0" - "oslash\0" "oe\0" "germandbls\0" -}; - -static const int16_t ps_standard_encoding_offset[256] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1/*space*/, 7/*exclam*/, 14/*quotedbl*/, 23/*numbersign*/, - 34/*dollar*/, 41/*percent*/, 49/*ampersand*/, 59/*quoteright*/, - 70/*parenleft*/, 80/*parenright*/, 91/*asterisk*/, 100/*plus*/, 105/*comma*/, - 111/*hyphen*/, 118/*period*/, 125/*slash*/, 131/*zero*/, 136/*one*/, - 140/*two*/, 144/*three*/, 150/*four*/, 155/*five*/, 160/*six*/, 164/*seven*/, - 170/*eight*/, 176/*nine*/, 181/*colon*/, 187/*semicolon*/, 197/*less*/, - 202/*equal*/, 208/*greater*/, 216/*question*/, 225/*at*/, 228/*A*/, 230/*B*/, - 232/*C*/, 234/*D*/, 236/*E*/, 238/*F*/, 240/*G*/, 242/*H*/, 244/*I*/, - 246/*J*/, 248/*K*/, 250/*L*/, 252/*M*/, 254/*N*/, 256/*O*/, 258/*P*/, - 260/*Q*/, 262/*R*/, 264/*S*/, 266/*T*/, 268/*U*/, 270/*V*/, 272/*W*/, - 274/*X*/, 276/*Y*/, 278/*Z*/, 280/*bracketleft*/, 292/*backslash*/, - 302/*bracketright*/, 315/*asciicircum*/, 327/*underscore*/, 338/*quoteleft*/, - 348/*a*/, 350/*b*/, 352/*c*/, 354/*d*/, 356/*e*/, 358/*f*/, 360/*g*/, - 362/*h*/, 364/*i*/, 366/*j*/, 368/*k*/, 370/*l*/, 372/*m*/, 374/*n*/, - 376/*o*/, 378/*p*/, 380/*q*/, 382/*r*/, 384/*s*/, 386/*t*/, 388/*u*/, - 390/*v*/, 392/*w*/, 394/*x*/, 396/*y*/, 398/*z*/, 400/*braceleft*/, - 410/*bar*/, 414/*braceright*/, 425/*asciitilde*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 436/*exclamdown*/, 447/*cent*/, 452/*sterling*/, 461/*fraction*/, 470/*yen*/, - 474/*florin*/, 481/*section*/, 489/*currency*/, 498/*quotesingle*/, - 510/*quotedblleft*/, 523/*guillemotleft*/, 537/*guilsinglleft*/, - 551/*guilsinglright*/, 566/*fi*/, 569/*fl*/, 0, 572/*endash*/, 579/*dagger*/, - 586/*daggerdbl*/, 596/*periodcentered*/, 0, 611/*paragraph*/, 621/*bullet*/, - 628/*quotesinglbase*/, 643/*quotedblbase*/, 656/*quotedblright*/, - 670/*guillemotright*/, 685/*ellipsis*/, 694/*perthousand*/, 0, - 706/*questiondown*/, 0, 719/*grave*/, 725/*acute*/, 731/*circumflex*/, - 742/*tilde*/, 748/*macron*/, 755/*breve*/, 761/*dotaccent*/, 771/*dieresis*/, - 0, 780/*ring*/, 785/*cedilla*/, 0, 793/*hungarumlaut*/, 806/*ogonek*/, - 813/*caron*/, 819/*emdash*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 826/*AE*/, 0, 829/*ordfeminine*/, 0, 0, 0, 0, 841/*Lslash*/, 848/*Oslash*/, - 855/*OE*/, 858/*ordmasculine*/, 0, 0, 0, 0, 0, 871/*ae*/, 0, 0, 0, - 874/*dotlessi*/, 0, 0, 883/*lslash*/, 890/*oslash*/, 897/*oe*/, - 900/*germandbls*/, 0, 0, 0, 0, -}; - -#define ps_standard_encoding(index) ((index) ? ps_standard_encoding_symbol+ps_standard_encoding_offset[(index)] : NULL) - -static cairo_status_t -use_standard_encoding_glyph (cairo_type1_font_subset_t *font, int index) -{ - const char *glyph_name; - - if (index < 0 || index > 255) - return CAIRO_STATUS_SUCCESS; - - glyph_name = ps_standard_encoding(index); - if (glyph_name == NULL) - return CAIRO_STATUS_SUCCESS; - - index = cairo_type1_font_subset_lookup_glyph (font, - glyph_name, - strlen(glyph_name)); - if (index < 0) - return CAIRO_INT_STATUS_UNSUPPORTED; - - cairo_type1_font_subset_use_glyph (font, index); - - return CAIRO_STATUS_SUCCESS; -} - -#define TYPE1_CHARSTRING_COMMAND_ESCAPE (12) -#define TYPE1_CHARSTRING_COMMAND_SEAC (32 + 6) - -static cairo_status_t -cairo_type1_font_subset_look_for_seac(cairo_type1_font_subset_t *font, - const char *name, int name_length, - const char *encrypted_charstring, int encrypted_charstring_length) -{ - cairo_status_t status; - unsigned char *charstring; - const unsigned char *end; - const unsigned char *p; - int stack[5], sp, value; - int command; - - charstring = malloc (encrypted_charstring_length); - if (charstring == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - cairo_type1_font_subset_decrypt_charstring ((const unsigned char *) - encrypted_charstring, - encrypted_charstring_length, - charstring); - end = charstring + encrypted_charstring_length; - - p = charstring + 4; - sp = 0; - - while (p < end) { - if (*p < 32) { - command = *p++; - - if (command == TYPE1_CHARSTRING_COMMAND_ESCAPE) - command = 32 + *p++; - - switch (command) { - case TYPE1_CHARSTRING_COMMAND_SEAC: - /* The seac command takes five integer arguments. The - * last two are glyph indices into the PS standard - * encoding give the names of the glyphs that this - * glyph is composed from. All we need to do is to - * make sure those glyphs are present in the subset - * under their standard names. */ - status = use_standard_encoding_glyph (font, stack[3]); - if (status) - return status; - - status = use_standard_encoding_glyph (font, stack[4]); - if (status) - return status; - - sp = 0; - break; - - default: - sp = 0; - break; - } - } else { - /* integer argument */ - p = cairo_type1_font_subset_decode_integer (p, &value); - if (sp < 5) - stack[sp++] = value; - } - } - - free (charstring); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -write_used_glyphs (cairo_type1_font_subset_t *font, - const char *name, int name_length, - const char *charstring, int charstring_length) -{ - cairo_status_t status; - char buffer[256]; - int length; - - length = snprintf (buffer, sizeof buffer, - "/%.*s %d %s ", - name_length, name, charstring_length, font->rd); - status = cairo_type1_font_subset_write_encrypted (font, buffer, length); - if (status) - return status; - - status = cairo_type1_font_subset_write_encrypted (font, - charstring, - charstring_length); - if (status) - return status; - - length = snprintf (buffer, sizeof buffer, "%s\n", font->nd); - status = cairo_type1_font_subset_write_encrypted (font, buffer, length); - if (status) - return status; - - return CAIRO_STATUS_SUCCESS; -} - -typedef cairo_status_t (*glyph_func_t) (cairo_type1_font_subset_t *font, - const char *name, int name_length, - const char *charstring, int charstring_length); - -static cairo_status_t -cairo_type1_font_subset_for_each_glyph (cairo_type1_font_subset_t *font, - const char *dict_start, - const char *dict_end, - glyph_func_t func, - const char **dict_out) -{ - int charstring_length, name_length, glyph_index; - const char *p, *charstring, *name; - char *end; - - /* We're looking at '/' in the name of the first glyph. The glyph - * definitions are on the form: - * - * /name 23 RD <23 binary bytes> ND - * - * or alternatively using -| and |- instead of RD and ND. - * - * We parse the glyph name and see if it is in the subset. If it - * is, we call the specified callback with the glyph name and - * glyph data, otherwise we just skip it. We need to parse - * through a glyph definition; we can't just find the next '/', - * since the binary data could contain a '/'. - */ - - p = dict_start; - - while (*p == '/') { - name = p + 1; - p = skip_token (p, dict_end); - name_length = p - name; - - charstring_length = strtol (p, &end, 10); - if (p == end) - return CAIRO_INT_STATUS_UNSUPPORTED; - - /* Skip past -| or RD to binary data. There is exactly one space - * between the -| or RD token and the encrypted data, thus '+ 1'. */ - charstring = skip_token (end, dict_end) + 1; - - /* Skip binary data and |- or ND token. */ - p = skip_token (charstring + charstring_length, dict_end); - while (p < dict_end && isspace(*p)) - p++; - - /* In case any of the skip_token() calls above reached EOF, p will - * be equal to dict_end. */ - if (p == dict_end) - return CAIRO_INT_STATUS_UNSUPPORTED; - - glyph_index = cairo_type1_font_subset_lookup_glyph (font, - name, name_length); - if (font->glyphs[glyph_index].subset_index >= 0) { - cairo_status_t status = func (font, - name, name_length, - charstring, charstring_length); - if (status) - return status; - } - } - - *dict_out = p; - - return CAIRO_STATUS_SUCCESS; -} - - -static cairo_status_t -cairo_type1_font_subset_write_private_dict (cairo_type1_font_subset_t *font, - const char *name) -{ - cairo_status_t status; - const char *p, *charstrings, *dict_start; - const char *closefile_token; - char buffer[32], *glyph_count_end; - int num_charstrings, length; - - /* The private dict holds hint information, common subroutines and - * the actual glyph definitions (charstrings). - * - * FIXME: update this comment. - * - * What we do here is scan directly the /CharString token, which - * marks the beginning of the glyph definitions. Then we parse - * through the glyph definitions and weed out the glyphs not in - * our subset. Everything else before and after the glyph - * definitions is copied verbatim to the output. It might be - * worthwile to figure out which of the common subroutines are - * used by the glyphs in the subset and get rid of the rest. */ - - /* FIXME: The /Subrs array contains binary data and could - * conceivably have "/CharStrings" in it, so we might need to skip - * this more cleverly. */ - charstrings = find_token (font->cleartext, font->cleartext_end, "/CharStrings"); - if (charstrings == NULL) - return CAIRO_INT_STATUS_UNSUPPORTED; - - /* Scan past /CharStrings and the integer following it. */ - p = charstrings + strlen ("/CharStrings"); - num_charstrings = strtol (p, &glyph_count_end, 10); - if (p == glyph_count_end) - return CAIRO_INT_STATUS_UNSUPPORTED; - - /* Look for a '/' which marks the beginning of the first glyph - * definition. */ - for (p = glyph_count_end; p < font->cleartext_end; p++) - if (*p == '/') - break; - if (p == font->cleartext_end) - return CAIRO_INT_STATUS_UNSUPPORTED; - dict_start = p; - - status = cairo_type1_font_subset_get_glyph_names_and_widths (font); - if (status) - return status; - - /* Now that we have the private dictionary broken down in - * sections, do the first pass through the glyph definitions to - * figure out which subrs and othersubrs are use and which extra - * glyphs may be required by the seac operator. */ - status = cairo_type1_font_subset_for_each_glyph (font, - dict_start, - font->cleartext_end, - cairo_type1_font_subset_look_for_seac, - &p); - if (status) - return status; - - closefile_token = find_token (p, font->cleartext_end, "closefile"); - if (closefile_token == NULL) - return CAIRO_INT_STATUS_UNSUPPORTED; - - status = cairo_type1_font_subset_get_glyph_names_and_widths (font); - if (status) - return status; - - /* We're ready to start outputting. First write the header, - * i.e. the public part of the font dict.*/ - status = cairo_type1_font_subset_write_header (font, name); - if (status) - return status; - - font->base.header_size = _cairo_output_stream_get_position (font->output); - - - /* Start outputting the private dict. First output everything up - * to the /CharStrings token. */ - status = cairo_type1_font_subset_write_encrypted (font, font->cleartext, - charstrings - font->cleartext); - if (status) - return status; - - /* Write out new charstring count */ - length = snprintf (buffer, sizeof buffer, - "/CharStrings %d", font->num_glyphs); - status = cairo_type1_font_subset_write_encrypted (font, buffer, length); - if (status) - return status; - - /* Write out text between the charstring count and the first - * charstring definition */ - status = cairo_type1_font_subset_write_encrypted (font, glyph_count_end, - dict_start - glyph_count_end); - if (status) - return status; - - /* Write out the charstring definitions for each of the glyphs in - * the subset. */ - status = cairo_type1_font_subset_for_each_glyph (font, - dict_start, - font->cleartext_end, - write_used_glyphs, - &p); - if (status) - return status; - - /* Output what's left between the end of the glyph definitions and - * the end of the private dict to the output. */ - status = cairo_type1_font_subset_write_encrypted (font, p, - closefile_token - p + strlen ("closefile") + 1); - if (status) - return status; - - _cairo_output_stream_write (font->output, "\n", 1); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -cairo_type1_font_subset_write_trailer(cairo_type1_font_subset_t *font) -{ - const char *cleartomark_token; - int i; - static const char zeros[65] = - "0000000000000000000000000000000000000000000000000000000000000000\n"; - - /* Some fonts have conditional save/restore around the entire font - * dict, so we need to retain whatever postscript code that may - * come after 'cleartomark'. */ - - for (i = 0; i < 8; i++) - _cairo_output_stream_write (font->output, zeros, sizeof zeros); - - cleartomark_token = find_token (font->type1_data, font->type1_end, "cleartomark"); - if (cleartomark_token == NULL) - return CAIRO_INT_STATUS_UNSUPPORTED; - - _cairo_output_stream_write (font->output, cleartomark_token, - font->type1_end - cleartomark_token); - - /* some fonts do not have a newline at the end of the last line */ - _cairo_output_stream_printf (font->output, "\n"); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -type1_font_write (void *closure, const unsigned char *data, unsigned int length) -{ - cairo_type1_font_subset_t *font = closure; - - return _cairo_array_append_multiple (&font->contents, data, length); -} - -static cairo_status_t -cairo_type1_font_subset_write (cairo_type1_font_subset_t *font, - const char *name) -{ - cairo_status_t status; - - status = cairo_type1_font_subset_find_segments (font); - if (status) - return status; - - status = cairo_type1_font_subset_decrypt_eexec_segment (font); - if (status) - return status; - - /* Determine which glyph definition delimiters to use. */ - if (find_token (font->cleartext, font->cleartext_end, "/-|") != NULL) { - font->rd = "-|"; - font->nd = "|-"; - } else if (find_token (font->cleartext, font->cleartext_end, "/RD") != NULL) { - font->rd = "RD"; - font->nd = "ND"; - } else { - /* Don't know *what* kind of font this is... */ - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - font->eexec_key = CAIRO_TYPE1_PRIVATE_DICT_KEY; - font->hex_column = 0; - - status = cairo_type1_font_subset_write_private_dict (font, name); - if (status) - return status; - - font->base.data_size = _cairo_output_stream_get_position (font->output) - - font->base.header_size; - - status = cairo_type1_font_subset_write_trailer (font); - if (status) - return status; - - font->base.trailer_size = - _cairo_output_stream_get_position (font->output) - - font->base.header_size - font->base.data_size; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -cairo_type1_font_subset_generate (void *abstract_font, - const char *name) - -{ - cairo_type1_font_subset_t *font = abstract_font; - cairo_ft_unscaled_font_t *ft_unscaled_font; - unsigned long ret; - cairo_status_t status; - - ft_unscaled_font = (cairo_ft_unscaled_font_t *) font->base.unscaled_font; - font->face = _cairo_ft_unscaled_font_lock_face (ft_unscaled_font); - if (font->face == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - font->type1_length = font->face->stream->size; - font->type1_data = malloc (font->type1_length); - if (font->type1_data == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto fail; - } - - if (font->face->stream->read != NULL) { - /* Note that read() may be implemented as a macro, thanks POSIX!, so we - * need to wrap the following usage in parentheses in order to - * disambiguate it for the pre-processor - using the verbose function - * pointer dereference for clarity. - */ - ret = (* font->face->stream->read) (font->face->stream, 0, - (unsigned char *) font->type1_data, - font->type1_length); - if (ret != font->type1_length) { - status = _cairo_error (CAIRO_STATUS_READ_ERROR); - goto fail; - } - } else { - memcpy (font->type1_data, - font->face->stream->base, font->type1_length); - } - - status = _cairo_array_grow_by (&font->contents, 4096); - if (status) - goto fail; - - font->output = _cairo_output_stream_create (type1_font_write, NULL, font); - if (_cairo_output_stream_get_status (font->output)) { - status = _cairo_output_stream_destroy (font->output); - goto fail; - } - - status = cairo_type1_font_subset_write (font, name); - if (status) - goto fail; - - font->base.data = _cairo_array_index (&font->contents, 0); - - fail: - _cairo_ft_unscaled_font_unlock_face (ft_unscaled_font); - - return status; -} - -static void -_cairo_type1_font_subset_fini (cairo_type1_font_subset_t *font) -{ - unsigned int i; - - /* If the subset generation failed, some of the pointers below may - * be NULL depending on at which point the error occurred. */ - - _cairo_array_fini (&font->contents); - - free (font->type1_data); - if (font->glyphs != NULL) - for (i = 0; i < font->base.num_glyphs; i++) { - free (font->glyphs[i].name); - } - - _cairo_unscaled_font_destroy (font->base.unscaled_font); - - if (font->base.base_font) - free (font->base.base_font); - free (font->glyphs); -} - -cairo_status_t -_cairo_type1_subset_init (cairo_type1_subset_t *type1_subset, - const char *name, - cairo_scaled_font_subset_t *scaled_font_subset, - cairo_bool_t hex_encode) -{ - cairo_type1_font_subset_t font; - cairo_status_t status; - unsigned long parent_glyph, length; - unsigned int i; - cairo_unscaled_font_t *unscaled_font; - char buf[30]; - - /* XXX: Need to fix this to work with a general cairo_unscaled_font_t. */ - if (!_cairo_scaled_font_is_ft (scaled_font_subset->scaled_font)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (_cairo_ft_scaled_font_is_vertical (scaled_font_subset->scaled_font)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - unscaled_font = _cairo_ft_scaled_font_get_unscaled_font (scaled_font_subset->scaled_font); - - status = _cairo_type1_font_subset_init (&font, unscaled_font, hex_encode); - if (status) - return status; - - for (i = 0; i < scaled_font_subset->num_glyphs; i++) { - parent_glyph = scaled_font_subset->glyphs[i]; - cairo_type1_font_subset_use_glyph (&font, parent_glyph); - } - - status = cairo_type1_font_subset_generate (&font, name); - if (status) - goto fail1; - - if (font.base.base_font) { - type1_subset->base_font = strdup (font.base.base_font); - } else { - snprintf(buf, sizeof (buf), "CairoFont-%u-%u", - scaled_font_subset->font_id, scaled_font_subset->subset_id); - type1_subset->base_font = strdup (buf); - } - if (type1_subset->base_font == NULL) - goto fail1; - - type1_subset->widths = calloc (sizeof (int), font.num_glyphs); - if (type1_subset->widths == NULL) - goto fail2; - for (i = 0; i < font.base.num_glyphs; i++) { - if (font.glyphs[i].subset_index < 0) - continue; - type1_subset->widths[font.glyphs[i].subset_index] = - font.glyphs[i].width; - } - - type1_subset->x_min = font.base.x_min; - type1_subset->y_min = font.base.y_min; - type1_subset->x_max = font.base.x_max; - type1_subset->y_max = font.base.y_max; - type1_subset->ascent = font.base.ascent; - type1_subset->descent = font.base.descent; - - length = font.base.header_size + - font.base.data_size + - font.base.trailer_size; - type1_subset->data = malloc (length); - if (type1_subset->data == NULL) - goto fail3; - - memcpy (type1_subset->data, - _cairo_array_index (&font.contents, 0), length); - - type1_subset->header_length = font.base.header_size; - type1_subset->data_length = font.base.data_size; - type1_subset->trailer_length = font.base.trailer_size; - - _cairo_type1_font_subset_fini (&font); - - return CAIRO_STATUS_SUCCESS; - - fail3: - free (type1_subset->widths); - fail2: - free (type1_subset->base_font); - fail1: - _cairo_type1_font_subset_fini (&font); - - return status; -} - -void -_cairo_type1_subset_fini (cairo_type1_subset_t *subset) -{ - free (subset->base_font); - free (subset->widths); - free (subset->data); -} - -cairo_bool_t -_cairo_type1_scaled_font_is_type1 (cairo_scaled_font_t *scaled_font) -{ - cairo_ft_unscaled_font_t *unscaled; - FT_Face face; - PS_FontInfoRec font_info; - cairo_bool_t is_type1 = FALSE; - - if (!_cairo_scaled_font_is_ft (scaled_font)) - return FALSE; - unscaled = (cairo_ft_unscaled_font_t *) _cairo_ft_scaled_font_get_unscaled_font (scaled_font); - face = _cairo_ft_unscaled_font_lock_face (unscaled); - if (!face) - return FALSE; - - if (FT_Get_PS_Font_Info(face, &font_info) == 0) - is_type1 = TRUE; - - /* OpenType/CFF fonts also have a PS_FontInfoRec */ -#if HAVE_FT_LOAD_SFNT_TABLE - if (FT_IS_SFNT (face)) - is_type1 = FALSE; -#endif - - _cairo_ft_unscaled_font_unlock_face (unscaled); - - return is_type1; -} - -#endif /* CAIRO_HAS_FT_FONT */ - -#endif /* CAIRO_HAS_FONT_SUBSET */ diff --git a/uppdev/plugin/cairo/lib/cairo-type3-glyph-surface-private.h b/uppdev/plugin/cairo/lib/cairo-type3-glyph-surface-private.h deleted file mode 100644 index 33314ae9e..000000000 --- a/uppdev/plugin/cairo/lib/cairo-type3-glyph-surface-private.h +++ /dev/null @@ -1,84 +0,0 @@ -/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2008 Adrian Johnson - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Adrian Johnson. - * - * Contributor(s): - * Adrian Johnson - */ - -#ifndef CAIRO_TYPE3_GLYPH_SURFACE_PRIVATE_H -#define CAIRO_TYPE3_GLYPH_SURFACE_PRIVATE_H - -#include "cairoint.h" - -#if CAIRO_HAS_FONT_SUBSET - -#include "cairo-surface-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 struct cairo_type3_glyph_surface { - cairo_surface_t base; - - cairo_scaled_font_t *scaled_font; - cairo_output_stream_t *stream; - cairo_pdf_operators_t pdf_operators; - cairo_matrix_t cairo_to_pdf; - cairo_type3_glyph_surface_emit_image_t emit_image; -} cairo_type3_glyph_surface_t; - -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_private void -_cairo_type3_glyph_surface_set_font_subsets_callback (void *abstract_surface, - cairo_pdf_operators_use_font_subset_t use_font_subset, - void *closure); - -cairo_private cairo_status_t -_cairo_type3_glyph_surface_analyze_glyph (void *abstract_surface, - unsigned long glyph_index); - -cairo_private cairo_status_t -_cairo_type3_glyph_surface_emit_glyph (void *abstract_surface, - cairo_output_stream_t *stream, - unsigned long glyph_index, - cairo_box_t *bbox, - double *width); - -#endif /* CAIRO_HAS_FONT_SUBSET */ - -#endif /* CAIRO_TYPE3_GLYPH_SURFACE_PRIVATE_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-type3-glyph-surface.c b/uppdev/plugin/cairo/lib/cairo-type3-glyph-surface.c deleted file mode 100644 index c84f5f05e..000000000 --- a/uppdev/plugin/cairo/lib/cairo-type3-glyph-surface.c +++ /dev/null @@ -1,528 +0,0 @@ -/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2008 Adrian Johnson - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Adrian Johnson. - * - * Contributor(s): - * Adrian Johnson - */ - -#include "cairoint.h" - -#if CAIRO_HAS_FONT_SUBSET - -#include "cairo-type3-glyph-surface-private.h" -#include "cairo-output-stream-private.h" -#include "cairo-meta-surface-private.h" -#include "cairo-analysis-surface-private.h" - -static const cairo_surface_backend_t cairo_type3_glyph_surface_backend; - -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_type3_glyph_surface_t *surface; - cairo_matrix_t invert_y_axis; - - surface = malloc (sizeof (cairo_type3_glyph_surface_t)); - if (surface == NULL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - _cairo_surface_init (&surface->base, &cairo_type3_glyph_surface_backend, - CAIRO_CONTENT_COLOR_ALPHA); - - surface->scaled_font = scaled_font; - surface->stream = stream; - surface->emit_image = emit_image; - - /* Setup the transform from the user-font device space to Type 3 - * font space. The Type 3 font space is defined by the FontMatrix - * entry in the Type 3 dictionary. In the PDF backend this is an - * identity matrix. */ - surface->cairo_to_pdf = scaled_font->scale_inverse; - cairo_matrix_init_scale (&invert_y_axis, 1, -1); - cairo_matrix_multiply (&surface->cairo_to_pdf, &surface->cairo_to_pdf, &invert_y_axis); - - _cairo_pdf_operators_init (&surface->pdf_operators, - surface->stream, - &surface->cairo_to_pdf, - font_subsets); - - return &surface->base; -} - -static cairo_status_t -_cairo_type3_glyph_surface_emit_image (cairo_type3_glyph_surface_t *surface, - cairo_image_surface_t *image, - cairo_matrix_t *image_matrix) -{ - cairo_status_t status; - cairo_image_surface_t *image_mask; - - /* The only image type supported by Type 3 fonts are 1-bit image - * masks */ - if (image->format == CAIRO_FORMAT_A1) { - image_mask = image; - } else { - image_mask = _cairo_image_surface_clone (image, CAIRO_FORMAT_A1); - status = cairo_surface_status (&image->base); - if (status) - return status; - } - - _cairo_output_stream_printf (surface->stream, - "q %f %f %f %f %f %f cm\n", - image_matrix->xx, - image_matrix->xy, - image_matrix->yx, - image_matrix->yy, - image_matrix->x0, - image_matrix->y0); - - status = surface->emit_image (image_mask, surface->stream); - - _cairo_output_stream_printf (surface->stream, - "Q\n"); - - if (image_mask != image) - cairo_surface_destroy (&image_mask->base); - - return status; -} - -static cairo_status_t -_cairo_type3_glyph_surface_emit_image_pattern (cairo_type3_glyph_surface_t *surface, - cairo_image_surface_t *image, - cairo_matrix_t *pattern_matrix) -{ - cairo_matrix_t mat, upside_down; - cairo_status_t status; - - if (image->width == 0 || image->height == 0) - return CAIRO_STATUS_SUCCESS; - - mat = *pattern_matrix; - - /* Get the pattern space to user space matrix */ - status = cairo_matrix_invert (&mat); - - /* cairo_pattern_set_matrix ensures the matrix is invertible */ - assert (status == CAIRO_STATUS_SUCCESS); - - /* Make this a pattern space to Type 3 font space matrix */ - cairo_matrix_multiply (&mat, &mat, &surface->cairo_to_pdf); - - /* PDF images are in a 1 unit by 1 unit image space. Turn the 1 by - * 1 image upside down to convert to flip the Y-axis going from - * cairo to PDF. Then scale the image up to the required size. */ - cairo_matrix_scale (&mat, image->width, image->height); - cairo_matrix_init (&upside_down, 1, 0, 0, -1, 0, 1); - cairo_matrix_multiply (&mat, &upside_down, &mat); - - return _cairo_type3_glyph_surface_emit_image (surface, image, &mat); -} - -static cairo_status_t -_cairo_type3_glyph_surface_finish (void *abstract_surface) -{ - cairo_type3_glyph_surface_t *surface = abstract_surface; - - return _cairo_pdf_operators_fini (&surface->pdf_operators); -} - -static cairo_int_status_t -_cairo_type3_glyph_surface_intersect_clip_path (void *abstract_surface, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_type3_glyph_surface_t *surface = abstract_surface; - - if (path == NULL) { - _cairo_output_stream_printf (surface->stream, "Q q\n"); - return CAIRO_STATUS_SUCCESS; - } - - return _cairo_pdf_operators_clip (&surface->pdf_operators, - path, - fill_rule); -} - -static cairo_int_status_t -_cairo_type3_glyph_surface_paint (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source) -{ - cairo_type3_glyph_surface_t *surface = abstract_surface; - cairo_surface_pattern_t *pattern; - cairo_image_surface_t *image; - void *image_extra; - cairo_status_t status; - - if (source->type != CAIRO_PATTERN_TYPE_SURFACE) - return CAIRO_INT_STATUS_IMAGE_FALLBACK; - - pattern = (cairo_surface_pattern_t *) source; - status = _cairo_surface_acquire_source_image (pattern->surface, &image, &image_extra); - if (status) - goto fail; - - status = _cairo_type3_glyph_surface_emit_image_pattern (surface, - image, - &pattern->base.matrix); - -fail: - _cairo_surface_release_source_image (pattern->surface, image, image_extra); - - return status; -} - -static cairo_int_status_t -_cairo_type3_glyph_surface_mask (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_pattern_t *mask) -{ - return _cairo_type3_glyph_surface_paint (abstract_surface, op, mask); -} - -static cairo_int_status_t -_cairo_type3_glyph_surface_stroke (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - 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_type3_glyph_surface_t *surface = abstract_surface; - - return _cairo_pdf_operators_stroke (&surface->pdf_operators, - path, - style, - ctm, - ctm_inverse); -} - -static cairo_int_status_t -_cairo_type3_glyph_surface_fill (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_type3_glyph_surface_t *surface = abstract_surface; - cairo_int_status_t status; - - status = _cairo_pdf_operators_fill (&surface->pdf_operators, - path, - fill_rule); - - return status; -} - -static cairo_int_status_t -_cairo_type3_glyph_surface_show_glyphs (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font, - int *remaining_glyphs) -{ - cairo_type3_glyph_surface_t *surface = abstract_surface; - cairo_int_status_t status; - cairo_scaled_font_t *font; - cairo_matrix_t new_ctm, ctm_inverse; - int i; - - for (i = 0; i < num_glyphs; i++) - cairo_matrix_transform_point (&surface->cairo_to_pdf, &glyphs[i].x, &glyphs[i].y); - - /* We require the matrix to be invertable. */ - ctm_inverse = scaled_font->ctm; - status = cairo_matrix_invert (&ctm_inverse); - if (status) - return CAIRO_INT_STATUS_IMAGE_FALLBACK; - - cairo_matrix_multiply (&new_ctm, &scaled_font->ctm, &ctm_inverse); - font = cairo_scaled_font_create (scaled_font->font_face, - &scaled_font->font_matrix, - &new_ctm, - &scaled_font->options); - - status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators, - NULL, 0, - glyphs, num_glyphs, - NULL, 0, - FALSE, - font); - - cairo_scaled_font_destroy (font); - - return status; -} - -static const cairo_surface_backend_t cairo_type3_glyph_surface_backend = { - CAIRO_INTERNAL_SURFACE_TYPE_TYPE3_GLYPH, - NULL, /* _cairo_type3_glyph_surface_create_similar */ - _cairo_type3_glyph_surface_finish, - NULL, /* acquire_source_image */ - NULL, /* release_source_image */ - NULL, /* acquire_dest_image */ - NULL, /* release_dest_image */ - NULL, /* clone_similar */ - NULL, /* composite */ - NULL, /* fill_rectangles */ - NULL, /* composite_trapezoids */ - NULL, /* cairo_type3_glyph_surface_copy_page */ - NULL, /* _cairo_type3_glyph_surface_show_page */ - NULL, /* set_clip_region */ - _cairo_type3_glyph_surface_intersect_clip_path, - NULL, /* _cairo_type3_glyph_surface_get_extents */ - NULL, /* old_show_glyphs */ - NULL, /* _cairo_type3_glyph_surface_get_font_options */ - NULL, /* flush */ - NULL, /* mark_dirty_rectangle */ - NULL, /* scaled_font_fini */ - NULL, /* scaled_glyph_fini */ - _cairo_type3_glyph_surface_paint, - _cairo_type3_glyph_surface_mask, - _cairo_type3_glyph_surface_stroke, - _cairo_type3_glyph_surface_fill, - _cairo_type3_glyph_surface_show_glyphs, - NULL, /* snapshot */ -}; - -static void -_cairo_type3_glyph_surface_set_stream (cairo_type3_glyph_surface_t *surface, - cairo_output_stream_t *stream) -{ - surface->stream = stream; - _cairo_pdf_operators_set_stream (&surface->pdf_operators, stream); -} - -static cairo_status_t -_cairo_type3_glyph_surface_emit_fallback_image (cairo_type3_glyph_surface_t *surface, - unsigned long glyph_index) -{ - cairo_scaled_glyph_t *scaled_glyph; - cairo_status_t status; - cairo_image_surface_t *image; - cairo_matrix_t mat; - double x, y; - - status = _cairo_scaled_glyph_lookup (surface->scaled_font, - glyph_index, - CAIRO_SCALED_GLYPH_INFO_METRICS | - CAIRO_SCALED_GLYPH_INFO_SURFACE, - &scaled_glyph); - if (status) - return status; - - image = scaled_glyph->surface; - if (image->width == 0 || image->height == 0) - return CAIRO_STATUS_SUCCESS; - - x = _cairo_fixed_to_double (scaled_glyph->bbox.p1.x); - y = _cairo_fixed_to_double (scaled_glyph->bbox.p2.y); - mat.xx = image->width; - mat.xy = 0; - mat.yx = 0; - mat.yy = image->height; - mat.x0 = x; - mat.y0 = y; - cairo_matrix_multiply (&mat, &mat, &surface->scaled_font->scale_inverse); - mat.y0 *= -1; - - return _cairo_type3_glyph_surface_emit_image (surface, image, &mat); -} - -void -_cairo_type3_glyph_surface_set_font_subsets_callback (void *abstract_surface, - cairo_pdf_operators_use_font_subset_t use_font_subset, - void *closure) -{ - cairo_type3_glyph_surface_t *surface = abstract_surface; - - _cairo_pdf_operators_set_font_subsets_callback (&surface->pdf_operators, - use_font_subset, - closure); -} - -cairo_status_t -_cairo_type3_glyph_surface_analyze_glyph (void *abstract_surface, - unsigned long glyph_index) -{ - cairo_type3_glyph_surface_t *surface = abstract_surface; - cairo_scaled_glyph_t *scaled_glyph; - cairo_status_t status, status2; - cairo_output_stream_t *null_stream; - - null_stream = _cairo_null_stream_create (); - _cairo_type3_glyph_surface_set_stream (surface, null_stream); - - _cairo_scaled_font_freeze_cache (surface->scaled_font); - status = _cairo_scaled_glyph_lookup (surface->scaled_font, - glyph_index, - CAIRO_SCALED_GLYPH_INFO_METRICS | - CAIRO_SCALED_GLYPH_INFO_META_SURFACE, - &scaled_glyph); - - if (_cairo_status_is_error (status)) - goto cleanup; - - if (status == CAIRO_INT_STATUS_UNSUPPORTED) { - status = CAIRO_STATUS_SUCCESS; - goto cleanup; - } - - status = _cairo_meta_surface_replay (scaled_glyph->meta_surface, - &surface->base); - if (status) - goto cleanup; - - status2 = _cairo_pdf_operators_flush (&surface->pdf_operators); - if (status == CAIRO_STATUS_SUCCESS) - status = status2; - - if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK) - status = CAIRO_STATUS_SUCCESS; - -cleanup: - _cairo_scaled_font_thaw_cache (surface->scaled_font); - - status2 = _cairo_output_stream_destroy (null_stream); - if (status == CAIRO_STATUS_SUCCESS) - status = status2; - - return status; -} - -cairo_status_t -_cairo_type3_glyph_surface_emit_glyph (void *abstract_surface, - cairo_output_stream_t *stream, - unsigned long glyph_index, - cairo_box_t *bbox, - double *width) -{ - cairo_type3_glyph_surface_t *surface = abstract_surface; - cairo_scaled_glyph_t *scaled_glyph; - cairo_status_t status, status2; - double x_advance, y_advance; - cairo_output_stream_t *mem_stream; - cairo_matrix_t font_matrix_inverse; - - _cairo_type3_glyph_surface_set_stream (surface, stream); - - _cairo_scaled_font_freeze_cache (surface->scaled_font); - status = _cairo_scaled_glyph_lookup (surface->scaled_font, - glyph_index, - CAIRO_SCALED_GLYPH_INFO_METRICS | - CAIRO_SCALED_GLYPH_INFO_META_SURFACE, - &scaled_glyph); - if (status == CAIRO_INT_STATUS_UNSUPPORTED) { - status = _cairo_scaled_glyph_lookup (surface->scaled_font, - glyph_index, - CAIRO_SCALED_GLYPH_INFO_METRICS, - &scaled_glyph); - if (status == CAIRO_STATUS_SUCCESS) - status = CAIRO_INT_STATUS_IMAGE_FALLBACK; - } - if (_cairo_status_is_error (status)) { - _cairo_scaled_font_thaw_cache (surface->scaled_font); - return status; - } - - x_advance = scaled_glyph->metrics.x_advance; - y_advance = scaled_glyph->metrics.y_advance; - font_matrix_inverse = surface->scaled_font->font_matrix; - status2 = cairo_matrix_invert (&font_matrix_inverse); - - /* The invertability of font_matrix is tested in - * pdf_operators_show_glyphs before any glyphs are mappped to the - * subset. */ - assert (status2 == CAIRO_STATUS_SUCCESS); - - cairo_matrix_transform_distance (&font_matrix_inverse, &x_advance, &y_advance); - *width = x_advance; - - *bbox = scaled_glyph->bbox; - _cairo_matrix_transform_bounding_box_fixed (&surface->scaled_font->scale_inverse, - bbox, NULL); - - _cairo_output_stream_printf (surface->stream, - "%f 0 %f %f %f %f d1\n", - x_advance, - _cairo_fixed_to_double (bbox->p1.x), - - _cairo_fixed_to_double (bbox->p2.y), - _cairo_fixed_to_double (bbox->p2.x), - - _cairo_fixed_to_double (bbox->p1.y)); - - if (status == CAIRO_STATUS_SUCCESS) { - mem_stream = _cairo_memory_stream_create (); - _cairo_type3_glyph_surface_set_stream (surface, mem_stream); - - _cairo_output_stream_printf (surface->stream, "q\n"); - status = _cairo_meta_surface_replay (scaled_glyph->meta_surface, - &surface->base); - - status2 = _cairo_pdf_operators_flush (&surface->pdf_operators); - if (status == CAIRO_STATUS_SUCCESS) - status = status2; - - _cairo_output_stream_printf (surface->stream, "Q\n"); - - _cairo_type3_glyph_surface_set_stream (surface, stream); - if (status == CAIRO_STATUS_SUCCESS) - _cairo_memory_stream_copy (mem_stream, stream); - - status2 = _cairo_output_stream_destroy (mem_stream); - if (status == CAIRO_STATUS_SUCCESS) - status = status2; - } - - if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK) - status = _cairo_type3_glyph_surface_emit_fallback_image (surface, glyph_index); - - _cairo_scaled_font_thaw_cache (surface->scaled_font); - - return status; -} - -#endif /* CAIRO_HAS_FONT_SUBSET */ diff --git a/uppdev/plugin/cairo/lib/cairo-types-private.h b/uppdev/plugin/cairo/lib/cairo-types-private.h deleted file mode 100644 index 12e1a20e5..000000000 --- a/uppdev/plugin/cairo/lib/cairo-types-private.h +++ /dev/null @@ -1,345 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - */ - -#ifndef CAIRO_TYPES_PRIVATE_H -#define CAIRO_TYPES_PRIVATE_H - -#include "cairo.h" -#include "cairo-fixed-type-private.h" - -typedef struct _cairo_array cairo_array_t; -typedef struct _cairo_cache cairo_cache_t; -typedef struct _cairo_clip cairo_clip_t; -typedef struct _cairo_clip_path cairo_clip_path_t; -typedef struct _cairo_color cairo_color_t; -typedef struct _cairo_font_face_backend cairo_font_face_backend_t; -typedef struct _cairo_gstate cairo_gstate_t; -typedef struct _cairo_hash_entry cairo_hash_entry_t; -typedef struct _cairo_hash_table cairo_hash_table_t; -typedef struct _cairo_image_surface cairo_image_surface_t; -typedef struct _cairo_output_stream cairo_output_stream_t; -typedef struct _cairo_paginated_surface_backend cairo_paginated_surface_backend_t; -typedef struct _cairo_path_fixed cairo_path_fixed_t; -typedef struct _cairo_rectangle_int16 cairo_glyph_size_t; -typedef struct _cairo_region cairo_region_t; -typedef struct _cairo_scaled_font_backend cairo_scaled_font_backend_t; -typedef struct _cairo_scaled_font_subsets cairo_scaled_font_subsets_t; -typedef struct _cairo_solid_pattern cairo_solid_pattern_t; -typedef struct _cairo_surface_backend cairo_surface_backend_t; -typedef struct _cairo_unscaled_font_backend cairo_unscaled_font_backend_t; -typedef struct _cairo_xlib_screen_info cairo_xlib_screen_info_t; - -typedef cairo_array_t cairo_user_data_array_t; - -/** - * cairo_hash_entry_t: - * - * 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 - * be type-compatible with this structure (eg. they must have an - * unsigned long as the first parameter. The easiest way to get this - * is to use: - * - * typedef _my_entry { - * cairo_hash_entry_t base; - * ... Remainder of key and value fields here .. - * } my_entry_t; - * - * which then allows a pointer to my_entry_t to be passed to any of - * the #cairo_hash_table_t functions as follows without requiring a cast: - * - * _cairo_hash_table_insert (hash_table, &my_entry->base); - * - * IMPORTANT: The caller is reponsible for initializing - * my_entry->base.hash with a hash code derived from the key. The - * essential property of the hash code is that keys_equal must never - * return %TRUE for two keys that have different hashes. The best hash - * code will reduce the frequency of two keys with the same code for - * which keys_equal returns %FALSE. - * - * Which parts of the entry make up the "key" and which part make up - * the value are entirely up to the caller, (as determined by the - * computation going into base.hash as well as the keys_equal - * function). A few of the #cairo_hash_table_t functions accept an entry - * which will be used exclusively as a "key", (indicated by a - * parameter name of key). In these cases, the value-related fields of - * the entry need not be initialized if so desired. - **/ -struct _cairo_hash_entry { - unsigned long hash; -}; - -struct _cairo_array { - unsigned int size; - unsigned int num_elements; - unsigned int element_size; - char **elements; - - cairo_bool_t is_snapshot; -}; - -struct _cairo_font_options { - cairo_antialias_t antialias; - cairo_subpixel_order_t subpixel_order; - cairo_hint_style_t hint_style; - cairo_hint_metrics_t hint_metrics; -}; - -struct _cairo_cache { - cairo_hash_table_t *hash_table; - - cairo_destroy_func_t entry_destroy; - - unsigned long max_size; - unsigned long size; - - int freeze_count; -}; - -/* XXX: Right now, the _cairo_color structure puts unpremultiplied - color in the doubles and premultiplied color in the shorts. Yes, - this is crazy insane, (but at least we don't export this - madness). I'm still working on a cleaner API, but in the meantime, - at least this does prevent precision loss in color when changing - alpha. */ -struct _cairo_color { - double red; - double green; - double blue; - double alpha; - - unsigned short red_short; - unsigned short green_short; - unsigned short blue_short; - unsigned short alpha_short; -}; - -typedef enum _cairo_paginated_mode { - CAIRO_PAGINATED_MODE_ANALYZE, /* analyze page regions */ - CAIRO_PAGINATED_MODE_RENDER, /* render page contents */ - CAIRO_PAGINATED_MODE_FALLBACK /* paint fallback images */ -} cairo_paginated_mode_t; - -/* 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 */ -typedef enum _cairo_int_status { - CAIRO_INT_STATUS_UNSUPPORTED = 100, - CAIRO_INT_STATUS_DEGENERATE, - CAIRO_INT_STATUS_NOTHING_TO_DO, - CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY, - CAIRO_INT_STATUS_IMAGE_FALLBACK, - CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN, - - CAIRO_INT_STATUS_LAST_STATUS -} cairo_int_status_t; - -typedef enum _cairo_internal_surface_type { - CAIRO_INTERNAL_SURFACE_TYPE_META = 0x1000, - CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED, - CAIRO_INTERNAL_SURFACE_TYPE_ANALYSIS, - CAIRO_INTERNAL_SURFACE_TYPE_TEST_META, - CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK, - CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED, - CAIRO_INTERNAL_SURFACE_TYPE_NULL, - CAIRO_INTERNAL_SURFACE_TYPE_TYPE3_GLYPH -} cairo_internal_surface_type_t; - -typedef struct _cairo_point { - cairo_fixed_t x; - cairo_fixed_t y; -} cairo_point_t; - -typedef struct _cairo_slope -{ - cairo_fixed_t dx; - cairo_fixed_t dy; -} cairo_slope_t, cairo_distance_t; - -typedef struct _cairo_point_double { - double x; - double y; -} cairo_point_double_t; - -typedef struct _cairo_distance_double { - double dx; - double dy; -} cairo_distance_double_t; - -typedef struct _cairo_line { - cairo_point_t p1; - cairo_point_t p2; -} cairo_line_t, cairo_box_t; - -typedef struct _cairo_trapezoid { - cairo_fixed_t top, bottom; - cairo_line_t left, right; -} cairo_trapezoid_t; - -struct _cairo_rectangle_int16 { - int16_t x, y; - uint16_t width, height; -}; - -struct _cairo_rectangle_int32 { - int32_t x, y; - uint32_t width, height; -}; - -struct _cairo_point_int16 { - int16_t x, y; -}; - -struct _cairo_point_int32 { - int32_t x, y; -}; - -#if CAIRO_FIXED_BITS == 32 && CAIRO_FIXED_FRAC_BITS >= 16 -typedef struct _cairo_rectangle_int16 cairo_rectangle_int_t; -typedef struct _cairo_point_int16 cairo_point_int_t; -#define CAIRO_RECT_INT_MIN (INT16_MIN >> (CAIRO_FIXED_FRAC_BITS - 16)) -#define CAIRO_RECT_INT_MAX (INT16_MAX >> (CAIRO_FIXED_FRAC_BITS - 16)) -#elif CAIRO_FIXED_BITS == 32 -typedef struct _cairo_rectangle_int32 cairo_rectangle_int_t; -typedef struct _cairo_point_int32 cairo_point_int_t; -#define CAIRO_RECT_INT_MIN (INT32_MIN >> CAIRO_FIXED_FRAC_BITS) -#define CAIRO_RECT_INT_MAX (INT32_MAX >> CAIRO_FIXED_FRAC_BITS) -#else -#error Not sure how to pick a cairo_rectangle_int_t and cairo_point_int_t for your CAIRO_FIXED_BITS! -#endif - -typedef struct _cairo_box_int { - cairo_point_int_t p1; - cairo_point_int_t p2; -} cairo_box_int_t; - -typedef enum _cairo_direction { - CAIRO_DIRECTION_FORWARD, - CAIRO_DIRECTION_REVERSE -} cairo_direction_t; - -typedef enum _cairo_clip_mode { - CAIRO_CLIP_MODE_PATH, - CAIRO_CLIP_MODE_REGION, - CAIRO_CLIP_MODE_MASK -} cairo_clip_mode_t; - -typedef struct _cairo_edge { - cairo_line_t edge; - int clockWise; - - cairo_fixed_t current_x; -} cairo_edge_t; - -typedef struct _cairo_polygon { - cairo_status_t status; - - cairo_point_t first_point; - cairo_point_t current_point; - cairo_bool_t has_current_point; - - int num_edges; - int edges_size; - cairo_edge_t *edges; - cairo_edge_t edges_embedded[32]; -} cairo_polygon_t; - -typedef struct _cairo_spline_knots { - cairo_point_t a, b, c, d; -} cairo_spline_knots_t; -typedef struct _cairo_spline { - cairo_spline_knots_t knots; - - cairo_slope_t initial_slope; - cairo_slope_t final_slope; - - int num_points; - int points_size; - cairo_point_t *points; - cairo_point_t points_embedded[64]; -} cairo_spline_t; - -typedef struct _cairo_pen_vertex { - cairo_point_t point; - - cairo_slope_t slope_ccw; - cairo_slope_t slope_cw; -} cairo_pen_vertex_t; - -typedef struct _cairo_pen { - double radius; - double tolerance; - - int num_vertices; - cairo_pen_vertex_t *vertices; - cairo_pen_vertex_t vertices_embedded[32]; -} cairo_pen_t; - -typedef struct _cairo_stroke_style { - double line_width; - cairo_line_cap_t line_cap; - cairo_line_join_t line_join; - double miter_limit; - double *dash; - unsigned int num_dashes; - double dash_offset; -} cairo_stroke_style_t; - -typedef struct _cairo_format_masks { - int bpp; - unsigned long alpha_mask; - unsigned long red_mask; - unsigned long green_mask; - unsigned long blue_mask; -} cairo_format_masks_t; - -typedef enum { - CAIRO_STOCK_WHITE, - CAIRO_STOCK_BLACK, - CAIRO_STOCK_TRANSPARENT -} cairo_stock_t; - -typedef enum _cairo_image_transparency { - CAIRO_IMAGE_IS_OPAQUE, - CAIRO_IMAGE_HAS_BILEVEL_ALPHA, - CAIRO_IMAGE_HAS_ALPHA, - CAIRO_IMAGE_UNKNOWN -} cairo_image_transparency_t; - -#endif /* CAIRO_TYPES_PRIVATE_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-unicode.c b/uppdev/plugin/cairo/lib/cairo-unicode.c deleted file mode 100644 index b1567d42d..000000000 --- a/uppdev/plugin/cairo/lib/cairo-unicode.c +++ /dev/null @@ -1,421 +0,0 @@ -/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */ -/* cairo - a vector graphics library with display and print output - * - * The code in this file is derived from GLib's gutf8.c and - * ultimately from libunicode. It is relicensed under the - * dual LGPL/MPL with permission of the original authors. - * - * Copyright © 1999 Tom Tromey - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Tom Tromey. - * and Red Hat, Inc. - * - * Contributor(s): - * Owen Taylor - */ - -#include "cairoint.h" - -#define UTF8_COMPUTE(Char, Mask, Len) \ - if (Char < 128) \ - { \ - Len = 1; \ - Mask = 0x7f; \ - } \ - else if ((Char & 0xe0) == 0xc0) \ - { \ - Len = 2; \ - Mask = 0x1f; \ - } \ - else if ((Char & 0xf0) == 0xe0) \ - { \ - Len = 3; \ - Mask = 0x0f; \ - } \ - else if ((Char & 0xf8) == 0xf0) \ - { \ - Len = 4; \ - Mask = 0x07; \ - } \ - else if ((Char & 0xfc) == 0xf8) \ - { \ - Len = 5; \ - Mask = 0x03; \ - } \ - else if ((Char & 0xfe) == 0xfc) \ - { \ - Len = 6; \ - Mask = 0x01; \ - } \ - else \ - Len = -1; - -#define UTF8_LENGTH(Char) \ - ((Char) < 0x80 ? 1 : \ - ((Char) < 0x800 ? 2 : \ - ((Char) < 0x10000 ? 3 : \ - ((Char) < 0x200000 ? 4 : \ - ((Char) < 0x4000000 ? 5 : 6))))) - -#define UTF8_GET(Result, Chars, Count, Mask, Len) \ - (Result) = (Chars)[0] & (Mask); \ - for ((Count) = 1; (Count) < (Len); ++(Count)) \ - { \ - if (((Chars)[(Count)] & 0xc0) != 0x80) \ - { \ - (Result) = -1; \ - break; \ - } \ - (Result) <<= 6; \ - (Result) |= ((Chars)[(Count)] & 0x3f); \ - } - -#define UNICODE_VALID(Char) \ - ((Char) < 0x110000 && \ - (((Char) & 0xFFFFF800) != 0xD800) && \ - ((Char) < 0xFDD0 || (Char) > 0xFDEF) && \ - ((Char) & 0xFFFE) != 0xFFFE) - -static const char utf8_skip_data[256] = { - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1 -}; - -#define UTF8_NEXT_CHAR(p) ((p) + utf8_skip_data[*(unsigned char *)(p)]) - -/* Converts a sequence of bytes encoded as UTF-8 to a Unicode character. - * If @p does not point to a valid UTF-8 encoded character, results are - * undefined. - **/ -static uint32_t -_utf8_get_char (const unsigned char *p) -{ - int i, mask = 0, len; - uint32_t result; - unsigned char c = (unsigned char) *p; - - UTF8_COMPUTE (c, mask, len); - if (len == -1) - return (uint32_t)-1; - UTF8_GET (result, p, i, mask, len); - - return result; -} - -/* Like _utf8_get_char, but take a maximum length - * and return (uint32_t)-2 on incomplete trailing character - */ -static uint32_t -_utf8_get_char_extended (const unsigned char *p, - long max_len) -{ - int i, len; - uint32_t wc = (unsigned char) *p; - - if (wc < 0x80) { - return wc; - } else if (wc < 0xc0) { - return (uint32_t)-1; - } else if (wc < 0xe0) { - len = 2; - wc &= 0x1f; - } else if (wc < 0xf0) { - len = 3; - wc &= 0x0f; - } else if (wc < 0xf8) { - len = 4; - wc &= 0x07; - } else if (wc < 0xfc) { - len = 5; - wc &= 0x03; - } else if (wc < 0xfe) { - len = 6; - wc &= 0x01; - } else { - return (uint32_t)-1; - } - - if (max_len >= 0 && len > max_len) { - for (i = 1; i < max_len; i++) { - if ((((unsigned char *)p)[i] & 0xc0) != 0x80) - return (uint32_t)-1; - } - return (uint32_t)-2; - } - - for (i = 1; i < len; ++i) { - uint32_t ch = ((unsigned char *)p)[i]; - - if ((ch & 0xc0) != 0x80) { - if (ch) - return (uint32_t)-1; - else - return (uint32_t)-2; - } - - wc <<= 6; - wc |= (ch & 0x3f); - } - - if (UTF8_LENGTH(wc) != len) - return (uint32_t)-1; - - return wc; -} - -/** - * _cairo_utf8_get_char_validated: - * @p: a UTF-8 string - * @unicode: location to store one Unicode character - * - * Decodes the first character of a valid UTF-8 string, and returns - * the number of bytes consumed. - * - * Note that the string should be valid. Do not use this without - * validating the string first. - * - * Returns: the number of bytes forming the character returned. - **/ -int -_cairo_utf8_get_char_validated (const char *p, - uint32_t *unicode) -{ - int i, mask = 0, len; - uint32_t result; - unsigned char c = (unsigned char) *p; - - UTF8_COMPUTE (c, mask, len); - if (len == -1) { - if (unicode) - *unicode = (uint32_t)-1; - return 1; - } - UTF8_GET (result, p, i, mask, len); - - if (unicode) - *unicode = result; - return len; -} - -/** - * _cairo_utf8_to_ucs4: - * @str: an UTF-8 string - * @len: length of @str in bytes, or -1 if it is nul-terminated. - * If @len is supplied and the string has an embedded nul - * byte, only the portion before the nul byte is converted. - * @result: location to store a pointer to a newly allocated UTF-32 - * string (always native endian), or %NULL. Free with free(). A 0 - * word will be written after the last character. - * @items_written: location to store number of 32-bit words - * written. (Not including the trailing 0) - * - * Converts a UTF-8 string to UCS-4. UCS-4 is an encoding of Unicode - * with 1 32-bit word per character. The string is validated to - * consist entirely of valid Unicode characters. - * - * Return value: %CAIRO_STATUS_SUCCESS if the entire string was - * successfully converted. %CAIRO_STATUS_INVALID_STRING if an - * invalid sequence was found. - **/ -cairo_status_t -_cairo_utf8_to_ucs4 (const char *str, - int len, - uint32_t **result, - int *items_written) -{ - uint32_t *str32 = NULL; - int n_chars, i; - const unsigned char *in; - const unsigned char * const ustr = (const unsigned char *) str; - - in = ustr; - n_chars = 0; - while ((len < 0 || ustr + len - in > 0) && *in) - { - uint32_t wc = _utf8_get_char_extended (in, ustr + len - in); - if (wc & 0x80000000 || !UNICODE_VALID (wc)) - return _cairo_error (CAIRO_STATUS_INVALID_STRING); - - n_chars++; - if (n_chars == INT_MAX) - return _cairo_error (CAIRO_STATUS_INVALID_STRING); - - in = UTF8_NEXT_CHAR (in); - } - - if (result) { - str32 = _cairo_malloc_ab (n_chars + 1, sizeof (uint32_t)); - if (!str32) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - in = ustr; - for (i=0; i < n_chars; i++) { - str32[i] = _utf8_get_char (in); - in = UTF8_NEXT_CHAR (in); - } - str32[i] = 0; - - *result = str32; - } - - if (items_written) - *items_written = n_chars; - - return CAIRO_STATUS_SUCCESS; -} - -/** - * _cairo_ucs4_to_utf8: - * @unicode: a UCS-4 character - * @utf8: buffer to write utf8 string into. Must have at least 4 bytes - * space available. Or %NULL. - * - * This space left intentionally blank. - * - * Return value: Number of bytes in the utf8 string or 0 if an invalid - * unicode character - **/ -int -_cairo_ucs4_to_utf8 (uint32_t unicode, - char *utf8) -{ - int bytes; - char *p; - - if (unicode < 0x80) { - if (utf8) - *utf8 = unicode; - return 1; - } else if (unicode < 0x800) { - bytes = 2; - } else if (unicode < 0x10000) { - bytes = 3; - } else if (unicode < 0x200000) { - bytes = 4; - } else { - return 0; - } - - if (!utf8) - return bytes; - - p = utf8 + bytes; - while (p > utf8) { - *--p = 0x80 | (unicode & 0x3f); - unicode >>= 6; - } - *p |= 0xf0 << (4 - bytes); - - return bytes; -} - -#if CAIRO_HAS_UTF8_TO_UTF16 -/** - * _cairo_utf8_to_utf16: - * @str: an UTF-8 string - * @len: length of @str in bytes, or -1 if it is nul-terminated. - * If @len is supplied and the string has an embedded nul - * byte, only the portion before the nul byte is converted. - * @result: location to store a pointer to a newly allocated UTF-16 - * string (always native endian). Free with free(). A 0 - * word will be written after the last character. - * @items_written: location to store number of 16-bit words - * written. (Not including the trailing 0) - * - * Converts a UTF-8 string to UTF-16. UTF-16 is an encoding of Unicode - * where characters are represented either as a single 16-bit word, or - * as a pair of 16-bit "surrogates". The string is validated to - * consist entirely of valid Unicode characters. - * - * Return value: %CAIRO_STATUS_SUCCESS if the entire string was - * successfully converted. %CAIRO_STATUS_INVALID_STRING if an - * an invalid sequence was found. - **/ -cairo_status_t -_cairo_utf8_to_utf16 (const char *str, - int len, - uint16_t **result, - int *items_written) -{ - uint16_t *str16 = NULL; - int n16, i; - const unsigned char *in; - const unsigned char * const ustr = (const unsigned char *) str; - - in = ustr; - n16 = 0; - while ((len < 0 || ustr + len - in > 0) && *in) { - uint32_t wc = _utf8_get_char_extended (in, ustr + len - in); - if (wc & 0x80000000 || !UNICODE_VALID (wc)) - return _cairo_error (CAIRO_STATUS_INVALID_STRING); - - if (wc < 0x10000) - n16 += 1; - else - n16 += 2; - - if (n16 == INT_MAX - 1 || n16 == INT_MAX) - return _cairo_error (CAIRO_STATUS_INVALID_STRING); - - in = UTF8_NEXT_CHAR (in); - } - - str16 = _cairo_malloc_ab (n16 + 1, sizeof (uint16_t)); - if (!str16) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - in = ustr; - for (i = 0; i < n16;) { - uint32_t wc = _utf8_get_char (in); - - if (wc < 0x10000) { - str16[i++] = wc; - } else { - str16[i++] = (wc - 0x10000) / 0x400 + 0xd800; - str16[i++] = (wc - 0x10000) % 0x400 + 0xdc00; - } - - in = UTF8_NEXT_CHAR (in); - } - - str16[i] = 0; - - *result = str16; - if (items_written) - *items_written = n16; - - return CAIRO_STATUS_SUCCESS; -} -#endif diff --git a/uppdev/plugin/cairo/lib/cairo-user-font-private.h b/uppdev/plugin/cairo/lib/cairo-user-font-private.h deleted file mode 100644 index 2a39ff97a..000000000 --- a/uppdev/plugin/cairo/lib/cairo-user-font-private.h +++ /dev/null @@ -1,46 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2006, 2008 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Kristian Høgsberg - * Behdad Esfahbod - */ - -#ifndef CAIRO_USER_FONT_PRIVATE_H -#define CAIRO_USER_FONT_PRIVATE_H - -#include "cairo.h" -#include "cairo-compiler-private.h" - -cairo_private cairo_bool_t -_cairo_font_face_is_user (cairo_font_face_t *font_face); - -#endif /* CAIRO_USER_FONT_PRIVATE_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-user-font.c b/uppdev/plugin/cairo/lib/cairo-user-font.c deleted file mode 100644 index ddcbc77c8..000000000 --- a/uppdev/plugin/cairo/lib/cairo-user-font.c +++ /dev/null @@ -1,843 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2006, 2008 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Kristian Høgsberg - * Behdad Esfahbod - */ - -#include "cairoint.h" -#include "cairo-user-font-private.h" -#include "cairo-meta-surface-private.h" -#include "cairo-analysis-surface-private.h" - -typedef struct _cairo_user_scaled_font_methods { - cairo_user_scaled_font_init_func_t init; - cairo_user_scaled_font_render_glyph_func_t render_glyph; - cairo_user_scaled_font_unicode_to_glyph_func_t unicode_to_glyph; - cairo_user_scaled_font_text_to_glyphs_func_t text_to_glyphs; -} cairo_user_scaled_font_methods_t; - -typedef struct _cairo_user_font_face { - cairo_font_face_t base; - - /* Set to true after first scaled font is created. At that point, - * the scaled_font_methods cannot change anymore. */ - cairo_bool_t immutable; - - cairo_user_scaled_font_methods_t scaled_font_methods; -} cairo_user_font_face_t; - -typedef struct _cairo_user_scaled_font { - cairo_scaled_font_t base; - - cairo_text_extents_t default_glyph_extents; - - /* space to compute extents in, and factors to convert back to user space */ - cairo_matrix_t extent_scale; - double extent_x_scale; - double extent_y_scale; - - /* multiplier for metrics hinting */ - double snap_x_scale; - double snap_y_scale; - -} cairo_user_scaled_font_t; - -/* #cairo_user_scaled_font_t */ - -static cairo_t * -_cairo_user_scaled_font_create_meta_context (cairo_user_scaled_font_t *scaled_font) -{ - cairo_content_t content; - cairo_surface_t *meta_surface; - cairo_t *cr; - - content = scaled_font->base.options.antialias == CAIRO_ANTIALIAS_SUBPIXEL ? - CAIRO_CONTENT_COLOR_ALPHA : - CAIRO_CONTENT_ALPHA; - - meta_surface = _cairo_meta_surface_create (content, -1, -1); - cr = cairo_create (meta_surface); - cairo_surface_destroy (meta_surface); - - cairo_set_matrix (cr, &scaled_font->base.scale); - cairo_set_font_size (cr, 1.0); - cairo_set_font_options (cr, &scaled_font->base.options); - - return cr; -} - -static cairo_int_status_t -_cairo_user_scaled_glyph_init (void *abstract_font, - cairo_scaled_glyph_t *scaled_glyph, - cairo_scaled_glyph_info_t info) -{ - cairo_int_status_t status = CAIRO_STATUS_SUCCESS; - cairo_user_scaled_font_t *scaled_font = abstract_font; - cairo_surface_t *meta_surface = scaled_glyph->meta_surface; - - if (!scaled_glyph->meta_surface) { - cairo_user_font_face_t *face = - (cairo_user_font_face_t *) scaled_font->base.font_face; - cairo_text_extents_t extents = scaled_font->default_glyph_extents; - cairo_t *cr; - - cr = _cairo_user_scaled_font_create_meta_context (scaled_font); - - if (face->scaled_font_methods.render_glyph) - status = face->scaled_font_methods.render_glyph ((cairo_scaled_font_t *)scaled_font, - _cairo_scaled_glyph_index(scaled_glyph), - cr, &extents); - else - status = CAIRO_STATUS_USER_FONT_ERROR; - - if (status == CAIRO_STATUS_SUCCESS) - status = cairo_status (cr); - - meta_surface = cairo_surface_reference (cairo_get_target (cr)); - - cairo_destroy (cr); - - if (status) { - cairo_surface_destroy (meta_surface); - return status; - } - - _cairo_scaled_glyph_set_meta_surface (scaled_glyph, - &scaled_font->base, - meta_surface); - - - /* set metrics */ - - if (extents.width == 0.) { - /* Compute extents.x/y/width/height from meta_surface, in font space */ - - cairo_box_t bbox; - double x1, y1, x2, y2; - double x_scale, y_scale; - cairo_surface_t *null_surface; - cairo_surface_t *analysis_surface; - - null_surface = _cairo_null_surface_create (cairo_surface_get_content (meta_surface)); - analysis_surface = _cairo_analysis_surface_create (null_surface, -1, -1); - cairo_surface_destroy (null_surface); - status = analysis_surface->status; - if (status) - return status; - - _cairo_analysis_surface_set_ctm (analysis_surface, - &scaled_font->extent_scale); - status = _cairo_meta_surface_replay (meta_surface, - analysis_surface); - _cairo_analysis_surface_get_bounding_box (analysis_surface, &bbox); - cairo_surface_destroy (analysis_surface); - - if (status) - return status; - - _cairo_box_to_doubles (&bbox, &x1, &y1, &x2, &y2); - - x_scale = scaled_font->extent_x_scale; - y_scale = scaled_font->extent_y_scale; - extents.x_bearing = x1 * x_scale; - extents.y_bearing = y1 * y_scale; - extents.width = (x2 - x1) * x_scale; - extents.height = (y2 - y1) * y_scale; - } - - if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) { - extents.x_advance = _cairo_lround (extents.x_advance / scaled_font->snap_x_scale) * scaled_font->snap_x_scale; - extents.y_advance = _cairo_lround (extents.y_advance / scaled_font->snap_y_scale) * scaled_font->snap_y_scale; - } - - _cairo_scaled_glyph_set_metrics (scaled_glyph, - &scaled_font->base, - &extents); - } - - if (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) { - cairo_surface_t *surface; - cairo_status_t status = CAIRO_STATUS_SUCCESS; - cairo_format_t format; - int width, height; - - /* TODO - * extend the glyph cache to support argb glyphs. - * need to figure out the semantics and interaction with subpixel - * rendering first. - */ - - width = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.x) - - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x); - height = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y) - - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y); - - switch (scaled_font->base.options.antialias) { - default: - case CAIRO_ANTIALIAS_DEFAULT: - case CAIRO_ANTIALIAS_GRAY: format = CAIRO_FORMAT_A8; break; - case CAIRO_ANTIALIAS_NONE: format = CAIRO_FORMAT_A1; break; - case CAIRO_ANTIALIAS_SUBPIXEL: format = CAIRO_FORMAT_ARGB32; break; - } - surface = cairo_image_surface_create (format, width, height); - - cairo_surface_set_device_offset (surface, - - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x), - - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y)); - status = _cairo_meta_surface_replay (meta_surface, surface); - - if (status) { - cairo_surface_destroy(surface); - return status; - } - - _cairo_scaled_glyph_set_surface (scaled_glyph, - &scaled_font->base, - (cairo_image_surface_t *) surface); - } - - if (info & CAIRO_SCALED_GLYPH_INFO_PATH) { - cairo_path_fixed_t *path = _cairo_path_fixed_create (); - if (!path) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - status = _cairo_meta_surface_get_path (meta_surface, path); - - if (status) { - _cairo_path_fixed_destroy (path); - return status; - } - - _cairo_scaled_glyph_set_path (scaled_glyph, - &scaled_font->base, - path); - } - - return status; -} - -static unsigned long -_cairo_user_ucs4_to_index (void *abstract_font, - uint32_t ucs4) -{ - cairo_user_scaled_font_t *scaled_font = abstract_font; - cairo_user_font_face_t *face = - (cairo_user_font_face_t *) scaled_font->base.font_face; - unsigned long glyph = 0; - - if (face->scaled_font_methods.unicode_to_glyph) { - cairo_status_t status; - - status = face->scaled_font_methods.unicode_to_glyph (&scaled_font->base, - ucs4, &glyph); - - if (status != CAIRO_STATUS_SUCCESS) { - status = _cairo_scaled_font_set_error (&scaled_font->base, status); - glyph = 0; - } - - } else { - glyph = ucs4; - } - - return glyph; -} - -static cairo_int_status_t -_cairo_user_text_to_glyphs (void *abstract_font, - double x, - double y, - const char *utf8, - int utf8_len, - cairo_glyph_t **glyphs, - int *num_glyphs, - cairo_text_cluster_t **clusters, - int *num_clusters, - cairo_text_cluster_flags_t *cluster_flags) -{ - cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED; - - cairo_user_scaled_font_t *scaled_font = abstract_font; - cairo_user_font_face_t *face = - (cairo_user_font_face_t *) scaled_font->base.font_face; - - if (face->scaled_font_methods.text_to_glyphs) { - int i; - cairo_glyph_t *orig_glyphs = *glyphs; - int orig_num_glyphs = *num_glyphs; - - status = face->scaled_font_methods.text_to_glyphs (&scaled_font->base, - utf8, utf8_len, - glyphs, num_glyphs, - clusters, num_clusters, cluster_flags); - - if (status != CAIRO_STATUS_SUCCESS) - return status; - - if (*num_glyphs < 0) { - if (orig_glyphs != *glyphs) { - cairo_glyph_free (*glyphs); - *glyphs = orig_glyphs; - } - *num_glyphs = orig_num_glyphs; - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - /* Convert from font space to user space and add x,y */ - for (i = 0; i < *num_glyphs; i++) { - double gx = (*glyphs)[i].x; - double gy = (*glyphs)[i].y; - - cairo_matrix_transform_point (&scaled_font->base.font_matrix, - &gx, &gy); - - (*glyphs)[i].x = gx + x; - (*glyphs)[i].y = gy + y; - } - } - - return status; -} - -static cairo_status_t -_cairo_user_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 **scaled_font); - -static cairo_status_t -_cairo_user_scaled_font_get_implementation (cairo_toy_font_face_t *toy_face, - cairo_font_face_t **font_face_out) -{ - static cairo_user_data_key_t twin_font_face_key; - - cairo_font_face_t *face; - cairo_status_t status; - - face = cairo_font_face_get_user_data (&toy_face->base, - &twin_font_face_key); - if (!face) { - face = _cairo_font_face_twin_create (cairo_toy_font_face_get_slant (&toy_face->base), - cairo_toy_font_face_get_weight (&toy_face->base)); - - status = cairo_font_face_set_user_data (&toy_face->base, - &twin_font_face_key, - face, - (cairo_destroy_func_t) cairo_font_face_destroy); - - if (status) { - cairo_font_face_destroy (face); - return status; - } - } - - *font_face_out = face; - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_user_scaled_font_create_toy (cairo_toy_font_face_t *toy_face, - const cairo_matrix_t *font_matrix, - const cairo_matrix_t *ctm, - const cairo_font_options_t *font_options, - cairo_scaled_font_t **font) -{ - cairo_font_face_t *face; - cairo_status_t status; - - status = _cairo_user_scaled_font_get_implementation (toy_face, &face); - if (status) - return status; - - status = _cairo_user_font_face_scaled_font_create (face, - font_matrix, - ctm, - font_options, - font); - if (status) - return status; - - return CAIRO_STATUS_SUCCESS; -} - -const cairo_scaled_font_backend_t _cairo_user_scaled_font_backend = { - CAIRO_FONT_TYPE_USER, - _cairo_user_scaled_font_get_implementation, - _cairo_user_scaled_font_create_toy, /* create_toy */ - NULL, /* scaled_font_fini */ - _cairo_user_scaled_glyph_init, - _cairo_user_text_to_glyphs, - _cairo_user_ucs4_to_index, - NULL, /* show_glyphs */ - NULL, /* load_truetype_table */ - NULL /* index_to_ucs4 */ -}; - -/* #cairo_user_font_face_t */ - -static cairo_status_t -_cairo_user_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 **scaled_font) -{ - cairo_status_t status = CAIRO_STATUS_SUCCESS; - cairo_user_font_face_t *font_face = abstract_face; - cairo_user_scaled_font_t *user_scaled_font = NULL; - cairo_font_extents_t font_extents = {1., 0., 1., 1., 0.}; - - font_face->immutable = TRUE; - - user_scaled_font = malloc (sizeof (cairo_user_scaled_font_t)); - if (user_scaled_font == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - status = _cairo_scaled_font_init (&user_scaled_font->base, - &font_face->base, - font_matrix, ctm, options, - &_cairo_user_scaled_font_backend); - - if (status) { - free (user_scaled_font); - return status; - } - - /* XXX metrics hinting? */ - - /* compute a normalized version of font scale matrix to compute - * extents in. This is to minimize error caused by the cairo_fixed_t - * representation. */ - { - double fixed_scale, x_scale, y_scale; - - user_scaled_font->extent_scale = user_scaled_font->base.scale_inverse; - status = _cairo_matrix_compute_basis_scale_factors (&user_scaled_font->extent_scale, - &x_scale, &y_scale, - 1); - if (status == CAIRO_STATUS_SUCCESS) { - - if (x_scale == 0) x_scale = 1.; - if (y_scale == 0) y_scale = 1.; - - user_scaled_font->snap_x_scale = x_scale; - user_scaled_font->snap_y_scale = y_scale; - - /* since glyphs are pretty much 1.0x1.0, we can reduce error by - * scaling to a larger square. say, 1024.x1024. */ - fixed_scale = 1024.; - x_scale /= fixed_scale; - y_scale /= fixed_scale; - - cairo_matrix_scale (&user_scaled_font->extent_scale, 1. / x_scale, 1. / y_scale); - - user_scaled_font->extent_x_scale = x_scale; - user_scaled_font->extent_y_scale = y_scale; - } - } - - if (status == CAIRO_STATUS_SUCCESS && - font_face->scaled_font_methods.init != NULL) - { - /* Lock the scaled_font mutex such that user doesn't accidentally try - * to use it just yet. */ - CAIRO_MUTEX_LOCK (user_scaled_font->base.mutex); - - /* Give away fontmap lock such that user-font can use other fonts */ - status = _cairo_scaled_font_register_placeholder_and_unlock_font_map (&user_scaled_font->base); - if (status == CAIRO_STATUS_SUCCESS) { - cairo_t *cr; - - cr = _cairo_user_scaled_font_create_meta_context (user_scaled_font); - - status = font_face->scaled_font_methods.init (&user_scaled_font->base, - cr, - &font_extents); - - if (status == CAIRO_STATUS_SUCCESS) - status = cairo_status (cr); - - cairo_destroy (cr); - - _cairo_scaled_font_unregister_placeholder_and_lock_font_map (&user_scaled_font->base); - } - - CAIRO_MUTEX_UNLOCK (user_scaled_font->base.mutex); - } - - if (status == CAIRO_STATUS_SUCCESS) - status = _cairo_scaled_font_set_metrics (&user_scaled_font->base, &font_extents); - - if (status != CAIRO_STATUS_SUCCESS) { - _cairo_scaled_font_fini (&user_scaled_font->base); - free (user_scaled_font); - } else { - user_scaled_font->default_glyph_extents.x_bearing = 0.; - user_scaled_font->default_glyph_extents.y_bearing = -font_extents.ascent; - user_scaled_font->default_glyph_extents.width = 0.; - user_scaled_font->default_glyph_extents.height = font_extents.ascent + font_extents.descent; - user_scaled_font->default_glyph_extents.x_advance = font_extents.max_x_advance; - user_scaled_font->default_glyph_extents.y_advance = 0.; - - *scaled_font = &user_scaled_font->base; - } - - return status; -} - -static const cairo_font_face_backend_t _cairo_user_font_face_backend = { - CAIRO_FONT_TYPE_USER, - NULL, /* destroy */ - NULL, /* direct implementation */ - _cairo_user_font_face_scaled_font_create -}; - - -cairo_bool_t -_cairo_font_face_is_user (cairo_font_face_t *font_face) -{ - return font_face->backend == &_cairo_user_font_face_backend; -} - -/* Implement the public interface */ - -/** - * cairo_user_font_face_create: - * - * Creates a new user font-face. - * - * Use the setter functions to associate callbacks with the returned - * user font. The only mandatory callback is render_glyph. - * - * After the font-face is created, the user can attach arbitrary data - * (the actual font data) to it using cairo_font_face_set_user_data() - * and access it from the user-font callbacks by using - * cairo_scaled_font_get_font_face() followed by - * cairo_font_face_get_user_data(). - * - * Return value: a newly created #cairo_font_face_t. Free with - * cairo_font_face_destroy() when you are done using it. - * - * Since: 1.8 - **/ -cairo_font_face_t * -cairo_user_font_face_create (void) -{ - cairo_user_font_face_t *font_face; - - font_face = malloc (sizeof (cairo_user_font_face_t)); - if (!font_face) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_font_face_t *)&_cairo_font_face_nil; - } - - _cairo_font_face_init (&font_face->base, &_cairo_user_font_face_backend); - - font_face->immutable = FALSE; - memset (&font_face->scaled_font_methods, 0, sizeof (font_face->scaled_font_methods)); - - return &font_face->base; -} -slim_hidden_def(cairo_user_font_face_create); - -/* User-font method setters */ - - -/** - * cairo_user_font_face_set_init_func: - * @font_face: A user font face - * @init_func: The init callback, or %NULL - * - * Sets the scaled-font initialization function of a user-font. - * See #cairo_user_scaled_font_init_func_t for details of how the callback - * works. - * - * The font-face should not be immutable or a %CAIRO_STATUS_USER_FONT_IMMUTABLE - * error will occur. A user font-face is immutable as soon as a scaled-font - * is created from it. - * - * Since: 1.8 - **/ -void -cairo_user_font_face_set_init_func (cairo_font_face_t *font_face, - cairo_user_scaled_font_init_func_t init_func) -{ - cairo_user_font_face_t *user_font_face; - - if (font_face->status) - return; - - if (! _cairo_font_face_is_user (font_face)) { - if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH)) - return; - } - - user_font_face = (cairo_user_font_face_t *) font_face; - if (user_font_face->immutable) { - if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE)) - return; - } - user_font_face->scaled_font_methods.init = init_func; -} -slim_hidden_def(cairo_user_font_face_set_init_func); - -/** - * cairo_user_font_face_set_render_glyph_func: - * @font_face: A user font face - * @render_glyph_func: The render_glyph callback, or %NULL - * - * Sets the glyph rendering function of a user-font. - * See #cairo_user_scaled_font_render_glyph_func_t for details of how the callback - * works. - * - * The font-face should not be immutable or a %CAIRO_STATUS_USER_FONT_IMMUTABLE - * error will occur. A user font-face is immutable as soon as a scaled-font - * is created from it. - * - * The render_glyph callback is the only mandatory callback of a user-font. - * If the callback is %NULL and a glyph is tried to be rendered using - * @font_face, a %CAIRO_STATUS_USER_FONT_ERROR will occur. - * - * Since: 1.8 - **/ -void -cairo_user_font_face_set_render_glyph_func (cairo_font_face_t *font_face, - cairo_user_scaled_font_render_glyph_func_t render_glyph_func) -{ - cairo_user_font_face_t *user_font_face; - - if (font_face->status) - return; - - if (! _cairo_font_face_is_user (font_face)) { - if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH)) - return; - } - - user_font_face = (cairo_user_font_face_t *) font_face; - if (user_font_face->immutable) { - if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE)) - return; - } - user_font_face->scaled_font_methods.render_glyph = render_glyph_func; -} -slim_hidden_def(cairo_user_font_face_set_render_glyph_func); - -/** - * cairo_user_font_face_set_text_to_glyphs_func: - * @font_face: A user font face - * @text_to_glyphs_func: The text_to_glyphs callback, or %NULL - * - * Sets th text-to-glyphs conversion function of a user-font. - * See #cairo_user_scaled_font_text_to_glyphs_func_t for details of how the callback - * works. - * - * The font-face should not be immutable or a %CAIRO_STATUS_USER_FONT_IMMUTABLE - * error will occur. A user font-face is immutable as soon as a scaled-font - * is created from it. - * - * Since: 1.8 - **/ -void -cairo_user_font_face_set_text_to_glyphs_func (cairo_font_face_t *font_face, - cairo_user_scaled_font_text_to_glyphs_func_t text_to_glyphs_func) -{ - cairo_user_font_face_t *user_font_face; - - if (font_face->status) - return; - - if (! _cairo_font_face_is_user (font_face)) { - if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH)) - return; - } - - user_font_face = (cairo_user_font_face_t *) font_face; - if (user_font_face->immutable) { - if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE)) - return; - } - user_font_face->scaled_font_methods.text_to_glyphs = text_to_glyphs_func; -} - -/** - * cairo_user_font_face_set_unicode_to_glyph_func: - * @font_face: A user font face - * @unicode_to_glyph_func: The unicode_to_glyph callback, or %NULL - * - * Sets the unicode-to-glyph conversion function of a user-font. - * See #cairo_user_scaled_font_unicode_to_glyph_func_t for details of how the callback - * works. - * - * The font-face should not be immutable or a %CAIRO_STATUS_USER_FONT_IMMUTABLE - * error will occur. A user font-face is immutable as soon as a scaled-font - * is created from it. - * - * Since: 1.8 - **/ -void -cairo_user_font_face_set_unicode_to_glyph_func (cairo_font_face_t *font_face, - cairo_user_scaled_font_unicode_to_glyph_func_t unicode_to_glyph_func) -{ - cairo_user_font_face_t *user_font_face; - if (font_face->status) - return; - - if (! _cairo_font_face_is_user (font_face)) { - if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH)) - return; - } - - user_font_face = (cairo_user_font_face_t *) font_face; - if (user_font_face->immutable) { - if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE)) - return; - } - user_font_face->scaled_font_methods.unicode_to_glyph = unicode_to_glyph_func; -} -slim_hidden_def(cairo_user_font_face_set_unicode_to_glyph_func); - -/* User-font method getters */ - -/** - * cairo_user_font_face_get_init_func: - * @font_face: A user font face - * - * Gets the scaled-font initialization function of a user-font. - * - * Return value: The init callback of @font_face - * or %NULL if none set or an error has occurred. - * - * Since: 1.8 - **/ -cairo_user_scaled_font_init_func_t -cairo_user_font_face_get_init_func (cairo_font_face_t *font_face) -{ - cairo_user_font_face_t *user_font_face; - - if (font_face->status) - return NULL; - - if (! _cairo_font_face_is_user (font_face)) { - if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH)) - return NULL; - } - - user_font_face = (cairo_user_font_face_t *) font_face; - return user_font_face->scaled_font_methods.init; -} - -/** - * cairo_user_font_face_get_render_glyph_func: - * @font_face: A user font face - * - * Gets the glyph rendering function of a user-font. - * - * Return value: The render_glyph callback of @font_face - * or %NULL if none set or an error has occurred. - * - * Since: 1.8 - **/ -cairo_user_scaled_font_render_glyph_func_t -cairo_user_font_face_get_render_glyph_func (cairo_font_face_t *font_face) -{ - cairo_user_font_face_t *user_font_face; - - if (font_face->status) - return NULL; - - if (! _cairo_font_face_is_user (font_face)) { - if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH)) - return NULL; - } - - user_font_face = (cairo_user_font_face_t *) font_face; - return user_font_face->scaled_font_methods.render_glyph; -} - -/** - * cairo_user_font_face_get_text_to_glyphs_func: - * @font_face: A user font face - * - * Gets the text-to-glyphs conversion function of a user-font. - * - * Return value: The text_to_glyphs callback of @font_face - * or %NULL if none set or an error occurred. - * - * Since: 1.8 - **/ -cairo_user_scaled_font_text_to_glyphs_func_t -cairo_user_font_face_get_text_to_glyphs_func (cairo_font_face_t *font_face) -{ - cairo_user_font_face_t *user_font_face; - - if (font_face->status) - return NULL; - - if (! _cairo_font_face_is_user (font_face)) { - if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH)) - return NULL; - } - - user_font_face = (cairo_user_font_face_t *) font_face; - return user_font_face->scaled_font_methods.text_to_glyphs; -} - -/** - * cairo_user_font_face_get_unicode_to_glyph_func: - * @font_face: A user font face - * - * Gets the unicode-to-glyph conversion function of a user-font. - * - * Return value: The unicode_to_glyph callback of @font_face - * or %NULL if none set or an error occurred. - * - * Since: 1.8 - **/ -cairo_user_scaled_font_unicode_to_glyph_func_t -cairo_user_font_face_get_unicode_to_glyph_func (cairo_font_face_t *font_face) -{ - cairo_user_font_face_t *user_font_face; - - if (font_face->status) - return NULL; - - if (! _cairo_font_face_is_user (font_face)) { - if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH)) - return NULL; - } - - user_font_face = (cairo_user_font_face_t *) font_face; - return user_font_face->scaled_font_methods.unicode_to_glyph; -} diff --git a/uppdev/plugin/cairo/lib/cairo-version.c b/uppdev/plugin/cairo/lib/cairo-version.c deleted file mode 100644 index a502988e2..000000000 --- a/uppdev/plugin/cairo/lib/cairo-version.c +++ /dev/null @@ -1,88 +0,0 @@ -/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - */ - -#define CAIRO_VERSION_H 1 - -#include "cairoint.h" - -/* get the "real" version info instead of dummy cairo-version.h */ -#undef CAIRO_VERSION_H -#include "../cairo-version.h" - -/** - * cairo_version: - * - * Returns the version of the cairo library encoded in a single - * integer as per %CAIRO_VERSION_ENCODE. The encoding ensures that - * later versions compare greater than earlier versions. - * - * A run-time comparison to check that cairo's version is greater than - * or equal to version X.Y.Z could be performed as follows: - * - * - * if (cairo_version() >= CAIRO_VERSION_ENCODE(X,Y,Z)) {...} - * - * - * See also cairo_version_string() as well as the compile-time - * equivalents %CAIRO_VERSION and %CAIRO_VERSION_STRING. - * - * Return value: the encoded version. - **/ -int -cairo_version (void) -{ - return CAIRO_VERSION; -} - -/** - * cairo_version_string: - * - * Returns the version of the cairo library as a human-readable string - * of the form "X.Y.Z". - * - * See also cairo_version() as well as the compile-time equivalents - * %CAIRO_VERSION_STRING and %CAIRO_VERSION. - * - * Return value: a string containing the version. - **/ -const char* -cairo_version_string (void) -{ - return CAIRO_VERSION_STRING; -} -slim_hidden_def (cairo_version_string); diff --git a/uppdev/plugin/cairo/lib/cairo-version.h b/uppdev/plugin/cairo/lib/cairo-version.h deleted file mode 100644 index 51008003f..000000000 --- a/uppdev/plugin/cairo/lib/cairo-version.h +++ /dev/null @@ -1,14 +0,0 @@ -/* This is a dummy file. - * The actual version info is in toplevel cairo-version.h. - * The purpose of this file is to make most of the source files NOT depend - * on the real cairo-version.h, and as a result, changing library version - * would not cause a complete rebuild of all object files (just a relink). - * This is useful when bisecting. */ -#ifndef CAIRO_VERSION_H -#define CAIRO_VERSION_H - -#define CAIRO_VERSION_MAJOR USE_cairo_version_OR_cairo_version_string_INSTEAD -#define CAIRO_VERSION_MINOR USE_cairo_version_OR_cairo_version_string_INSTEAD -#define CAIRO_VERSION_MICRO USE_cairo_version_OR_cairo_version_string_INSTEAD - -#endif diff --git a/uppdev/plugin/cairo/lib/cairo-wideint-private.h b/uppdev/plugin/cairo/lib/cairo-wideint-private.h deleted file mode 100644 index f5aac2848..000000000 --- a/uppdev/plugin/cairo/lib/cairo-wideint-private.h +++ /dev/null @@ -1,277 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2004 Keith Packard - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Keith Packard - * - * Contributor(s): - * Keith R. Packard - * - */ - -#ifndef CAIRO_WIDEINT_H -#define CAIRO_WIDEINT_H - -#include "cairo-wideint-type-private.h" - -#include "cairo-compiler-private.h" - -/* - * 64-bit datatypes. Two separate implementations, one using - * built-in 64-bit signed/unsigned types another implemented - * as a pair of 32-bit ints - */ - -#define I cairo_private cairo_const - -#if !HAVE_UINT64_T - -cairo_uint64_t I _cairo_uint32_to_uint64 (uint32_t i); -#define _cairo_uint64_to_uint32(a) ((a).lo) -cairo_uint64_t I _cairo_uint64_add (cairo_uint64_t a, cairo_uint64_t b); -cairo_uint64_t I _cairo_uint64_sub (cairo_uint64_t a, cairo_uint64_t b); -cairo_uint64_t I _cairo_uint64_mul (cairo_uint64_t a, cairo_uint64_t b); -cairo_uint64_t I _cairo_uint32x32_64_mul (uint32_t a, uint32_t b); -cairo_uint64_t I _cairo_uint64_lsl (cairo_uint64_t a, int shift); -cairo_uint64_t I _cairo_uint64_rsl (cairo_uint64_t a, int shift); -cairo_uint64_t I _cairo_uint64_rsa (cairo_uint64_t a, int shift); -int I _cairo_uint64_lt (cairo_uint64_t a, cairo_uint64_t b); -int I _cairo_uint64_cmp (cairo_uint64_t a, cairo_uint64_t b); -int I _cairo_uint64_eq (cairo_uint64_t a, cairo_uint64_t b); -cairo_uint64_t I _cairo_uint64_negate (cairo_uint64_t a); -#define _cairo_uint64_is_zero(a) ((a).hi == 0 && (a).lo == 0) -#define _cairo_uint64_negative(a) (((int32_t) ((a).hi)) < 0) -cairo_uint64_t I _cairo_uint64_not (cairo_uint64_t a); - -#define _cairo_uint64_to_int64(i) (i) -#define _cairo_int64_to_uint64(i) (i) - -cairo_int64_t I _cairo_int32_to_int64(int32_t i); -#define _cairo_int64_to_int32(a) ((int32_t) _cairo_uint64_to_uint32(a)) -#define _cairo_int64_add(a,b) _cairo_uint64_add (a,b) -#define _cairo_int64_sub(a,b) _cairo_uint64_sub (a,b) -#define _cairo_int64_mul(a,b) _cairo_uint64_mul (a,b) -cairo_int64_t I _cairo_int32x32_64_mul (int32_t a, int32_t b); -int I _cairo_int64_lt (cairo_int64_t a, cairo_int64_t b); -int I _cairo_int64_cmp (cairo_int64_t a, cairo_int64_t b); -#define _cairo_int64_is_zero(a) _cairo_uint64_is_zero (a) -#define _cairo_int64_eq(a,b) _cairo_uint64_eq (a,b) -#define _cairo_int64_lsl(a,b) _cairo_uint64_lsl (a,b) -#define _cairo_int64_rsl(a,b) _cairo_uint64_rsl (a,b) -#define _cairo_int64_rsa(a,b) _cairo_uint64_rsa (a,b) -#define _cairo_int64_negate(a) _cairo_uint64_negate(a) -#define _cairo_int64_negative(a) (((int32_t) ((a).hi)) < 0) -#define _cairo_int64_not(a) _cairo_uint64_not(a) - -#else - -#define _cairo_uint32_to_uint64(i) ((uint64_t) (i)) -#define _cairo_uint64_to_uint32(i) ((uint32_t) (i)) -#define _cairo_uint64_add(a,b) ((a) + (b)) -#define _cairo_uint64_sub(a,b) ((a) - (b)) -#define _cairo_uint64_mul(a,b) ((a) * (b)) -#define _cairo_uint32x32_64_mul(a,b) ((uint64_t) (a) * (b)) -#define _cairo_uint64_lsl(a,b) ((a) << (b)) -#define _cairo_uint64_rsl(a,b) ((uint64_t) (a) >> (b)) -#define _cairo_uint64_rsa(a,b) ((uint64_t) ((int64_t) (a) >> (b))) -#define _cairo_uint64_lt(a,b) ((a) < (b)) -#define _cairo_uint64_cmp(a,b) ((a) == (b) ? 0 : (a) < (b) ? -1 : 1) -#define _cairo_uint64_is_zero(a) ((a) == 0) -#define _cairo_uint64_eq(a,b) ((a) == (b)) -#define _cairo_uint64_negate(a) ((uint64_t) -((int64_t) (a))) -#define _cairo_uint64_negative(a) ((int64_t) (a) < 0) -#define _cairo_uint64_not(a) (~(a)) - -#define _cairo_uint64_to_int64(i) ((int64_t) (i)) -#define _cairo_int64_to_uint64(i) ((uint64_t) (i)) - -#define _cairo_int32_to_int64(i) ((int64_t) (i)) -#define _cairo_int64_to_int32(i) ((int32_t) (i)) -#define _cairo_int64_add(a,b) ((a) + (b)) -#define _cairo_int64_sub(a,b) ((a) - (b)) -#define _cairo_int64_mul(a,b) ((a) * (b)) -#define _cairo_int32x32_64_mul(a,b) ((int64_t) (a) * (b)) -#define _cairo_int64_lt(a,b) ((a) < (b)) -#define _cairo_int64_cmp(a,b) ((a) == (b) ? 0 : (a) < (b) ? -1 : 1) -#define _cairo_int64_is_zero(a) ((a) == 0) -#define _cairo_int64_eq(a,b) ((a) == (b)) -#define _cairo_int64_lsl(a,b) ((a) << (b)) -#define _cairo_int64_rsl(a,b) ((int64_t) ((uint64_t) (a) >> (b))) -#define _cairo_int64_rsa(a,b) ((int64_t) (a) >> (b)) -#define _cairo_int64_negate(a) (-(a)) -#define _cairo_int64_negative(a) ((a) < 0) -#define _cairo_int64_not(a) (~(a)) - -#endif - -/* - * 64-bit comparisions derived from lt or eq - */ -#define _cairo_uint64_le(a,b) (!_cairo_uint64_gt(a,b)) -#define _cairo_uint64_ne(a,b) (!_cairo_uint64_eq(a,b)) -#define _cairo_uint64_ge(a,b) (!_cairo_uint64_lt(a,b)) -#define _cairo_uint64_gt(a,b) _cairo_uint64_lt(b,a) - -#define _cairo_int64_le(a,b) (!_cairo_int64_gt(a,b)) -#define _cairo_int64_ne(a,b) (!_cairo_int64_eq(a,b)) -#define _cairo_int64_ge(a,b) (!_cairo_int64_lt(a,b)) -#define _cairo_int64_gt(a,b) _cairo_int64_lt(b,a) - -/* - * As the C implementation always computes both, create - * a function which returns both for the 'native' type as well - */ - -cairo_uquorem64_t I -_cairo_uint64_divrem (cairo_uint64_t num, cairo_uint64_t den); - -cairo_quorem64_t I -_cairo_int64_divrem (cairo_int64_t num, cairo_int64_t den); - -/* - * 128-bit datatypes. Again, provide two implementations in - * case the machine has a native 128-bit datatype. GCC supports int128_t - * on ia64 - */ - -#if !HAVE_UINT128_T - -cairo_uint128_t I _cairo_uint32_to_uint128 (uint32_t i); -cairo_uint128_t I _cairo_uint64_to_uint128 (cairo_uint64_t i); -#define _cairo_uint128_to_uint64(a) ((a).lo) -#define _cairo_uint128_to_uint32(a) _cairo_uint64_to_uint32(_cairo_uint128_to_uint64(a)) -cairo_uint128_t I _cairo_uint128_add (cairo_uint128_t a, cairo_uint128_t b); -cairo_uint128_t I _cairo_uint128_sub (cairo_uint128_t a, cairo_uint128_t b); -cairo_uint128_t I _cairo_uint128_mul (cairo_uint128_t a, cairo_uint128_t b); -cairo_uint128_t I _cairo_uint64x64_128_mul (cairo_uint64_t a, cairo_uint64_t b); -cairo_uint128_t I _cairo_uint128_lsl (cairo_uint128_t a, int shift); -cairo_uint128_t I _cairo_uint128_rsl (cairo_uint128_t a, int shift); -cairo_uint128_t I _cairo_uint128_rsa (cairo_uint128_t a, int shift); -int I _cairo_uint128_lt (cairo_uint128_t a, cairo_uint128_t b); -int I _cairo_uint128_cmp (cairo_uint128_t a, cairo_uint128_t b); -int I _cairo_uint128_eq (cairo_uint128_t a, cairo_uint128_t b); -#define _cairo_uint128_is_zero(a) (_cairo_uint64_is_zero ((a).hi) && _cairo_uint64_is_zero ((a).lo)) -cairo_uint128_t I _cairo_uint128_negate (cairo_uint128_t a); -#define _cairo_uint128_negative(a) (_cairo_uint64_negative(a.hi)) -cairo_uint128_t I _cairo_uint128_not (cairo_uint128_t a); - -#define _cairo_uint128_to_int128(i) (i) -#define _cairo_int128_to_uint128(i) (i) - -cairo_int128_t I _cairo_int32_to_int128 (int32_t i); -cairo_int128_t I _cairo_int64_to_int128 (cairo_int64_t i); -#define _cairo_int128_to_int64(a) ((cairo_int64_t) (a).lo) -#define _cairo_int128_to_int32(a) _cairo_int64_to_int32(_cairo_int128_to_int64(a)) -#define _cairo_int128_add(a,b) _cairo_uint128_add(a,b) -#define _cairo_int128_sub(a,b) _cairo_uint128_sub(a,b) -#define _cairo_int128_mul(a,b) _cairo_uint128_mul(a,b) -cairo_int128_t I _cairo_int64x64_128_mul (cairo_int64_t a, cairo_int64_t b); -#define _cairo_int64x32_128_mul(a, b) _cairo_int64x64_128_mul(a, _cairo_int32_to_int64(b)) -#define _cairo_int128_lsl(a,b) _cairo_uint128_lsl(a,b) -#define _cairo_int128_rsl(a,b) _cairo_uint128_rsl(a,b) -#define _cairo_int128_rsa(a,b) _cairo_uint128_rsa(a,b) -int I _cairo_int128_lt (cairo_int128_t a, cairo_int128_t b); -int I _cairo_int128_cmp (cairo_int128_t a, cairo_int128_t b); -#define _cairo_int128_is_zero(a) _cairo_uint128_is_zero (a) -#define _cairo_int128_eq(a,b) _cairo_uint128_eq (a,b) -#define _cairo_int128_negate(a) _cairo_uint128_negate(a) -#define _cairo_int128_negative(a) (_cairo_uint128_negative(a)) -#define _cairo_int128_not(a) _cairo_uint128_not(a) - -#else /* !HAVE_UINT128_T */ - -#define _cairo_uint32_to_uint128(i) ((uint128_t) (i)) -#define _cairo_uint64_to_uint128(i) ((uint128_t) (i)) -#define _cairo_uint128_to_uint64(i) ((uint64_t) (i)) -#define _cairo_uint128_to_uint32(i) ((uint32_t) (i)) -#define _cairo_uint128_add(a,b) ((a) + (b)) -#define _cairo_uint128_sub(a,b) ((a) - (b)) -#define _cairo_uint128_mul(a,b) ((a) * (b)) -#define _cairo_uint64x64_128_mul(a,b) ((uint128_t) (a) * (b)) -#define _cairo_uint128_lsl(a,b) ((a) << (b)) -#define _cairo_uint128_rsl(a,b) ((uint128_t) (a) >> (b)) -#define _cairo_uint128_rsa(a,b) ((uint128_t) ((int128_t) (a) >> (b))) -#define _cairo_uint128_lt(a,b) ((a) < (b)) -#define _cairo_uint128_cmp(a,b) ((a) == (b) ? 0 : (a) < (b) ? -1 : 1) -#define _cairo_uint128_is_zero(a) ((a) == 0) -#define _cairo_uint128_eq(a,b) ((a) == (b)) -#define _cairo_uint128_negate(a) ((uint128_t) -((int128_t) (a))) -#define _cairo_uint128_negative(a) ((int128_t) (a) < 0) -#define _cairo_uint128_not(a) (~(a)) - -#define _cairo_uint128_to_int128(i) ((int128_t) (i)) -#define _cairo_int128_to_uint128(i) ((uint128_t) (i)) - -#define _cairo_int32_to_int128(i) ((int128_t) (i)) -#define _cairo_int64_to_int128(i) ((int128_t) (i)) -#define _cairo_int128_to_int64(i) ((int64_t) (i)) -#define _cairo_int128_to_int32(i) ((int32_t) (i)) -#define _cairo_int128_add(a,b) ((a) + (b)) -#define _cairo_int128_sub(a,b) ((a) - (b)) -#define _cairo_int128_mul(a,b) ((a) * (b)) -#define _cairo_int64x64_128_mul(a,b) ((int128_t) (a) * (b)) -#define _cairo_int128_lt(a,b) ((a) < (b)) -#define _cairo_int128_cmp(a,b) ((a) == (b) ? 0 : (a) < (b) ? -1 : 1) -#define _cairo_int128_is_zero(a) ((a) == 0) -#define _cairo_int128_eq(a,b) ((a) == (b)) -#define _cairo_int128_lsl(a,b) ((a) << (b)) -#define _cairo_int128_rsl(a,b) ((int128_t) ((uint128_t) (a) >> (b))) -#define _cairo_int128_rsa(a,b) ((int128_t) (a) >> (b)) -#define _cairo_int128_negate(a) (-(a)) -#define _cairo_int128_negative(a) ((a) < 0) -#define _cairo_int128_not(a) (~(a)) - -#endif /* HAVE_UINT128_T */ - -cairo_uquorem128_t I -_cairo_uint128_divrem (cairo_uint128_t num, cairo_uint128_t den); - -cairo_quorem128_t I -_cairo_int128_divrem (cairo_int128_t num, cairo_int128_t den); - -cairo_uquorem64_t I -_cairo_uint_96by64_32x64_divrem (cairo_uint128_t num, - cairo_uint64_t den); - -cairo_quorem64_t I -_cairo_int_96by64_32x64_divrem (cairo_int128_t num, - cairo_int64_t den); - -#define _cairo_uint128_le(a,b) (!_cairo_uint128_gt(a,b)) -#define _cairo_uint128_ne(a,b) (!_cairo_uint128_eq(a,b)) -#define _cairo_uint128_ge(a,b) (!_cairo_uint128_lt(a,b)) -#define _cairo_uint128_gt(a,b) _cairo_uint128_lt(b,a) - -#define _cairo_int128_le(a,b) (!_cairo_int128_gt(a,b)) -#define _cairo_int128_ne(a,b) (!_cairo_int128_eq(a,b)) -#define _cairo_int128_ge(a,b) (!_cairo_int128_lt(a,b)) -#define _cairo_int128_gt(a,b) _cairo_int128_lt(b,a) - -#undef I - -#endif /* CAIRO_WIDEINT_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-wideint-type-private.h b/uppdev/plugin/cairo/lib/cairo-wideint-type-private.h deleted file mode 100644 index 3d241502a..000000000 --- a/uppdev/plugin/cairo/lib/cairo-wideint-type-private.h +++ /dev/null @@ -1,149 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2004 Keith Packard - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Keith Packard - * - * Contributor(s): - * Keith R. Packard - * - */ - -#ifndef CAIRO_WIDEINT_TYPE_H -#define CAIRO_WIDEINT_TYPE_H - -#include "cairo.h" - -#if HAVE_CONFIG_H -#include "config.h" -#endif - -#if HAVE_STDINT_H -# include -#elif HAVE_INTTYPES_H -# include -#elif HAVE_SYS_INT_TYPES_H -# include -#elif defined(_MSC_VER) - typedef __int8 int8_t; - typedef unsigned __int8 uint8_t; - typedef __int16 int16_t; - typedef unsigned __int16 uint16_t; - typedef __int32 int32_t; - typedef unsigned __int32 uint32_t; - typedef __int64 int64_t; - typedef unsigned __int64 uint64_t; -# ifndef HAVE_UINT64_T -# define HAVE_UINT64_T 1 -# endif -#else -#error Cannot find definitions for fixed-width integral types (uint8_t, uint32_t, etc.) -#endif - -#ifndef INT16_MIN -# define INT16_MIN (-32767-1) -#endif -#ifndef INT16_MAX -# define INT16_MAX (32767) -#endif -#ifndef UINT16_MAX -# define UINT16_MAX (65535) -#endif -#ifndef INT32_MIN -# define INT32_MIN (-2147483647-1) -#endif -#ifndef INT32_MAX -# define INT32_MAX (2147483647) -#endif - -#if HAVE_BYTESWAP_H -# include -#endif -#ifndef bswap_16 -# define bswap_16(p) \ - (((((uint16_t)(p)) & 0x00ff) << 8) | \ - (((uint16_t)(p)) >> 8)); -#endif -#ifndef bswap_32 -# define bswap_32(p) \ - (((((uint32_t)(p)) & 0x000000ff) << 24) | \ - ((((uint32_t)(p)) & 0x0000ff00) << 8) | \ - ((((uint32_t)(p)) & 0x00ff0000) >> 8) | \ - ((((uint32_t)(p))) >> 24)); -#endif - - -#if !HAVE_UINT64_T - -typedef struct _cairo_uint64 { - uint32_t lo, hi; -} cairo_uint64_t, cairo_int64_t; - -#else - -typedef uint64_t cairo_uint64_t; -typedef int64_t cairo_int64_t; - -#endif - -typedef struct _cairo_uquorem64 { - cairo_uint64_t quo; - cairo_uint64_t rem; -} cairo_uquorem64_t; - -typedef struct _cairo_quorem64 { - cairo_int64_t quo; - cairo_int64_t rem; -} cairo_quorem64_t; - - -#if !HAVE_UINT128_T - -typedef struct cairo_uint128 { - cairo_uint64_t lo, hi; -} cairo_uint128_t, cairo_int128_t; - -#else - -typedef uint128_t cairo_uint128_t; -typedef int128_t cairo_int128_t; - -#endif - -typedef struct _cairo_uquorem128 { - cairo_uint128_t quo; - cairo_uint128_t rem; -} cairo_uquorem128_t; - -typedef struct _cairo_quorem128 { - cairo_int128_t quo; - cairo_int128_t rem; -} cairo_quorem128_t; - - -#endif /* CAIRO_WIDEINT_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-wideint.c b/uppdev/plugin/cairo/lib/cairo-wideint.c deleted file mode 100644 index 456559386..000000000 --- a/uppdev/plugin/cairo/lib/cairo-wideint.c +++ /dev/null @@ -1,860 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2004 Keith Packard - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Keith Packard - * - * Contributor(s): - * Keith R. Packard - */ - -#include "cairoint.h" - -#if HAVE_UINT64_T - -#define _cairo_uint32s_to_uint64(h,l) ((uint64_t) (h) << 32 | (l)) - -cairo_uquorem64_t -_cairo_uint64_divrem (cairo_uint64_t num, cairo_uint64_t den) -{ - cairo_uquorem64_t qr; - - qr.quo = num / den; - qr.rem = num % den; - return qr; -} - -#else - -cairo_uint64_t -_cairo_uint32_to_uint64 (uint32_t i) -{ - cairo_uint64_t q; - - q.lo = i; - q.hi = 0; - return q; -} - -cairo_int64_t -_cairo_int32_to_int64 (int32_t i) -{ - cairo_uint64_t q; - - q.lo = i; - q.hi = i < 0 ? -1 : 0; - return q; -} - -static cairo_uint64_t -_cairo_uint32s_to_uint64 (uint32_t h, uint32_t l) -{ - cairo_uint64_t q; - - q.lo = l; - q.hi = h; - return q; -} - -cairo_uint64_t -_cairo_uint64_add (cairo_uint64_t a, cairo_uint64_t b) -{ - cairo_uint64_t s; - - s.hi = a.hi + b.hi; - s.lo = a.lo + b.lo; - if (s.lo < a.lo) - s.hi++; - return s; -} - -cairo_uint64_t -_cairo_uint64_sub (cairo_uint64_t a, cairo_uint64_t b) -{ - cairo_uint64_t s; - - s.hi = a.hi - b.hi; - s.lo = a.lo - b.lo; - if (s.lo > a.lo) - s.hi--; - return s; -} - -#define uint32_lo(i) ((i) & 0xffff) -#define uint32_hi(i) ((i) >> 16) -#define uint32_carry16 ((1) << 16) - -cairo_uint64_t -_cairo_uint32x32_64_mul (uint32_t a, uint32_t b) -{ - cairo_uint64_t s; - - uint16_t ah, al, bh, bl; - uint32_t r0, r1, r2, r3; - - al = uint32_lo (a); - ah = uint32_hi (a); - bl = uint32_lo (b); - bh = uint32_hi (b); - - r0 = (uint32_t) al * bl; - r1 = (uint32_t) al * bh; - r2 = (uint32_t) ah * bl; - r3 = (uint32_t) ah * bh; - - r1 += uint32_hi(r0); /* no carry possible */ - r1 += r2; /* but this can carry */ - if (r1 < r2) /* check */ - r3 += uint32_carry16; - - s.hi = r3 + uint32_hi(r1); - s.lo = (uint32_lo (r1) << 16) + uint32_lo (r0); - return s; -} - -cairo_int64_t -_cairo_int32x32_64_mul (int32_t a, int32_t b) -{ - cairo_int64_t s; - s = _cairo_uint32x32_64_mul ((uint32_t) a, (uint32_t) b); - if (a < 0) - s.hi -= b; - if (b < 0) - s.hi -= a; - return s; -} - -cairo_uint64_t -_cairo_uint64_mul (cairo_uint64_t a, cairo_uint64_t b) -{ - cairo_uint64_t s; - - s = _cairo_uint32x32_64_mul (a.lo, b.lo); - s.hi += a.lo * b.hi + a.hi * b.lo; - return s; -} - -cairo_uint64_t -_cairo_uint64_lsl (cairo_uint64_t a, int shift) -{ - if (shift >= 32) - { - a.hi = a.lo; - a.lo = 0; - shift -= 32; - } - if (shift) - { - a.hi = a.hi << shift | a.lo >> (32 - shift); - a.lo = a.lo << shift; - } - return a; -} - -cairo_uint64_t -_cairo_uint64_rsl (cairo_uint64_t a, int shift) -{ - if (shift >= 32) - { - a.lo = a.hi; - a.hi = 0; - shift -= 32; - } - if (shift) - { - a.lo = a.lo >> shift | a.hi << (32 - shift); - a.hi = a.hi >> shift; - } - return a; -} - -#define _cairo_uint32_rsa(a,n) ((uint32_t) (((int32_t) (a)) >> (n))) - -cairo_int64_t -_cairo_uint64_rsa (cairo_int64_t a, int shift) -{ - if (shift >= 32) - { - a.lo = a.hi; - a.hi = _cairo_uint32_rsa (a.hi, 31); - shift -= 32; - } - if (shift) - { - a.lo = a.lo >> shift | a.hi << (32 - shift); - a.hi = _cairo_uint32_rsa (a.hi, shift); - } - return a; -} - -int -_cairo_uint64_lt (cairo_uint64_t a, cairo_uint64_t b) -{ - return (a.hi < b.hi || - (a.hi == b.hi && a.lo < b.lo)); -} - -int -_cairo_uint64_eq (cairo_uint64_t a, cairo_uint64_t b) -{ - return a.hi == b.hi && a.lo == b.lo; -} - -int -_cairo_int64_lt (cairo_int64_t a, cairo_int64_t b) -{ - if (_cairo_int64_negative (a) && !_cairo_int64_negative (b)) - return 1; - if (!_cairo_int64_negative (a) && _cairo_int64_negative (b)) - return 0; - return _cairo_uint64_lt (a, b); -} - -int -_cairo_uint64_cmp (cairo_uint64_t a, cairo_uint64_t b) -{ - if (a.hi < b.hi) - return -1; - else if (a.hi > b.hi) - return 1; - else if (a.lo < b.lo) - return -1; - else if (a.lo > b.lo) - return 1; - else - return 0; -} - -int -_cairo_int64_cmp (cairo_int64_t a, cairo_int64_t b) -{ - if (_cairo_int64_negative (a) && !_cairo_int64_negative (b)) - return -1; - if (!_cairo_int64_negative (a) && _cairo_int64_negative (b)) - return 1; - - return _cairo_uint64_cmp (a, b); -} - -cairo_uint64_t -_cairo_uint64_not (cairo_uint64_t a) -{ - a.lo = ~a.lo; - a.hi = ~a.hi; - return a; -} - -cairo_uint64_t -_cairo_uint64_negate (cairo_uint64_t a) -{ - a.lo = ~a.lo; - a.hi = ~a.hi; - if (++a.lo == 0) - ++a.hi; - return a; -} - -/* - * Simple bit-at-a-time divide. - */ -cairo_uquorem64_t -_cairo_uint64_divrem (cairo_uint64_t num, cairo_uint64_t den) -{ - cairo_uquorem64_t qr; - cairo_uint64_t bit; - cairo_uint64_t quo; - - bit = _cairo_uint32_to_uint64 (1); - - /* normalize to make den >= num, but not overflow */ - while (_cairo_uint64_lt (den, num) && (den.hi & 0x80000000) == 0) - { - bit = _cairo_uint64_lsl (bit, 1); - den = _cairo_uint64_lsl (den, 1); - } - quo = _cairo_uint32_to_uint64 (0); - - /* generate quotient, one bit at a time */ - while (bit.hi | bit.lo) - { - if (_cairo_uint64_le (den, num)) - { - num = _cairo_uint64_sub (num, den); - quo = _cairo_uint64_add (quo, bit); - } - bit = _cairo_uint64_rsl (bit, 1); - den = _cairo_uint64_rsl (den, 1); - } - qr.quo = quo; - qr.rem = num; - return qr; -} - -#endif /* !HAVE_UINT64_T */ - -cairo_quorem64_t -_cairo_int64_divrem (cairo_int64_t num, cairo_int64_t den) -{ - int num_neg = _cairo_int64_negative (num); - int den_neg = _cairo_int64_negative (den); - cairo_uquorem64_t uqr; - cairo_quorem64_t qr; - - if (num_neg) - num = _cairo_int64_negate (num); - if (den_neg) - den = _cairo_int64_negate (den); - uqr = _cairo_uint64_divrem (num, den); - if (num_neg) - qr.rem = _cairo_int64_negate (uqr.rem); - else - qr.rem = uqr.rem; - if (num_neg != den_neg) - qr.quo = (cairo_int64_t) _cairo_int64_negate (uqr.quo); - else - qr.quo = (cairo_int64_t) uqr.quo; - return qr; -} - -#if HAVE_UINT128_T - -cairo_uquorem128_t -_cairo_uint128_divrem (cairo_uint128_t num, cairo_uint128_t den) -{ - cairo_uquorem128_t qr; - - qr.quo = num / den; - qr.rem = num % den; - return qr; -} - -#else - -cairo_uint128_t -_cairo_uint32_to_uint128 (uint32_t i) -{ - cairo_uint128_t q; - - q.lo = _cairo_uint32_to_uint64 (i); - q.hi = _cairo_uint32_to_uint64 (0); - return q; -} - -cairo_int128_t -_cairo_int32_to_int128 (int32_t i) -{ - cairo_int128_t q; - - q.lo = _cairo_int32_to_int64 (i); - q.hi = _cairo_int32_to_int64 (i < 0 ? -1 : 0); - return q; -} - -cairo_uint128_t -_cairo_uint64_to_uint128 (cairo_uint64_t i) -{ - cairo_uint128_t q; - - q.lo = i; - q.hi = _cairo_uint32_to_uint64 (0); - return q; -} - -cairo_int128_t -_cairo_int64_to_int128 (cairo_int64_t i) -{ - cairo_int128_t q; - - q.lo = i; - q.hi = _cairo_int32_to_int64 (_cairo_int64_negative(i) ? -1 : 0); - return q; -} - -cairo_uint128_t -_cairo_uint128_add (cairo_uint128_t a, cairo_uint128_t b) -{ - cairo_uint128_t s; - - s.hi = _cairo_uint64_add (a.hi, b.hi); - s.lo = _cairo_uint64_add (a.lo, b.lo); - if (_cairo_uint64_lt (s.lo, a.lo)) - s.hi = _cairo_uint64_add (s.hi, _cairo_uint32_to_uint64 (1)); - return s; -} - -cairo_uint128_t -_cairo_uint128_sub (cairo_uint128_t a, cairo_uint128_t b) -{ - cairo_uint128_t s; - - s.hi = _cairo_uint64_sub (a.hi, b.hi); - s.lo = _cairo_uint64_sub (a.lo, b.lo); - if (_cairo_uint64_gt (s.lo, a.lo)) - s.hi = _cairo_uint64_sub (s.hi, _cairo_uint32_to_uint64(1)); - return s; -} - -#if HAVE_UINT64_T - -#define uint64_lo32(i) ((i) & 0xffffffff) -#define uint64_hi32(i) ((i) >> 32) -#define uint64_lo(i) ((i) & 0xffffffff) -#define uint64_hi(i) ((i) >> 32) -#define uint64_shift32(i) ((i) << 32) -#define uint64_carry32 (((uint64_t) 1) << 32) - -#else - -#define uint64_lo32(i) ((i).lo) -#define uint64_hi32(i) ((i).hi) - -static cairo_uint64_t -uint64_lo (cairo_uint64_t i) -{ - cairo_uint64_t s; - - s.lo = i.lo; - s.hi = 0; - return s; -} - -static cairo_uint64_t -uint64_hi (cairo_uint64_t i) -{ - cairo_uint64_t s; - - s.lo = i.hi; - s.hi = 0; - return s; -} - -static cairo_uint64_t -uint64_shift32 (cairo_uint64_t i) -{ - cairo_uint64_t s; - - s.lo = 0; - s.hi = i.lo; - return s; -} - -static const cairo_uint64_t uint64_carry32 = { 0, 1 }; - -#endif - -cairo_uint128_t -_cairo_uint64x64_128_mul (cairo_uint64_t a, cairo_uint64_t b) -{ - cairo_uint128_t s; - uint32_t ah, al, bh, bl; - cairo_uint64_t r0, r1, r2, r3; - - al = uint64_lo32 (a); - ah = uint64_hi32 (a); - bl = uint64_lo32 (b); - bh = uint64_hi32 (b); - - r0 = _cairo_uint32x32_64_mul (al, bl); - r1 = _cairo_uint32x32_64_mul (al, bh); - r2 = _cairo_uint32x32_64_mul (ah, bl); - r3 = _cairo_uint32x32_64_mul (ah, bh); - - r1 = _cairo_uint64_add (r1, uint64_hi (r0)); /* no carry possible */ - r1 = _cairo_uint64_add (r1, r2); /* but this can carry */ - if (_cairo_uint64_lt (r1, r2)) /* check */ - r3 = _cairo_uint64_add (r3, uint64_carry32); - - s.hi = _cairo_uint64_add (r3, uint64_hi(r1)); - s.lo = _cairo_uint64_add (uint64_shift32 (r1), - uint64_lo (r0)); - return s; -} - -cairo_int128_t -_cairo_int64x64_128_mul (cairo_int64_t a, cairo_int64_t b) -{ - cairo_int128_t s; - s = _cairo_uint64x64_128_mul (_cairo_int64_to_uint64(a), - _cairo_int64_to_uint64(b)); - if (_cairo_int64_negative (a)) - s.hi = _cairo_uint64_sub (s.hi, - _cairo_int64_to_uint64 (b)); - if (_cairo_int64_negative (b)) - s.hi = _cairo_uint64_sub (s.hi, - _cairo_int64_to_uint64 (a)); - return s; -} - -cairo_uint128_t -_cairo_uint128_mul (cairo_uint128_t a, cairo_uint128_t b) -{ - cairo_uint128_t s; - - s = _cairo_uint64x64_128_mul (a.lo, b.lo); - s.hi = _cairo_uint64_add (s.hi, - _cairo_uint64_mul (a.lo, b.hi)); - s.hi = _cairo_uint64_add (s.hi, - _cairo_uint64_mul (a.hi, b.lo)); - return s; -} - -cairo_uint128_t -_cairo_uint128_lsl (cairo_uint128_t a, int shift) -{ - if (shift >= 64) - { - a.hi = a.lo; - a.lo = _cairo_uint32_to_uint64 (0); - shift -= 64; - } - if (shift) - { - a.hi = _cairo_uint64_add (_cairo_uint64_lsl (a.hi, shift), - _cairo_uint64_rsl (a.lo, (64 - shift))); - a.lo = _cairo_uint64_lsl (a.lo, shift); - } - return a; -} - -cairo_uint128_t -_cairo_uint128_rsl (cairo_uint128_t a, int shift) -{ - if (shift >= 64) - { - a.lo = a.hi; - a.hi = _cairo_uint32_to_uint64 (0); - shift -= 64; - } - if (shift) - { - a.lo = _cairo_uint64_add (_cairo_uint64_rsl (a.lo, shift), - _cairo_uint64_lsl (a.hi, (64 - shift))); - a.hi = _cairo_uint64_rsl (a.hi, shift); - } - return a; -} - -cairo_uint128_t -_cairo_uint128_rsa (cairo_int128_t a, int shift) -{ - if (shift >= 64) - { - a.lo = a.hi; - a.hi = _cairo_uint64_rsa (a.hi, 64-1); - shift -= 64; - } - if (shift) - { - a.lo = _cairo_uint64_add (_cairo_uint64_rsl (a.lo, shift), - _cairo_uint64_lsl (a.hi, (64 - shift))); - a.hi = _cairo_uint64_rsa (a.hi, shift); - } - return a; -} - -int -_cairo_uint128_lt (cairo_uint128_t a, cairo_uint128_t b) -{ - return (_cairo_uint64_lt (a.hi, b.hi) || - (_cairo_uint64_eq (a.hi, b.hi) && - _cairo_uint64_lt (a.lo, b.lo))); -} - -int -_cairo_int128_lt (cairo_int128_t a, cairo_int128_t b) -{ - if (_cairo_int128_negative (a) && !_cairo_int128_negative (b)) - return 1; - if (!_cairo_int128_negative (a) && _cairo_int128_negative (b)) - return 0; - return _cairo_uint128_lt (a, b); -} - -int -_cairo_uint128_cmp (cairo_uint128_t a, cairo_uint128_t b) -{ - int cmp; - - cmp = _cairo_uint64_cmp (a.hi, b.hi); - if (cmp) - return cmp; - return _cairo_uint64_cmp (a.lo, b.lo); -} - -int -_cairo_int128_cmp (cairo_int128_t a, cairo_int128_t b) -{ - if (_cairo_int128_negative (a) && !_cairo_int128_negative (b)) - return -1; - if (!_cairo_int128_negative (a) && _cairo_int128_negative (b)) - return 1; - - return _cairo_uint128_cmp (a, b); -} - -int -_cairo_uint128_eq (cairo_uint128_t a, cairo_uint128_t b) -{ - return (_cairo_uint64_eq (a.hi, b.hi) && - _cairo_uint64_eq (a.lo, b.lo)); -} - -#if HAVE_UINT64_T -#define _cairo_msbset64(q) (q & ((uint64_t) 1 << 63)) -#else -#define _cairo_msbset64(q) (q.hi & ((uint32_t) 1 << 31)) -#endif - -cairo_uquorem128_t -_cairo_uint128_divrem (cairo_uint128_t num, cairo_uint128_t den) -{ - cairo_uquorem128_t qr; - cairo_uint128_t bit; - cairo_uint128_t quo; - - bit = _cairo_uint32_to_uint128 (1); - - /* normalize to make den >= num, but not overflow */ - while (_cairo_uint128_lt (den, num) && !_cairo_msbset64(den.hi)) - { - bit = _cairo_uint128_lsl (bit, 1); - den = _cairo_uint128_lsl (den, 1); - } - quo = _cairo_uint32_to_uint128 (0); - - /* generate quotient, one bit at a time */ - while (_cairo_uint128_ne (bit, _cairo_uint32_to_uint128(0))) - { - if (_cairo_uint128_le (den, num)) - { - num = _cairo_uint128_sub (num, den); - quo = _cairo_uint128_add (quo, bit); - } - bit = _cairo_uint128_rsl (bit, 1); - den = _cairo_uint128_rsl (den, 1); - } - qr.quo = quo; - qr.rem = num; - return qr; -} - -cairo_int128_t -_cairo_int128_negate (cairo_int128_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) -{ - a.lo = _cairo_uint64_not (a.lo); - a.hi = _cairo_uint64_not (a.hi); - return a; -} - -#endif /* !HAVE_UINT128_T */ - -cairo_quorem128_t -_cairo_int128_divrem (cairo_int128_t num, cairo_int128_t den) -{ - int num_neg = _cairo_int128_negative (num); - int den_neg = _cairo_int128_negative (den); - cairo_uquorem128_t uqr; - cairo_quorem128_t qr; - - if (num_neg) - num = _cairo_int128_negate (num); - if (den_neg) - den = _cairo_int128_negate (den); - uqr = _cairo_uint128_divrem (num, den); - if (num_neg) - qr.rem = _cairo_int128_negate (uqr.rem); - else - qr.rem = uqr.rem; - if (num_neg != den_neg) - qr.quo = _cairo_int128_negate (uqr.quo); - else - qr.quo = uqr.quo; - return qr; -} - -/** - * _cairo_uint_96by64_32x64_divrem: - * - * Compute a 32 bit quotient and 64 bit remainder of a 96 bit unsigned - * dividend and 64 bit divisor. If the quotient doesn't fit into 32 - * bits then the returned remainder is equal to the divisor, and the - * quotient is the largest representable 64 bit integer. It is an - * error to call this function with the high 32 bits of @num being - * non-zero. */ -cairo_uquorem64_t -_cairo_uint_96by64_32x64_divrem (cairo_uint128_t num, - cairo_uint64_t den) -{ - cairo_uquorem64_t result; - cairo_uint64_t B = _cairo_uint32s_to_uint64 (1, 0); - - /* These are the high 64 bits of the *96* bit numerator. We're - * going to represent the numerator as xB + y, where x is a 64, - * and y is a 32 bit number. */ - cairo_uint64_t x = _cairo_uint128_to_uint64 (_cairo_uint128_rsl(num, 32)); - - /* Initialise the result to indicate overflow. */ - result.quo = _cairo_uint32s_to_uint64 (-1U, -1U); - result.rem = den; - - /* Don't bother if the quotient is going to overflow. */ - if (_cairo_uint64_ge (x, den)) { - return /* overflow */ result; - } - - if (_cairo_uint64_lt (x, B)) { - /* When the final quotient is known to fit in 32 bits, then - * num < 2^64 if and only if den < 2^32. */ - return _cairo_uint64_divrem (_cairo_uint128_to_uint64 (num), den); - } - else { - /* Denominator is >= 2^32. the numerator is >= 2^64, and the - * division won't overflow: need two divrems. Write the - * numerator and denominator as - * - * num = xB + y x : 64 bits, y : 32 bits - * den = uB + v u, v : 32 bits - */ - uint32_t y = _cairo_uint128_to_uint32 (num); - uint32_t u = uint64_hi32 (den); - uint32_t v = _cairo_uint64_to_uint32 (den); - - /* Compute a lower bound approximate quotient of num/den - * from x/(u+1). Then we have - * - * x = q(u+1) + r ; q : 32 bits, r <= u : 32 bits. - * - * xB + y = q(u+1)B + (rB+y) - * = q(uB + B + v - v) + (rB+y) - * = q(uB + v) + qB - qv + (rB+y) - * = q(uB + v) + q(B-v) + (rB+y) - * - * The true quotient of num/den then is q plus the - * contribution of q(B-v) + (rB+y). The main contribution - * comes from the term q(B-v), with the term (rB+y) only - * contributing at most one part. - * - * The term q(B-v) must fit into 64 bits, since q fits into 32 - * bits on account of being a lower bound to the true - * quotient, and as B-v <= 2^32, we may safely use a single - * 64/64 bit division to find its contribution. */ - - cairo_uquorem64_t quorem; - cairo_uint64_t remainder; /* will contain final remainder */ - uint32_t quotient; /* will contain final quotient. */ - uint32_t q; - uint32_t r; - - /* Approximate quotient by dividing the high 64 bits of num by - * u+1. Watch out for overflow of u+1. */ - if (u+1) { - quorem = _cairo_uint64_divrem (x, _cairo_uint32_to_uint64 (u+1)); - q = _cairo_uint64_to_uint32 (quorem.quo); - r = _cairo_uint64_to_uint32 (quorem.rem); - } - else { - q = uint64_hi32 (x); - r = _cairo_uint64_to_uint32 (x); - } - quotient = q; - - /* Add the main term's contribution to quotient. Note B-v = - * -v as an uint32 (unless v = 0) */ - if (v) - quorem = _cairo_uint64_divrem (_cairo_uint32x32_64_mul (q, -v), den); - else - quorem = _cairo_uint64_divrem (_cairo_uint32s_to_uint64 (q, 0), den); - quotient += _cairo_uint64_to_uint32 (quorem.quo); - - /* Add the contribution of the subterm and start computing the - * true remainder. */ - remainder = _cairo_uint32s_to_uint64 (r, y); - if (_cairo_uint64_ge (remainder, den)) { - remainder = _cairo_uint64_sub (remainder, den); - quotient++; - } - - /* Add the contribution of the main term's remainder. The - * funky test here checks that remainder + main_rem >= den, - * taking into account overflow of the addition. */ - remainder = _cairo_uint64_add (remainder, quorem.rem); - if (_cairo_uint64_ge (remainder, den) || - _cairo_uint64_lt (remainder, quorem.rem)) - { - remainder = _cairo_uint64_sub (remainder, den); - quotient++; - } - - result.quo = _cairo_uint32_to_uint64 (quotient); - result.rem = remainder; - } - return result; -} - -cairo_quorem64_t -_cairo_int_96by64_32x64_divrem (cairo_int128_t num, cairo_int64_t den) -{ - int num_neg = _cairo_int128_negative (num); - int den_neg = _cairo_int64_negative (den); - cairo_uint64_t nonneg_den; - cairo_uquorem64_t uqr; - cairo_quorem64_t qr; - - if (num_neg) - num = _cairo_int128_negate (num); - if (den_neg) - nonneg_den = _cairo_int64_negate (den); - else - nonneg_den = den; - - uqr = _cairo_uint_96by64_32x64_divrem (num, nonneg_den); - if (_cairo_uint64_eq (uqr.rem, nonneg_den)) { - /* bail on overflow. */ - qr.quo = _cairo_uint32s_to_uint64 (0x7FFFFFFF, -1U);; - qr.rem = den; - return qr; - } - - if (num_neg) - qr.rem = _cairo_int64_negate (uqr.rem); - else - qr.rem = uqr.rem; - if (num_neg != den_neg) - qr.quo = _cairo_int64_negate (uqr.quo); - else - qr.quo = uqr.quo; - return qr; -} diff --git a/uppdev/plugin/cairo/lib/cairo-win32-font.c b/uppdev/plugin/cairo/lib/cairo-win32-font.c deleted file mode 100644 index 879cfac79..000000000 --- a/uppdev/plugin/cairo/lib/cairo-win32-font.c +++ /dev/null @@ -1,2156 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* cairo - a vector graphics library with display and print output - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - */ - -#define WIN32_LEAN_AND_MEAN -/* We require Windows 2000 features such as GetGlyphIndices */ -#if !defined(WINVER) || (WINVER < 0x0500) -# define WINVER 0x0500 -#endif -#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500) -# define _WIN32_WINNT 0x0500 -#endif - -#include "cairoint.h" - -#include "cairo-win32-private.h" - -#ifndef SPI_GETFONTSMOOTHINGTYPE -#define SPI_GETFONTSMOOTHINGTYPE 0x200a -#endif -#ifndef FE_FONTSMOOTHINGCLEARTYPE -#define FE_FONTSMOOTHINGCLEARTYPE 2 -#endif -#ifndef CLEARTYPE_QUALITY -#define CLEARTYPE_QUALITY 5 -#endif -#ifndef TT_PRIM_CSPLINE -#define TT_PRIM_CSPLINE 3 -#endif - -#define CMAP_TAG 0x70616d63 - -const cairo_scaled_font_backend_t _cairo_win32_scaled_font_backend; - -typedef struct { - cairo_scaled_font_t base; - - LOGFONTW logfont; - - BYTE quality; - - /* We do drawing and metrics computation in a "logical space" which - * is similar to font space, except that it is scaled by a factor - * of the (desired font size) * (WIN32_FONT_LOGICAL_SCALE). The multiplication - * by WIN32_FONT_LOGICAL_SCALE allows for sub-pixel precision. - */ - double logical_scale; - - /* The size we should actually request the font at from Windows; differs - * from the logical_scale because it is quantized for orthogonal - * transformations - */ - double logical_size; - - /* Transformations from device <=> logical space - */ - cairo_matrix_t logical_to_device; - cairo_matrix_t device_to_logical; - - /* We special case combinations of 90-degree-rotations, scales and - * flips ... that is transformations that take the axes to the - * axes. If preserve_axes is true, then swap_axes/swap_x/swap_y - * encode the 8 possibilities for orientation (4 rotation angles with - * and without a flip), and scale_x, scale_y the scale components. - */ - cairo_bool_t preserve_axes; - cairo_bool_t swap_axes; - cairo_bool_t swap_x; - cairo_bool_t swap_y; - double x_scale; - double y_scale; - - /* The size of the design unit of the font - */ - int em_square; - - HFONT scaled_hfont; - HFONT unscaled_hfont; - - cairo_bool_t is_bitmap; - cairo_bool_t is_type1; - cairo_bool_t delete_scaled_hfont; -} cairo_win32_scaled_font_t; - -static cairo_status_t -_cairo_win32_scaled_font_set_metrics (cairo_win32_scaled_font_t *scaled_font); - -static cairo_status_t -_cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_font, - cairo_scaled_glyph_t *scaled_glyph); - -static cairo_status_t -_cairo_win32_scaled_font_init_glyph_surface (cairo_win32_scaled_font_t *scaled_font, - cairo_scaled_glyph_t *scaled_glyph); - -static cairo_status_t -_cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font, - cairo_scaled_glyph_t *scaled_glyph); - -#define NEARLY_ZERO(d) (fabs(d) < (1. / 65536.)) - -static HDC -_get_global_font_dc (void) -{ - static HDC hdc; - - if (!hdc) { - hdc = CreateCompatibleDC (NULL); - if (!hdc) { - _cairo_win32_print_gdi_error ("_get_global_font_dc"); - return NULL; - } - - if (!SetGraphicsMode (hdc, GM_ADVANCED)) { - _cairo_win32_print_gdi_error ("_get_global_font_dc"); - DeleteDC (hdc); - return NULL; - } - } - - return hdc; -} - -static cairo_status_t -_compute_transform (cairo_win32_scaled_font_t *scaled_font, - cairo_matrix_t *sc) -{ - cairo_status_t status; - - if (NEARLY_ZERO (sc->yx) && NEARLY_ZERO (sc->xy)) { - scaled_font->preserve_axes = TRUE; - scaled_font->x_scale = sc->xx; - scaled_font->swap_x = (sc->xx < 0); - scaled_font->y_scale = sc->yy; - scaled_font->swap_y = (sc->yy < 0); - scaled_font->swap_axes = FALSE; - - } else if (NEARLY_ZERO (sc->xx) && NEARLY_ZERO (sc->yy)) { - scaled_font->preserve_axes = TRUE; - scaled_font->x_scale = sc->yx; - scaled_font->swap_x = (sc->yx < 0); - scaled_font->y_scale = sc->xy; - scaled_font->swap_y = (sc->xy < 0); - scaled_font->swap_axes = TRUE; - - } else { - scaled_font->preserve_axes = FALSE; - scaled_font->swap_x = scaled_font->swap_y = scaled_font->swap_axes = FALSE; - } - - if (scaled_font->preserve_axes) { - if (scaled_font->swap_x) - scaled_font->x_scale = - scaled_font->x_scale; - if (scaled_font->swap_y) - scaled_font->y_scale = - scaled_font->y_scale; - - scaled_font->logical_scale = WIN32_FONT_LOGICAL_SCALE * scaled_font->y_scale; - scaled_font->logical_size = WIN32_FONT_LOGICAL_SCALE * - _cairo_lround (scaled_font->y_scale); - } - - /* The font matrix has x and y "scale" components which we extract and - * use as character scale values. - */ - cairo_matrix_init (&scaled_font->logical_to_device, - sc->xx, sc->yx, sc->xy, sc->yy, 0, 0); - - if (!scaled_font->preserve_axes) { - status = _cairo_matrix_compute_basis_scale_factors (&scaled_font->logical_to_device, - &scaled_font->x_scale, &scaled_font->y_scale, - TRUE); /* XXX: Handle vertical text */ - if (status) - return status; - - scaled_font->logical_size = _cairo_lround (WIN32_FONT_LOGICAL_SCALE * - scaled_font->y_scale); - scaled_font->logical_scale = WIN32_FONT_LOGICAL_SCALE * scaled_font->y_scale; - } - - cairo_matrix_scale (&scaled_font->logical_to_device, - 1.0 / scaled_font->logical_scale, 1.0 / scaled_font->logical_scale); - - scaled_font->device_to_logical = scaled_font->logical_to_device; - - status = cairo_matrix_invert (&scaled_font->device_to_logical); - if (status) - cairo_matrix_init_identity (&scaled_font->device_to_logical); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_bool_t -_have_cleartype_quality (void) -{ - OSVERSIONINFO version_info; - - version_info.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); - - if (!GetVersionEx (&version_info)) { - _cairo_win32_print_gdi_error ("_have_cleartype_quality"); - return FALSE; - } - - return (version_info.dwMajorVersion > 5 || - (version_info.dwMajorVersion == 5 && - version_info.dwMinorVersion >= 1)); /* XP or newer */ -} - -static BYTE -_get_system_quality (void) -{ - BOOL font_smoothing; - UINT smoothing_type; - - if (!SystemParametersInfo (SPI_GETFONTSMOOTHING, 0, &font_smoothing, 0)) { - _cairo_win32_print_gdi_error ("_get_system_quality"); - return DEFAULT_QUALITY; - } - - if (font_smoothing) { - if (_have_cleartype_quality ()) { - if (!SystemParametersInfo (SPI_GETFONTSMOOTHINGTYPE, - 0, &smoothing_type, 0)) { - _cairo_win32_print_gdi_error ("_get_system_quality"); - return DEFAULT_QUALITY; - } - - if (smoothing_type == FE_FONTSMOOTHINGCLEARTYPE) - return CLEARTYPE_QUALITY; - } - - return ANTIALIASED_QUALITY; - } else { - return DEFAULT_QUALITY; - } -} - -/* If face_hfont is non-%NULL then font_matrix must be a simple scale by some - * factor S, ctm must be the identity, logfont->lfHeight must be -S, - * logfont->lfWidth, logfont->lfEscapement, logfont->lfOrientation must - * all be 0, and face_hfont is the result of calling CreateFontIndirectW on - * logfont. - */ -static cairo_status_t -_win32_scaled_font_create (LOGFONTW *logfont, - HFONT face_hfont, - cairo_font_face_t *font_face, - const cairo_matrix_t *font_matrix, - const cairo_matrix_t *ctm, - const cairo_font_options_t *options, - cairo_scaled_font_t **font_out) -{ - HDC hdc; - cairo_win32_scaled_font_t *f; - cairo_matrix_t scale; - cairo_status_t status; - - hdc = _get_global_font_dc (); - if (hdc == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - f = malloc (sizeof(cairo_win32_scaled_font_t)); - if (f == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - f->logfont = *logfont; - - /* We don't have any control over the hinting style or subpixel - * order in the Win32 font API, so we ignore those parts of - * cairo_font_options_t. We use the 'antialias' field to set - * the 'quality'. - * - * XXX: The other option we could pay attention to, but don't - * here is the hint_metrics options. - */ - if (options->antialias == CAIRO_ANTIALIAS_DEFAULT) - f->quality = _get_system_quality (); - else { - switch (options->antialias) { - case CAIRO_ANTIALIAS_NONE: - f->quality = NONANTIALIASED_QUALITY; - break; - case CAIRO_ANTIALIAS_GRAY: - f->quality = ANTIALIASED_QUALITY; - break; - case CAIRO_ANTIALIAS_SUBPIXEL: - if (_have_cleartype_quality ()) - f->quality = CLEARTYPE_QUALITY; - else - f->quality = ANTIALIASED_QUALITY; - break; - case CAIRO_ANTIALIAS_DEFAULT: - ASSERT_NOT_REACHED; - } - } - - f->em_square = 0; - f->scaled_hfont = NULL; - f->unscaled_hfont = NULL; - - if (f->quality == logfont->lfQuality || - (logfont->lfQuality == DEFAULT_QUALITY && - options->antialias == CAIRO_ANTIALIAS_DEFAULT)) { - /* If face_hfont is non-NULL, then we can use it to avoid creating our - * own --- because the constraints on face_hfont mentioned above - * guarantee it was created in exactly the same way that - * _win32_scaled_font_get_scaled_hfont would create it. - */ - f->scaled_hfont = face_hfont; - } - /* don't delete the hfont if we're using the one passed in to us */ - f->delete_scaled_hfont = !f->scaled_hfont; - - cairo_matrix_multiply (&scale, font_matrix, ctm); - status = _compute_transform (f, &scale); - if (status) - goto FAIL; - - status = _cairo_scaled_font_init (&f->base, font_face, - font_matrix, ctm, options, - &_cairo_win32_scaled_font_backend); - if (status) - goto FAIL; - - status = _cairo_win32_scaled_font_set_metrics (f); - if (status) { - _cairo_scaled_font_fini (&f->base); - goto FAIL; - } - - *font_out = &f->base; - return CAIRO_STATUS_SUCCESS; - - FAIL: - free (f); - return status; -} - -static cairo_status_t -_win32_scaled_font_set_world_transform (cairo_win32_scaled_font_t *scaled_font, - HDC hdc) -{ - XFORM xform; - - _cairo_matrix_to_win32_xform (&scaled_font->logical_to_device, &xform); - - if (!SetWorldTransform (hdc, &xform)) - return _cairo_win32_print_gdi_error ("_win32_scaled_font_set_world_transform"); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_win32_scaled_font_set_identity_transform (HDC hdc) -{ - if (!ModifyWorldTransform (hdc, NULL, MWT_IDENTITY)) - return _cairo_win32_print_gdi_error ("_win32_scaled_font_set_identity_transform"); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_win32_scaled_font_get_scaled_hfont (cairo_win32_scaled_font_t *scaled_font, - HFONT *hfont_out) -{ - if (!scaled_font->scaled_hfont) { - LOGFONTW logfont = scaled_font->logfont; - logfont.lfHeight = -scaled_font->logical_size; - logfont.lfWidth = 0; - logfont.lfEscapement = 0; - logfont.lfOrientation = 0; - logfont.lfQuality = scaled_font->quality; - - scaled_font->scaled_hfont = CreateFontIndirectW (&logfont); - if (!scaled_font->scaled_hfont) - return _cairo_win32_print_gdi_error ("_win32_scaled_font_get_scaled_hfont"); - } - - *hfont_out = scaled_font->scaled_hfont; - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_win32_scaled_font_get_unscaled_hfont (cairo_win32_scaled_font_t *scaled_font, - HDC hdc, - HFONT *hfont_out) -{ - if (scaled_font->unscaled_hfont == NULL) { - OUTLINETEXTMETRIC *otm; - unsigned int otm_size; - HFONT scaled_hfont; - LOGFONTW logfont; - cairo_status_t status; - - status = _win32_scaled_font_get_scaled_hfont (scaled_font, - &scaled_hfont); - if (status) - return status; - - if (! SelectObject (hdc, scaled_hfont)) - return _cairo_win32_print_gdi_error ("_win32_scaled_font_get_unscaled_hfont:SelectObject"); - - otm_size = GetOutlineTextMetrics (hdc, 0, NULL); - if (! otm_size) - return _cairo_win32_print_gdi_error ("_win32_scaled_font_get_unscaled_hfont:GetOutlineTextMetrics"); - - otm = malloc (otm_size); - if (otm == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - if (! GetOutlineTextMetrics (hdc, otm_size, otm)) { - status = _cairo_win32_print_gdi_error ("_win32_scaled_font_get_unscaled_hfont:GetOutlineTextMetrics"); - free (otm); - return status; - } - - scaled_font->em_square = otm->otmEMSquare; - free (otm); - - logfont = scaled_font->logfont; - logfont.lfHeight = -scaled_font->em_square; - logfont.lfWidth = 0; - logfont.lfEscapement = 0; - logfont.lfOrientation = 0; - logfont.lfQuality = scaled_font->quality; - - scaled_font->unscaled_hfont = CreateFontIndirectW (&logfont); - if (! scaled_font->unscaled_hfont) - return _cairo_win32_print_gdi_error ("_win32_scaled_font_get_unscaled_hfont:CreateIndirect"); - } - - *hfont_out = scaled_font->unscaled_hfont; - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_win32_scaled_font_select_unscaled_font (cairo_scaled_font_t *scaled_font, - HDC hdc) -{ - cairo_status_t status; - HFONT hfont; - HFONT old_hfont = NULL; - - status = _win32_scaled_font_get_unscaled_hfont ((cairo_win32_scaled_font_t *)scaled_font, hdc, &hfont); - if (status) - return status; - - old_hfont = SelectObject (hdc, hfont); - if (!old_hfont) - return _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_select_unscaled_font"); - - status = _win32_scaled_font_set_identity_transform (hdc); - if (status) { - SelectObject (hdc, old_hfont); - return status; - } - - SetMapMode (hdc, MM_TEXT); - - return CAIRO_STATUS_SUCCESS; -} - -cairo_bool_t -_cairo_win32_scaled_font_is_type1 (cairo_scaled_font_t *scaled_font) -{ - cairo_win32_scaled_font_t *win32_scaled_font; - - win32_scaled_font = (cairo_win32_scaled_font_t *) scaled_font; - - return win32_scaled_font->is_type1; -} - -cairo_bool_t -_cairo_win32_scaled_font_is_bitmap (cairo_scaled_font_t *scaled_font) -{ - cairo_win32_scaled_font_t *win32_scaled_font; - - win32_scaled_font = (cairo_win32_scaled_font_t *) scaled_font; - - return win32_scaled_font->is_bitmap; -} - -static void -_cairo_win32_scaled_font_done_unscaled_font (cairo_scaled_font_t *scaled_font) -{ -} - -/* implement the font backend interface */ - -static cairo_status_t -_cairo_win32_scaled_font_create_toy (cairo_toy_font_face_t *toy_face, - const cairo_matrix_t *font_matrix, - const cairo_matrix_t *ctm, - const cairo_font_options_t *options, - cairo_scaled_font_t **scaled_font_out) -{ - LOGFONTW logfont; - uint16_t *face_name; - int face_name_len; - cairo_status_t status; - - status = _cairo_utf8_to_utf16 (toy_face->family, -1, - &face_name, &face_name_len); - if (status) - return status; - - if (face_name_len > LF_FACESIZE - 1) { - free (face_name); - return _cairo_error (CAIRO_STATUS_INVALID_STRING); - } - - memcpy (logfont.lfFaceName, face_name, sizeof (uint16_t) * (face_name_len + 1)); - free (face_name); - - logfont.lfHeight = 0; /* filled in later */ - logfont.lfWidth = 0; /* filled in later */ - logfont.lfEscapement = 0; /* filled in later */ - logfont.lfOrientation = 0; /* filled in later */ - - switch (toy_face->weight) { - case CAIRO_FONT_WEIGHT_NORMAL: - default: - logfont.lfWeight = FW_NORMAL; - break; - case CAIRO_FONT_WEIGHT_BOLD: - logfont.lfWeight = FW_BOLD; - break; - } - - switch (toy_face->slant) { - case CAIRO_FONT_SLANT_NORMAL: - default: - logfont.lfItalic = FALSE; - break; - case CAIRO_FONT_SLANT_ITALIC: - case CAIRO_FONT_SLANT_OBLIQUE: - logfont.lfItalic = TRUE; - break; - } - - logfont.lfUnderline = FALSE; - logfont.lfStrikeOut = FALSE; - /* The docs for LOGFONT discourage using this, since the - * interpretation is locale-specific, but it's not clear what - * would be a better alternative. - */ - logfont.lfCharSet = DEFAULT_CHARSET; - logfont.lfOutPrecision = OUT_DEFAULT_PRECIS; - logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS; - logfont.lfQuality = DEFAULT_QUALITY; /* filled in later */ - logfont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; - - if (!logfont.lfFaceName) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - return _win32_scaled_font_create (&logfont, NULL, &toy_face->base, - font_matrix, ctm, options, - scaled_font_out); -} - -static void -_cairo_win32_scaled_font_fini (void *abstract_font) -{ - cairo_win32_scaled_font_t *scaled_font = abstract_font; - - if (scaled_font == NULL) - return; - - if (scaled_font->scaled_hfont && scaled_font->delete_scaled_hfont) - DeleteObject (scaled_font->scaled_hfont); - - if (scaled_font->unscaled_hfont) - DeleteObject (scaled_font->unscaled_hfont); -} - -static cairo_int_status_t -_cairo_win32_scaled_font_type1_text_to_glyphs (cairo_win32_scaled_font_t *scaled_font, - double x, - double y, - const char *utf8, - cairo_glyph_t **glyphs, - int *num_glyphs) -{ - uint16_t *utf16; - int n16; - int i; - WORD *glyph_indices = NULL; - cairo_status_t status; - double x_pos, y_pos; - HDC hdc = NULL; - cairo_matrix_t mat; - - status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &n16); - if (status) - return status; - - glyph_indices = _cairo_malloc_ab (n16 + 1, sizeof (WORD)); - if (!glyph_indices) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto FAIL1; - } - - hdc = _get_global_font_dc (); - assert (hdc != NULL); - - status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc); - if (status) - goto FAIL2; - - if (GetGlyphIndicesW (hdc, utf16, n16, glyph_indices, 0) == GDI_ERROR) { - status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_type1_text_to_glyphs:GetGlyphIndicesW"); - goto FAIL3; - } - - *num_glyphs = n16; - *glyphs = _cairo_malloc_ab (n16, sizeof (cairo_glyph_t)); - if (!*glyphs) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto FAIL3; - } - - x_pos = x; - y_pos = y; - - mat = scaled_font->base.ctm; - status = cairo_matrix_invert (&mat); - assert (status == CAIRO_STATUS_SUCCESS); - - _cairo_scaled_font_freeze_cache (&scaled_font->base); - - for (i = 0; i < n16; i++) { - cairo_scaled_glyph_t *scaled_glyph; - - (*glyphs)[i].index = glyph_indices[i]; - (*glyphs)[i].x = x_pos; - (*glyphs)[i].y = y_pos; - - status = _cairo_scaled_glyph_lookup (&scaled_font->base, - glyph_indices[i], - CAIRO_SCALED_GLYPH_INFO_METRICS, - &scaled_glyph); - if (status) { - free (*glyphs); - *glyphs = NULL; - break; - } - - x = scaled_glyph->x_advance; - y = scaled_glyph->y_advance; - cairo_matrix_transform_distance (&mat, &x, &y); - x_pos += x; - y_pos += y; - } - - _cairo_scaled_font_thaw_cache (&scaled_font->base); - -FAIL3: - cairo_win32_scaled_font_done_font (&scaled_font->base); -FAIL2: - free (glyph_indices); -FAIL1: - free (utf16); - - return status; -} - -static cairo_int_status_t -_cairo_win32_scaled_font_text_to_glyphs (void *abstract_font, - double x, - double y, - const char *utf8, - cairo_glyph_t **glyphs, - int *num_glyphs) -{ - cairo_win32_scaled_font_t *scaled_font = abstract_font; - uint16_t *utf16; - int n16; - GCP_RESULTSW gcp_results; - unsigned int buffer_size, i; - WCHAR *glyph_indices = NULL; - int *dx = NULL; - cairo_status_t status; - double x_pos, y_pos; - double x_incr, y_incr; - HDC hdc = NULL; - - /* GetCharacterPlacement() returns utf16 instead of glyph indices - * for Type 1 fonts. Use GetGlyphIndices for Type 1 fonts. */ - if (scaled_font->is_type1) - return _cairo_win32_scaled_font_type1_text_to_glyphs (scaled_font, - x, - y, - utf8, - glyphs, - num_glyphs); - - /* Compute a vector in user space along the baseline of length one logical space unit */ - x_incr = 1; - y_incr = 0; - cairo_matrix_transform_distance (&scaled_font->base.font_matrix, &x_incr, &y_incr); - x_incr /= scaled_font->logical_scale; - y_incr /= scaled_font->logical_scale; - - status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &n16); - if (status) - return status; - - gcp_results.lStructSize = sizeof (GCP_RESULTS); - gcp_results.lpOutString = NULL; - gcp_results.lpOrder = NULL; - gcp_results.lpCaretPos = NULL; - gcp_results.lpClass = NULL; - - buffer_size = MAX (n16 * 1.2, 16); /* Initially guess number of chars plus a few */ - if (buffer_size > INT_MAX) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto FAIL1; - } - - hdc = _get_global_font_dc (); - assert (hdc != NULL); - - status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc); - if (status) - goto FAIL1; - - while (TRUE) { - if (glyph_indices) { - free (glyph_indices); - glyph_indices = NULL; - } - if (dx) { - free (dx); - dx = NULL; - } - - glyph_indices = _cairo_malloc_ab (buffer_size, sizeof (WCHAR)); - dx = _cairo_malloc_ab (buffer_size, sizeof (int)); - if (!glyph_indices || !dx) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto FAIL2; - } - - gcp_results.nGlyphs = buffer_size; - gcp_results.lpDx = dx; - gcp_results.lpGlyphs = glyph_indices; - - if (!GetCharacterPlacementW (hdc, utf16, n16, - 0, - &gcp_results, - GCP_DIACRITIC | GCP_LIGATE | GCP_GLYPHSHAPE | GCP_REORDER)) { - status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_text_to_glyphs"); - goto FAIL2; - } - - if (gcp_results.lpDx && gcp_results.lpGlyphs) - break; - - /* Too small a buffer, try again */ - - buffer_size += buffer_size / 2; - if (buffer_size > INT_MAX) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto FAIL2; - } - } - - *num_glyphs = gcp_results.nGlyphs; - *glyphs = _cairo_malloc_ab (gcp_results.nGlyphs, sizeof (cairo_glyph_t)); - if (!*glyphs) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto FAIL2; - } - - x_pos = x; - y_pos = y; - - for (i = 0; i < gcp_results.nGlyphs; i++) { - (*glyphs)[i].index = glyph_indices[i]; - (*glyphs)[i].x = x_pos ; - (*glyphs)[i].y = y_pos; - - x_pos += x_incr * dx[i]; - y_pos += y_incr * dx[i]; - } - - FAIL2: - if (glyph_indices) - free (glyph_indices); - if (dx) - free (dx); - - cairo_win32_scaled_font_done_font (&scaled_font->base); - - FAIL1: - free (utf16); - - return status; -} - -static unsigned long -_cairo_win32_scaled_font_ucs4_to_index (void *abstract_font, - uint32_t ucs4) -{ - cairo_win32_scaled_font_t *scaled_font = abstract_font; - wchar_t unicode[2]; - WORD glyph_index; - HDC hdc = NULL; - cairo_status_t status; - - hdc = _get_global_font_dc (); - assert (hdc != NULL); - - status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc); - if (status) - return 0; - - unicode[0] = ucs4; - unicode[1] = 0; - if (GetGlyphIndicesW (hdc, unicode, 1, &glyph_index, 0) == GDI_ERROR) { - _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_ucs4_to_index:GetGlyphIndicesW"); - glyph_index = 0; - } - - cairo_win32_scaled_font_done_font (&scaled_font->base); - - return glyph_index; -} - -static cairo_status_t -_cairo_win32_scaled_font_set_metrics (cairo_win32_scaled_font_t *scaled_font) -{ - cairo_status_t status; - cairo_font_extents_t extents; - - TEXTMETRIC metrics; - HDC hdc; - - hdc = _get_global_font_dc (); - assert (hdc != NULL); - - if (scaled_font->preserve_axes || scaled_font->base.options.hint_metrics == CAIRO_HINT_METRICS_OFF) { - /* For 90-degree rotations (including 0), we get the metrics - * from the GDI in logical space, then convert back to font space - */ - status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc); - if (status) - return status; - GetTextMetrics (hdc, &metrics); - cairo_win32_scaled_font_done_font (&scaled_font->base); - - extents.ascent = metrics.tmAscent / scaled_font->logical_scale; - extents.descent = metrics.tmDescent / scaled_font->logical_scale; - - extents.height = (metrics.tmHeight + metrics.tmExternalLeading) / scaled_font->logical_scale; - extents.max_x_advance = metrics.tmMaxCharWidth / scaled_font->logical_scale; - extents.max_y_advance = 0; - - } else { - /* For all other transformations, we use the design metrics - * of the font. The GDI results from GetTextMetrics() on a - * transformed font are inexplicably large and we want to - * avoid them. - */ - status = _cairo_win32_scaled_font_select_unscaled_font (&scaled_font->base, hdc); - if (status) - return status; - GetTextMetrics (hdc, &metrics); - _cairo_win32_scaled_font_done_unscaled_font (&scaled_font->base); - - extents.ascent = (double)metrics.tmAscent / scaled_font->em_square; - extents.descent = (double)metrics.tmDescent / scaled_font->em_square; - extents.height = (double)(metrics.tmHeight + metrics.tmExternalLeading) / scaled_font->em_square; - extents.max_x_advance = (double)(metrics.tmMaxCharWidth) / scaled_font->em_square; - extents.max_y_advance = 0; - - } - - scaled_font->is_bitmap = !(metrics.tmPitchAndFamily & TMPF_VECTOR); - - /* Need to determine if this is a Type 1 font for the special - * handling in _text_to_glyphs. Unlike TrueType or OpenType, - * Type1 fonts do not have a "cmap" table (or any other table). - * However GetFontData() will retrieve a Type1 font when - * requesting that GetFontData() retrieve data from the start of - * the file. This is to distinguish Type1 from stroke fonts such - * as "Script" and "Modern". The TMPF_TRUETYPE test is redundant - * but improves performance for the most common fonts. - */ - scaled_font->is_type1 = FALSE; - if (!(metrics.tmPitchAndFamily & TMPF_TRUETYPE) && - (metrics.tmPitchAndFamily & TMPF_VECTOR)) - { - if ((GetFontData (hdc, CMAP_TAG, 0, NULL, 0) == GDI_ERROR) && - (GetFontData (hdc, 0, 0, NULL, 0) != GDI_ERROR)) - { - scaled_font->is_type1 = TRUE; - } - } - - return _cairo_scaled_font_set_metrics (&scaled_font->base, &extents); -} - -static cairo_status_t -_cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_font, - cairo_scaled_glyph_t *scaled_glyph) -{ - static const MAT2 matrix = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, 1 } }; - GLYPHMETRICS metrics; - cairo_status_t status; - cairo_text_extents_t extents; - HDC hdc; - - hdc = _get_global_font_dc (); - assert (hdc != NULL); - - if (scaled_font->is_bitmap) { - /* GetGlyphOutline will not work. Assume that the glyph does not extend outside the font box. */ - cairo_font_extents_t font_extents; - INT width = 0; - UINT charIndex = _cairo_scaled_glyph_index (scaled_glyph); - - cairo_scaled_font_extents (&scaled_font->base, &font_extents); - - status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc); - if (status) - return status; - - if (!GetCharWidth32(hdc, charIndex, charIndex, &width)) { - status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_init_glyph_metrics:GetCharWidth32"); - width = 0; - } - cairo_win32_scaled_font_done_font (&scaled_font->base); - if (status) - return status; - - extents.x_bearing = 0; - extents.y_bearing = scaled_font->base.ctm.yy * (-font_extents.ascent / scaled_font->y_scale); - extents.width = width / (WIN32_FONT_LOGICAL_SCALE * scaled_font->x_scale); - extents.height = scaled_font->base.ctm.yy * (font_extents.ascent + font_extents.descent) / scaled_font->y_scale; - extents.x_advance = extents.width; - extents.y_advance = 0; - } else if (scaled_font->preserve_axes && scaled_font->base.options.hint_style != CAIRO_HINT_METRICS_OFF) { - /* If we aren't rotating / skewing the axes, then we get the metrics - * from the GDI in device space and convert to font space. - */ - status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc); - if (status) - return status; - - if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph), - GGO_METRICS | GGO_GLYPH_INDEX, - &metrics, 0, NULL, &matrix) == GDI_ERROR) { - status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_init_glyph_metrics:GetGlyphOutlineW"); - memset (&metrics, 0, sizeof (GLYPHMETRICS)); - } - cairo_win32_scaled_font_done_font (&scaled_font->base); - if (status) - return status; - - if (scaled_font->swap_axes) { - extents.x_bearing = - metrics.gmptGlyphOrigin.y / scaled_font->y_scale; - extents.y_bearing = metrics.gmptGlyphOrigin.x / scaled_font->x_scale; - extents.width = metrics.gmBlackBoxY / scaled_font->y_scale; - extents.height = metrics.gmBlackBoxX / scaled_font->x_scale; - extents.x_advance = metrics.gmCellIncY / scaled_font->x_scale; - extents.y_advance = metrics.gmCellIncX / scaled_font->y_scale; - } else { - extents.x_bearing = metrics.gmptGlyphOrigin.x / scaled_font->x_scale; - extents.y_bearing = - metrics.gmptGlyphOrigin.y / scaled_font->y_scale; - extents.width = metrics.gmBlackBoxX / scaled_font->x_scale; - extents.height = metrics.gmBlackBoxY / scaled_font->y_scale; - extents.x_advance = metrics.gmCellIncX / scaled_font->x_scale; - extents.y_advance = metrics.gmCellIncY / scaled_font->y_scale; - } - - if (scaled_font->swap_x) { - extents.x_bearing = (- extents.x_bearing - extents.width); - extents.x_advance = - extents.x_advance; - } - - if (scaled_font->swap_y) { - extents.y_bearing = (- extents.y_bearing - extents.height); - extents.y_advance = - extents.y_advance; - } - - } else { - /* For all other transformations, we use the design metrics - * of the font. - */ - status = _cairo_win32_scaled_font_select_unscaled_font (&scaled_font->base, hdc); - if (status) - return status; - - if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph), - GGO_METRICS | GGO_GLYPH_INDEX, - &metrics, 0, NULL, &matrix) == GDI_ERROR) { - status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_init_glyph_metrics:GetGlyphOutlineW"); - memset (&metrics, 0, sizeof (GLYPHMETRICS)); - } - _cairo_win32_scaled_font_done_unscaled_font (&scaled_font->base); - if (status) - return status; - - extents.x_bearing = (double)metrics.gmptGlyphOrigin.x / scaled_font->em_square; - extents.y_bearing = - (double)metrics.gmptGlyphOrigin.y / scaled_font->em_square; - extents.width = (double)metrics.gmBlackBoxX / scaled_font->em_square; - extents.height = (double)metrics.gmBlackBoxY / scaled_font->em_square; - extents.x_advance = (double)metrics.gmCellIncX / scaled_font->em_square; - extents.y_advance = (double)metrics.gmCellIncY / scaled_font->em_square; - } - - _cairo_scaled_glyph_set_metrics (scaled_glyph, - &scaled_font->base, - &extents); - - return CAIRO_STATUS_SUCCESS; -} - -/* Not currently used code, but may be useful in the future if we add - * back the capability to the scaled font backend interface to get the - * actual device space bbox rather than computing it from the - * font-space metrics. - */ -#if 0 -static cairo_status_t -_cairo_win32_scaled_font_glyph_bbox (void *abstract_font, - const cairo_glyph_t *glyphs, - int num_glyphs, - cairo_box_t *bbox) -{ - static const MAT2 matrix = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, 1 } }; - cairo_win32_scaled_font_t *scaled_font = abstract_font; - int x1 = 0, x2 = 0, y1 = 0, y2 = 0; - - if (num_glyphs > 0) { - HDC hdc; - GLYPHMETRICS metrics; - cairo_status_t status; - int i; - - hdc = _get_global_font_dc (); - assert (hdc != NULL); - - status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc); - if (status) - return status; - - for (i = 0; i < num_glyphs; i++) { - int x = _cairo_lround (glyphs[i].x); - int y = _cairo_lround (glyphs[i].y); - - GetGlyphOutlineW (hdc, glyphs[i].index, GGO_METRICS | GGO_GLYPH_INDEX, - &metrics, 0, NULL, &matrix); - - if (i == 0 || x1 > x + metrics.gmptGlyphOrigin.x) - x1 = x + metrics.gmptGlyphOrigin.x; - if (i == 0 || y1 > y - metrics.gmptGlyphOrigin.y) - y1 = y - metrics.gmptGlyphOrigin.y; - if (i == 0 || x2 < x + metrics.gmptGlyphOrigin.x + (int)metrics.gmBlackBoxX) - x2 = x + metrics.gmptGlyphOrigin.x + (int)metrics.gmBlackBoxX; - if (i == 0 || y2 < y - metrics.gmptGlyphOrigin.y + (int)metrics.gmBlackBoxY) - y2 = y - metrics.gmptGlyphOrigin.y + (int)metrics.gmBlackBoxY; - } - - cairo_win32_scaled_font_done_font (&scaled_font->base); - } - - bbox->p1.x = _cairo_fixed_from_int (x1); - bbox->p1.y = _cairo_fixed_from_int (y1); - bbox->p2.x = _cairo_fixed_from_int (x2); - bbox->p2.y = _cairo_fixed_from_int (y2); - - return CAIRO_STATUS_SUCCESS; -} -#endif - -typedef struct { - cairo_win32_scaled_font_t *scaled_font; - HDC hdc; - - cairo_array_t glyphs; - cairo_array_t dx; - - int start_x; - int last_x; - int last_y; -} cairo_glyph_state_t; - -static void -_start_glyphs (cairo_glyph_state_t *state, - cairo_win32_scaled_font_t *scaled_font, - HDC hdc) -{ - state->hdc = hdc; - state->scaled_font = scaled_font; - - _cairo_array_init (&state->glyphs, sizeof (WCHAR)); - _cairo_array_init (&state->dx, sizeof (int)); -} - -static cairo_status_t -_flush_glyphs (cairo_glyph_state_t *state) -{ - cairo_status_t status; - int dx = 0; - WCHAR * elements; - int * dx_elements; - - status = _cairo_array_append (&state->dx, &dx); - if (status) - return status; - - elements = _cairo_array_index (&state->glyphs, 0); - dx_elements = _cairo_array_index (&state->dx, 0); - if (!ExtTextOutW (state->hdc, - state->start_x, state->last_y, - ETO_GLYPH_INDEX, - NULL, - elements, - state->glyphs.num_elements, - dx_elements)) { - return _cairo_win32_print_gdi_error ("_flush_glyphs"); - } - - _cairo_array_truncate (&state->glyphs, 0); - _cairo_array_truncate (&state->dx, 0); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_add_glyph (cairo_glyph_state_t *state, - unsigned long index, - double device_x, - double device_y) -{ - cairo_status_t status; - double user_x = device_x; - double user_y = device_y; - WCHAR glyph_index = index; - int logical_x, logical_y; - - cairo_matrix_transform_point (&state->scaled_font->device_to_logical, &user_x, &user_y); - - logical_x = _cairo_lround (user_x); - logical_y = _cairo_lround (user_y); - - if (state->glyphs.num_elements > 0) { - int dx; - - if (logical_y != state->last_y) { - status = _flush_glyphs (state); - if (status) - return status; - state->start_x = logical_x; - } - - dx = logical_x - state->last_x; - status = _cairo_array_append (&state->dx, &dx); - if (status) - return status; - } else { - state->start_x = logical_x; - } - - state->last_x = logical_x; - state->last_y = logical_y; - - status = _cairo_array_append (&state->glyphs, &glyph_index); - if (status) - return status; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_finish_glyphs (cairo_glyph_state_t *state) -{ - cairo_status_t status; - - status = _flush_glyphs (state); - - _cairo_array_fini (&state->glyphs); - _cairo_array_fini (&state->dx); - - return status; -} - -static cairo_status_t -_draw_glyphs_on_surface (cairo_win32_surface_t *surface, - cairo_win32_scaled_font_t *scaled_font, - COLORREF color, - int x_offset, - int y_offset, - const cairo_glyph_t *glyphs, - int num_glyphs) -{ - cairo_glyph_state_t state; - cairo_status_t status, status2; - int i; - - if (!SaveDC (surface->dc)) - return _cairo_win32_print_gdi_error ("_draw_glyphs_on_surface:SaveDC"); - - status = cairo_win32_scaled_font_select_font (&scaled_font->base, surface->dc); - if (status) - goto FAIL1; - - SetTextColor (surface->dc, color); - SetTextAlign (surface->dc, TA_BASELINE | TA_LEFT); - SetBkMode (surface->dc, TRANSPARENT); - - _start_glyphs (&state, scaled_font, surface->dc); - - for (i = 0; i < num_glyphs; i++) { - status = _add_glyph (&state, glyphs[i].index, - glyphs[i].x - x_offset, glyphs[i].y - y_offset); - if (status) - goto FAIL2; - } - - FAIL2: - status2 = _finish_glyphs (&state); - if (status == CAIRO_STATUS_SUCCESS) - status = status2; - - cairo_win32_scaled_font_done_font (&scaled_font->base); - FAIL1: - RestoreDC (surface->dc, -1); - - return status; -} - -/* Duplicate the green channel of a 4-channel mask in the alpha channel, then - * invert the whole mask. - */ -static void -_compute_argb32_mask_alpha (cairo_win32_surface_t *mask_surface) -{ - cairo_image_surface_t *image = (cairo_image_surface_t *)mask_surface->image; - int i, j; - - for (i = 0; i < image->height; i++) { - uint32_t *p = (uint32_t *) (image->data + i * image->stride); - for (j = 0; j < image->width; j++) { - *p = 0xffffffff ^ (*p | ((*p & 0x0000ff00) << 16)); - p++; - } - } -} - -/* Invert a mask - */ -static void -_invert_argb32_mask (cairo_win32_surface_t *mask_surface) -{ - cairo_image_surface_t *image = (cairo_image_surface_t *)mask_surface->image; - int i, j; - - for (i = 0; i < image->height; i++) { - uint32_t *p = (uint32_t *) (image->data + i * image->stride); - for (j = 0; j < image->width; j++) { - *p = 0xffffffff ^ *p; - p++; - } - } -} - -/* Compute an alpha-mask from a monochrome RGB24 image - */ -static cairo_surface_t * -_compute_a8_mask (cairo_win32_surface_t *mask_surface) -{ - cairo_image_surface_t *image24 = (cairo_image_surface_t *)mask_surface->image; - cairo_image_surface_t *image8; - int i, j; - - if (image24->base.status) - return cairo_surface_reference (&image24->base); - - image8 = (cairo_image_surface_t *)cairo_image_surface_create (CAIRO_FORMAT_A8, - image24->width, image24->height); - if (image8->base.status) - return &image8->base; - - for (i = 0; i < image24->height; i++) { - uint32_t *p = (uint32_t *) (image24->data + i * image24->stride); - unsigned char *q = (unsigned char *) (image8->data + i * image8->stride); - - for (j = 0; j < image24->width; j++) { - *q = 255 - ((*p & 0x0000ff00) >> 8); - p++; - q++; - } - } - - return &image8->base; -} - -static cairo_int_status_t -_cairo_win32_scaled_font_glyph_init (void *abstract_font, - cairo_scaled_glyph_t *scaled_glyph, - cairo_scaled_glyph_info_t info) -{ - cairo_win32_scaled_font_t *scaled_font = abstract_font; - cairo_status_t status; - - if ((info & CAIRO_SCALED_GLYPH_INFO_METRICS) != 0) { - status = _cairo_win32_scaled_font_init_glyph_metrics (scaled_font, scaled_glyph); - if (status) - return status; - } - - if (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) { - status = _cairo_win32_scaled_font_init_glyph_surface (scaled_font, scaled_glyph); - if (status) - return status; - } - - if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0) { - status = _cairo_win32_scaled_font_init_glyph_path (scaled_font, scaled_glyph); - if (status) - return status; - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_win32_scaled_font_show_glyphs (void *abstract_font, - cairo_operator_t op, - cairo_pattern_t *pattern, - cairo_surface_t *generic_surface, - int source_x, - int source_y, - int dest_x, - int dest_y, - unsigned int width, - unsigned int height, - cairo_glyph_t *glyphs, - int num_glyphs, - int *remaining_glyphs) -{ - cairo_win32_scaled_font_t *scaled_font = abstract_font; - cairo_win32_surface_t *surface = (cairo_win32_surface_t *)generic_surface; - cairo_status_t status; - - if (width == 0 || height == 0) - return CAIRO_STATUS_SUCCESS; - - if (_cairo_surface_is_win32 (generic_surface) && - surface->format == CAIRO_FORMAT_RGB24 && - op == CAIRO_OPERATOR_OVER && - _cairo_pattern_is_opaque_solid (pattern)) { - - cairo_solid_pattern_t *solid_pattern = (cairo_solid_pattern_t *)pattern; - - /* When compositing OVER on a GDI-understood surface, with a - * solid opaque color, we can just call ExtTextOut directly. - */ - COLORREF new_color; - - new_color = RGB (((int)solid_pattern->color.red_short) >> 8, - ((int)solid_pattern->color.green_short) >> 8, - ((int)solid_pattern->color.blue_short) >> 8); - - status = _draw_glyphs_on_surface (surface, scaled_font, new_color, - 0, 0, - glyphs, num_glyphs); - - return status; - } else { - /* Otherwise, we need to draw using software fallbacks. We create a mask - * surface by drawing the the glyphs onto a DIB, black-on-white then - * inverting. GDI outputs gamma-corrected images so inverted black-on-white - * is very different from white-on-black. We favor the more common - * case where the final output is dark-on-light. - */ - cairo_win32_surface_t *tmp_surface; - cairo_surface_t *mask_surface; - cairo_surface_pattern_t mask; - RECT r; - - tmp_surface = (cairo_win32_surface_t *)cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32, width, height); - if (tmp_surface->base.status) - return tmp_surface->base.status; - - r.left = 0; - r.top = 0; - r.right = width; - r.bottom = height; - FillRect (tmp_surface->dc, &r, GetStockObject (WHITE_BRUSH)); - - status = _draw_glyphs_on_surface (tmp_surface, - scaled_font, RGB (0, 0, 0), - dest_x, dest_y, - glyphs, num_glyphs); - if (status) { - cairo_surface_destroy (&tmp_surface->base); - return status; - } - - if (scaled_font->quality == CLEARTYPE_QUALITY) { - /* For ClearType, we need a 4-channel mask. If we are compositing on - * a surface with alpha, we need to compute the alpha channel of - * the mask (we just copy the green channel). But for a destination - * surface without alpha the alpha channel of the mask is ignored - */ - - if (surface->format != CAIRO_FORMAT_RGB24) - _compute_argb32_mask_alpha (tmp_surface); - else - _invert_argb32_mask (tmp_surface); - - mask_surface = &tmp_surface->base; - - /* XXX: Hacky, should expose this in cairo_image_surface */ - pixman_image_set_component_alpha (((cairo_image_surface_t *)tmp_surface->image)->pixman_image, TRUE); - - } else { - mask_surface = _compute_a8_mask (tmp_surface); - cairo_surface_destroy (&tmp_surface->base); - status = mask_surface->status; - if (status) - return status; - } - - /* For op == OVER, no-cleartype, a possible optimization here is to - * draw onto an intermediate ARGB32 surface and alpha-blend that with the - * destination - */ - _cairo_pattern_init_for_surface (&mask, mask_surface); - - status = _cairo_surface_composite (op, pattern, - &mask.base, - &surface->base, - source_x, source_y, - 0, 0, - dest_x, dest_y, - width, height); - - _cairo_pattern_fini (&mask.base); - - cairo_surface_destroy (mask_surface); - - return status; - } -} - -static cairo_int_status_t -_cairo_win32_scaled_font_load_truetype_table (void *abstract_font, - unsigned long tag, - long offset, - unsigned char *buffer, - unsigned long *length) -{ - cairo_win32_scaled_font_t *scaled_font = abstract_font; - HDC hdc; - cairo_status_t status; - - hdc = _get_global_font_dc (); - assert (hdc != NULL); - - tag = (tag&0x000000ff)<<24 | (tag&0x0000ff00)<<8 | (tag&0x00ff0000)>>8 | (tag&0xff000000)>>24; - status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc); - if (status) - return status; - - *length = GetFontData (hdc, tag, offset, buffer, *length); - if (*length == GDI_ERROR) - status = CAIRO_INT_STATUS_UNSUPPORTED; - - cairo_win32_scaled_font_done_font (&scaled_font->base); - - return status; -} - -static cairo_int_status_t -_cairo_win32_scaled_font_index_to_ucs4 (void *abstract_font, - unsigned long index, - uint32_t *ucs4) -{ - cairo_win32_scaled_font_t *scaled_font = abstract_font; - GLYPHSET *glyph_set; - uint16_t *utf16 = NULL; - WORD *glyph_indices = NULL; - HDC hdc = NULL; - int res; - unsigned int i, j, num_glyphs; - cairo_status_t status; - - hdc = _get_global_font_dc (); - assert (hdc != NULL); - - status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc); - if (status) - return status; - - res = GetFontUnicodeRanges(hdc, NULL); - if (res == 0) { - status = _cairo_win32_print_gdi_error ( - "_cairo_win32_scaled_font_index_to_ucs4:GetFontUnicodeRanges"); - goto exit1; - } - - glyph_set = malloc (res); - if (glyph_set == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto exit1; - } - - res = GetFontUnicodeRanges(hdc, glyph_set); - if (res == 0) { - status = _cairo_win32_print_gdi_error ( - "_cairo_win32_scaled_font_index_to_ucs4:GetFontUnicodeRanges"); - goto exit1; - } - - for (i = 0; i < glyph_set->cRanges; i++) { - num_glyphs = glyph_set->ranges[i].cGlyphs; - - utf16 = _cairo_malloc_ab (num_glyphs + 1, sizeof (uint16_t)); - if (utf16 == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto exit1; - } - - glyph_indices = _cairo_malloc_ab (num_glyphs + 1, sizeof (WORD)); - if (glyph_indices == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto exit2; - } - - for (j = 0; j < num_glyphs; j++) - utf16[j] = glyph_set->ranges[i].wcLow + j; - utf16[j] = 0; - - if (GetGlyphIndicesW (hdc, utf16, num_glyphs, glyph_indices, 0) == GDI_ERROR) { - status = _cairo_win32_print_gdi_error ( - "_cairo_win32_scaled_font_index_to_ucs4:GetGlyphIndicesW"); - goto exit2; - } - - for (j = 0; j < num_glyphs; j++) { - if (glyph_indices[j] == index) { - *ucs4 = utf16[j]; - goto exit2; - } - } - - free (glyph_indices); - glyph_indices = NULL; - free (utf16); - utf16 = NULL; - } - -exit2: - if (glyph_indices) - free (glyph_indices); - if (utf16) - free (utf16); - free (glyph_set); -exit1: - cairo_win32_scaled_font_done_font (&scaled_font->base); - - return status; -} - -static cairo_status_t -_cairo_win32_scaled_font_init_glyph_surface (cairo_win32_scaled_font_t *scaled_font, - cairo_scaled_glyph_t *scaled_glyph) -{ - cairo_status_t status; - cairo_glyph_t glyph; - cairo_win32_surface_t *surface; - cairo_t *cr; - cairo_surface_t *image; - int width, height; - int x1, y1, x2, y2; - - x1 = _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x); - y1 = _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y); - x2 = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.x); - y2 = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y); - width = x2 - x1; - height = y2 - y1; - - surface = (cairo_win32_surface_t *) - cairo_win32_surface_create_with_dib (CAIRO_FORMAT_RGB24, width, height); - - cr = cairo_create (&surface->base); - cairo_set_source_rgb (cr, 1, 1, 1); - cairo_paint (cr); - status = cairo_status (cr); - cairo_destroy(cr); - if (status) - goto FAIL; - - glyph.index = _cairo_scaled_glyph_index (scaled_glyph); - glyph.x = -x1; - glyph.y = -y1; - status = _draw_glyphs_on_surface (surface, scaled_font, RGB(0,0,0), - 0, 0, &glyph, 1); - if (status) - goto FAIL; - - GdiFlush(); - - image = _compute_a8_mask (surface); - status = image->status; - if (status) - goto FAIL; - - cairo_surface_set_device_offset (image, -x1, -y1); - _cairo_scaled_glyph_set_surface (scaled_glyph, - &scaled_font->base, - (cairo_image_surface_t *) image); - - FAIL: - cairo_surface_destroy (&surface->base); - - return status; -} - -static void -_cairo_win32_transform_FIXED_to_fixed (cairo_matrix_t *matrix, - FIXED Fx, FIXED Fy, - cairo_fixed_t *fx, cairo_fixed_t *fy) -{ - double x = Fx.value + Fx.fract / 65536.0; - double y = Fy.value + Fy.fract / 65536.0; - cairo_matrix_transform_point (matrix, &x, &y); - *fx = _cairo_fixed_from_double (x); - *fy = _cairo_fixed_from_double (y); -} - -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 const MAT2 matrix = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, -1 } }; - cairo_status_t status; - GLYPHMETRICS metrics; - HDC hdc; - DWORD bytesGlyph; - unsigned char *buffer, *ptr; - cairo_path_fixed_t *path; - cairo_matrix_t transform; - cairo_fixed_t x, y; - - if (scaled_font->is_bitmap) - return CAIRO_INT_STATUS_UNSUPPORTED; - - hdc = _get_global_font_dc (); - assert (hdc != NULL); - - path = _cairo_path_fixed_create (); - if (!path) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - if (scaled_font->base.options.hint_style == CAIRO_HINT_STYLE_NONE) { - status = _cairo_win32_scaled_font_select_unscaled_font (&scaled_font->base, hdc); - transform = scaled_font->base.scale; - cairo_matrix_scale (&transform, 1.0/scaled_font->em_square, 1.0/scaled_font->em_square); - } else { - status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc); - cairo_matrix_init_identity(&transform); - } - if (status) - goto CLEANUP_PATH; - - bytesGlyph = GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph), - GGO_NATIVE | GGO_GLYPH_INDEX, - &metrics, 0, NULL, &matrix); - - if (bytesGlyph == GDI_ERROR) { - status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_glyph_path"); - goto CLEANUP_FONT; - } - - ptr = buffer = malloc (bytesGlyph); - if (!buffer) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto CLEANUP_FONT; - } - - if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph), - GGO_NATIVE | GGO_GLYPH_INDEX, - &metrics, bytesGlyph, buffer, &matrix) == GDI_ERROR) { - status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_glyph_path"); - goto CLEANUP_BUFFER; - } - - while (ptr < buffer + bytesGlyph) { - TTPOLYGONHEADER *header = (TTPOLYGONHEADER *)ptr; - unsigned char *endPoly = ptr + header->cb; - - ptr += sizeof (TTPOLYGONHEADER); - - _cairo_win32_transform_FIXED_to_fixed (&transform, - header->pfxStart.x, - header->pfxStart.y, - &x, &y); - status = _cairo_path_fixed_move_to (path, x, y); - if (status) - goto CLEANUP_BUFFER; - - while (ptr < endPoly) { - TTPOLYCURVE *curve = (TTPOLYCURVE *)ptr; - POINTFX *points = curve->apfx; - int i; - switch (curve->wType) { - case TT_PRIM_LINE: - for (i = 0; i < curve->cpfx; i++) { - _cairo_win32_transform_FIXED_to_fixed (&transform, - points[i].x, - points[i].y, - &x, &y); - status = _cairo_path_fixed_line_to (path, x, y); - if (status) - goto CLEANUP_BUFFER; - } - break; - case TT_PRIM_QSPLINE: - for (i = 0; i < curve->cpfx - 1; i++) { - cairo_fixed_t p1x, p1y, p2x, p2y, cx, cy, c1x, c1y, c2x, c2y; - if (! _cairo_path_fixed_get_current_point (path, &p1x, &p1y)) - goto CLEANUP_BUFFER; - _cairo_win32_transform_FIXED_to_fixed (&transform, - points[i].x, - points[i].y, - &cx, &cy); - - if (i + 1 == curve->cpfx - 1) { - _cairo_win32_transform_FIXED_to_fixed (&transform, - points[i + 1].x, - points[i + 1].y, - &p2x, &p2y); - } else { - /* records with more than one curve use interpolation for - control points, per http://support.microsoft.com/kb/q87115/ */ - _cairo_win32_transform_FIXED_to_fixed (&transform, - points[i + 1].x, - points[i + 1].y, - &x, &y); - p2x = (cx + x) / 2; - p2y = (cy + y) / 2; - } - - c1x = 2 * cx / 3 + p1x / 3; - c1y = 2 * cy / 3 + p1y / 3; - c2x = 2 * cx / 3 + p2x / 3; - c2y = 2 * cy / 3 + p2y / 3; - - status = _cairo_path_fixed_curve_to (path, c1x, c1y, c2x, c2y, p2x, p2y); - if (status) - goto CLEANUP_BUFFER; - } - break; - case TT_PRIM_CSPLINE: - for (i = 0; i < curve->cpfx - 2; i += 2) { - cairo_fixed_t x1, y1, x2, y2; - _cairo_win32_transform_FIXED_to_fixed (&transform, - points[i].x, - points[i].y, - &x, &y); - _cairo_win32_transform_FIXED_to_fixed (&transform, - points[i + 1].x, - points[i + 1].y, - &x1, &y1); - _cairo_win32_transform_FIXED_to_fixed (&transform, - points[i + 2].x, - points[i + 2].y, - &x2, &y2); - status = _cairo_path_fixed_curve_to (path, x, y, x1, y1, x2, y2); - if (status) - goto CLEANUP_BUFFER; - } - break; - } - ptr += sizeof(TTPOLYCURVE) + sizeof (POINTFX) * (curve->cpfx - 1); - } - status = _cairo_path_fixed_close_path (path); - if (status) - goto CLEANUP_BUFFER; - } - - _cairo_scaled_glyph_set_path (scaled_glyph, - &scaled_font->base, - path); - - CLEANUP_BUFFER: - free (buffer); - - CLEANUP_FONT: - cairo_win32_scaled_font_done_font (&scaled_font->base); - - CLEANUP_PATH: - if (status != CAIRO_STATUS_SUCCESS) - _cairo_path_fixed_destroy (path); - - return status; -} - -const cairo_scaled_font_backend_t _cairo_win32_scaled_font_backend = { - CAIRO_FONT_TYPE_WIN32, - NULL, - _cairo_win32_scaled_font_create_toy, - _cairo_win32_scaled_font_fini, - _cairo_win32_scaled_font_glyph_init, - NULL, /* _cairo_win32_scaled_font_text_to_glyphs, FIXME */ - _cairo_win32_scaled_font_ucs4_to_index, - _cairo_win32_scaled_font_show_glyphs, - _cairo_win32_scaled_font_load_truetype_table, - _cairo_win32_scaled_font_index_to_ucs4, -}; - -/* #cairo_win32_font_face_t */ - -typedef struct _cairo_win32_font_face cairo_win32_font_face_t; - -/* If hfont is non-%NULL then logfont->lfHeight must be -S for some S, - * logfont->lfWidth, logfont->lfEscapement, logfont->lfOrientation must - * all be 0, and hfont is the result of calling CreateFontIndirectW on - * logfont. - */ -struct _cairo_win32_font_face { - cairo_font_face_t base; - LOGFONTW logfont; - HFONT hfont; -}; - -/* implement the platform-specific interface */ - -static void -_cairo_win32_font_face_destroy (void *abstract_face) -{ -} - -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); -} - -static const cairo_font_face_backend_t _cairo_win32_font_face_backend = { - CAIRO_FONT_TYPE_WIN32, - _cairo_win32_font_face_destroy, - NULL, /* direct implementation */ - _cairo_win32_font_face_scaled_font_create -}; - -/** - * cairo_win32_font_face_create_for_logfontw_hfont: - * @logfont: A #LOGFONTW structure specifying the font to use. - * If hfont is null then the lfHeight, lfWidth, lfOrientation and lfEscapement - * fields of this structure are ignored. Otherwise lfWidth, lfOrientation and - * lfEscapement must be zero. - * @font: An #HFONT that can be used when the font matrix is a scale by - * -lfHeight and the CTM is identity. - * - * Creates a new font for the Win32 font backend based on a - * #LOGFONT. This font can then be used with - * cairo_set_font_face() or cairo_scaled_font_create(). - * The #cairo_scaled_font_t - * returned from cairo_scaled_font_create() is also for the Win32 backend - * and can be used with functions such as cairo_win32_scaled_font_select_font(). - * - * Return value: a newly created #cairo_font_face_t. Free with - * cairo_font_face_destroy() when you are done using it. - **/ -cairo_font_face_t * -cairo_win32_font_face_create_for_logfontw_hfont (LOGFONTW *logfont, HFONT font) -{ - cairo_win32_font_face_t *font_face; - - font_face = malloc (sizeof (cairo_win32_font_face_t)); - if (!font_face) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_font_face_t *)&_cairo_font_face_nil; - } - - font_face->logfont = *logfont; - font_face->hfont = font; - - _cairo_font_face_init (&font_face->base, &_cairo_win32_font_face_backend); - - return &font_face->base; -} - -/** - * cairo_win32_font_face_create_for_logfontw: - * @logfont: A #LOGFONTW structure specifying the font to use. - * The lfHeight, lfWidth, lfOrientation and lfEscapement - * fields of this structure are ignored. - * - * Creates a new font for the Win32 font backend based on a - * #LOGFONT. This font can then be used with - * cairo_set_font_face() or cairo_scaled_font_create(). - * The #cairo_scaled_font_t - * returned from cairo_scaled_font_create() is also for the Win32 backend - * and can be used with functions such as cairo_win32_scaled_font_select_font(). - * - * Return value: a newly created #cairo_font_face_t. Free with - * cairo_font_face_destroy() when you are done using it. - **/ -cairo_font_face_t * -cairo_win32_font_face_create_for_logfontw (LOGFONTW *logfont) -{ - return cairo_win32_font_face_create_for_logfontw_hfont (logfont, NULL); -} - -/** - * cairo_win32_font_face_create_for_hfont: - * @font: An #HFONT structure specifying the font to use. - * - * Creates a new font for the Win32 font backend based on a - * #HFONT. This font can then be used with - * cairo_set_font_face() or cairo_scaled_font_create(). - * The #cairo_scaled_font_t - * returned from cairo_scaled_font_create() is also for the Win32 backend - * and can be used with functions such as cairo_win32_scaled_font_select_font(). - * - * Return value: a newly created #cairo_font_face_t. Free with - * cairo_font_face_destroy() when you are done using it. - **/ -cairo_font_face_t * -cairo_win32_font_face_create_for_hfont (HFONT font) -{ - LOGFONTW logfont; - GetObjectW (font, sizeof(logfont), &logfont); - - if (logfont.lfEscapement != 0 || logfont.lfOrientation != 0 || - logfont.lfWidth != 0) { - /* We can't use this font because that optimization requires that - * lfEscapement, lfOrientation and lfWidth be zero. */ - font = NULL; - } - - return cairo_win32_font_face_create_for_logfontw_hfont (&logfont, font); -} - -static cairo_bool_t -_cairo_scaled_font_is_win32 (cairo_scaled_font_t *scaled_font) -{ - return scaled_font->backend == &_cairo_win32_scaled_font_backend; -} - -/** - * cairo_win32_scaled_font_select_font: - * @scaled_font: A #cairo_scaled_font_t from the Win32 font backend. Such an - * object can be created with cairo_win32_scaled_font_create_for_logfontw(). - * @hdc: a device context - * - * Selects the font into the given device context and changes the - * map mode and world transformation of the device context to match - * that of the font. This function is intended for use when using - * layout APIs such as Uniscribe to do text layout with the - * cairo font. After finishing using the device context, you must call - * cairo_win32_scaled_font_done_font() to release any resources allocated - * by this function. - * - * See cairo_win32_scaled_font_get_metrics_factor() for converting logical - * coordinates from the device context to font space. - * - * Normally, calls to SaveDC() and RestoreDC() would be made around - * the use of this function to preserve the original graphics state. - * - * Return value: %CAIRO_STATUS_SUCCESS if the operation succeeded. - * otherwise an error such as %CAIRO_STATUS_NO_MEMORY and - * the device context is unchanged. - **/ -cairo_status_t -cairo_win32_scaled_font_select_font (cairo_scaled_font_t *scaled_font, - HDC hdc) -{ - cairo_status_t status; - HFONT hfont; - HFONT old_hfont = NULL; - int old_mode; - - if (! _cairo_scaled_font_is_win32 (scaled_font)) { - return _cairo_error (CAIRO_STATUS_FONT_TYPE_MISMATCH); - } - - if (scaled_font->status) - return scaled_font->status; - - status = _win32_scaled_font_get_scaled_hfont ((cairo_win32_scaled_font_t *)scaled_font, &hfont); - if (status) - return status; - - old_hfont = SelectObject (hdc, hfont); - if (!old_hfont) - return _cairo_win32_print_gdi_error ("cairo_win32_scaled_font_select_font:SelectObject"); - - old_mode = SetGraphicsMode (hdc, GM_ADVANCED); - if (!old_mode) { - status = _cairo_win32_print_gdi_error ("cairo_win32_scaled_font_select_font:SetGraphicsMode"); - SelectObject (hdc, old_hfont); - return status; - } - - status = _win32_scaled_font_set_world_transform ((cairo_win32_scaled_font_t *)scaled_font, hdc); - if (status) { - SetGraphicsMode (hdc, old_mode); - SelectObject (hdc, old_hfont); - return status; - } - - SetMapMode (hdc, MM_TEXT); - - return CAIRO_STATUS_SUCCESS; -} - -/** - * cairo_win32_scaled_font_done_font: - * @scaled_font: A scaled font from the Win32 font backend. - * - * Releases any resources allocated by cairo_win32_scaled_font_select_font() - **/ -void -cairo_win32_scaled_font_done_font (cairo_scaled_font_t *scaled_font) -{ - if (! _cairo_scaled_font_is_win32 (scaled_font)) { - _cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH); - } -} - -/** - * cairo_win32_scaled_font_get_metrics_factor: - * @scaled_font: a scaled font from the Win32 font backend - * - * Gets a scale factor between logical coordinates in the coordinate - * space used by cairo_win32_scaled_font_select_font() (that is, the - * coordinate system used by the Windows functions to return metrics) and - * font space coordinates. - * - * Return value: factor to multiply logical units by to get font space - * coordinates. - **/ -double -cairo_win32_scaled_font_get_metrics_factor (cairo_scaled_font_t *scaled_font) -{ - if (! _cairo_scaled_font_is_win32 (scaled_font)) { - _cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH); - return 1.; - } - return 1. / ((cairo_win32_scaled_font_t *)scaled_font)->logical_scale; -} - -/** - * cairo_win32_scaled_font_get_logical_to_device: - * @scaled_font: a scaled font from the Win32 font backend - * @logical_to_device: matrix to return - * - * Gets the transformation mapping the logical space used by @scaled_font - * to device space. - * - * Since: 1.4 - **/ -void -cairo_win32_scaled_font_get_logical_to_device (cairo_scaled_font_t *scaled_font, - cairo_matrix_t *logical_to_device) -{ - cairo_win32_scaled_font_t *win_font = (cairo_win32_scaled_font_t *)scaled_font; - if (! _cairo_scaled_font_is_win32 (scaled_font)) { - _cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH); - cairo_matrix_init_identity (logical_to_device); - return; - } - *logical_to_device = win_font->logical_to_device; -} - -/** - * cairo_win32_scaled_font_get_device_to_logical: - * @scaled_font: a scaled font from the Win32 font backend - * @device_to_logical: matrix to return - * - * Gets the transformation mapping device space to the logical space - * used by @scaled_font. - * - * Since: 1.4 - **/ -void -cairo_win32_scaled_font_get_device_to_logical (cairo_scaled_font_t *scaled_font, - cairo_matrix_t *device_to_logical) -{ - cairo_win32_scaled_font_t *win_font = (cairo_win32_scaled_font_t *)scaled_font; - if (! _cairo_scaled_font_is_win32 (scaled_font)) { - _cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH); - cairo_matrix_init_identity (device_to_logical); - return; - } - *device_to_logical = win_font->device_to_logical; -} diff --git a/uppdev/plugin/cairo/lib/cairo-win32-printing-surface.c b/uppdev/plugin/cairo/lib/cairo-win32-printing-surface.c deleted file mode 100644 index 2c2f061d9..000000000 --- a/uppdev/plugin/cairo/lib/cairo-win32-printing-surface.c +++ /dev/null @@ -1,1653 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* Cairo - a vector graphics library with display and print output - * - * Copyright © 2007 Adrian Johnson - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Adrian Johnson. - * - * Contributor(s): - * Adrian Johnson - * Vladimir Vukicevic - */ - -#define WIN32_LEAN_AND_MEAN -/* We require Windows 2000 features such as ETO_PDY */ -#if !defined(WINVER) || (WINVER < 0x0500) -# define WINVER 0x0500 -#endif -#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500) -# define _WIN32_WINNT 0x0500 -#endif - -#include "cairoint.h" - -#include "cairo-paginated-private.h" - -#include "cairo-clip-private.h" -#include "cairo-win32-private.h" -#include "cairo-meta-surface-private.h" -#include "cairo-scaled-font-subsets-private.h" - -#include - -#if !defined(POSTSCRIPT_IDENTIFY) -# define POSTSCRIPT_IDENTIFY 0x1015 -#endif - -#if !defined(PSIDENT_GDICENTRIC) -# define PSIDENT_GDICENTRIC 0x0000 -#endif - -#if !defined(GET_PS_FEATURESETTING) -# define GET_PS_FEATURESETTING 0x1019 -#endif - -#if !defined(FEATURESETTING_PSLEVEL) -# define FEATURESETTING_PSLEVEL 0x0002 -#endif - -#if !defined(GRADIENT_FILL_RECT_H) -# define GRADIENT_FILL_RECT_H 0x00 -#endif - -#define PELS_72DPI ((LONG)(72. / 0.0254)) - -static const cairo_surface_backend_t cairo_win32_printing_surface_backend; -static const cairo_paginated_surface_backend_t cairo_win32_surface_paginated_backend; - -static void -_cairo_win32_printing_surface_init_ps_mode (cairo_win32_surface_t *surface) -{ - DWORD word; - INT ps_feature, ps_level; - - word = PSIDENT_GDICENTRIC; - if (ExtEscape (surface->dc, POSTSCRIPT_IDENTIFY, sizeof(DWORD), (char *)&word, 0, (char *)NULL) <= 0) - return; - - ps_feature = FEATURESETTING_PSLEVEL; - if (ExtEscape (surface->dc, GET_PS_FEATURESETTING, sizeof(INT), - (char *)&ps_feature, sizeof(INT), (char *)&ps_level) <= 0) - return; - - if (ps_level >= 3) - surface->flags |= CAIRO_WIN32_SURFACE_CAN_RECT_GRADIENT; -} - -static cairo_int_status_t -analyze_surface_pattern_transparency (cairo_surface_pattern_t *pattern) -{ - cairo_image_surface_t *image; - void *image_extra; - cairo_int_status_t status; - int x, y; - - status = _cairo_surface_acquire_source_image (pattern->surface, - &image, - &image_extra); - if (status) - return status; - - if (image->base.status) - return image->base.status; - - if (image->format == CAIRO_FORMAT_RGB24) { - status = CAIRO_STATUS_SUCCESS; - goto RELEASE_SOURCE; - } - - if (image->format != CAIRO_FORMAT_ARGB32) { - /* If the surface does not support the image format, assume - * that it does have alpha. The image will be converted to - * rgb24 when the surface blends the image into the page - * color to remove the transparency. */ - status = CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY; - goto RELEASE_SOURCE; - } - - for (y = 0; y < image->height; y++) { - int a; - uint32_t *pixel = (uint32_t *) (image->data + y * image->stride); - - for (x = 0; x < image->width; x++, pixel++) { - a = (*pixel & 0xff000000) >> 24; - if (a != 255) { - status = CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY; - goto RELEASE_SOURCE; - } - } - } - status = CAIRO_STATUS_SUCCESS; - -RELEASE_SOURCE: - _cairo_surface_release_source_image (pattern->surface, image, image_extra); - - return status; -} - -static cairo_bool_t -surface_pattern_supported (const cairo_surface_pattern_t *pattern) -{ - cairo_extend_t extend; - - if (_cairo_surface_is_meta (pattern->surface)) - return TRUE; - - if (cairo_surface_get_type (pattern->surface) != CAIRO_SURFACE_TYPE_WIN32 && - pattern->surface->backend->acquire_source_image == NULL) - { - return FALSE; - } - - extend = cairo_pattern_get_extend ((cairo_pattern_t*)&pattern->base); - switch (extend) { - case CAIRO_EXTEND_NONE: - case CAIRO_EXTEND_REPEAT: - case CAIRO_EXTEND_REFLECT: - /* There's no point returning FALSE for EXTEND_PAD, as the image - * surface does not currently implement it either */ - case CAIRO_EXTEND_PAD: - return TRUE; - } - - ASSERT_NOT_REACHED; - return FALSE; -} - -static cairo_bool_t -pattern_supported (cairo_win32_surface_t *surface, const cairo_pattern_t *pattern) -{ - if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) - return TRUE; - - if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) - return surface_pattern_supported ((const cairo_surface_pattern_t *) pattern); - - if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR) - return surface->flags & CAIRO_WIN32_SURFACE_CAN_RECT_GRADIENT; - - return FALSE; -} - -static cairo_int_status_t -_cairo_win32_printing_surface_analyze_operation (cairo_win32_surface_t *surface, - cairo_operator_t op, - const cairo_pattern_t *pattern) -{ - if (! pattern_supported (surface, pattern)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (!(op == CAIRO_OPERATOR_SOURCE || - op == CAIRO_OPERATOR_OVER || - op == CAIRO_OPERATOR_CLEAR)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) { - cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern; - - if ( _cairo_surface_is_meta (surface_pattern->surface)) - return CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN; - } - - if (op == CAIRO_OPERATOR_SOURCE || - op == CAIRO_OPERATOR_CLEAR) - return CAIRO_STATUS_SUCCESS; - - /* CAIRO_OPERATOR_OVER is only supported for opaque patterns. If - * the pattern contains transparency, we return - * CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY to the analysis - * surface. If the analysis surface determines that there is - * anything drawn under this operation, a fallback image will be - * used. Otherwise the operation will be replayed during the - * render stage and we blend the transarency into the white - * background to convert the pattern to opaque. - */ - - if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) { - cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern; - - return analyze_surface_pattern_transparency (surface_pattern); - } - - if (_cairo_pattern_is_opaque (pattern)) - return CAIRO_STATUS_SUCCESS; - else - return CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY; -} - -static cairo_bool_t -_cairo_win32_printing_surface_operation_supported (cairo_win32_surface_t *surface, - cairo_operator_t op, - const cairo_pattern_t *pattern) -{ - if (_cairo_win32_printing_surface_analyze_operation (surface, op, pattern) != CAIRO_INT_STATUS_UNSUPPORTED) - return TRUE; - else - return FALSE; -} - -static void -_cairo_win32_printing_surface_init_clear_color (cairo_win32_surface_t *surface, - cairo_solid_pattern_t *color) -{ - if (surface->content == CAIRO_CONTENT_COLOR_ALPHA) - _cairo_pattern_init_solid (color, CAIRO_COLOR_WHITE, CAIRO_CONTENT_COLOR); - else - _cairo_pattern_init_solid (color, CAIRO_COLOR_BLACK, CAIRO_CONTENT_COLOR); -} - -static COLORREF -_cairo_win32_printing_surface_flatten_transparency (cairo_win32_surface_t *surface, - const cairo_color_t *color) -{ - COLORREF c; - BYTE red, green, blue; - - red = color->red_short >> 8; - green = color->green_short >> 8; - blue = color->blue_short >> 8; - - if (!CAIRO_COLOR_IS_OPAQUE(color)) { - if (surface->content == CAIRO_CONTENT_COLOR_ALPHA) { - /* Blend into white */ - uint8_t one_minus_alpha = 255 - (color->alpha_short >> 8); - - red = (color->red_short >> 8) + one_minus_alpha; - green = (color->green_short >> 8) + one_minus_alpha; - blue = (color->blue_short >> 8) + one_minus_alpha; - } else { - /* Blend into black */ - red = (color->red_short >> 8); - green = (color->green_short >> 8); - blue = (color->blue_short >> 8); - } - } - c = RGB (red, green, blue); - - return c; -} - -static cairo_status_t -_cairo_win32_printing_surface_select_solid_brush (cairo_win32_surface_t *surface, - cairo_pattern_t *source) -{ - cairo_solid_pattern_t *pattern = (cairo_solid_pattern_t *) source; - COLORREF color; - - color = _cairo_win32_printing_surface_flatten_transparency (surface, - &pattern->color); - surface->brush = CreateSolidBrush (color); - if (!surface->brush) - return _cairo_win32_print_gdi_error ("_cairo_win32_surface_select_solid_brush(CreateSolidBrush)"); - surface->old_brush = SelectObject (surface->dc, surface->brush); - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_win32_printing_surface_done_solid_brush (cairo_win32_surface_t *surface) -{ - if (surface->old_brush) { - SelectObject (surface->dc, surface->old_brush); - DeleteObject (surface->brush); - surface->old_brush = NULL; - } -} - -static cairo_status_t -_cairo_win32_printing_surface_get_ctm_clip_box (cairo_win32_surface_t *surface, - RECT *clip) -{ - XFORM xform; - - _cairo_matrix_to_win32_xform (&surface->ctm, &xform); - if (!SetWorldTransform (surface->dc, &xform)) - return _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_get_clip_box:SetWorldTransform"); - GetClipBox (surface->dc, clip); - if (!ModifyWorldTransform (surface->dc, &xform, MWT_IDENTITY)) - return _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_get_clip_box:ModifyWorldTransform"); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_win32_printing_surface_paint_solid_pattern (cairo_win32_surface_t *surface, - cairo_pattern_t *pattern) -{ - RECT clip; - cairo_status_t status; - - GetClipBox (surface->dc, &clip); - status = _cairo_win32_printing_surface_select_solid_brush (surface, pattern); - if (status) - return status; - - FillRect (surface->dc, &clip, surface->brush); - _cairo_win32_printing_surface_done_solid_brush (surface); - - return 0; -} - -static cairo_status_t -_cairo_win32_printing_surface_paint_meta_pattern (cairo_win32_surface_t *surface, - cairo_surface_pattern_t *pattern) -{ - cairo_content_t old_content; - cairo_matrix_t old_ctm; - cairo_bool_t old_has_ctm; - cairo_rectangle_int_t meta_extents; - cairo_status_t status; - cairo_extend_t extend; - cairo_matrix_t p2d; - XFORM xform; - int x_tile, y_tile, left, right, top, bottom; - RECT clip; - cairo_surface_t *meta_surface = pattern->surface; - - extend = cairo_pattern_get_extend (&pattern->base); - - p2d = pattern->base.matrix; - status = cairo_matrix_invert (&p2d); - /* _cairo_pattern_set_matrix guarantees invertibility */ - assert (status == CAIRO_STATUS_SUCCESS); - - old_ctm = surface->ctm; - old_has_ctm = surface->has_ctm; - cairo_matrix_multiply (&p2d, &p2d, &surface->ctm); - surface->ctm = p2d; - SaveDC (surface->dc); - _cairo_matrix_to_win32_xform (&p2d, &xform); - - status = _cairo_surface_get_extents (meta_surface, &meta_extents); - if (status) - return status; - - status = _cairo_win32_printing_surface_get_ctm_clip_box (surface, &clip); - if (status) - return status; - - if (extend == CAIRO_EXTEND_REPEAT || extend == CAIRO_EXTEND_REFLECT) { - left = (int) floor((double)clip.left/meta_extents.width); - right = (int) ceil((double)clip.right/meta_extents.width); - top = (int) floor((double)clip.top/meta_extents.height); - bottom = (int) ceil((double)clip.bottom/meta_extents.height); - } else { - left = 0; - right = 1; - top = 0; - bottom = 1; - } - - old_content = surface->content; - if (cairo_surface_get_content (meta_surface) == CAIRO_CONTENT_COLOR) { - cairo_pattern_t *source; - cairo_solid_pattern_t black; - - surface->content = CAIRO_CONTENT_COLOR; - _cairo_pattern_init_solid (&black, CAIRO_COLOR_BLACK, CAIRO_CONTENT_COLOR); - source = (cairo_pattern_t*) &black; - _cairo_win32_printing_surface_paint_solid_pattern (surface, source); - } - - for (y_tile = top; y_tile < bottom; y_tile++) { - for (x_tile = left; x_tile < right; x_tile++) { - cairo_matrix_t m; - double x, y; - - SaveDC (surface->dc); - m = p2d; - cairo_matrix_translate (&m, - x_tile*meta_extents.width, - y_tile*meta_extents.height); - if (extend == CAIRO_EXTEND_REFLECT) { - if (x_tile % 2) { - cairo_matrix_translate (&m, meta_extents.width, 0); - cairo_matrix_scale (&m, -1, 1); - } - if (y_tile % 2) { - cairo_matrix_translate (&m, 0, meta_extents.height); - cairo_matrix_scale (&m, 1, -1); - } - } - surface->ctm = m; - surface->has_ctm = !_cairo_matrix_is_identity (&surface->ctm); - - /* Set clip path around bbox of the pattern. */ - BeginPath (surface->dc); - - x = 0; - y = 0; - cairo_matrix_transform_point (&surface->ctm, &x, &y); - MoveToEx (surface->dc, (int) x, (int) y, NULL); - - x = meta_extents.width; - y = 0; - cairo_matrix_transform_point (&surface->ctm, &x, &y); - LineTo (surface->dc, (int) x, (int) y); - - x = meta_extents.width; - y = meta_extents.height; - cairo_matrix_transform_point (&surface->ctm, &x, &y); - LineTo (surface->dc, (int) x, (int) y); - - x = 0; - y = meta_extents.height; - cairo_matrix_transform_point (&surface->ctm, &x, &y); - LineTo (surface->dc, (int) x, (int) y); - - CloseFigure (surface->dc); - EndPath (surface->dc); - SelectClipPath (surface->dc, RGN_AND); - - SaveDC (surface->dc); /* Allow clip path to be reset during replay */ - status = _cairo_meta_surface_replay_region (meta_surface, &surface->base, - CAIRO_META_REGION_NATIVE); - assert (status != CAIRO_INT_STATUS_UNSUPPORTED); - /* Restore both the clip save and our earlier path SaveDC */ - RestoreDC (surface->dc, -2); - - if (status) - return status; - } - } - - surface->content = old_content; - surface->ctm = old_ctm; - surface->has_ctm = old_has_ctm; - RestoreDC (surface->dc, -1); - - return status; -} - -static cairo_status_t -_cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surface, - cairo_surface_pattern_t *pattern) -{ - cairo_status_t status; - cairo_extend_t extend; - cairo_surface_attributes_t pat_attr; - cairo_image_surface_t *image; - void *image_extra; - cairo_surface_t *opaque_surface; - cairo_image_surface_t *opaque_image = NULL; - BITMAPINFO bi; - cairo_matrix_t m; - int oldmode; - XFORM xform; - int x_tile, y_tile, left, right, top, bottom; - RECT clip; - const cairo_color_t *background_color; - - /* If we can't use StretchDIBits with this surface, we can't do anything - * here. - */ - if (!(surface->flags & CAIRO_WIN32_SURFACE_CAN_STRETCHDIB)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (surface->content == CAIRO_CONTENT_COLOR_ALPHA) - background_color = CAIRO_COLOR_WHITE; - else - background_color = CAIRO_COLOR_BLACK; - - extend = cairo_pattern_get_extend (&pattern->base); - - status = _cairo_surface_acquire_source_image (pattern->surface, - &image, &image_extra); - if (status) - return status; - - if (image->base.status) { - status = image->base.status; - goto CLEANUP_IMAGE; - } - - if (image->width == 0 || image->height == 0) { - status = CAIRO_STATUS_SUCCESS; - goto CLEANUP_IMAGE; - } - - if (image->format != CAIRO_FORMAT_RGB24) { - cairo_surface_pattern_t opaque_pattern; - - opaque_surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, - image->width, - image->height); - if (opaque_surface->status) { - status = opaque_surface->status; - goto CLEANUP_OPAQUE_IMAGE; - } - - _cairo_pattern_init_for_surface (&opaque_pattern, &image->base); - - status = _cairo_surface_fill_rectangle (opaque_surface, - CAIRO_OPERATOR_SOURCE, - background_color, - 0, 0, - image->width, image->height); - if (status) { - _cairo_pattern_fini (&opaque_pattern.base); - goto CLEANUP_OPAQUE_IMAGE; - } - - status = _cairo_surface_composite (CAIRO_OPERATOR_OVER, - &opaque_pattern.base, - NULL, - opaque_surface, - 0, 0, - 0, 0, - 0, 0, - image->width, - image->height); - if (status) { - _cairo_pattern_fini (&opaque_pattern.base); - goto CLEANUP_OPAQUE_IMAGE; - } - - _cairo_pattern_fini (&opaque_pattern.base); - opaque_image = (cairo_image_surface_t *) opaque_surface; - } else { - opaque_surface = &image->base; - opaque_image = image; - } - - bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bi.bmiHeader.biWidth = opaque_image->width; - bi.bmiHeader.biHeight = -opaque_image->height; - bi.bmiHeader.biSizeImage = 0; - bi.bmiHeader.biXPelsPerMeter = PELS_72DPI; - bi.bmiHeader.biYPelsPerMeter = PELS_72DPI; - bi.bmiHeader.biPlanes = 1; - bi.bmiHeader.biBitCount = 32; - bi.bmiHeader.biCompression = BI_RGB; - bi.bmiHeader.biClrUsed = 0; - bi.bmiHeader.biClrImportant = 0; - - m = pattern->base.matrix; - status = cairo_matrix_invert (&m); - /* _cairo_pattern_set_matrix guarantees invertibility */ - assert (status == CAIRO_STATUS_SUCCESS); - - cairo_matrix_multiply (&m, &m, &surface->ctm); - SaveDC (surface->dc); - _cairo_matrix_to_win32_xform (&m, &xform); - - if (! SetWorldTransform (surface->dc, &xform)) { - status = _cairo_win32_print_gdi_error ("_win32_scaled_font_set_world_transform"); - goto CLEANUP_OPAQUE_IMAGE; - } - - oldmode = SetStretchBltMode(surface->dc, HALFTONE); - - GetClipBox (surface->dc, &clip); - if (extend == CAIRO_EXTEND_REPEAT || extend == CAIRO_EXTEND_REFLECT) { - left = (int) floor((double)clip.left/opaque_image->width); - right = (int) ceil((double)clip.right/opaque_image->width); - top = (int) floor((double)clip.top/opaque_image->height); - bottom = (int) ceil((double)clip.bottom/opaque_image->height); - } else { - left = 0; - right = 1; - top = 0; - bottom = 1; - } - - for (y_tile = top; y_tile < bottom; y_tile++) { - for (x_tile = left; x_tile < right; x_tile++) { - if (!StretchDIBits (surface->dc, - x_tile*opaque_image->width, - y_tile*opaque_image->height, - opaque_image->width, - opaque_image->height, - 0, - 0, - opaque_image->width, - opaque_image->height, - opaque_image->data, - &bi, - DIB_RGB_COLORS, - SRCCOPY)) - { - status = _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_paint(StretchDIBits)"); - goto CLEANUP_OPAQUE_IMAGE; - } - } - } - SetStretchBltMode(surface->dc, oldmode); - RestoreDC (surface->dc, -1); - -CLEANUP_OPAQUE_IMAGE: - if (opaque_image != image) - cairo_surface_destroy (opaque_surface); -CLEANUP_IMAGE: - _cairo_surface_release_source_image (pattern->surface, image, image_extra); - - return status; -} - -static cairo_status_t -_cairo_win32_printing_surface_paint_surface_pattern (cairo_win32_surface_t *surface, - cairo_surface_pattern_t *pattern) -{ - if (_cairo_surface_is_meta (pattern->surface)) { - return _cairo_win32_printing_surface_paint_meta_pattern (surface, - pattern); - } else { - return _cairo_win32_printing_surface_paint_image_pattern (surface, - pattern); - } -} - -static void -vertex_set_color (TRIVERTEX *vert, cairo_color_t *color) -{ - /* MSDN says that the range here is 0x0000 .. 0xff00; - * that may well be a typo, but just chop the low bits - * here. */ - vert->Alpha = 0xff00; - vert->Red = color->red_short & 0xff00; - vert->Green = color->green_short & 0xff00; - vert->Blue = color->blue_short & 0xff00; -} - -static cairo_int_status_t -_cairo_win32_printing_surface_paint_linear_pattern (cairo_win32_surface_t *surface, - cairo_linear_pattern_t *pattern) -{ - TRIVERTEX *vert; - GRADIENT_RECT *rect; - RECT clip; - XFORM xform; - int i, num_stops; - cairo_matrix_t mat, rot; - double p1x, p1y, p2x, p2y, xd, yd, d, sn, cs; - cairo_extend_t extend; - int range_start, range_stop, num_ranges, num_rects, stop; - int total_verts, total_rects; - cairo_status_t status; - - extend = cairo_pattern_get_extend (&pattern->base.base); - SaveDC (surface->dc); - - mat = pattern->base.base.matrix; - status = cairo_matrix_invert (&mat); - /* _cairo_pattern_set_matrix guarantees invertibility */ - assert (status == CAIRO_STATUS_SUCCESS); - - cairo_matrix_multiply (&mat, &surface->ctm, &mat); - - p1x = _cairo_fixed_to_double (pattern->p1.x); - p1y = _cairo_fixed_to_double (pattern->p1.y); - p2x = _cairo_fixed_to_double (pattern->p2.x); - p2y = _cairo_fixed_to_double (pattern->p2.y); - cairo_matrix_translate (&mat, p1x, p1y); - - xd = p2x - p1x; - yd = p2y - p1y; - d = sqrt (xd*xd + yd*yd); - sn = yd/d; - cs = xd/d; - cairo_matrix_init (&rot, - cs, sn, - -sn, cs, - 0, 0); - cairo_matrix_multiply (&mat, &rot, &mat); - - _cairo_matrix_to_win32_xform (&mat, &xform); - - if (!SetWorldTransform (surface->dc, &xform)) - return _cairo_win32_print_gdi_error ("_win32_printing_surface_paint_linear_pattern:SetWorldTransform2"); - - GetClipBox (surface->dc, &clip); - - if (extend == CAIRO_EXTEND_REPEAT || extend == CAIRO_EXTEND_REFLECT) { - range_start = (int) floor(clip.left/d); - range_stop = (int) ceil(clip.right/d); - } else { - range_start = 0; - range_stop = 1; - } - num_ranges = range_stop - range_start; - num_stops = pattern->base.n_stops; - num_rects = num_stops - 1; - - /* Add an extra four points and two rectangles for EXTEND_PAD */ - vert = malloc (sizeof (TRIVERTEX) * (num_rects*2*num_ranges + 4)); - rect = malloc (sizeof (GRADIENT_RECT) * (num_rects*num_ranges + 2)); - - for (i = 0; i < num_ranges*num_rects; i++) { - vert[i*2].y = (LONG) clip.top; - if (i%num_rects == 0) { - stop = 0; - if (extend == CAIRO_EXTEND_REFLECT && (range_start+(i/num_rects))%2) - stop = num_rects; - vert[i*2].x = (LONG)(d*(range_start + i/num_rects)); - vertex_set_color (&vert[i*2], &pattern->base.stops[stop].color); - } else { - vert[i*2].x = vert[i*2-1].x; - vert[i*2].Red = vert[i*2-1].Red; - vert[i*2].Green = vert[i*2-1].Green; - vert[i*2].Blue = vert[i*2-1].Blue; - vert[i*2].Alpha = vert[i*2-1].Alpha; - } - - stop = i%num_rects + 1; - vert[i*2+1].x = (LONG)(d*(range_start + i/num_rects + pattern->base.stops[stop].offset)); - vert[i*2+1].y = (LONG) clip.bottom; - if (extend == CAIRO_EXTEND_REFLECT && (range_start+(i/num_rects))%2) - stop = num_rects - stop; - vertex_set_color (&vert[i*2+1], &pattern->base.stops[stop].color); - - rect[i].UpperLeft = i*2; - rect[i].LowerRight = i*2 + 1; - } - total_verts = 2*num_ranges*num_rects; - total_rects = num_ranges*num_rects; - - if (extend == CAIRO_EXTEND_PAD) { - vert[i*2].x = vert[i*2-1].x; - vert[i*2].y = (LONG) clip.top; - vert[i*2].Red = vert[i*2-1].Red; - vert[i*2].Green = vert[i*2-1].Green; - vert[i*2].Blue = vert[i*2-1].Blue; - vert[i*2].Alpha = 0xff00; - vert[i*2+1].x = clip.right; - vert[i*2+1].y = (LONG) clip.bottom; - vert[i*2+1].Red = vert[i*2-1].Red; - vert[i*2+1].Green = vert[i*2-1].Green; - vert[i*2+1].Blue = vert[i*2-1].Blue; - vert[i*2+1].Alpha = 0xff00; - rect[i].UpperLeft = i*2; - rect[i].LowerRight = i*2 + 1; - - i++; - - vert[i*2].x = clip.left; - vert[i*2].y = (LONG) clip.top; - vert[i*2].Red = vert[0].Red; - vert[i*2].Green = vert[0].Green; - vert[i*2].Blue = vert[0].Blue; - vert[i*2].Alpha = 0xff00; - vert[i*2+1].x = vert[0].x; - vert[i*2+1].y = (LONG) clip.bottom; - vert[i*2+1].Red = vert[0].Red; - vert[i*2+1].Green = vert[0].Green; - vert[i*2+1].Blue = vert[0].Blue; - vert[i*2+1].Alpha = 0xff00; - rect[i].UpperLeft = i*2; - rect[i].LowerRight = i*2 + 1; - - total_verts += 4; - total_rects += 2; - } - - if (!GradientFill (surface->dc, - vert, total_verts, - rect, total_rects, - GRADIENT_FILL_RECT_H)) - return _cairo_win32_print_gdi_error ("_win32_printing_surface_paint_linear_pattern:GradientFill"); - - free (rect); - free (vert); - RestoreDC (surface->dc, -1); - - return 0; -} - -static cairo_int_status_t -_cairo_win32_printing_surface_paint_pattern (cairo_win32_surface_t *surface, - cairo_pattern_t *pattern) -{ - cairo_status_t status; - - switch (pattern->type) { - case CAIRO_PATTERN_TYPE_SOLID: - status = _cairo_win32_printing_surface_paint_solid_pattern (surface, pattern); - if (status) - return status; - break; - - case CAIRO_PATTERN_TYPE_SURFACE: - status = _cairo_win32_printing_surface_paint_surface_pattern (surface, - (cairo_surface_pattern_t *) pattern); - if (status) - return status; - break; - - case CAIRO_PATTERN_TYPE_LINEAR: - status = _cairo_win32_printing_surface_paint_linear_pattern (surface, (cairo_linear_pattern_t *) pattern); - if (status) - return status; - break; - - case CAIRO_PATTERN_TYPE_RADIAL: - return CAIRO_INT_STATUS_UNSUPPORTED; - break; - } - - return CAIRO_STATUS_SUCCESS; -} - -typedef struct _win32_print_path_info { - cairo_win32_surface_t *surface; -} win32_path_info_t; - -static cairo_status_t -_cairo_win32_printing_surface_path_move_to (void *closure, cairo_point_t *point) -{ - win32_path_info_t *path_info = closure; - - if (path_info->surface->has_ctm) { - double x, y; - - x = _cairo_fixed_to_double (point->x); - y = _cairo_fixed_to_double (point->y); - cairo_matrix_transform_point (&path_info->surface->ctm, &x, &y); - MoveToEx (path_info->surface->dc, (int) x, (int) y, NULL); - } else { - MoveToEx (path_info->surface->dc, - _cairo_fixed_integer_part (point->x), - _cairo_fixed_integer_part (point->y), - NULL); - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_win32_printing_surface_path_line_to (void *closure, cairo_point_t *point) -{ - win32_path_info_t *path_info = closure; - - path_info->surface->path_empty = FALSE; - if (path_info->surface->has_ctm) { - double x, y; - - x = _cairo_fixed_to_double (point->x); - y = _cairo_fixed_to_double (point->y); - cairo_matrix_transform_point (&path_info->surface->ctm, &x, &y); - LineTo (path_info->surface->dc, (int) x, (int) y); - } else { - LineTo (path_info->surface->dc, - _cairo_fixed_integer_part (point->x), - _cairo_fixed_integer_part (point->y)); - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_win32_printing_surface_path_curve_to (void *closure, - cairo_point_t *b, - cairo_point_t *c, - cairo_point_t *d) -{ - win32_path_info_t *path_info = closure; - POINT points[3]; - - path_info->surface->path_empty = FALSE; - if (path_info->surface->has_ctm) { - double x, y; - - x = _cairo_fixed_to_double (b->x); - y = _cairo_fixed_to_double (b->y); - cairo_matrix_transform_point (&path_info->surface->ctm, &x, &y); - points[0].x = (LONG) x; - points[0].y = (LONG) y; - - x = _cairo_fixed_to_double (c->x); - y = _cairo_fixed_to_double (c->y); - cairo_matrix_transform_point (&path_info->surface->ctm, &x, &y); - points[1].x = (LONG) x; - points[1].y = (LONG) y; - - x = _cairo_fixed_to_double (d->x); - y = _cairo_fixed_to_double (d->y); - cairo_matrix_transform_point (&path_info->surface->ctm, &x, &y); - points[2].x = (LONG) x; - points[2].y = (LONG) y; - } else { - points[0].x = _cairo_fixed_integer_part (b->x); - points[0].y = _cairo_fixed_integer_part (b->y); - points[1].x = _cairo_fixed_integer_part (c->x); - points[1].y = _cairo_fixed_integer_part (c->y); - points[2].x = _cairo_fixed_integer_part (d->x); - points[2].y = _cairo_fixed_integer_part (d->y); - } - PolyBezierTo (path_info->surface->dc, points, 3); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_win32_printing_surface_path_close_path (void *closure) -{ - win32_path_info_t *path_info = closure; - - CloseFigure (path_info->surface->dc); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_win32_printing_surface_emit_path (cairo_win32_surface_t *surface, - cairo_path_fixed_t *path) -{ - win32_path_info_t path_info; - cairo_status_t status; - - path_info.surface = surface; - status = _cairo_path_fixed_interpret (path, - CAIRO_DIRECTION_FORWARD, - _cairo_win32_printing_surface_path_move_to, - _cairo_win32_printing_surface_path_line_to, - _cairo_win32_printing_surface_path_curve_to, - _cairo_win32_printing_surface_path_close_path, - &path_info); - return status; -} - -static cairo_int_status_t -_cairo_win32_printing_surface_show_page (void *abstract_surface) -{ - cairo_win32_surface_t *surface = abstract_surface; - - /* Undo both SaveDC's that we did in start_page */ - RestoreDC (surface->dc, -2); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_win32_printing_surface_intersect_clip_path (void *abstract_surface, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_win32_surface_t *surface = abstract_surface; - cairo_status_t status; - - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return CAIRO_STATUS_SUCCESS; - - if (path == NULL) { - RestoreDC (surface->dc, -1); - SaveDC (surface->dc); - - return CAIRO_STATUS_SUCCESS; - } - - BeginPath (surface->dc); - status = _cairo_win32_printing_surface_emit_path (surface, path); - EndPath (surface->dc); - - switch (fill_rule) { - case CAIRO_FILL_RULE_WINDING: - SetPolyFillMode (surface->dc, WINDING); - break; - case CAIRO_FILL_RULE_EVEN_ODD: - SetPolyFillMode (surface->dc, ALTERNATE); - break; - default: - ASSERT_NOT_REACHED; - } - - SelectClipPath (surface->dc, RGN_AND); - - return status; -} - -static void -_cairo_win32_printing_surface_get_font_options (void *abstract_surface, - cairo_font_options_t *options) -{ - _cairo_font_options_init_default (options); - - cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_NONE); - cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF); - cairo_font_options_set_antialias (options, CAIRO_ANTIALIAS_GRAY); -} - -static cairo_int_status_t -_cairo_win32_printing_surface_paint (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source) -{ - cairo_win32_surface_t *surface = abstract_surface; - cairo_solid_pattern_t clear; - - if (op == CAIRO_OPERATOR_CLEAR) { - _cairo_win32_printing_surface_init_clear_color (surface, &clear); - source = (cairo_pattern_t*) &clear; - op = CAIRO_OPERATOR_SOURCE; - } - - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return _cairo_win32_printing_surface_analyze_operation (surface, op, source); - - assert (_cairo_win32_printing_surface_operation_supported (surface, op, source)); - - return _cairo_win32_printing_surface_paint_pattern (surface, source); -} - -static int -_cairo_win32_line_cap (cairo_line_cap_t cap) -{ - switch (cap) { - case CAIRO_LINE_CAP_BUTT: - return PS_ENDCAP_FLAT; - case CAIRO_LINE_CAP_ROUND: - return PS_ENDCAP_ROUND; - case CAIRO_LINE_CAP_SQUARE: - return PS_ENDCAP_SQUARE; - default: - ASSERT_NOT_REACHED; - return 0; - } -} - -static int -_cairo_win32_line_join (cairo_line_join_t join) -{ - switch (join) { - case CAIRO_LINE_JOIN_MITER: - return PS_JOIN_MITER; - case CAIRO_LINE_JOIN_ROUND: - return PS_JOIN_ROUND; - case CAIRO_LINE_JOIN_BEVEL: - return PS_JOIN_BEVEL; - default: - ASSERT_NOT_REACHED; - return 0; - } -} - -static void -_cairo_matrix_factor_out_scale (cairo_matrix_t *m, double *scale) -{ - double s; - - 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); - *scale = s; - s = 1.0/s; - cairo_matrix_scale (m, s, s); -} - -static cairo_int_status_t -_cairo_win32_printing_surface_stroke (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_path_fixed_t *path, - cairo_stroke_style_t *style, - cairo_matrix_t *stroke_ctm, - cairo_matrix_t *stroke_ctm_inverse, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_win32_surface_t *surface = abstract_surface; - cairo_int_status_t status; - HPEN pen; - LOGBRUSH brush; - COLORREF color; - XFORM xform; - DWORD pen_style; - DWORD *dash_array; - HGDIOBJ obj; - unsigned int i; - cairo_solid_pattern_t clear; - cairo_matrix_t mat; - double scale; - - if (op == CAIRO_OPERATOR_CLEAR) { - _cairo_win32_printing_surface_init_clear_color (surface, &clear); - source = (cairo_pattern_t*) &clear; - op = CAIRO_OPERATOR_SOURCE; - } - - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { - /* Win32 does not support a dash offset. */ - if (style->num_dashes > 0 && style->dash_offset != 0.0) - return CAIRO_INT_STATUS_UNSUPPORTED; - - return _cairo_win32_printing_surface_analyze_operation (surface, op, source); - } - - assert (_cairo_win32_printing_surface_operation_supported (surface, op, source)); - assert (!(style->num_dashes > 0 && style->dash_offset != 0.0)); - - cairo_matrix_multiply (&mat, stroke_ctm, &surface->ctm); - _cairo_matrix_factor_out_scale (&mat, &scale); - - pen_style = PS_GEOMETRIC; - dash_array = NULL; - if (style->num_dashes) { - pen_style |= PS_USERSTYLE; - dash_array = calloc (sizeof (DWORD), style->num_dashes); - for (i = 0; i < style->num_dashes; i++) { - dash_array[i] = (DWORD) (scale * style->dash[i]); - } - } else { - pen_style |= PS_SOLID; - } - - SetMiterLimit (surface->dc, (FLOAT) (style->miter_limit), NULL); - if (source->type == CAIRO_PATTERN_TYPE_SOLID) { - cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) source; - - - color = _cairo_win32_printing_surface_flatten_transparency (surface, - &solid->color); - } else { - /* Color not used as the pen will only be used by WidenPath() */ - color = RGB (0,0,0); - } - brush.lbStyle = BS_SOLID; - brush.lbColor = color; - brush.lbHatch = 0; - pen_style |= _cairo_win32_line_cap (style->line_cap); - pen_style |= _cairo_win32_line_join (style->line_join); - pen = ExtCreatePen(pen_style, - scale * style->line_width, - &brush, - style->num_dashes, - dash_array); - if (pen == NULL) - return _cairo_win32_print_gdi_error ("_win32_surface_stroke:ExtCreatePen"); - obj = SelectObject (surface->dc, pen); - if (obj == NULL) - return _cairo_win32_print_gdi_error ("_win32_surface_stroke:SelectObject"); - - BeginPath (surface->dc); - status = _cairo_win32_printing_surface_emit_path (surface, path); - EndPath (surface->dc); - if (status) - return status; - - /* - * Switch to user space to set line parameters - */ - SaveDC (surface->dc); - - _cairo_matrix_to_win32_xform (&mat, &xform); - xform.eDx = 0.0f; - xform.eDy = 0.0f; - - if (!SetWorldTransform (surface->dc, &xform)) - return _cairo_win32_print_gdi_error ("_win32_surface_stroke:SetWorldTransform"); - - if (source->type == CAIRO_PATTERN_TYPE_SOLID) { - StrokePath (surface->dc); - } else { - if (!WidenPath (surface->dc)) - return _cairo_win32_print_gdi_error ("_win32_surface_stroke:WidenPath"); - if (!SelectClipPath (surface->dc, RGN_AND)) - return _cairo_win32_print_gdi_error ("_win32_surface_stroke:SelectClipPath"); - - /* Return to device space to paint the pattern */ - if (!ModifyWorldTransform (surface->dc, &xform, MWT_IDENTITY)) - return _cairo_win32_print_gdi_error ("_win32_surface_stroke:ModifyWorldTransform"); - status = _cairo_win32_printing_surface_paint_pattern (surface, source); - } - RestoreDC (surface->dc, -1); - DeleteObject (pen); - if (dash_array) - free (dash_array); - - return status; -} - -static cairo_int_status_t -_cairo_win32_printing_surface_fill (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_win32_surface_t *surface = abstract_surface; - cairo_int_status_t status; - cairo_solid_pattern_t clear; - - if (op == CAIRO_OPERATOR_CLEAR) { - _cairo_win32_printing_surface_init_clear_color (surface, &clear); - source = (cairo_pattern_t*) &clear; - op = CAIRO_OPERATOR_SOURCE; - } - - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return _cairo_win32_printing_surface_analyze_operation (surface, op, source); - - assert (_cairo_win32_printing_surface_operation_supported (surface, op, source)); - - surface->path_empty = TRUE; - BeginPath (surface->dc); - status = _cairo_win32_printing_surface_emit_path (surface, path); - EndPath (surface->dc); - - switch (fill_rule) { - case CAIRO_FILL_RULE_WINDING: - SetPolyFillMode (surface->dc, WINDING); - break; - case CAIRO_FILL_RULE_EVEN_ODD: - SetPolyFillMode (surface->dc, ALTERNATE); - break; - default: - ASSERT_NOT_REACHED; - } - - if (source->type == CAIRO_PATTERN_TYPE_SOLID) { - status = _cairo_win32_printing_surface_select_solid_brush (surface, source); - if (status) - return status; - - FillPath (surface->dc); - _cairo_win32_printing_surface_done_solid_brush (surface); - } else if (surface->path_empty == FALSE) { - SaveDC (surface->dc); - SelectClipPath (surface->dc, RGN_AND); - status = _cairo_win32_printing_surface_paint_pattern (surface, source); - RestoreDC (surface->dc, -1); - } - - fflush(stderr); - - return status; -} - -static cairo_int_status_t -_cairo_win32_printing_surface_show_glyphs (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font, - int *remaining_glyphs) -{ - cairo_win32_surface_t *surface = abstract_surface; - cairo_status_t status = CAIRO_STATUS_SUCCESS; - cairo_scaled_glyph_t *scaled_glyph; - cairo_pattern_t *opaque = NULL; - int i; - cairo_matrix_t old_ctm; - cairo_bool_t old_has_ctm; - cairo_solid_pattern_t clear; - - if (op == CAIRO_OPERATOR_CLEAR) { - _cairo_win32_printing_surface_init_clear_color (surface, &clear); - source = (cairo_pattern_t*) &clear; - op = CAIRO_OPERATOR_SOURCE; - } - - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { - /* When printing bitmap fonts to a printer DC, Windows may - * substitute an outline font for bitmap font. As the win32 - * font backend always uses a screen DC when obtaining the - * font metrics the metrics of the substituted font will not - * match the metrics that the win32 font backend returns. - * - * If we are printing a bitmap font, use fallback images to - * ensure the font is not substituted. - */ - if (cairo_scaled_font_get_type (scaled_font) == CAIRO_FONT_TYPE_WIN32) { - if (_cairo_win32_scaled_font_is_bitmap (scaled_font)) - return CAIRO_INT_STATUS_UNSUPPORTED; - else - return _cairo_win32_printing_surface_analyze_operation (surface, op, source); - } - - /* For non win32 fonts we need to check that each glyph has a - * path available. If a path is not available, - * _cairo_scaled_glyph_lookup() will return - * CAIRO_INT_STATUS_UNSUPPORTED and a fallback image will be - * used. - */ - 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; - } - - return _cairo_win32_printing_surface_analyze_operation (surface, op, source); - } - - if (source->type == CAIRO_PATTERN_TYPE_SOLID) { - cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) source; - COLORREF color; - - color = _cairo_win32_printing_surface_flatten_transparency (surface, - &solid->color); - opaque = cairo_pattern_create_rgb (GetRValue (color) / 255.0, - GetGValue (color) / 255.0, - GetBValue (color) / 255.0); - if (opaque->status) - return opaque->status; - source = opaque; - } - - if (cairo_scaled_font_get_type (scaled_font) == CAIRO_FONT_TYPE_WIN32 && - source->type == CAIRO_PATTERN_TYPE_SOLID) - { - cairo_matrix_t ctm; - cairo_glyph_t *type1_glyphs = NULL; - cairo_scaled_font_subsets_glyph_t subset_glyph; - - /* Calling ExtTextOutW() with ETO_GLYPH_INDEX and a Type 1 - * font on a printer DC prints garbled text. The text displays - * correctly on a display DC. When using a printer - * DC, ExtTextOutW() only works with characters and not glyph - * indices. - * - * For Type 1 fonts the glyph indices are converted back to - * unicode characters before calling _cairo_win32_surface_show_glyphs(). - * - * As _cairo_win32_scaled_font_index_to_ucs4() is a slow - * operation, the font subsetting function - * _cairo_scaled_font_subsets_map_glyph() is used to obtain - * the unicode value because it caches the reverse mapping in - * the subsets. - */ - if (_cairo_win32_scaled_font_is_type1 (scaled_font)) { - type1_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t)); - if (type1_glyphs == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - memcpy (type1_glyphs, glyphs, num_glyphs * sizeof (cairo_glyph_t)); - for (i = 0; i < num_glyphs; i++) { - status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets, - scaled_font, - type1_glyphs[i].index, - NULL, 0, - &subset_glyph); - if (status) - return status; - - type1_glyphs[i].index = subset_glyph.unicode; - } - glyphs = type1_glyphs; - } - - if (surface->has_ctm) { - for (i = 0; i < num_glyphs; i++) - cairo_matrix_transform_point (&surface->ctm, &glyphs[i].x, &glyphs[i].y); - cairo_matrix_multiply (&ctm, &scaled_font->ctm, &surface->ctm); - scaled_font = cairo_scaled_font_create (scaled_font->font_face, - &scaled_font->font_matrix, - &ctm, - &scaled_font->options); - } - status = _cairo_win32_surface_show_glyphs (surface, op, - source, glyphs, - num_glyphs, scaled_font, - remaining_glyphs); - if (surface->has_ctm) - cairo_scaled_font_destroy (scaled_font); - - if (type1_glyphs != NULL) - free (type1_glyphs); - - return status; - } - - SaveDC (surface->dc); - old_ctm = surface->ctm; - old_has_ctm = surface->has_ctm; - surface->has_ctm = TRUE; - surface->path_empty = TRUE; - BeginPath (surface->dc); - 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) - break; - surface->ctm = old_ctm; - cairo_matrix_translate (&surface->ctm, glyphs[i].x, glyphs[i].y); - status = _cairo_win32_printing_surface_emit_path (surface, scaled_glyph->path); - } - EndPath (surface->dc); - surface->ctm = old_ctm; - surface->has_ctm = old_has_ctm; - if (status == CAIRO_STATUS_SUCCESS && surface->path_empty == FALSE) { - if (source->type == CAIRO_PATTERN_TYPE_SOLID) { - status = _cairo_win32_printing_surface_select_solid_brush (surface, source); - if (status) - return status; - - SetPolyFillMode (surface->dc, WINDING); - FillPath (surface->dc); - _cairo_win32_printing_surface_done_solid_brush (surface); - } else { - SelectClipPath (surface->dc, RGN_AND); - status = _cairo_win32_printing_surface_paint_pattern (surface, source); - } - } - RestoreDC (surface->dc, -1); - - if (opaque) - cairo_pattern_destroy (opaque); - - return status; -} - -static cairo_surface_t * -_cairo_win32_printing_surface_create_similar (void *abstract_surface, - cairo_content_t content, - int width, - int height) -{ - return _cairo_meta_surface_create (content, width, height); -} - -static cairo_int_status_t -_cairo_win32_printing_surface_start_page (void *abstract_surface) -{ - cairo_win32_surface_t *surface = abstract_surface; - XFORM xform; - double x_res, y_res; - cairo_matrix_t inverse_ctm; - cairo_status_t status; - - SaveDC (surface->dc); /* Save application context first, before doing MWT */ - - SetGraphicsMode (surface->dc, GM_ADVANCED); - GetWorldTransform(surface->dc, &xform); - surface->ctm.xx = xform.eM11; - surface->ctm.xy = xform.eM21; - surface->ctm.yx = xform.eM12; - surface->ctm.yy = xform.eM22; - surface->ctm.x0 = xform.eDx; - surface->ctm.y0 = xform.eDy; - surface->has_ctm = !_cairo_matrix_is_identity (&surface->ctm); - - inverse_ctm = surface->ctm; - status = cairo_matrix_invert (&inverse_ctm); - if (status) - return status; - - x_res = (double) GetDeviceCaps(surface->dc, LOGPIXELSX); - y_res = (double) GetDeviceCaps(surface->dc, LOGPIXELSY); - cairo_matrix_transform_distance (&inverse_ctm, &x_res, &y_res); - _cairo_surface_set_resolution (&surface->base, x_res, y_res); - - if (!ModifyWorldTransform (surface->dc, NULL, MWT_IDENTITY)) - return _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_start_page:ModifyWorldTransform"); - - SaveDC (surface->dc); /* Then save Cairo's known-good clip state, so the clip path can be reset */ - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_win32_printing_surface_set_paginated_mode (void *abstract_surface, - cairo_paginated_mode_t paginated_mode) -{ - cairo_win32_surface_t *surface = abstract_surface; - - surface->paginated_mode = paginated_mode; -} - -static cairo_bool_t -_cairo_win32_printing_surface_supports_fine_grained_fallbacks (void *abstract_surface) -{ - return TRUE; -} - -/** - * cairo_win32_printing_surface_create: - * @hdc: the DC to create a surface for - * - * Creates a cairo surface that targets the given DC. The DC will be - * queried for its initial clip extents, and this will be used as the - * size of the cairo surface. The DC should be a printing DC; - * antialiasing will be ignored, and GDI will be used as much as - * possible to draw to the surface. - * - * The returned surface will be wrapped using the paginated surface to - * provide correct complex rendering behaviour; show_page() and - * associated methods must be used for correct output. - * - * Return value: the newly created surface - * - * Since: 1.6 - **/ -cairo_surface_t * -cairo_win32_printing_surface_create (HDC hdc) -{ - cairo_win32_surface_t *surface; - cairo_surface_t *paginated; - RECT rect; - - surface = malloc (sizeof (cairo_win32_surface_t)); - if (surface == NULL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - if (_cairo_win32_save_initial_clip (hdc, surface) != CAIRO_STATUS_SUCCESS) { - free (surface); - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - } - - surface->image = NULL; - surface->format = CAIRO_FORMAT_RGB24; - surface->content = CAIRO_CONTENT_COLOR_ALPHA; - - surface->dc = hdc; - surface->bitmap = NULL; - surface->is_dib = FALSE; - surface->saved_dc_bitmap = NULL; - surface->brush = NULL; - surface->old_brush = NULL; - surface->font_subsets = _cairo_scaled_font_subsets_create_scaled (); - if (surface->font_subsets == NULL) { - free (surface); - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - } - - GetClipBox(hdc, &rect); - surface->extents.x = rect.left; - surface->extents.y = rect.top; - surface->extents.width = rect.right - rect.left; - surface->extents.height = rect.bottom - rect.top; - - surface->flags = _cairo_win32_flags_for_dc (surface->dc); - surface->flags |= CAIRO_WIN32_SURFACE_FOR_PRINTING; - - _cairo_win32_printing_surface_init_ps_mode (surface); - _cairo_surface_init (&surface->base, &cairo_win32_printing_surface_backend, - CAIRO_CONTENT_COLOR_ALPHA); - - paginated = _cairo_paginated_surface_create (&surface->base, - CAIRO_CONTENT_COLOR_ALPHA, - surface->extents.width, - surface->extents.height, - &cairo_win32_surface_paginated_backend); - - /* paginated keeps the only reference to surface now, drop ours */ - cairo_surface_destroy (&surface->base); - - return paginated; -} - -cairo_bool_t -_cairo_surface_is_win32_printing (cairo_surface_t *surface) -{ - return surface->backend == &cairo_win32_printing_surface_backend; -} - -static const cairo_surface_backend_t cairo_win32_printing_surface_backend = { - CAIRO_SURFACE_TYPE_WIN32_PRINTING, - _cairo_win32_printing_surface_create_similar, - _cairo_win32_surface_finish, - NULL, /* acquire_source_image */ - NULL, /* release_source_image */ - NULL, /* acquire_dest_image */ - NULL, /* release_dest_image */ - _cairo_win32_surface_clone_similar, - NULL, /* composite */ - NULL, /* fill_rectangles */ - NULL, /* composite_trapezoids */ - NULL, /* copy_page */ - _cairo_win32_printing_surface_show_page, - NULL, /* set_clip_region */ - _cairo_win32_printing_surface_intersect_clip_path, - _cairo_win32_surface_get_extents, - NULL, /* old_show_glyphs */ - _cairo_win32_printing_surface_get_font_options, - NULL, /* flush */ - NULL, /* mark_dirty_rectangle */ - NULL, /* scaled_font_fini */ - NULL, /* scaled_glyph_fini */ - - _cairo_win32_printing_surface_paint, - NULL, /* mask */ - _cairo_win32_printing_surface_stroke, - _cairo_win32_printing_surface_fill, - _cairo_win32_printing_surface_show_glyphs, - NULL, /* snapshot */ - NULL, /* is_similar */ - NULL, /* reset */ - NULL, /* fill_stroke */ -}; - -static const cairo_paginated_surface_backend_t cairo_win32_surface_paginated_backend = { - _cairo_win32_printing_surface_start_page, - _cairo_win32_printing_surface_set_paginated_mode, - NULL, /* set_bounding_box */ - NULL, /* _cairo_win32_printing_surface_has_fallback_images, */ - _cairo_win32_printing_surface_supports_fine_grained_fallbacks, -}; diff --git a/uppdev/plugin/cairo/lib/cairo-win32-private.h b/uppdev/plugin/cairo/lib/cairo-win32-private.h deleted file mode 100644 index 21b04be35..000000000 --- a/uppdev/plugin/cairo/lib/cairo-win32-private.h +++ /dev/null @@ -1,194 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Owen Taylor - */ - -#ifndef CAIRO_WIN32_PRIVATE_H -#define CAIRO_WIN32_PRIVATE_H - -#include "cairo-win32.h" -#include "cairoint.h" - -#ifndef SHADEBLENDCAPS -#define SHADEBLENDCAPS 120 -#endif -#ifndef SB_NONE -#define SB_NONE 0 -#endif - -#define WIN32_FONT_LOGICAL_SCALE 32 - -typedef struct _cairo_win32_surface { - cairo_surface_t base; - - cairo_format_t format; - - HDC dc; - - /* We create off-screen surfaces as DIBs or DDBs, based on what we created - * originally*/ - HBITMAP bitmap; - cairo_bool_t is_dib; - - /* Used to save the initial 1x1 monochrome bitmap for the DC to - * select back into the DC before deleting the DC and our - * bitmap. For Windows XP, this doesn't seem to be necessary - * ... we can just delete the DC and that automatically unselects - * out bitmap. But it's standard practice so apparently is needed - * on some versions of Windows. - */ - HBITMAP saved_dc_bitmap; - - cairo_surface_t *image; - - cairo_rectangle_int_t extents; - - /* Initial clip bits - * We need these kept around so that we maintain - * whatever clip was set on the original DC at creation - * time when cairo is asked to reset the surface clip. - */ - cairo_rectangle_int_t clip_rect; - HRGN initial_clip_rgn; - cairo_bool_t had_simple_clip; - - /* Surface DC flags */ - uint32_t flags; - - /* printing surface bits */ - cairo_paginated_mode_t paginated_mode; - cairo_content_t content; - cairo_bool_t path_empty; - cairo_bool_t has_ctm; - cairo_matrix_t ctm; - HBRUSH brush, old_brush; - cairo_scaled_font_subsets_t *font_subsets; -} cairo_win32_surface_t; - -/* Surface DC flag values */ -enum { - /* If this is a surface created for printing or not */ - CAIRO_WIN32_SURFACE_FOR_PRINTING = (1<<0), - - /* Whether the DC is a display DC or not */ - CAIRO_WIN32_SURFACE_IS_DISPLAY = (1<<1), - - /* Whether we can use BitBlt with this surface */ - CAIRO_WIN32_SURFACE_CAN_BITBLT = (1<<2), - - /* Whether we can use AlphaBlend with this surface */ - CAIRO_WIN32_SURFACE_CAN_ALPHABLEND = (1<<3), - - /* Whether we can use StretchBlt with this surface */ - CAIRO_WIN32_SURFACE_CAN_STRETCHBLT = (1<<4), - - /* Whether we can use StretchDIBits with this surface */ - CAIRO_WIN32_SURFACE_CAN_STRETCHDIB = (1<<5), - - /* Whether we can use GradientFill rectangles with this surface */ - CAIRO_WIN32_SURFACE_CAN_RECT_GRADIENT = (1<<6), -}; - -cairo_status_t -_cairo_win32_print_gdi_error (const char *context); - -cairo_bool_t -_cairo_surface_is_win32 (cairo_surface_t *surface); - -cairo_bool_t -_cairo_surface_is_win32_printing (cairo_surface_t *surface); - -cairo_status_t -_cairo_win32_surface_finish (void *abstract_surface); - -cairo_int_status_t -_cairo_win32_surface_get_extents (void *abstract_surface, - cairo_rectangle_int_t *rectangle); - -uint32_t -_cairo_win32_flags_for_dc (HDC dc); - -cairo_int_status_t -_cairo_win32_surface_show_glyphs (void *surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font, - int *remaining_glyphs); - -cairo_surface_t * -_cairo_win32_surface_create_similar (void *abstract_src, - cairo_content_t content, - int width, - int height); - -cairo_status_t -_cairo_win32_surface_clone_similar (void *abstract_surface, - cairo_surface_t *src, - int src_x, - int src_y, - int width, - int height, - int *clone_offset_x, - int *clone_offset_y, - cairo_surface_t **clone_out); - -static inline void -_cairo_matrix_to_win32_xform (const cairo_matrix_t *m, - XFORM *xform) -{ - xform->eM11 = (FLOAT) m->xx; - xform->eM21 = (FLOAT) m->xy; - xform->eM12 = (FLOAT) m->yx; - xform->eM22 = (FLOAT) m->yy; - xform->eDx = (FLOAT) m->x0; - xform->eDy = (FLOAT) m->y0; -} - -cairo_int_status_t -_cairo_win32_save_initial_clip (HDC dc, cairo_win32_surface_t *surface); - -cairo_int_status_t -_cairo_win32_restore_initial_clip (cairo_win32_surface_t *surface); - -void -_cairo_win32_debug_dump_hrgn (HRGN rgn, char *header); - -cairo_bool_t -_cairo_win32_scaled_font_is_type1 (cairo_scaled_font_t *scaled_font); - -cairo_bool_t -_cairo_win32_scaled_font_is_bitmap (cairo_scaled_font_t *scaled_font); - -#endif /* CAIRO_WIN32_PRIVATE_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-win32-surface.c b/uppdev/plugin/cairo/lib/cairo-win32-surface.c deleted file mode 100644 index 5787e2619..000000000 --- a/uppdev/plugin/cairo/lib/cairo-win32-surface.c +++ /dev/null @@ -1,2134 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* Cairo - a vector graphics library with display and print output - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Owen Taylor - * Stuart Parmenter - * Vladimir Vukicevic - */ - -#define WIN32_LEAN_AND_MEAN -/* We require Windows 2000 features such as ETO_PDY */ -#if !defined(WINVER) || (WINVER < 0x0500) -# define WINVER 0x0500 -#endif -#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500) -# define _WIN32_WINNT 0x0500 -#endif - -#include "cairoint.h" - -#include "cairo-clip-private.h" -#include "cairo-paginated-private.h" -#include "cairo-win32-private.h" -#include "cairo-scaled-font-subsets-private.h" - -#include - -#if defined(__MINGW32__) && !defined(ETO_PDY) -# define ETO_PDY 0x2000 -#endif - -#undef DEBUG_COMPOSITE - -/* for older SDKs */ -#ifndef SHADEBLENDCAPS -#define SHADEBLENDCAPS 120 -#endif -#ifndef SB_NONE -#define SB_NONE 0x00000000 -#endif - -#define PELS_72DPI ((LONG)(72. / 0.0254)) - -static const cairo_surface_backend_t cairo_win32_surface_backend; - -/** - * _cairo_win32_print_gdi_error: - * @context: context string to display along with the error - * - * Helper function to dump out a human readable form of the - * current error code. - * - * Return value: A cairo status code for the error code - **/ -cairo_status_t -_cairo_win32_print_gdi_error (const char *context) -{ - void *lpMsgBuf; - DWORD last_error = GetLastError (); - - if (!FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM, - NULL, - last_error, - MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPSTR) &lpMsgBuf, - 0, NULL)) { - fprintf (stderr, "%s: Unknown GDI error", context); - } else { - fwprintf (stderr, "%S: %s", context, (char *)lpMsgBuf); - - LocalFree (lpMsgBuf); - } - - /* We should switch off of last_status, but we'd either return - * CAIRO_STATUS_NO_MEMORY or CAIRO_STATUS_UNKNOWN_ERROR and there - * is no CAIRO_STATUS_UNKNOWN_ERROR. - */ - - return _cairo_error (CAIRO_STATUS_NO_MEMORY); -} - -uint32_t -_cairo_win32_flags_for_dc (HDC dc) -{ - uint32_t flags = 0; - - if (GetDeviceCaps(dc, TECHNOLOGY) == DT_RASDISPLAY) { - flags |= CAIRO_WIN32_SURFACE_IS_DISPLAY; - - /* These will always be possible, but the actual GetDeviceCaps - * calls will return whether they're accelerated or not. - * We may want to use our own (pixman) routines sometimes - * if they're eventually faster, but for now have GDI do - * everything. - */ - flags |= CAIRO_WIN32_SURFACE_CAN_BITBLT; - flags |= CAIRO_WIN32_SURFACE_CAN_ALPHABLEND; - flags |= CAIRO_WIN32_SURFACE_CAN_STRETCHBLT; - flags |= CAIRO_WIN32_SURFACE_CAN_STRETCHDIB; - } else { - int cap; - - cap = GetDeviceCaps(dc, SHADEBLENDCAPS); - if (cap != SB_NONE) - flags |= CAIRO_WIN32_SURFACE_CAN_ALPHABLEND; - - cap = GetDeviceCaps(dc, RASTERCAPS); - if (cap & RC_BITBLT) - flags |= CAIRO_WIN32_SURFACE_CAN_BITBLT; - if (cap & RC_STRETCHBLT) - flags |= CAIRO_WIN32_SURFACE_CAN_STRETCHBLT; - if (cap & RC_STRETCHDIB) - flags |= CAIRO_WIN32_SURFACE_CAN_STRETCHDIB; - } - - return flags; -} - -static cairo_status_t -_create_dc_and_bitmap (cairo_win32_surface_t *surface, - HDC original_dc, - cairo_format_t format, - int width, - int height, - unsigned char **bits_out, - int *rowstride_out) -{ - cairo_status_t status; - - BITMAPINFO *bitmap_info = NULL; - struct { - BITMAPINFOHEADER bmiHeader; - RGBQUAD bmiColors[2]; - } bmi_stack; - void *bits; - - int num_palette = 0; /* Quiet GCC */ - int i; - - surface->dc = NULL; - surface->bitmap = NULL; - surface->is_dib = FALSE; - - switch (format) { - case CAIRO_FORMAT_ARGB32: - case CAIRO_FORMAT_RGB24: - num_palette = 0; - break; - - case CAIRO_FORMAT_A8: - num_palette = 256; - break; - - case CAIRO_FORMAT_A1: - num_palette = 2; - break; - } - - if (num_palette > 2) { - bitmap_info = _cairo_malloc_ab_plus_c (num_palette, sizeof(RGBQUAD), sizeof(BITMAPINFOHEADER)); - if (!bitmap_info) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } else { - bitmap_info = (BITMAPINFO *)&bmi_stack; - } - - bitmap_info->bmiHeader.biSize = sizeof (BITMAPINFOHEADER); - bitmap_info->bmiHeader.biWidth = width == 0 ? 1 : width; - bitmap_info->bmiHeader.biHeight = height == 0 ? -1 : - height; /* top-down */ - bitmap_info->bmiHeader.biSizeImage = 0; - bitmap_info->bmiHeader.biXPelsPerMeter = PELS_72DPI; /* unused here */ - bitmap_info->bmiHeader.biYPelsPerMeter = PELS_72DPI; /* unused here */ - bitmap_info->bmiHeader.biPlanes = 1; - - switch (format) { - /* We can't create real RGB24 bitmaps because something seems to - * break if we do, especially if we don't set up an image - * fallback. It could be a bug with using a 24bpp pixman image - * (and creating one with masks). So treat them like 32bpp. - * Note: This causes problems when using BitBlt/AlphaBlend/etc! - * see end of file. - */ - case CAIRO_FORMAT_RGB24: - case CAIRO_FORMAT_ARGB32: - bitmap_info->bmiHeader.biBitCount = 32; - bitmap_info->bmiHeader.biCompression = BI_RGB; - bitmap_info->bmiHeader.biClrUsed = 0; /* unused */ - bitmap_info->bmiHeader.biClrImportant = 0; - break; - - case CAIRO_FORMAT_A8: - bitmap_info->bmiHeader.biBitCount = 8; - bitmap_info->bmiHeader.biCompression = BI_RGB; - bitmap_info->bmiHeader.biClrUsed = 256; - bitmap_info->bmiHeader.biClrImportant = 0; - - for (i = 0; i < 256; i++) { - bitmap_info->bmiColors[i].rgbBlue = i; - bitmap_info->bmiColors[i].rgbGreen = i; - bitmap_info->bmiColors[i].rgbRed = i; - bitmap_info->bmiColors[i].rgbReserved = 0; - } - - break; - - case CAIRO_FORMAT_A1: - bitmap_info->bmiHeader.biBitCount = 1; - bitmap_info->bmiHeader.biCompression = BI_RGB; - bitmap_info->bmiHeader.biClrUsed = 2; - bitmap_info->bmiHeader.biClrImportant = 0; - - for (i = 0; i < 2; i++) { - bitmap_info->bmiColors[i].rgbBlue = i * 255; - bitmap_info->bmiColors[i].rgbGreen = i * 255; - bitmap_info->bmiColors[i].rgbRed = i * 255; - bitmap_info->bmiColors[i].rgbReserved = 0; - } - - break; - } - - surface->dc = CreateCompatibleDC (original_dc); - if (!surface->dc) - goto FAIL; - - surface->bitmap = CreateDIBSection (surface->dc, - bitmap_info, - DIB_RGB_COLORS, - &bits, - NULL, 0); - if (!surface->bitmap) - goto FAIL; - - surface->is_dib = TRUE; - - GdiFlush(); - - surface->saved_dc_bitmap = SelectObject (surface->dc, - surface->bitmap); - if (!surface->saved_dc_bitmap) - goto FAIL; - - if (bitmap_info && num_palette > 2) - free (bitmap_info); - - if (bits_out) - *bits_out = bits; - - if (rowstride_out) { - /* Windows bitmaps are padded to 32-bit (dword) boundaries */ - switch (format) { - case CAIRO_FORMAT_ARGB32: - case CAIRO_FORMAT_RGB24: - *rowstride_out = 4 * width; - break; - - case CAIRO_FORMAT_A8: - *rowstride_out = (width + 3) & ~3; - break; - - case CAIRO_FORMAT_A1: - *rowstride_out = ((width + 31) & ~31) / 8; - break; - } - } - - surface->flags = _cairo_win32_flags_for_dc (surface->dc); - - return CAIRO_STATUS_SUCCESS; - - FAIL: - status = _cairo_win32_print_gdi_error ("_create_dc_and_bitmap"); - - if (bitmap_info && num_palette > 2) - free (bitmap_info); - - if (surface->saved_dc_bitmap) { - SelectObject (surface->dc, surface->saved_dc_bitmap); - surface->saved_dc_bitmap = NULL; - } - - if (surface->bitmap) { - DeleteObject (surface->bitmap); - surface->bitmap = NULL; - } - - if (surface->dc) { - DeleteDC (surface->dc); - surface->dc = NULL; - } - - return status; -} - -static cairo_surface_t * -_cairo_win32_surface_create_for_dc (HDC original_dc, - cairo_format_t format, - int width, - int height) -{ - cairo_status_t status; - cairo_win32_surface_t *surface; - unsigned char *bits; - int rowstride; - - surface = malloc (sizeof (cairo_win32_surface_t)); - if (surface == NULL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - status = _create_dc_and_bitmap (surface, original_dc, format, - width, height, - &bits, &rowstride); - if (status) - goto FAIL; - - surface->image = cairo_image_surface_create_for_data (bits, format, - width, height, rowstride); - status = surface->image->status; - if (status) - goto FAIL; - - surface->format = format; - - surface->clip_rect.x = 0; - surface->clip_rect.y = 0; - surface->clip_rect.width = width; - surface->clip_rect.height = height; - - surface->initial_clip_rgn = NULL; - surface->had_simple_clip = FALSE; - - surface->extents = surface->clip_rect; - surface->font_subsets = NULL; - - _cairo_surface_init (&surface->base, &cairo_win32_surface_backend, - _cairo_content_from_format (format)); - - return &surface->base; - - FAIL: - if (surface->bitmap) { - SelectObject (surface->dc, surface->saved_dc_bitmap); - DeleteObject (surface->bitmap); - DeleteDC (surface->dc); - } - free (surface); - - return _cairo_surface_create_in_error (status); -} - -static cairo_surface_t * -_cairo_win32_surface_create_similar_internal (void *abstract_src, - cairo_content_t content, - int width, - int height, - cairo_bool_t force_dib) -{ - cairo_win32_surface_t *src = abstract_src; - cairo_format_t format = _cairo_format_from_content (content); - cairo_surface_t *new_surf = NULL; - - /* We force a DIB always if: - * - we need alpha; or - * - the parent is a DIB; or - * - the parent is for printing (because we don't care about the bit depth at that point) - * - * We also might end up with a DIB even if a DDB is requested if DDB creation failed - * due to out of memory. - */ - if (src->is_dib || - (content & CAIRO_CONTENT_ALPHA) || - src->base.backend->type == CAIRO_SURFACE_TYPE_WIN32_PRINTING) - { - force_dib = TRUE; - } - - if (!force_dib) { - /* try to create a ddb */ - new_surf = cairo_win32_surface_create_with_ddb (src->dc, CAIRO_FORMAT_RGB24, width, height); - - if (new_surf->status != CAIRO_STATUS_SUCCESS) - new_surf = NULL; - } - - if (new_surf == NULL) { - new_surf = _cairo_win32_surface_create_for_dc (src->dc, format, width, height); - } - - return new_surf; -} - -cairo_surface_t * -_cairo_win32_surface_create_similar (void *abstract_src, - cairo_content_t content, - int width, - int height) -{ - return _cairo_win32_surface_create_similar_internal (abstract_src, content, width, height, FALSE); -} - -cairo_status_t -_cairo_win32_surface_clone_similar (void *abstract_surface, - cairo_surface_t *src, - int src_x, - int src_y, - int width, - int height, - int *clone_offset_x, - int *clone_offset_y, - cairo_surface_t **clone_out) -{ - cairo_content_t src_content; - cairo_surface_t *new_surface; - cairo_status_t status; - cairo_surface_pattern_t pattern; - - src_content = cairo_surface_get_content(src); - new_surface = - _cairo_win32_surface_create_similar_internal (abstract_surface, - src_content, - width, height, - FALSE); - if (new_surface == NULL) - return CAIRO_INT_STATUS_UNSUPPORTED; - - status = new_surface->status; - if (status) - return status; - - _cairo_pattern_init_for_surface (&pattern, src); - - status = _cairo_surface_composite (CAIRO_OPERATOR_SOURCE, - &pattern.base, - NULL, - new_surface, - src_x, src_y, - 0, 0, - 0, 0, - width, height); - - _cairo_pattern_fini (&pattern.base); - - if (status == CAIRO_STATUS_SUCCESS) { - *clone_offset_x = src_x; - *clone_offset_y = src_y; - *clone_out = new_surface; - } else - cairo_surface_destroy (new_surface); - - return status; -} - - -cairo_status_t -_cairo_win32_surface_finish (void *abstract_surface) -{ - cairo_win32_surface_t *surface = abstract_surface; - - if (surface->image) - cairo_surface_destroy (surface->image); - - /* If we created the Bitmap and DC, destroy them */ - if (surface->bitmap) { - SelectObject (surface->dc, surface->saved_dc_bitmap); - DeleteObject (surface->bitmap); - DeleteDC (surface->dc); - } else { - _cairo_win32_restore_initial_clip (surface); - } - - if (surface->initial_clip_rgn) - DeleteObject (surface->initial_clip_rgn); - - if (surface->font_subsets != NULL) - _cairo_scaled_font_subsets_destroy (surface->font_subsets); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_win32_surface_get_subimage (cairo_win32_surface_t *surface, - int x, - int y, - int width, - int height, - cairo_win32_surface_t **local_out) -{ - cairo_win32_surface_t *local; - cairo_int_status_t status; - cairo_content_t content = _cairo_content_from_format (surface->format); - - local = - (cairo_win32_surface_t *) _cairo_win32_surface_create_similar_internal - (surface, content, width, height, TRUE); - if (local == NULL) - return CAIRO_INT_STATUS_UNSUPPORTED; - if (local->base.status) - return local->base.status; - - status = CAIRO_INT_STATUS_UNSUPPORTED; - - /* Only BitBlt if the source surface supports it. */ - if ((surface->flags & CAIRO_WIN32_SURFACE_CAN_BITBLT) && - BitBlt (local->dc, - 0, 0, - width, height, - surface->dc, - x, y, - SRCCOPY)) - { - status = CAIRO_STATUS_SUCCESS; - } - - if (status) { - /* If we failed here, most likely the source or dest doesn't - * support BitBlt/AlphaBlend (e.g. a printer). - * You can't reliably get bits from a printer DC, so just fill in - * the surface as white (common case for printing). - */ - - RECT r; - r.left = r.top = 0; - r.right = width; - r.bottom = height; - FillRect(local->dc, &r, (HBRUSH)GetStockObject(WHITE_BRUSH)); - } - - *local_out = local; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_win32_surface_acquire_source_image (void *abstract_surface, - cairo_image_surface_t **image_out, - void **image_extra) -{ - cairo_win32_surface_t *surface = abstract_surface; - cairo_win32_surface_t *local = NULL; - cairo_status_t status; - - if (surface->image) { - *image_out = (cairo_image_surface_t *)surface->image; - *image_extra = NULL; - - return CAIRO_STATUS_SUCCESS; - } - - status = _cairo_win32_surface_get_subimage (abstract_surface, 0, 0, - surface->extents.width, - surface->extents.height, &local); - if (status) - return status; - - *image_out = (cairo_image_surface_t *)local->image; - *image_extra = local; - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_win32_surface_release_source_image (void *abstract_surface, - cairo_image_surface_t *image, - void *image_extra) -{ - cairo_win32_surface_t *local = image_extra; - - if (local) - cairo_surface_destroy ((cairo_surface_t *)local); -} - -static cairo_status_t -_cairo_win32_surface_acquire_dest_image (void *abstract_surface, - cairo_rectangle_int_t *interest_rect, - cairo_image_surface_t **image_out, - cairo_rectangle_int_t *image_rect, - void **image_extra) -{ - cairo_win32_surface_t *surface = abstract_surface; - cairo_win32_surface_t *local = NULL; - cairo_status_t status; - RECT clip_box; - int x1, y1, x2, y2; - - if (surface->image) { - GdiFlush(); - - image_rect->x = 0; - image_rect->y = 0; - image_rect->width = surface->extents.width; - image_rect->height = surface->extents.height; - - *image_out = (cairo_image_surface_t *)surface->image; - *image_extra = NULL; - - return CAIRO_STATUS_SUCCESS; - } - - if (GetClipBox (surface->dc, &clip_box) == ERROR) - return _cairo_win32_print_gdi_error ("_cairo_win3_surface_acquire_dest_image"); - - x1 = clip_box.left; - x2 = clip_box.right; - y1 = clip_box.top; - y2 = clip_box.bottom; - - if (interest_rect->x > x1) - x1 = interest_rect->x; - if (interest_rect->y > y1) - y1 = interest_rect->y; - if ((int) (interest_rect->x + interest_rect->width) < x2) - x2 = interest_rect->x + interest_rect->width; - if ((int) (interest_rect->y + interest_rect->height) < y2) - y2 = interest_rect->y + interest_rect->height; - - if (x1 >= x2 || y1 >= y2) { - *image_out = NULL; - *image_extra = NULL; - - return CAIRO_STATUS_SUCCESS; - } - - status = _cairo_win32_surface_get_subimage (abstract_surface, - x1, y1, x2 - x1, y2 - y1, - &local); - if (status) - return status; - - *image_out = (cairo_image_surface_t *)local->image; - *image_extra = local; - - image_rect->x = x1; - image_rect->y = y1; - image_rect->width = x2 - x1; - image_rect->height = y2 - y1; - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_win32_surface_release_dest_image (void *abstract_surface, - cairo_rectangle_int_t *interest_rect, - cairo_image_surface_t *image, - cairo_rectangle_int_t *image_rect, - void *image_extra) -{ - cairo_win32_surface_t *surface = abstract_surface; - cairo_win32_surface_t *local = image_extra; - - if (!local) - return; - - if (!BitBlt (surface->dc, - image_rect->x, image_rect->y, - image_rect->width, image_rect->height, - local->dc, - 0, 0, - SRCCOPY)) - _cairo_win32_print_gdi_error ("_cairo_win32_surface_release_dest_image"); - - cairo_surface_destroy ((cairo_surface_t *)local); -} - -#if !defined(AC_SRC_OVER) -#define AC_SRC_OVER 0x00 -#pragma pack(1) -typedef struct { - BYTE BlendOp; - BYTE BlendFlags; - BYTE SourceConstantAlpha; - BYTE AlphaFormat; -}BLENDFUNCTION; -#pragma pack() -#endif - -/* for compatibility with VC++ 6 */ -#ifndef AC_SRC_ALPHA -#define AC_SRC_ALPHA 0x01 -#endif - -typedef BOOL (WINAPI *cairo_alpha_blend_func_t) (HDC hdcDest, - int nXOriginDest, - int nYOriginDest, - int nWidthDest, - int hHeightDest, - HDC hdcSrc, - int nXOriginSrc, - int nYOriginSrc, - int nWidthSrc, - int nHeightSrc, - BLENDFUNCTION blendFunction); - -static cairo_int_status_t -_composite_alpha_blend (cairo_win32_surface_t *dst, - cairo_win32_surface_t *src, - int alpha, - int src_x, - int src_y, - int src_w, - int src_h, - int dst_x, - int dst_y, - int dst_w, - int dst_h) -{ - static unsigned alpha_blend_checked = FALSE; - static cairo_alpha_blend_func_t alpha_blend = NULL; - - BLENDFUNCTION blend_function; - - /* Check for AlphaBlend dynamically to allow compiling on - * MSVC 6 and use on older windows versions - */ - if (!alpha_blend_checked) { - OSVERSIONINFO os; - - os.dwOSVersionInfoSize = sizeof (os); - GetVersionEx (&os); - - /* If running on Win98, disable using AlphaBlend() - * to avoid Win98 AlphaBlend() bug */ - if (VER_PLATFORM_WIN32_WINDOWS != os.dwPlatformId || - os.dwMajorVersion != 4 || os.dwMinorVersion != 10) - { - HMODULE msimg32_dll = LoadLibraryW (L"msimg32"); - - if (msimg32_dll != NULL) - alpha_blend = (cairo_alpha_blend_func_t)GetProcAddress (msimg32_dll, - "AlphaBlend"); - } - - alpha_blend_checked = TRUE; - } - - if (alpha_blend == NULL) - return CAIRO_INT_STATUS_UNSUPPORTED; - if (!(dst->flags & CAIRO_WIN32_SURFACE_CAN_ALPHABLEND)) - return CAIRO_INT_STATUS_UNSUPPORTED; - if (src->format == CAIRO_FORMAT_RGB24 && dst->format == CAIRO_FORMAT_ARGB32) - return CAIRO_INT_STATUS_UNSUPPORTED; - - blend_function.BlendOp = AC_SRC_OVER; - blend_function.BlendFlags = 0; - blend_function.SourceConstantAlpha = alpha; - blend_function.AlphaFormat = (src->format == CAIRO_FORMAT_ARGB32) ? AC_SRC_ALPHA : 0; - - if (!alpha_blend (dst->dc, - dst_x, dst_y, - dst_w, dst_h, - src->dc, - src_x, src_y, - src_w, src_h, - blend_function)) - return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite(AlphaBlend)"); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_win32_surface_composite_inner (cairo_win32_surface_t *src, - cairo_image_surface_t *src_image, - cairo_win32_surface_t *dst, - cairo_rectangle_int_t src_extents, - cairo_rectangle_int_t src_r, - cairo_rectangle_int_t dst_r, - int alpha, - cairo_bool_t needs_alpha, - cairo_bool_t needs_scale) -{ - /* Then do BitBlt, StretchDIBits, StretchBlt, AlphaBlend, or MaskBlt */ - if (src_image) { - if (needs_alpha || needs_scale) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (dst->flags & CAIRO_WIN32_SURFACE_CAN_STRETCHBLT) { - BITMAPINFO bi; - bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bi.bmiHeader.biWidth = src_image->width; - bi.bmiHeader.biHeight = - src_image->height; - bi.bmiHeader.biSizeImage = 0; - bi.bmiHeader.biXPelsPerMeter = PELS_72DPI; - bi.bmiHeader.biYPelsPerMeter = PELS_72DPI; - bi.bmiHeader.biPlanes = 1; - bi.bmiHeader.biBitCount = 32; - bi.bmiHeader.biCompression = BI_RGB; - bi.bmiHeader.biClrUsed = 0; - bi.bmiHeader.biClrImportant = 0; - - /* StretchDIBits is broken with top-down dibs; you need to do some - * special munging to make the coordinate space work (basically, - * need to address everything based on the bottom left, instead of top left, - * and need to tell it to flip the resulting image. - * - * See http://blog.vlad1.com/archives/2006/10/26/134/ and comments. - */ - if (!StretchDIBits (dst->dc, - /* dst x,y,w,h */ - dst_r.x, dst_r.y + dst_r.height - 1, - dst_r.width, - (int) dst_r.height, - /* src x,y,w,h */ - src_r.x, src_extents.height - src_r.y + 1, - src_r.width, - (int) src_r.height, - src_image->data, - &bi, - DIB_RGB_COLORS, - SRCCOPY)) - return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite(StretchDIBits)"); - } - } else if (!needs_alpha) { - /* BitBlt or StretchBlt? */ - if (!needs_scale && (dst->flags & CAIRO_WIN32_SURFACE_CAN_BITBLT)) { - if (!BitBlt (dst->dc, - dst_r.x, dst_r.y, - dst_r.width, dst_r.height, - src->dc, - src_r.x, src_r.y, - SRCCOPY)) - return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite(BitBlt)"); - } else if (dst->flags & CAIRO_WIN32_SURFACE_CAN_STRETCHBLT) { - /* StretchBlt? */ - /* XXX check if we want HALFTONE, based on the src filter */ - BOOL success; - int oldmode = SetStretchBltMode(dst->dc, HALFTONE); - success = StretchBlt(dst->dc, - dst_r.x, dst_r.y, - dst_r.width, dst_r.height, - src->dc, - src_r.x, src_r.y, - src_r.width, src_r.height, - SRCCOPY); - SetStretchBltMode(dst->dc, oldmode); - - if (!success) - return _cairo_win32_print_gdi_error ("StretchBlt"); - } - } else if (needs_alpha && !needs_scale) { - return _composite_alpha_blend (dst, src, alpha, - src_r.x, src_r.y, src_r.width, src_r.height, - dst_r.x, dst_r.y, dst_r.width, dst_r.height); - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_win32_surface_composite (cairo_operator_t op, - cairo_pattern_t *pattern, - cairo_pattern_t *mask_pattern, - void *abstract_dst, - 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_win32_surface_t *dst = abstract_dst; - cairo_win32_surface_t *src; - cairo_surface_pattern_t *src_surface_pattern; - int alpha; - double scalex, scaley; - cairo_fixed_t x0_fixed, y0_fixed; - cairo_int_status_t status; - - cairo_bool_t needs_alpha, needs_scale, needs_repeat; - cairo_image_surface_t *src_image = NULL; - - cairo_format_t src_format; - cairo_rectangle_int_t src_extents; - - cairo_rectangle_int_t src_r = { src_x, src_y, width, height }; - cairo_rectangle_int_t dst_r = { dst_x, dst_y, width, height }; - -#ifdef DEBUG_COMPOSITE - fprintf (stderr, "+++ composite: %d %p %p %p [%d %d] [%d %d] [%d %d] %dx%d\n", - op, pattern, mask_pattern, abstract_dst, src_x, src_y, mask_x, mask_y, dst_x, dst_y, width, height); -#endif - - /* If the destination can't do any of these, then - * we may as well give up, since this is what we'll - * look to for optimization. - */ - if ((dst->flags & (CAIRO_WIN32_SURFACE_CAN_BITBLT | - CAIRO_WIN32_SURFACE_CAN_ALPHABLEND | - CAIRO_WIN32_SURFACE_CAN_STRETCHBLT | - CAIRO_WIN32_SURFACE_CAN_STRETCHDIB)) - == 0) - { - goto UNSUPPORTED; - } - - if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE) - goto UNSUPPORTED; - - if (pattern->extend != CAIRO_EXTEND_NONE && - pattern->extend != CAIRO_EXTEND_REPEAT) - goto UNSUPPORTED; - - if (mask_pattern) { - /* FIXME: When we fully support RENDER style 4-channel - * masks we need to check r/g/b != 1.0. - */ - if (mask_pattern->type != CAIRO_PATTERN_TYPE_SOLID) - return CAIRO_INT_STATUS_UNSUPPORTED; - - alpha = ((cairo_solid_pattern_t *)mask_pattern)->color.alpha_short >> 8; - } else { - alpha = 255; - } - - src_surface_pattern = (cairo_surface_pattern_t *)pattern; - src = (cairo_win32_surface_t *)src_surface_pattern->surface; - - if (src->base.type == CAIRO_SURFACE_TYPE_IMAGE && - dst->flags & (CAIRO_WIN32_SURFACE_CAN_STRETCHDIB)) - { - /* In some very limited cases, we can use StretchDIBits to draw - * an image surface directly: - * - source is CAIRO_FORMAT_ARGB32 - * - dest is CAIRO_FORMAT_ARGB32 - * - alpha is 255 - * - operator is SOURCE or OVER - * - image stride is 4*width - */ - src_image = (cairo_image_surface_t*) src; - - if (src_image->format != CAIRO_FORMAT_RGB24 || - dst->format != CAIRO_FORMAT_RGB24 || - alpha != 255 || - (op != CAIRO_OPERATOR_SOURCE && op != CAIRO_OPERATOR_OVER) || - src_image->stride != (src_image->width * 4)) - { - goto UNSUPPORTED; - } - - src_format = src_image->format; - src_extents.x = 0; - src_extents.y = 0; - src_extents.width = src_image->width; - src_extents.height = src_image->height; - } else if (src->base.backend != dst->base.backend) { - goto UNSUPPORTED; - } else { - src_format = src->format; - src_extents = src->extents; - } - - -#ifdef DEBUG_COMPOSITE - fprintf (stderr, "Before check: src size: (%d %d) xy [%d %d] -> dst [%d %d %d %d] {srcmat %f %f %f %f}\n", - src_extents.width, src_extents.height, - src_x, src_y, - dst_x, dst_y, width, height, - pattern->matrix.x0, pattern->matrix.y0, pattern->matrix.xx, pattern->matrix.yy); -#endif - - /* We can only use GDI functions if the source and destination rectangles - * are on integer pixel boundaries. Figure that out here. - */ - x0_fixed = _cairo_fixed_from_double(pattern->matrix.x0 / pattern->matrix.xx); - y0_fixed = _cairo_fixed_from_double(pattern->matrix.y0 / pattern->matrix.yy); - - if (pattern->matrix.yx != 0.0 || - pattern->matrix.xy != 0.0 || - !_cairo_fixed_is_integer(x0_fixed) || - !_cairo_fixed_is_integer(y0_fixed)) - { - goto UNSUPPORTED; - } - - scalex = pattern->matrix.xx; - scaley = pattern->matrix.yy; - - src_r.x += _cairo_fixed_integer_part(x0_fixed); - src_r.y += _cairo_fixed_integer_part(y0_fixed); - - /* Success, right? */ - if (scalex == 0.0 || scaley == 0.0) - return CAIRO_STATUS_SUCCESS; - - if (scalex != 1.0 || scaley != 1.0) - goto UNSUPPORTED; - - /* If the src coordinates are outside of the source surface bounds, - * we have to fix them up, because this is an error for the GDI - * functions. - */ - -#ifdef DEBUG_COMPOSITE - fprintf (stderr, "before: [%d %d %d %d] -> [%d %d %d %d]\n", - src_r.x, src_r.y, src_r.width, src_r.height, - dst_r.x, dst_r.y, dst_r.width, dst_r.height); - fflush (stderr); -#endif - - /* If the src recangle doesn't wholly lie within the src extents, - * fudge things. We really need to do fixup on the unpainted - * region -- e.g. the SOURCE operator is broken for areas outside - * of the extents, because it won't clear that area to transparent - * black. - */ - - if (pattern->extend != CAIRO_EXTEND_REPEAT) { - needs_repeat = FALSE; - - /* If the src rect and the extents of the source image don't overlap at all, - * we can't do anything useful here. - */ - if (src_r.x > src_extents.width || src_r.y > src_extents.height || - (src_r.x + src_r.width) < 0 || (src_r.y + src_r.height) < 0) - { - if (op == CAIRO_OPERATOR_OVER) - return CAIRO_STATUS_SUCCESS; - goto UNSUPPORTED; - } - - if (src_r.x < 0) { - src_r.width += src_r.x; - src_r.x = 0; - - dst_r.width += src_r.x; - dst_r.x -= src_r.x; - } - - if (src_r.y < 0) { - src_r.height += src_r.y; - src_r.y = 0; - - dst_r.height += dst_r.y; - dst_r.y -= src_r.y; - } - - if (src_r.x + src_r.width > src_extents.width) { - src_r.width = src_extents.width - src_r.x; - dst_r.width = src_r.width; - } - - if (src_r.y + src_r.height > src_extents.height) { - src_r.height = src_extents.height - src_r.y; - dst_r.height = src_r.height; - } - } else { - needs_repeat = TRUE; - } - - /* - * Operations that we can do: - * - * RGB OVER RGB -> BitBlt (same as SOURCE) - * RGB OVER ARGB -> UNSUPPORTED (AlphaBlend treats this as a BitBlt, even with SCA 255 and no AC_SRC_ALPHA) - * ARGB OVER ARGB -> AlphaBlend, with AC_SRC_ALPHA - * ARGB OVER RGB -> AlphaBlend, with AC_SRC_ALPHA; we'll have junk in the dst A byte - * - * RGB OVER RGB + mask -> AlphaBlend, no AC_SRC_ALPHA - * RGB OVER ARGB + mask -> UNSUPPORTED - * ARGB OVER ARGB + mask -> AlphaBlend, with AC_SRC_ALPHA - * ARGB OVER RGB + mask -> AlphaBlend, with AC_SRC_ALPHA; junk in the dst A byte - * - * RGB SOURCE RGB -> BitBlt - * RGB SOURCE ARGB -> UNSUPPORTED (AlphaBlend treats this as a BitBlt, even with SCA 255 and no AC_SRC_ALPHA) - * ARGB SOURCE ARGB -> BitBlt - * ARGB SOURCE RGB -> BitBlt - * - * RGB SOURCE RGB + mask -> unsupported - * RGB SOURCE ARGB + mask -> unsupported - * ARGB SOURCE ARGB + mask -> unsupported - * ARGB SOURCE RGB + mask -> unsupported - */ - - /* - * Figure out what action to take. - */ - if (op == CAIRO_OPERATOR_OVER) { - if (alpha == 0) - return CAIRO_STATUS_SUCCESS; - - if (src_format == dst->format) { - if (alpha == 255 && src_format == CAIRO_FORMAT_RGB24) { - needs_alpha = FALSE; - } else { - needs_alpha = TRUE; - } - } else if (src_format == CAIRO_FORMAT_ARGB32 && - dst->format == CAIRO_FORMAT_RGB24) - { - needs_alpha = TRUE; - } else { - goto UNSUPPORTED; - } - } else if (alpha == 255 && op == CAIRO_OPERATOR_SOURCE) { - if ((src_format == dst->format) || - (src_format == CAIRO_FORMAT_ARGB32 && dst->format == CAIRO_FORMAT_RGB24)) - { - needs_alpha = FALSE; - } else { - goto UNSUPPORTED; - } - } else { - goto UNSUPPORTED; - } - - if (scalex == 1.0 && scaley == 1.0) { - needs_scale = FALSE; - } else { - /* Should never be reached until we turn StretchBlt back on */ - needs_scale = TRUE; - } - -#ifdef DEBUG_COMPOSITE - fprintf (stderr, "action: [%d %d %d %d] -> [%d %d %d %d]\n", - src_r.x, src_r.y, src_r.width, src_r.height, - dst_r.x, dst_r.y, dst_r.width, dst_r.height); - fflush (stderr); -#endif - - /* If we need to repeat, we turn the repeated blit into - * a bunch of piece-by-piece blits. - */ - if (needs_repeat) { - cairo_rectangle_int_t piece_src_r, piece_dst_r; - uint32_t rendered_width = 0, rendered_height = 0; - uint32_t to_render_height, to_render_width; - int32_t piece_x, piece_y; - int32_t src_start_x = src_r.x % src_extents.width; - int32_t src_start_y = src_r.y % src_extents.height; - - if (needs_scale) - goto UNSUPPORTED; - - /* If both the src and dest have an image, we may as well fall - * back, because it will be faster than our separate blits. - * Our blit code will be fastest when the src is a DDB and the - * destination is a DDB. - */ - if ((src_image || src->image) && dst->image) - goto UNSUPPORTED; - - /* If the src is not a bitmap but an on-screen (or unknown) - * DC, chances are that fallback will be faster. - */ - if (src->bitmap == NULL) - goto UNSUPPORTED; - - /* If we can use PatBlt, just do so */ - if (!src_image && !needs_alpha) - { - HBRUSH brush; - HGDIOBJ old_brush; - POINT old_brush_origin; - - /* Set up the brush with our bitmap */ - brush = CreatePatternBrush (src->bitmap); - - /* SetBrushOrgEx sets the coordinates in the destination DC of where the - * pattern should start. - */ - SetBrushOrgEx (dst->dc, dst_r.x - src_start_x, - dst_r.y - src_start_y, &old_brush_origin); - - old_brush = SelectObject (dst->dc, brush); - - PatBlt (dst->dc, dst_r.x, dst_r.y, dst_r.width, dst_r.height, PATCOPY); - - /* Restore the old brush and pen */ - SetBrushOrgEx (dst->dc, old_brush_origin.x, old_brush_origin.y, NULL); - SelectObject (dst->dc, old_brush); - DeleteObject (brush); - - return CAIRO_STATUS_SUCCESS; - } - - /* If we were not able to use PatBlt, then manually expand out the blit */ - - /* Arbitrary factor; we think that going through - * fallback will be faster if we have to do more - * than this amount of blits in either direction. - */ - if (dst_r.width / src_extents.width > 5 || - dst_r.height / src_extents.height > 5) - goto UNSUPPORTED; - - for (rendered_height = 0; - rendered_height < dst_r.height; - rendered_height += to_render_height) - { - piece_y = (src_start_y + rendered_height) % src_extents.height; - to_render_height = src_extents.height - piece_y; - - if (rendered_height + to_render_height > dst_r.height) - to_render_height = dst_r.height - rendered_height; - - for (rendered_width = 0; - rendered_width < dst_r.width; - rendered_width += to_render_width) - { - piece_x = (src_start_x + rendered_width) % src_extents.width; - to_render_width = src_extents.width - piece_x; - - if (rendered_width + to_render_width > dst_r.width) - to_render_width = dst_r.width - rendered_width; - - piece_src_r.x = piece_x; - piece_src_r.y = piece_y; - piece_src_r.width = to_render_width; - piece_src_r.height = to_render_height; - - piece_dst_r.x = dst_r.x + rendered_width; - piece_dst_r.y = dst_r.y + rendered_height; - piece_dst_r.width = to_render_width; - piece_dst_r.height = to_render_height; - - status = _cairo_win32_surface_composite_inner (src, src_image, dst, - src_extents, piece_src_r, piece_dst_r, - alpha, needs_alpha, needs_scale); - if (status != CAIRO_STATUS_SUCCESS) { - /* Uh oh. If something failed, and it's the first - * piece, then we can jump to UNSUPPORTED. - * Otherwise, this is bad times, because part of the - * rendering was already done. */ - if (rendered_width == 0 && - rendered_height == 0) - { - goto UNSUPPORTED; - } - - return status; - } - } - } - } else { - status = _cairo_win32_surface_composite_inner (src, src_image, dst, - src_extents, src_r, dst_r, - alpha, needs_alpha, needs_scale); - } - - if (status == CAIRO_STATUS_SUCCESS) - return status; - -UNSUPPORTED: - /* Fall back to image surface directly, if this is a DIB surface */ - if (dst->image) { - GdiFlush(); - - return dst->image->backend->composite (op, pattern, mask_pattern, - dst->image, - src_x, src_y, - mask_x, mask_y, - dst_x, dst_y, - width, height); - } - - return CAIRO_INT_STATUS_UNSUPPORTED; -} - -/* This big function tells us how to optimize operators for the - * case of solid destination and constant-alpha source - * - * Note: This function needs revisiting if we add support for - * super-luminescent colors (a == 0, r,g,b > 0) - */ -static enum { DO_CLEAR, DO_SOURCE, DO_NOTHING, DO_UNSUPPORTED } -categorize_solid_dest_operator (cairo_operator_t op, - unsigned short alpha) -{ - enum { SOURCE_TRANSPARENT, SOURCE_LIGHT, SOURCE_SOLID, SOURCE_OTHER } source; - - if (alpha >= 0xff00) - source = SOURCE_SOLID; - else if (alpha < 0x100) - source = SOURCE_TRANSPARENT; - else - source = SOURCE_OTHER; - - switch (op) { - case CAIRO_OPERATOR_CLEAR: /* 0 0 */ - case CAIRO_OPERATOR_OUT: /* 1 - Ab 0 */ - return DO_CLEAR; - break; - - case CAIRO_OPERATOR_SOURCE: /* 1 0 */ - case CAIRO_OPERATOR_IN: /* Ab 0 */ - return DO_SOURCE; - break; - - case CAIRO_OPERATOR_OVER: /* 1 1 - Aa */ - case CAIRO_OPERATOR_ATOP: /* Ab 1 - Aa */ - if (source == SOURCE_SOLID) - return DO_SOURCE; - else if (source == SOURCE_TRANSPARENT) - return DO_NOTHING; - else - return DO_UNSUPPORTED; - break; - - case CAIRO_OPERATOR_DEST_OUT: /* 0 1 - Aa */ - case CAIRO_OPERATOR_XOR: /* 1 - Ab 1 - Aa */ - if (source == SOURCE_SOLID) - return DO_CLEAR; - else if (source == SOURCE_TRANSPARENT) - return DO_NOTHING; - else - return DO_UNSUPPORTED; - break; - - case CAIRO_OPERATOR_DEST: /* 0 1 */ - case CAIRO_OPERATOR_DEST_OVER:/* 1 - Ab 1 */ - case CAIRO_OPERATOR_SATURATE: /* min(1,(1-Ab)/Aa) 1 */ - return DO_NOTHING; - break; - - case CAIRO_OPERATOR_DEST_IN: /* 0 Aa */ - case CAIRO_OPERATOR_DEST_ATOP:/* 1 - Ab Aa */ - if (source == SOURCE_SOLID) - return DO_NOTHING; - else if (source == SOURCE_TRANSPARENT) - return DO_CLEAR; - else - return DO_UNSUPPORTED; - break; - - case CAIRO_OPERATOR_ADD: /* 1 1 */ - if (source == SOURCE_TRANSPARENT) - return DO_NOTHING; - else - return DO_UNSUPPORTED; - break; - } - - ASSERT_NOT_REACHED; - return DO_UNSUPPORTED; -} - -static cairo_int_status_t -_cairo_win32_surface_fill_rectangles (void *abstract_surface, - cairo_operator_t op, - const cairo_color_t *color, - cairo_rectangle_int_t *rects, - int num_rects) -{ - cairo_win32_surface_t *surface = abstract_surface; - cairo_status_t status; - COLORREF new_color; - HBRUSH new_brush; - int i; - - /* XXXperf If it's not RGB24, we need to do a little more checking - * to figure out when we can use GDI. We don't have that checking - * anywhere at the moment, so just bail and use the fallback - * paths. */ - if (surface->format != CAIRO_FORMAT_RGB24) - return CAIRO_INT_STATUS_UNSUPPORTED; - - /* Optimize for no destination alpha (surface->pixman_image is non-NULL for all - * surfaces with alpha.) - */ - switch (categorize_solid_dest_operator (op, color->alpha_short)) { - case DO_CLEAR: - new_color = RGB (0, 0, 0); - break; - case DO_SOURCE: - new_color = RGB (color->red_short >> 8, color->green_short >> 8, color->blue_short >> 8); - break; - case DO_NOTHING: - return CAIRO_STATUS_SUCCESS; - case DO_UNSUPPORTED: - default: - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - new_brush = CreateSolidBrush (new_color); - if (!new_brush) - return _cairo_win32_print_gdi_error ("_cairo_win32_surface_fill_rectangles"); - - for (i = 0; i < num_rects; i++) { - RECT rect; - - rect.left = rects[i].x; - rect.top = rects[i].y; - rect.right = rects[i].x + rects[i].width; - rect.bottom = rects[i].y + rects[i].height; - - if (!FillRect (surface->dc, &rect, new_brush)) - goto FAIL; - } - - DeleteObject (new_brush); - - return CAIRO_STATUS_SUCCESS; - - FAIL: - status = _cairo_win32_print_gdi_error ("_cairo_win32_surface_fill_rectangles"); - - DeleteObject (new_brush); - - return status; -} - -static cairo_int_status_t -_cairo_win32_surface_set_clip_region (void *abstract_surface, - cairo_region_t *region) -{ - cairo_win32_surface_t *surface = abstract_surface; - cairo_status_t status = CAIRO_STATUS_SUCCESS; - - /* If we are in-memory, then we set the clip on the image surface - * as well as on the underlying GDI surface. - */ - if (surface->image) { - unsigned int serial; - - serial = _cairo_surface_allocate_clip_serial (surface->image); - status = _cairo_surface_set_clip_region (surface->image, region, serial); - if (status) - return status; - } - - /* The semantics we want is that any clip set by cairo combines - * is intersected with the clip on device context that the - * surface was created for. To implement this, we need to - * save the original clip when first setting a clip on surface. - */ - - /* Clear any clip set by cairo, return to the original first */ - status = _cairo_win32_restore_initial_clip (surface); - - /* Then combine any new region with it */ - if (region) { - cairo_rectangle_int_t extents; - cairo_box_int_t *boxes; - int num_boxes; - RGNDATA *data; - size_t data_size; - RECT *rects; - int i; - HRGN gdi_region; - - /* Create a GDI region for the cairo region */ - - _cairo_region_get_extents (region, &extents); - status = _cairo_region_get_boxes (region, &num_boxes, &boxes); - if (status) - return status; - - if (num_boxes == 1 && - boxes[0].p1.x == 0 && - boxes[0].p1.y == 0 && - boxes[0].p2.x == surface->extents.width && - boxes[0].p2.y == surface->extents.height) - { - gdi_region = NULL; - - SelectClipRgn (surface->dc, NULL); - IntersectClipRect (surface->dc, - boxes[0].p1.x, - boxes[0].p1.y, - boxes[0].p2.x, - boxes[0].p2.y); - - _cairo_region_boxes_fini (region, boxes); - } else { - /* XXX see notes in _cairo_win32_save_initial_clip -- - * this code will interact badly with a HDC which had an initial - * world transform -- we should probably manually transform the - * region rects, because SelectClipRgn takes device units, not - * logical units (unlike IntersectClipRect). - */ - - data_size = sizeof (RGNDATAHEADER) + num_boxes * sizeof (RECT); - data = malloc (data_size); - if (!data) { - _cairo_region_boxes_fini (region, boxes); - return _cairo_error(CAIRO_STATUS_NO_MEMORY); - } - rects = (RECT *)data->Buffer; - - data->rdh.dwSize = sizeof (RGNDATAHEADER); - data->rdh.iType = RDH_RECTANGLES; - data->rdh.nCount = num_boxes; - data->rdh.nRgnSize = num_boxes * sizeof (RECT); - data->rdh.rcBound.left = extents.x; - data->rdh.rcBound.top = extents.y; - data->rdh.rcBound.right = extents.x + extents.width; - data->rdh.rcBound.bottom = extents.y + extents.height; - - for (i = 0; i < num_boxes; i++) { - rects[i].left = boxes[i].p1.x; - rects[i].top = boxes[i].p1.y; - rects[i].right = boxes[i].p2.x; - rects[i].bottom = boxes[i].p2.y; - } - - _cairo_region_boxes_fini (region, boxes); - - gdi_region = ExtCreateRegion (NULL, data_size, data); - free (data); - - if (!gdi_region) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - /* AND the new region into our DC */ - if (ExtSelectClipRgn (surface->dc, gdi_region, RGN_AND) == ERROR) - status = _cairo_win32_print_gdi_error ("_cairo_win32_surface_set_clip_region"); - - DeleteObject (gdi_region); - } - } - - return status; -} - -cairo_int_status_t -_cairo_win32_surface_get_extents (void *abstract_surface, - cairo_rectangle_int_t *rectangle) -{ - cairo_win32_surface_t *surface = abstract_surface; - - *rectangle = surface->extents; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_win32_surface_flush (void *abstract_surface) -{ - return _cairo_surface_reset_clip (abstract_surface); -} - -#define STACK_GLYPH_SIZE 256 - -cairo_int_status_t -_cairo_win32_surface_show_glyphs (void *surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font, - int *remaining_glyphs) -{ -#if CAIRO_HAS_WIN32_FONT - cairo_win32_surface_t *dst = surface; - - WORD glyph_buf_stack[STACK_GLYPH_SIZE]; - WORD *glyph_buf = glyph_buf_stack; - int dxy_buf_stack[2 * STACK_GLYPH_SIZE]; - int *dxy_buf = dxy_buf_stack; - - BOOL win_result = 0; - int i, j; - - cairo_solid_pattern_t *solid_pattern; - COLORREF color; - - cairo_matrix_t device_to_logical; - - int start_x, start_y; - double user_x, user_y; - int logical_x, logical_y; - unsigned int glyph_index_option; - - /* We can only handle win32 fonts */ - if (cairo_scaled_font_get_type (scaled_font) != CAIRO_FONT_TYPE_WIN32) - return CAIRO_INT_STATUS_UNSUPPORTED; - - /* We can only handle opaque solid color sources */ - if (!_cairo_pattern_is_opaque_solid(source)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - /* We can only handle operator SOURCE or OVER with the destination - * having no alpha */ - if ((op != CAIRO_OPERATOR_SOURCE && op != CAIRO_OPERATOR_OVER) || - (dst->format != CAIRO_FORMAT_RGB24)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - /* If we have a fallback mask clip set on the dst, we have - * to go through the fallback path, but only if we're not - * doing this for printing */ - if (dst->base.clip && - !(dst->flags & CAIRO_WIN32_SURFACE_FOR_PRINTING) && - (dst->base.clip->mode != CAIRO_CLIP_MODE_REGION || - dst->base.clip->surface != NULL)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - solid_pattern = (cairo_solid_pattern_t *)source; - color = RGB(((int)solid_pattern->color.red_short) >> 8, - ((int)solid_pattern->color.green_short) >> 8, - ((int)solid_pattern->color.blue_short) >> 8); - - cairo_win32_scaled_font_get_device_to_logical(scaled_font, &device_to_logical); - - SaveDC(dst->dc); - - cairo_win32_scaled_font_select_font(scaled_font, dst->dc); - SetTextColor(dst->dc, color); - SetTextAlign(dst->dc, TA_BASELINE | TA_LEFT); - SetBkMode(dst->dc, TRANSPARENT); - - if (num_glyphs > STACK_GLYPH_SIZE) { - glyph_buf = (WORD *) _cairo_malloc_ab (num_glyphs, sizeof(WORD)); - dxy_buf = (int *) _cairo_malloc_abc (num_glyphs, sizeof(int), 2); - } - - /* It is vital that dx values for dxy_buf are calculated from the delta of - * _logical_ x coordinates (not user x coordinates) or else the sum of all - * previous dx values may start to diverge from the current glyph's x - * coordinate due to accumulated rounding error. As a result strings could - * be painted shorter or longer than expected. */ - - user_x = glyphs[0].x; - user_y = glyphs[0].y; - - cairo_matrix_transform_point(&device_to_logical, - &user_x, &user_y); - - logical_x = _cairo_lround (user_x); - logical_y = _cairo_lround (user_y); - - start_x = logical_x; - start_y = logical_y; - - for (i = 0, j = 0; i < num_glyphs; ++i, j = 2 * i) { - glyph_buf[i] = (WORD) glyphs[i].index; - if (i == num_glyphs - 1) { - dxy_buf[j] = 0; - dxy_buf[j+1] = 0; - } else { - double next_user_x = glyphs[i+1].x; - double next_user_y = glyphs[i+1].y; - int next_logical_x, next_logical_y; - - cairo_matrix_transform_point(&device_to_logical, - &next_user_x, &next_user_y); - - next_logical_x = _cairo_lround (next_user_x); - next_logical_y = _cairo_lround (next_user_y); - - dxy_buf[j] = _cairo_lround (next_logical_x - logical_x); - dxy_buf[j+1] = _cairo_lround (next_logical_y - logical_y); - - logical_x = next_logical_x; - logical_y = next_logical_y; - } - } - - /* Using glyph indices for a Type 1 font does not work on a - * printer DC. The win32 printing surface will convert the the - * glyph indices of Type 1 fonts to the unicode values. - */ - if ((dst->flags & CAIRO_WIN32_SURFACE_FOR_PRINTING) && - _cairo_win32_scaled_font_is_type1 (scaled_font)) - { - glyph_index_option = 0; - } - else - { - glyph_index_option = ETO_GLYPH_INDEX; - } - - win_result = ExtTextOutW(dst->dc, - start_x, - start_y, - glyph_index_option | ETO_PDY, - NULL, - glyph_buf, - num_glyphs, - dxy_buf); - if (!win_result) { - _cairo_win32_print_gdi_error("_cairo_win32_surface_show_glyphs(ExtTextOutW failed)"); - } - - RestoreDC(dst->dc, -1); - - if (glyph_buf != glyph_buf_stack) { - free(glyph_buf); - free(dxy_buf); - } - return (win_result) ? CAIRO_STATUS_SUCCESS : CAIRO_INT_STATUS_UNSUPPORTED; -#else - return CAIRO_INT_STATUS_UNSUPPORTED; -#endif -} - -#undef STACK_GLYPH_SIZE - -/** - * cairo_win32_surface_create: - * @hdc: the DC to create a surface for - * - * Creates a cairo surface that targets the given DC. The DC will be - * queried for its initial clip extents, and this will be used as the - * size of the cairo surface. The resulting surface will always be of - * format %CAIRO_FORMAT_RGB24; should you need another surface format, - * you will need to create one through - * cairo_win32_surface_create_with_dib(). - * - * Return value: the newly created surface - **/ -cairo_surface_t * -cairo_win32_surface_create (HDC hdc) -{ - cairo_win32_surface_t *surface; - - cairo_format_t format; - RECT rect; - - /* Assume that everything coming in as a HDC is RGB24 */ - format = CAIRO_FORMAT_RGB24; - - surface = malloc (sizeof (cairo_win32_surface_t)); - if (surface == NULL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - if (_cairo_win32_save_initial_clip (hdc, surface) != CAIRO_STATUS_SUCCESS) { - free (surface); - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - } - - surface->image = NULL; - surface->format = format; - - surface->dc = hdc; - surface->bitmap = NULL; - surface->is_dib = FALSE; - surface->saved_dc_bitmap = NULL; - surface->brush = NULL; - surface->old_brush = NULL; - surface->font_subsets = NULL; - - GetClipBox(hdc, &rect); - surface->extents.x = rect.left; - surface->extents.y = rect.top; - surface->extents.width = rect.right - rect.left; - surface->extents.height = rect.bottom - rect.top; - - surface->flags = _cairo_win32_flags_for_dc (surface->dc); - - _cairo_surface_init (&surface->base, &cairo_win32_surface_backend, - _cairo_content_from_format (format)); - - return (cairo_surface_t *)surface; -} - -/** - * cairo_win32_surface_create_with_dib: - * @format: format of pixels in the surface to create - * @width: width of the surface, in pixels - * @height: height of the surface, in pixels - * - * Creates a device-independent-bitmap surface not associated with - * any particular existing surface or device context. The created - * bitmap will be uninitialized. - * - * Return value: the newly created surface - * - * Since: 1.2 - **/ -cairo_surface_t * -cairo_win32_surface_create_with_dib (cairo_format_t format, - int width, - int height) -{ - return _cairo_win32_surface_create_for_dc (NULL, format, width, height); -} - -/** - * cairo_win32_surface_create_with_ddb: - * @hdc: the DC to create a surface for - * @format: format of pixels in the surface to create - * @width: width of the surface, in pixels - * @height: height of the surface, in pixels - * - * Creates a device-independent-bitmap surface not associated with - * any particular existing surface or device context. The created - * bitmap will be uninitialized. - * - * Return value: the newly created surface - * - * Since: 1.4 - **/ -cairo_surface_t * -cairo_win32_surface_create_with_ddb (HDC hdc, - cairo_format_t format, - int width, - int height) -{ - cairo_win32_surface_t *new_surf; - HBITMAP ddb; - HDC screen_dc, ddb_dc; - HBITMAP saved_dc_bitmap; - - if (format != CAIRO_FORMAT_RGB24) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); -/* XXX handle these eventually - format != CAIRO_FORMAT_A8 || - format != CAIRO_FORMAT_A1) -*/ - - if (!hdc) { - screen_dc = GetDC (NULL); - hdc = screen_dc; - } else { - screen_dc = NULL; - } - - ddb_dc = CreateCompatibleDC (hdc); - if (ddb_dc == NULL) { - new_surf = (cairo_win32_surface_t*) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - goto FINISH; - } - - ddb = CreateCompatibleBitmap (hdc, width, height); - if (ddb == NULL) { - DeleteDC (ddb_dc); - - /* Note that if an app actually does hit this out of memory - * condition, it's going to have lots of other issues, as - * video memory is probably exhausted. However, it can often - * continue using DIBs instead of DDBs. - */ - new_surf = (cairo_win32_surface_t*) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - goto FINISH; - } - - saved_dc_bitmap = SelectObject (ddb_dc, ddb); - - new_surf = (cairo_win32_surface_t*) cairo_win32_surface_create (ddb_dc); - new_surf->bitmap = ddb; - new_surf->saved_dc_bitmap = saved_dc_bitmap; - new_surf->is_dib = FALSE; - -FINISH: - if (screen_dc) - ReleaseDC (NULL, screen_dc); - - return (cairo_surface_t*) new_surf; -} - -/** - * _cairo_surface_is_win32: - * @surface: a #cairo_surface_t - * - * Checks if a surface is a win32 surface. This will - * return False if this is a win32 printing surface; use - * _cairo_surface_is_win32_printing() to check for that. - * - * Return value: True if the surface is an win32 surface - **/ -int -_cairo_surface_is_win32 (cairo_surface_t *surface) -{ - return surface->backend == &cairo_win32_surface_backend; -} - -/** - * cairo_win32_surface_get_dc - * @surface: a #cairo_surface_t - * - * Returns the HDC associated with this surface, or %NULL if none. - * Also returns %NULL if the surface is not a win32 surface. - * - * Return value: HDC or %NULL if no HDC available. - * - * Since: 1.2 - **/ -HDC -cairo_win32_surface_get_dc (cairo_surface_t *surface) -{ - cairo_win32_surface_t *winsurf; - - if (_cairo_surface_is_win32 (surface)){ - winsurf = (cairo_win32_surface_t *) surface; - - return winsurf->dc; - } - - if (_cairo_surface_is_paginated (surface)) { - cairo_surface_t *target; - - target = _cairo_paginated_surface_get_target (surface); - - if (_cairo_surface_is_win32_printing (target)) { - winsurf = (cairo_win32_surface_t *) target; - - return winsurf->dc; - } - } - - return NULL; -} - -/** - * cairo_win32_surface_get_image - * @surface: a #cairo_surface_t - * - * Returns a #cairo_surface_t image surface that refers to the same bits - * as the DIB of the Win32 surface. If the passed-in win32 surface - * is not a DIB surface, %NULL is returned. - * - * Return value: a #cairo_surface_t (owned by the win32 #cairo_surface_t), - * or %NULL if the win32 surface is not a DIB. - * - * Since: 1.4 - */ -cairo_surface_t * -cairo_win32_surface_get_image (cairo_surface_t *surface) -{ - if (!_cairo_surface_is_win32(surface)) - return NULL; - - return ((cairo_win32_surface_t*)surface)->image; -} - -static cairo_bool_t -_cairo_win32_surface_is_similar (void *surface_a, - void *surface_b, - cairo_content_t content) -{ - cairo_win32_surface_t *a = surface_a; - cairo_win32_surface_t *b = surface_b; - - return a->dc == b->dc; -} - -static cairo_status_t -_cairo_win32_surface_reset (void *abstract_surface) -{ - cairo_win32_surface_t *surface = abstract_surface; - cairo_status_t status; - - status = _cairo_win32_surface_set_clip_region (surface, NULL); - if (status) - return status; - - return CAIRO_STATUS_SUCCESS; -} - -static const cairo_surface_backend_t cairo_win32_surface_backend = { - CAIRO_SURFACE_TYPE_WIN32, - _cairo_win32_surface_create_similar, - _cairo_win32_surface_finish, - _cairo_win32_surface_acquire_source_image, - _cairo_win32_surface_release_source_image, - _cairo_win32_surface_acquire_dest_image, - _cairo_win32_surface_release_dest_image, - _cairo_win32_surface_clone_similar, - _cairo_win32_surface_composite, - _cairo_win32_surface_fill_rectangles, - NULL, /* composite_trapezoids */ - NULL, /* copy_page */ - NULL, /* show_page */ - _cairo_win32_surface_set_clip_region, - NULL, /* intersect_clip_path */ - _cairo_win32_surface_get_extents, - NULL, /* old_show_glyphs */ - NULL, /* get_font_options */ - _cairo_win32_surface_flush, - NULL, /* mark_dirty_rectangle */ - NULL, /* scaled_font_fini */ - NULL, /* scaled_glyph_fini */ - - NULL, /* paint */ - NULL, /* mask */ - NULL, /* stroke */ - NULL, /* fill */ - _cairo_win32_surface_show_glyphs, - - NULL, /* snapshot */ - _cairo_win32_surface_is_similar, - - _cairo_win32_surface_reset -}; - -/* Notes: - * - * Win32 alpha-understanding functions - * - * BitBlt - will copy full 32 bits from a 32bpp DIB to result - * (so it's safe to use for ARGB32->ARGB32 SOURCE blits) - * (but not safe going RGB24->ARGB32, if RGB24 is also represented - * as a 32bpp DIB, since the alpha isn't discarded!) - * - * AlphaBlend - if both the source and dest have alpha, even if AC_SRC_ALPHA isn't set, - * it will still copy over the src alpha, because the SCA value (255) will be - * multiplied by all the src components. - */ - - -cairo_int_status_t -_cairo_win32_save_initial_clip (HDC hdc, cairo_win32_surface_t *surface) -{ - RECT rect; - int clipBoxType; - int gm; - XFORM saved_xform; - - /* GetClipBox/GetClipRgn and friends interact badly with a world transform - * set. GetClipBox returns values in logical (transformed) coordinates; - * it's unclear what GetClipRgn returns, because the region is empty in the - * case of a SIMPLEREGION clip, but I assume device (untransformed) coordinates. - * Similarily, IntersectClipRect works in logical units, whereas SelectClipRgn - * works in device units. - * - * So, avoid the whole mess and get rid of the world transform - * while we store our initial data and when we restore initial coordinates. - * - * XXX we may need to modify x/y by the ViewportOrg or WindowOrg - * here in GM_COMPATIBLE; unclear. - */ - gm = GetGraphicsMode (hdc); - if (gm == GM_ADVANCED) { - GetWorldTransform (hdc, &saved_xform); - ModifyWorldTransform (hdc, NULL, MWT_IDENTITY); - } - - clipBoxType = GetClipBox (hdc, &rect); - if (clipBoxType == ERROR) { - _cairo_win32_print_gdi_error ("cairo_win32_surface_create"); - SetGraphicsMode (hdc, gm); - /* XXX: Can we make a more reasonable guess at the error cause here? */ - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - surface->clip_rect.x = rect.left; - surface->clip_rect.y = rect.top; - surface->clip_rect.width = rect.right - rect.left; - surface->clip_rect.height = rect.bottom - rect.top; - - surface->initial_clip_rgn = NULL; - surface->had_simple_clip = FALSE; - - if (clipBoxType == COMPLEXREGION) { - surface->initial_clip_rgn = CreateRectRgn (0, 0, 0, 0); - if (GetClipRgn (hdc, surface->initial_clip_rgn) <= 0) { - DeleteObject(surface->initial_clip_rgn); - surface->initial_clip_rgn = NULL; - } - } else if (clipBoxType == SIMPLEREGION) { - surface->had_simple_clip = TRUE; - } - - if (gm == GM_ADVANCED) - SetWorldTransform (hdc, &saved_xform); - - return CAIRO_STATUS_SUCCESS; -} - -cairo_int_status_t -_cairo_win32_restore_initial_clip (cairo_win32_surface_t *surface) -{ - cairo_int_status_t status = CAIRO_STATUS_SUCCESS; - - XFORM saved_xform; - int gm = GetGraphicsMode (surface->dc); - if (gm == GM_ADVANCED) { - GetWorldTransform (surface->dc, &saved_xform); - ModifyWorldTransform (surface->dc, NULL, MWT_IDENTITY); - } - - /* initial_clip_rgn will either be a real region or NULL (which means reset to no clip region) */ - SelectClipRgn (surface->dc, surface->initial_clip_rgn); - - if (surface->had_simple_clip) { - /* then if we had a simple clip, intersect */ - IntersectClipRect (surface->dc, - surface->clip_rect.x, - surface->clip_rect.y, - surface->clip_rect.x + surface->clip_rect.width, - surface->clip_rect.y + surface->clip_rect.height); - } - - if (gm == GM_ADVANCED) - SetWorldTransform (surface->dc, &saved_xform); - - return status; -} - -void -_cairo_win32_debug_dump_hrgn (HRGN rgn, char *header) -{ - RGNDATA *rd; - int z; - - if (header) - fprintf (stderr, "%s\n", header); - - if (rgn == NULL) { - fprintf (stderr, " NULL\n"); - } - - z = GetRegionData(rgn, 0, NULL); - rd = (RGNDATA*) malloc(z); - z = GetRegionData(rgn, z, rd); - - fprintf (stderr, " %d rects, bounds: %d %d %d %d\n", rd->rdh.nCount, rd->rdh.rcBound.left, rd->rdh.rcBound.top, rd->rdh.rcBound.right - rd->rdh.rcBound.left, rd->rdh.rcBound.bottom - rd->rdh.rcBound.top); - - for (z = 0; z < rd->rdh.nCount; z++) { - RECT r = ((RECT*)rd->Buffer)[z]; - fprintf (stderr, " [%d]: [%d %d %d %d]\n", z, r.left, r.top, r.right - r.left, r.bottom - r.top); - } - - free(rd); - fflush (stderr); -} diff --git a/uppdev/plugin/cairo/lib/cairo-win32.h b/uppdev/plugin/cairo/lib/cairo-win32.h deleted file mode 100644 index cb517bc87..000000000 --- a/uppdev/plugin/cairo/lib/cairo-win32.h +++ /dev/null @@ -1,112 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* cairo - a vector graphics library with display and print output - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Owen Taylor - */ - -#ifndef _CAIRO_WIN32_H_ -#define _CAIRO_WIN32_H_ - -#include "cairo.h" - -#if CAIRO_HAS_WIN32_SURFACE - -#include - -CAIRO_BEGIN_DECLS - -cairo_public cairo_surface_t * -cairo_win32_surface_create (HDC hdc); - -cairo_public cairo_surface_t * -cairo_win32_printing_surface_create (HDC hdc); - -cairo_public cairo_surface_t * -cairo_win32_surface_create_with_ddb (HDC hdc, - cairo_format_t format, - int width, - int height); - -cairo_public cairo_surface_t * -cairo_win32_surface_create_with_dib (cairo_format_t format, - int width, - int height); - -cairo_public HDC -cairo_win32_surface_get_dc (cairo_surface_t *surface); - -cairo_public cairo_surface_t * -cairo_win32_surface_get_image (cairo_surface_t *surface); - -#if CAIRO_HAS_WIN32_FONT - -/* - * Win32 font support - */ - -cairo_public cairo_font_face_t * -cairo_win32_font_face_create_for_logfontw (LOGFONTW *logfont); - -cairo_public cairo_font_face_t * -cairo_win32_font_face_create_for_hfont (HFONT font); - -cairo_public cairo_font_face_t * -cairo_win32_font_face_create_for_logfontw_hfont (LOGFONTW *logfont, HFONT font); - -cairo_public cairo_status_t -cairo_win32_scaled_font_select_font (cairo_scaled_font_t *scaled_font, - HDC hdc); - -cairo_public void -cairo_win32_scaled_font_done_font (cairo_scaled_font_t *scaled_font); - -cairo_public double -cairo_win32_scaled_font_get_metrics_factor (cairo_scaled_font_t *scaled_font); - -cairo_public void -cairo_win32_scaled_font_get_logical_to_device (cairo_scaled_font_t *scaled_font, - cairo_matrix_t *logical_to_device); - -cairo_public void -cairo_win32_scaled_font_get_device_to_logical (cairo_scaled_font_t *scaled_font, - cairo_matrix_t *device_to_logical); - -#endif /* CAIRO_HAS_WIN32_FONT */ - -CAIRO_END_DECLS - -#else /* CAIRO_HAS_WIN32_SURFACE */ -# error Cairo was not compiled with support for the win32 backend -#endif /* CAIRO_HAS_WIN32_SURFACE */ - -#endif /* _CAIRO_WIN32_H_ */ diff --git a/uppdev/plugin/cairo/lib/cairo-xcb-surface.c b/uppdev/plugin/cairo/lib/cairo-xcb-surface.c deleted file mode 100644 index dede00f3b..000000000 --- a/uppdev/plugin/cairo/lib/cairo-xcb-surface.c +++ /dev/null @@ -1,2551 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - */ - -#include "cairoint.h" -#include "cairo-xcb.h" -#include "cairo-xcb-xrender.h" -#include "cairo-clip-private.h" -#include - -#define AllPlanes ((unsigned long)~0L) - -slim_hidden_proto (cairo_xcb_surface_create_with_xrender_format); - -/* - * Instead of taking two round trips for each blending request, - * assume that if a particular drawable fails GetImage that it will - * fail for a "while"; use temporary pixmaps to avoid the errors - */ - -#define CAIRO_ASSUME_PIXMAP 20 - -typedef struct cairo_xcb_surface { - cairo_surface_t base; - - xcb_connection_t *dpy; - xcb_screen_t *screen; - - xcb_gcontext_t gc; - xcb_drawable_t drawable; - cairo_bool_t owns_pixmap; - xcb_visualtype_t *visual; - - int use_pixmap; - - int render_major; - int render_minor; - - int width; - int height; - int depth; - - cairo_bool_t have_clip_rects; - xcb_rectangle_t *clip_rects; - int num_clip_rects; - - xcb_render_picture_t src_picture, dst_picture; - xcb_render_pictforminfo_t xrender_format; -} cairo_xcb_surface_t; - -#define CAIRO_SURFACE_RENDER_AT_LEAST(surface, major, minor) \ - (((surface)->render_major > major) || \ - (((surface)->render_major == major) && ((surface)->render_minor >= minor))) - -#define CAIRO_SURFACE_RENDER_HAS_CREATE_PICTURE(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 0) -#define CAIRO_SURFACE_RENDER_HAS_COMPOSITE(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 0) -#define CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 0) - -#define CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLE(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 1) -#define CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLES(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 1) - -#define CAIRO_SURFACE_RENDER_HAS_DISJOINT(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 2) -#define CAIRO_SURFACE_RENDER_HAS_CONJOINT(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 2) - -#define CAIRO_SURFACE_RENDER_HAS_TRAPEZOIDS(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 4) -#define CAIRO_SURFACE_RENDER_HAS_TRIANGLES(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 4) -#define CAIRO_SURFACE_RENDER_HAS_TRISTRIP(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 4) -#define CAIRO_SURFACE_RENDER_HAS_TRIFAN(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 4) - -#define CAIRO_SURFACE_RENDER_HAS_PICTURE_TRANSFORM(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 6) -#define CAIRO_SURFACE_RENDER_HAS_FILTERS(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 6) - -static void -_cairo_xcb_surface_ensure_gc (cairo_xcb_surface_t *surface); - -static int -_CAIRO_FORMAT_DEPTH (cairo_format_t format) -{ - switch (format) { - case CAIRO_FORMAT_A1: - return 1; - case CAIRO_FORMAT_A8: - return 8; - case CAIRO_FORMAT_RGB24: - return 24; - case CAIRO_FORMAT_ARGB32: - default: - return 32; - } -} - -static xcb_render_pictforminfo_t * -_CAIRO_FORMAT_TO_XRENDER_FORMAT(xcb_connection_t *dpy, cairo_format_t format) -{ - xcb_pict_standard_t std_format; - switch (format) { - case CAIRO_FORMAT_A1: - std_format = XCB_PICT_STANDARD_A_1; break; - case CAIRO_FORMAT_A8: - std_format = XCB_PICT_STANDARD_A_8; break; - case CAIRO_FORMAT_RGB24: - std_format = XCB_PICT_STANDARD_RGB_24; break; - case CAIRO_FORMAT_ARGB32: - default: - std_format = XCB_PICT_STANDARD_ARGB_32; break; - } - return xcb_render_util_find_standard_format (xcb_render_util_query_formats (dpy), std_format); -} - -static cairo_content_t -_xcb_render_format_to_content (xcb_render_pictforminfo_t *xrender_format) -{ - cairo_bool_t xrender_format_has_alpha; - cairo_bool_t xrender_format_has_color; - - /* This only happens when using a non-Render server. Let's punt - * and say there's no alpha here. */ - if (xrender_format == NULL) - return CAIRO_CONTENT_COLOR; - - xrender_format_has_alpha = (xrender_format->direct.alpha_mask != 0); - xrender_format_has_color = (xrender_format->direct.red_mask != 0 || - xrender_format->direct.green_mask != 0 || - xrender_format->direct.blue_mask != 0); - - if (xrender_format_has_alpha) - if (xrender_format_has_color) - return CAIRO_CONTENT_COLOR_ALPHA; - else - return CAIRO_CONTENT_ALPHA; - else - return CAIRO_CONTENT_COLOR; -} - -static cairo_surface_t * -_cairo_xcb_surface_create_similar (void *abstract_src, - cairo_content_t content, - int width, - int height) -{ - cairo_xcb_surface_t *src = abstract_src; - xcb_connection_t *dpy = src->dpy; - xcb_pixmap_t pixmap; - cairo_xcb_surface_t *surface; - cairo_format_t format = _cairo_format_from_content (content); - xcb_render_pictforminfo_t *xrender_format; - - /* As a good first approximation, if the display doesn't have COMPOSITE, - * we're better off using image surfaces for all temporary operations - */ - if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE (src)) { - return cairo_image_surface_create (format, width, height); - } - - pixmap = xcb_generate_id (dpy); - xcb_create_pixmap (dpy, _CAIRO_FORMAT_DEPTH (format), - pixmap, src->drawable, - width <= 0 ? 1 : width, - height <= 0 ? 1 : height); - - xrender_format = _CAIRO_FORMAT_TO_XRENDER_FORMAT (dpy, format); - /* XXX: what to do if xrender_format is null? */ - surface = (cairo_xcb_surface_t *) - cairo_xcb_surface_create_with_xrender_format (dpy, pixmap, src->screen, - xrender_format, - width, height); - if (surface->base.status) - return &surface->base; - - surface->owns_pixmap = TRUE; - - return &surface->base; -} - -static cairo_status_t -_cairo_xcb_surface_finish (void *abstract_surface) -{ - cairo_xcb_surface_t *surface = abstract_surface; - if (surface->dst_picture != XCB_NONE) - xcb_render_free_picture (surface->dpy, surface->dst_picture); - - if (surface->src_picture != XCB_NONE) - xcb_render_free_picture (surface->dpy, surface->src_picture); - - if (surface->owns_pixmap) - xcb_free_pixmap (surface->dpy, surface->drawable); - - if (surface->gc != XCB_NONE) - xcb_free_gc (surface->dpy, surface->gc); - - free (surface->clip_rects); - - surface->dpy = NULL; - - return CAIRO_STATUS_SUCCESS; -} - -static int -_bits_per_pixel(xcb_connection_t *c, int depth) -{ - xcb_format_t *fmt = xcb_setup_pixmap_formats(xcb_get_setup(c)); - xcb_format_t *fmtend = fmt + xcb_setup_pixmap_formats_length(xcb_get_setup(c)); - - for(; fmt != fmtend; ++fmt) - if(fmt->depth == depth) - return fmt->bits_per_pixel; - - if(depth <= 4) - return 4; - if(depth <= 8) - return 8; - if(depth <= 16) - return 16; - return 32; -} - -static int -_bytes_per_line(xcb_connection_t *c, int width, int bpp) -{ - int bitmap_pad = xcb_get_setup(c)->bitmap_format_scanline_pad; - return ((bpp * width + bitmap_pad - 1) & -bitmap_pad) >> 3; -} - -static cairo_bool_t -_CAIRO_MASK_FORMAT (cairo_format_masks_t *masks, cairo_format_t *format) -{ - switch (masks->bpp) { - case 32: - if (masks->alpha_mask == 0xff000000 && - masks->red_mask == 0x00ff0000 && - masks->green_mask == 0x0000ff00 && - masks->blue_mask == 0x000000ff) - { - *format = CAIRO_FORMAT_ARGB32; - return TRUE; - } - if (masks->alpha_mask == 0x00000000 && - masks->red_mask == 0x00ff0000 && - masks->green_mask == 0x0000ff00 && - masks->blue_mask == 0x000000ff) - { - *format = CAIRO_FORMAT_RGB24; - return TRUE; - } - break; - case 8: - if (masks->alpha_mask == 0xff) - { - *format = CAIRO_FORMAT_A8; - return TRUE; - } - break; - case 1: - if (masks->alpha_mask == 0x1) - { - *format = CAIRO_FORMAT_A1; - return TRUE; - } - break; - } - return FALSE; -} - -static cairo_status_t -_get_image_surface (cairo_xcb_surface_t *surface, - cairo_rectangle_int_t *interest_rect, - cairo_image_surface_t **image_out, - cairo_rectangle_int_t *image_rect) -{ - cairo_image_surface_t *image; - xcb_get_image_reply_t *imagerep; - int bpp, bytes_per_line; - cairo_rectangle_int_t extents; - unsigned char *data; - cairo_format_masks_t masks; - cairo_format_t format; - - extents.x = 0; - extents.y = 0; - extents.width = surface->width; - extents.height = surface->height; - - if (interest_rect) { - if (! _cairo_rectangle_intersect (&extents, interest_rect)) { - *image_out = NULL; - return CAIRO_STATUS_SUCCESS; - } - } - - if (image_rect) - *image_rect = extents; - - /* XXX: This should try to use the XShm extension if available */ - - if (surface->use_pixmap == 0) - { - xcb_generic_error_t *error; - imagerep = xcb_get_image_reply(surface->dpy, - xcb_get_image(surface->dpy, XCB_IMAGE_FORMAT_Z_PIXMAP, - surface->drawable, - extents.x, extents.y, - extents.width, extents.height, - AllPlanes), &error); - - /* If we get an error, the surface must have been a window, - * so retry with the safe code path. - */ - if (error) - surface->use_pixmap = CAIRO_ASSUME_PIXMAP; - } - else - { - surface->use_pixmap--; - imagerep = NULL; - } - - if (!imagerep) - { - /* xcb_get_image_t from a window is dangerous because it can - * produce errors if the window is unmapped or partially - * outside the screen. We could check for errors and - * retry, but to keep things simple, we just create a - * temporary pixmap - */ - xcb_pixmap_t pixmap; - pixmap = xcb_generate_id (surface->dpy); - xcb_create_pixmap (surface->dpy, - surface->depth, - pixmap, - surface->drawable, - extents.width, extents.height); - _cairo_xcb_surface_ensure_gc (surface); - - xcb_copy_area (surface->dpy, surface->drawable, pixmap, surface->gc, - extents.x, extents.y, 0, 0, extents.width, extents.height); - - imagerep = xcb_get_image_reply(surface->dpy, - xcb_get_image(surface->dpy, XCB_IMAGE_FORMAT_Z_PIXMAP, - pixmap, - extents.x, extents.y, - extents.width, extents.height, - AllPlanes), 0); - xcb_free_pixmap (surface->dpy, pixmap); - - } - if (!imagerep) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - bpp = _bits_per_pixel(surface->dpy, imagerep->depth); - bytes_per_line = _bytes_per_line(surface->dpy, surface->width, bpp); - - data = _cairo_malloc_ab (surface->height, bytes_per_line); - if (data == NULL) { - free (imagerep); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - memcpy (data, xcb_get_image_data (imagerep), bytes_per_line * surface->height); - free (imagerep); - - /* - * Compute the pixel format masks from either an xcb_visualtype_t or - * a xcb_render_pctforminfo_t, failing we assume the drawable is an - * alpha-only pixmap as it could only have been created that way - * through the cairo_xlib_surface_create_for_bitmap function. - */ - if (surface->visual) { - masks.bpp = bpp; - masks.alpha_mask = 0; - masks.red_mask = surface->visual->red_mask; - masks.green_mask = surface->visual->green_mask; - masks.blue_mask = surface->visual->blue_mask; - } else if (surface->xrender_format.id != XCB_NONE) { - masks.bpp = bpp; - masks.red_mask = (unsigned long)surface->xrender_format.direct.red_mask << surface->xrender_format.direct.red_shift; - masks.green_mask = (unsigned long)surface->xrender_format.direct.green_mask << surface->xrender_format.direct.green_shift; - masks.blue_mask = (unsigned long)surface->xrender_format.direct.blue_mask << surface->xrender_format.direct.blue_shift; - masks.alpha_mask = (unsigned long)surface->xrender_format.direct.alpha_mask << surface->xrender_format.direct.alpha_shift; - } else { - masks.bpp = bpp; - masks.red_mask = 0; - masks.green_mask = 0; - masks.blue_mask = 0; - if (surface->depth < 32) - masks.alpha_mask = (1 << surface->depth) - 1; - else - masks.alpha_mask = 0xffffffff; - } - - /* - * Prefer to use a standard pixman format instead of the - * general masks case. - */ - if (_CAIRO_MASK_FORMAT (&masks, &format)) { - image = (cairo_image_surface_t *) - cairo_image_surface_create_for_data (data, - format, - extents.width, - extents.height, - bytes_per_line); - if (image->base.status) - goto FAIL; - } else { - /* - * XXX This can't work. We must convert the data to one of the - * supported pixman formats. Pixman needs another function - * which takes data in an arbitrary format and converts it - * to something supported by that library. - */ - image = (cairo_image_surface_t *) - _cairo_image_surface_create_with_masks (data, - &masks, - extents.width, - extents.height, - bytes_per_line); - if (image->base.status) - goto FAIL; - } - - /* Let the surface take ownership of the data */ - _cairo_image_surface_assume_ownership_of_data (image); - - *image_out = image; - return CAIRO_STATUS_SUCCESS; - - FAIL: - free (data); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); -} - -static void -_cairo_xcb_surface_ensure_src_picture (cairo_xcb_surface_t *surface) -{ - if (!surface->src_picture) { - surface->src_picture = xcb_generate_id(surface->dpy); - xcb_render_create_picture (surface->dpy, - surface->src_picture, - surface->drawable, - surface->xrender_format.id, - 0, NULL); - } -} - -static void -_cairo_xcb_surface_set_picture_clip_rects (cairo_xcb_surface_t *surface) -{ - if (surface->have_clip_rects) - xcb_render_set_picture_clip_rectangles (surface->dpy, surface->dst_picture, - 0, 0, - surface->num_clip_rects, - surface->clip_rects); -} - -static void -_cairo_xcb_surface_set_gc_clip_rects (cairo_xcb_surface_t *surface) -{ - if (surface->have_clip_rects) - xcb_set_clip_rectangles(surface->dpy, XCB_CLIP_ORDERING_YX_SORTED, surface->gc, - 0, 0, - surface->num_clip_rects, - surface->clip_rects ); -} - -static void -_cairo_xcb_surface_ensure_dst_picture (cairo_xcb_surface_t *surface) -{ - if (!surface->dst_picture) { - surface->dst_picture = xcb_generate_id(surface->dpy); - xcb_render_create_picture (surface->dpy, - surface->dst_picture, - surface->drawable, - surface->xrender_format.id, - 0, NULL); - _cairo_xcb_surface_set_picture_clip_rects (surface); - } - -} - -static void -_cairo_xcb_surface_ensure_gc (cairo_xcb_surface_t *surface) -{ - if (surface->gc) - return; - - surface->gc = xcb_generate_id(surface->dpy); - xcb_create_gc (surface->dpy, surface->gc, surface->drawable, 0, 0); - _cairo_xcb_surface_set_gc_clip_rects(surface); -} - -static cairo_status_t -_draw_image_surface (cairo_xcb_surface_t *surface, - cairo_image_surface_t *image, - int src_x, - int src_y, - int width, - int height, - int dst_x, - int dst_y) -{ - int bpp, bpl; - uint32_t data_len; - uint8_t *data, left_pad=0; - - /* equivalent of XPutImage(..., src_x,src_y, dst_x,dst_y, width,height); */ - /* XXX: assumes image and surface formats and depths are the same */ - /* XXX: assumes depth is a multiple of 8 (not bitmap) */ - - /* fit src_{x,y,width,height} within image->{0,0,width,height} */ - if (src_x < 0) { - width += src_x; - src_x = 0; - } - if (src_y < 0) { - height += src_y; - src_y = 0; - } - if (width + src_x > image->width) - width = image->width - src_x; - if (height + src_y > image->height) - height = image->height - src_y; - if (width <= 0 || height <= 0) - return CAIRO_STATUS_SUCCESS; - - bpp = _bits_per_pixel(surface->dpy, image->depth); - /* XXX: could use bpl = image->stride? */ - bpl = _bytes_per_line(surface->dpy, image->width, bpp); - - if (src_x == 0 && width == image->width) { - /* can work in-place */ - data_len = height * bpl; - data = image->data + src_y * bpl; - } else { - /* must copy {src_x,src_y,width,height} into new data */ - int line = 0; - uint8_t *data_line, *image_line; - int data_bpl = _bytes_per_line(surface->dpy, width, bpp); - data_len = height * data_bpl; - data_line = data = malloc(data_len); - if (data == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - image_line = image->data + src_y * bpl + (src_x * bpp / 8); - while (line++ < height) { - memcpy(data_line, image_line, data_bpl); - data_line += data_bpl; - image_line += bpl; - } - } - _cairo_xcb_surface_ensure_gc (surface); - xcb_put_image (surface->dpy, XCB_IMAGE_FORMAT_Z_PIXMAP, - surface->drawable, surface->gc, - width, height, - dst_x, dst_y, - left_pad, image->depth, - data_len, data); - - if (data < image->data || data >= image->data + image->height * bpl) - free(data); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_xcb_surface_acquire_source_image (void *abstract_surface, - cairo_image_surface_t **image_out, - void **image_extra) -{ - cairo_xcb_surface_t *surface = abstract_surface; - cairo_image_surface_t *image; - cairo_status_t status; - - status = _get_image_surface (surface, NULL, &image, NULL); - if (status) - return status; - - *image_out = image; - *image_extra = NULL; - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_xcb_surface_release_source_image (void *abstract_surface, - cairo_image_surface_t *image, - void *image_extra) -{ - cairo_surface_destroy (&image->base); -} - -static cairo_status_t -_cairo_xcb_surface_acquire_dest_image (void *abstract_surface, - cairo_rectangle_int_t *interest_rect, - cairo_image_surface_t **image_out, - cairo_rectangle_int_t *image_rect_out, - void **image_extra) -{ - cairo_xcb_surface_t *surface = abstract_surface; - cairo_image_surface_t *image; - cairo_status_t status; - - status = _get_image_surface (surface, interest_rect, &image, image_rect_out); - if (status) - return status; - - *image_out = image; - *image_extra = NULL; - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_xcb_surface_release_dest_image (void *abstract_surface, - cairo_rectangle_int_t *interest_rect, - cairo_image_surface_t *image, - cairo_rectangle_int_t *image_rect, - void *image_extra) -{ - cairo_xcb_surface_t *surface = abstract_surface; - - /* ignore errors */ - _draw_image_surface (surface, image, 0, 0, image->width, image->height, - image_rect->x, image_rect->y); - - cairo_surface_destroy (&image->base); -} - -/* - * Return whether two xcb surfaces share the same - * screen. Both core and Render drawing require this - * when using multiple drawables in an operation. - */ -static cairo_bool_t -_cairo_xcb_surface_same_screen (cairo_xcb_surface_t *dst, - cairo_xcb_surface_t *src) -{ - return dst->dpy == src->dpy && dst->screen == src->screen; -} - -static cairo_status_t -_cairo_xcb_surface_clone_similar (void *abstract_surface, - cairo_surface_t *src, - int src_x, - int src_y, - int width, - int height, - int *clone_offset_x, - int *clone_offset_y, - cairo_surface_t **clone_out) -{ - cairo_xcb_surface_t *surface = abstract_surface; - cairo_xcb_surface_t *clone; - - if (src->backend == surface->base.backend ) { - cairo_xcb_surface_t *xcb_src = (cairo_xcb_surface_t *)src; - - if (_cairo_xcb_surface_same_screen(surface, xcb_src)) { - *clone_offset_x = 0; - *clone_offset_y = 0; - *clone_out = cairo_surface_reference (src); - - return CAIRO_STATUS_SUCCESS; - } - } else if (_cairo_surface_is_image (src)) { - cairo_image_surface_t *image_src = (cairo_image_surface_t *)src; - cairo_content_t content = _cairo_content_from_format (image_src->format); - cairo_status_t status; - - if (surface->base.status) - return surface->base.status; - - clone = (cairo_xcb_surface_t *) - _cairo_xcb_surface_create_similar (surface, content, width, height); - if (clone == NULL) - return CAIRO_INT_STATUS_UNSUPPORTED; - if (clone->base.status) - return clone->base.status; - - status = _draw_image_surface (clone, image_src, - src_x, src_y, - width, height, - 0, 0); - if (status) { - cairo_surface_destroy (&clone->base); - return status; - } - - *clone_offset_x = src_x; - *clone_offset_y = src_y; - *clone_out = &clone->base; - - return CAIRO_STATUS_SUCCESS; - } - - return CAIRO_INT_STATUS_UNSUPPORTED; -} - -static cairo_status_t -_cairo_xcb_surface_set_matrix (cairo_xcb_surface_t *surface, - cairo_matrix_t *matrix) -{ - xcb_render_transform_t xtransform; - - if (!surface->src_picture) - return CAIRO_STATUS_SUCCESS; - - xtransform.matrix11 = _cairo_fixed_16_16_from_double (matrix->xx); - xtransform.matrix12 = _cairo_fixed_16_16_from_double (matrix->xy); - xtransform.matrix13 = _cairo_fixed_16_16_from_double (matrix->x0); - - xtransform.matrix21 = _cairo_fixed_16_16_from_double (matrix->yx); - xtransform.matrix22 = _cairo_fixed_16_16_from_double (matrix->yy); - xtransform.matrix23 = _cairo_fixed_16_16_from_double (matrix->y0); - - xtransform.matrix31 = 0; - xtransform.matrix32 = 0; - xtransform.matrix33 = 1 << 16; - - if (!CAIRO_SURFACE_RENDER_HAS_PICTURE_TRANSFORM (surface)) - { - static const xcb_render_transform_t identity = { - 1 << 16, 0x00000, 0x00000, - 0x00000, 1 << 16, 0x00000, - 0x00000, 0x00000, 1 << 16 - }; - - if (memcmp (&xtransform, &identity, sizeof (xcb_render_transform_t)) == 0) - return CAIRO_STATUS_SUCCESS; - - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - xcb_render_set_picture_transform (surface->dpy, surface->src_picture, xtransform); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_xcb_surface_set_filter (cairo_xcb_surface_t *surface, - cairo_filter_t filter) -{ - const char *render_filter; - - if (!surface->src_picture) - return CAIRO_STATUS_SUCCESS; - - if (!CAIRO_SURFACE_RENDER_HAS_FILTERS (surface)) - { - if (filter == CAIRO_FILTER_FAST || filter == CAIRO_FILTER_NEAREST) - return CAIRO_STATUS_SUCCESS; - - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - switch (filter) { - case CAIRO_FILTER_FAST: - render_filter = "fast"; - break; - case CAIRO_FILTER_GOOD: - render_filter = "good"; - break; - case CAIRO_FILTER_BEST: - render_filter = "best"; - break; - case CAIRO_FILTER_NEAREST: - render_filter = "nearest"; - break; - case CAIRO_FILTER_BILINEAR: - render_filter = "bilinear"; - break; - case CAIRO_FILTER_GAUSSIAN: - default: - render_filter = "best"; - break; - } - - xcb_render_set_picture_filter(surface->dpy, surface->src_picture, - strlen(render_filter), render_filter, 0, NULL); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_xcb_surface_set_repeat (cairo_xcb_surface_t *surface, int repeat) -{ - uint32_t mask = XCB_RENDER_CP_REPEAT; - uint32_t pa[] = { repeat }; - - if (!surface->src_picture) - return CAIRO_STATUS_SUCCESS; - - xcb_render_change_picture (surface->dpy, surface->src_picture, mask, pa); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_xcb_surface_set_attributes (cairo_xcb_surface_t *surface, - cairo_surface_attributes_t *attributes) -{ - cairo_int_status_t status; - - _cairo_xcb_surface_ensure_src_picture (surface); - - status = _cairo_xcb_surface_set_matrix (surface, &attributes->matrix); - if (status) - return status; - - switch (attributes->extend) { - case CAIRO_EXTEND_NONE: - _cairo_xcb_surface_set_repeat (surface, 0); - break; - case CAIRO_EXTEND_REPEAT: - _cairo_xcb_surface_set_repeat (surface, 1); - break; - case CAIRO_EXTEND_REFLECT: - case CAIRO_EXTEND_PAD: - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - status = _cairo_xcb_surface_set_filter (surface, attributes->filter); - if (status) - return status; - - return CAIRO_STATUS_SUCCESS; -} - -/* Checks whether we can can directly draw from src to dst with - * the core protocol: either with CopyArea or using src as a - * a tile in a GC. - */ -static cairo_bool_t -_surfaces_compatible (cairo_xcb_surface_t *dst, - cairo_xcb_surface_t *src) -{ - /* same screen */ - if (!_cairo_xcb_surface_same_screen (dst, src)) - return FALSE; - - /* same depth (for core) */ - if (src->depth != dst->depth) - return FALSE; - - /* if Render is supported, match picture formats */ - if (src->xrender_format.id != dst->xrender_format.id) - return FALSE; - else if (src->xrender_format.id != XCB_NONE) - return TRUE; - - /* Without Render, match visuals instead */ - if (src->visual == dst->visual) - return TRUE; - - return FALSE; -} - -static cairo_bool_t -_surface_has_alpha (cairo_xcb_surface_t *surface) -{ - if (surface->xrender_format.id != XCB_NONE) { - if (surface->xrender_format.type == XCB_RENDER_PICT_TYPE_DIRECT && - surface->xrender_format.direct.alpha_mask != 0) - return TRUE; - else - return FALSE; - } else { - - /* In the no-render case, we never have alpha */ - return FALSE; - } -} - -/* Returns true if the given operator and source-alpha combination - * requires alpha compositing to complete. - */ -static cairo_bool_t -_operator_needs_alpha_composite (cairo_operator_t op, - cairo_bool_t surface_has_alpha) -{ - if (op == CAIRO_OPERATOR_SOURCE || - (!surface_has_alpha && - (op == CAIRO_OPERATOR_OVER || - op == CAIRO_OPERATOR_ATOP || - op == CAIRO_OPERATOR_IN))) - return FALSE; - - return TRUE; -} - -/* There is a bug in most older X servers with compositing using a - * untransformed repeating source pattern when the source is in off-screen - * video memory, and another with repeated transformed images using a - * general transform matrix. When these bugs could be triggered, we need a - * fallback: in the common case where we have no transformation and the - * source and destination have the same format/visual, we can do the - * operation using the core protocol for the first bug, otherwise, we need - * a software fallback. - * - * We can also often optimize a compositing operation by calling XCopyArea - * for some common cases where there is no alpha compositing to be done. - * We figure that out here as well. - */ -typedef enum { - DO_RENDER, /* use render */ - DO_XCOPYAREA, /* core protocol XCopyArea optimization/fallback */ - DO_XTILE, /* core protocol XSetTile optimization/fallback */ - DO_UNSUPPORTED /* software fallback */ -} composite_operation_t; - -/* Initial check for the render bugs; we need to recheck for the - * offscreen-memory bug after we turn patterns into surfaces, since that - * may introduce a repeating pattern for gradient patterns. We don't need - * to check for the repeat+transform bug because gradient surfaces aren't - * transformed. - * - * All we do here is reject cases where we *know* are going to - * hit the bug and won't be able to use a core protocol fallback. - */ -static composite_operation_t -_categorize_composite_operation (cairo_xcb_surface_t *dst, - cairo_operator_t op, - cairo_pattern_t *src_pattern, - cairo_bool_t have_mask) - -{ -#if XXX_BUGGY_REPEAT - if (!dst->buggy_repeat) - return DO_RENDER; - - if (src_pattern->type == CAIRO_PATTERN_TYPE_SURFACE) - { - cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *)src_pattern; - - if (_cairo_matrix_is_integer_translation (&src_pattern->matrix, NULL, NULL) && - src_pattern->extend == CAIRO_EXTEND_REPEAT) - { - /* This is the case where we have the bug involving - * untransformed repeating source patterns with off-screen - * video memory; reject some cases where a core protocol - * fallback is impossible. - */ - if (have_mask || - !(op == CAIRO_OPERATOR_SOURCE || op == CAIRO_OPERATOR_OVER)) - return DO_UNSUPPORTED; - - if (_cairo_surface_is_xcb (surface_pattern->surface)) { - cairo_xcb_surface_t *src = (cairo_xcb_surface_t *)surface_pattern->surface; - - if (op == CAIRO_OPERATOR_OVER && _surface_has_alpha (src)) - return DO_UNSUPPORTED; - - /* If these are on the same screen but otherwise incompatible, - * make a copy as core drawing can't cross depths and doesn't - * work rightacross visuals of the same depth - */ - if (_cairo_xcb_surface_same_screen (dst, src) && - !_surfaces_compatible (dst, src)) - return DO_UNSUPPORTED; - } - } - - /* Check for the other bug involving repeat patterns with general - * transforms. */ - if (!_cairo_matrix_is_integer_translation (&src_pattern->matrix, NULL, NULL) && - src_pattern->extend == CAIRO_EXTEND_REPEAT) - return DO_UNSUPPORTED; - } -#endif - return DO_RENDER; -} - -/* Recheck for composite-repeat once we've turned patterns into Xlib surfaces - * If we end up returning DO_UNSUPPORTED here, we're throwing away work we - * did to turn gradients into a pattern, but most of the time we can handle - * that case with core protocol fallback. - * - * Also check here if we can just use XCopyArea, instead of going through - * Render. - */ -static composite_operation_t -_recategorize_composite_operation (cairo_xcb_surface_t *dst, - cairo_operator_t op, - cairo_xcb_surface_t *src, - cairo_surface_attributes_t *src_attr, - cairo_bool_t have_mask) -{ - cairo_bool_t is_integer_translation = - _cairo_matrix_is_integer_translation (&src_attr->matrix, NULL, NULL); - cairo_bool_t needs_alpha_composite = - _operator_needs_alpha_composite (op, _surface_has_alpha (src)); - - if (!have_mask && - is_integer_translation && - src_attr->extend == CAIRO_EXTEND_NONE && - !needs_alpha_composite && - _surfaces_compatible(src, dst)) - { - return DO_XCOPYAREA; - } -#if XXX_BUGGY_REPEAT - if (!dst->buggy_repeat) - return DO_RENDER; - - if (is_integer_translation && - src_attr->extend == CAIRO_EXTEND_REPEAT && - (src->width != 1 || src->height != 1)) - { - if (!have_mask && - !needs_alpha_composite && - _surfaces_compatible (dst, src)) - { - return DO_XTILE; - } - - return DO_UNSUPPORTED; - } -#endif - return DO_RENDER; -} - -static int -_render_operator (cairo_operator_t op) -{ - switch (op) { - case CAIRO_OPERATOR_CLEAR: - return XCB_RENDER_PICT_OP_CLEAR; - case CAIRO_OPERATOR_SOURCE: - return XCB_RENDER_PICT_OP_SRC; - case CAIRO_OPERATOR_DEST: - return XCB_RENDER_PICT_OP_DST; - case CAIRO_OPERATOR_OVER: - return XCB_RENDER_PICT_OP_OVER; - case CAIRO_OPERATOR_DEST_OVER: - return XCB_RENDER_PICT_OP_OVER_REVERSE; - case CAIRO_OPERATOR_IN: - return XCB_RENDER_PICT_OP_IN; - case CAIRO_OPERATOR_DEST_IN: - return XCB_RENDER_PICT_OP_IN_REVERSE; - case CAIRO_OPERATOR_OUT: - return XCB_RENDER_PICT_OP_OUT; - case CAIRO_OPERATOR_DEST_OUT: - return XCB_RENDER_PICT_OP_OUT_REVERSE; - case CAIRO_OPERATOR_ATOP: - return XCB_RENDER_PICT_OP_ATOP; - case CAIRO_OPERATOR_DEST_ATOP: - return XCB_RENDER_PICT_OP_ATOP_REVERSE; - case CAIRO_OPERATOR_XOR: - return XCB_RENDER_PICT_OP_XOR; - case CAIRO_OPERATOR_ADD: - return XCB_RENDER_PICT_OP_ADD; - case CAIRO_OPERATOR_SATURATE: - return XCB_RENDER_PICT_OP_SATURATE; - default: - return XCB_RENDER_PICT_OP_OVER; - } -} - -static cairo_int_status_t -_cairo_xcb_surface_composite (cairo_operator_t op, - cairo_pattern_t *src_pattern, - cairo_pattern_t *mask_pattern, - void *abstract_dst, - 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_surface_attributes_t src_attr, mask_attr; - cairo_xcb_surface_t *dst = abstract_dst; - cairo_xcb_surface_t *src; - cairo_xcb_surface_t *mask; - cairo_int_status_t status; - composite_operation_t operation; - int itx, ity; - cairo_bool_t is_integer_translation; - - if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - operation = _categorize_composite_operation (dst, op, src_pattern, - mask_pattern != NULL); - if (operation == DO_UNSUPPORTED) - return CAIRO_INT_STATUS_UNSUPPORTED; - - status = _cairo_pattern_acquire_surfaces (src_pattern, mask_pattern, - &dst->base, - src_x, src_y, - mask_x, mask_y, - width, height, - (cairo_surface_t **) &src, - (cairo_surface_t **) &mask, - &src_attr, &mask_attr); - if (status) - return status; - - operation = _recategorize_composite_operation (dst, op, src, &src_attr, - mask_pattern != NULL); - if (operation == DO_UNSUPPORTED) { - status = CAIRO_INT_STATUS_UNSUPPORTED; - goto BAIL; - } - - status = _cairo_xcb_surface_set_attributes (src, &src_attr); - if (status) - goto BAIL; - - switch (operation) - { - case DO_RENDER: - _cairo_xcb_surface_ensure_dst_picture (dst); - if (mask) { - status = _cairo_xcb_surface_set_attributes (mask, &mask_attr); - if (status) - goto BAIL; - - xcb_render_composite (dst->dpy, - _render_operator (op), - src->src_picture, - mask->src_picture, - dst->dst_picture, - src_x + src_attr.x_offset, - src_y + src_attr.y_offset, - mask_x + mask_attr.x_offset, - mask_y + mask_attr.y_offset, - dst_x, dst_y, - width, height); - } else { - static xcb_render_picture_t maskpict = { XCB_NONE }; - - xcb_render_composite (dst->dpy, - _render_operator (op), - src->src_picture, - maskpict, - dst->dst_picture, - src_x + src_attr.x_offset, - src_y + src_attr.y_offset, - 0, 0, - dst_x, dst_y, - width, height); - } - break; - - case DO_XCOPYAREA: - _cairo_xcb_surface_ensure_gc (dst); - xcb_copy_area (dst->dpy, - src->drawable, - dst->drawable, - dst->gc, - src_x + src_attr.x_offset, - src_y + src_attr.y_offset, - dst_x, dst_y, - width, height); - break; - - case DO_XTILE: - /* This case is only used for bug fallbacks, though it is theoretically - * applicable to the case where we don't have the RENDER extension as - * well. - * - * We've checked that we have a repeating unscaled source in - * _recategorize_composite_operation. - */ - - _cairo_xcb_surface_ensure_gc (dst); - is_integer_translation = - _cairo_matrix_is_integer_translation (&src_attr.matrix, &itx, &ity); - assert (is_integer_translation == TRUE); - { - uint32_t mask = XCB_GC_FILL_STYLE | XCB_GC_TILE - | XCB_GC_TILE_STIPPLE_ORIGIN_X - | XCB_GC_TILE_STIPPLE_ORIGIN_Y; - uint32_t values[] = { - XCB_FILL_STYLE_TILED, src->drawable, - - (itx + src_attr.x_offset), - - (ity + src_attr.y_offset) - }; - xcb_rectangle_t rect = { dst_x, dst_y, width, height }; - - xcb_change_gc( dst->dpy, dst->gc, mask, values ); - xcb_poly_fill_rectangle(dst->dpy, dst->drawable, dst->gc, 1, &rect); - } - break; - - case DO_UNSUPPORTED: - default: - ASSERT_NOT_REACHED; - } - - if (!_cairo_operator_bounded_by_source (op)) - status = _cairo_surface_composite_fixup_unbounded (&dst->base, - &src_attr, src->width, src->height, - mask ? &mask_attr : NULL, - mask ? mask->width : 0, - mask ? mask->height : 0, - src_x, src_y, - mask_x, mask_y, - dst_x, dst_y, width, height); - - BAIL: - if (mask) - _cairo_pattern_release_surface (mask_pattern, &mask->base, &mask_attr); - - _cairo_pattern_release_surface (src_pattern, &src->base, &src_attr); - - return status; -} - -static cairo_int_status_t -_cairo_xcb_surface_fill_rectangles (void *abstract_surface, - cairo_operator_t op, - const cairo_color_t * color, - cairo_rectangle_int_t *rects, - int num_rects) -{ - cairo_xcb_surface_t *surface = abstract_surface; - xcb_render_color_t render_color; - xcb_rectangle_t static_xrects[16]; - xcb_rectangle_t *xrects = static_xrects; - int i; - - if (!CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLE (surface)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - render_color.red = color->red_short; - render_color.green = color->green_short; - render_color.blue = color->blue_short; - render_color.alpha = color->alpha_short; - - if (num_rects > ARRAY_LENGTH(static_xrects)) { - xrects = _cairo_malloc_ab (num_rects, sizeof(xcb_rectangle_t)); - if (xrects == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - for (i = 0; i < num_rects; i++) { - xrects[i].x = rects[i].x; - xrects[i].y = rects[i].y; - xrects[i].width = rects[i].width; - xrects[i].height = rects[i].height; - } - - _cairo_xcb_surface_ensure_dst_picture (surface); - xcb_render_fill_rectangles (surface->dpy, - _render_operator (op), - surface->dst_picture, - render_color, num_rects, xrects); - - if (xrects != static_xrects) - free(xrects); - - return CAIRO_STATUS_SUCCESS; -} - -/* Creates an A8 picture of size @width x @height, initialized with @color - */ -static xcb_render_picture_t -_create_a8_picture (cairo_xcb_surface_t *surface, - xcb_render_color_t *color, - int width, - int height, - cairo_bool_t repeat) -{ - uint32_t values[] = { TRUE }; - uint32_t mask = repeat ? XCB_RENDER_CP_REPEAT : 0; - - xcb_pixmap_t pixmap = xcb_generate_id (surface->dpy); - xcb_render_picture_t picture = xcb_generate_id (surface->dpy); - - xcb_render_pictforminfo_t *format - = _CAIRO_FORMAT_TO_XRENDER_FORMAT (surface->dpy, CAIRO_FORMAT_A8); - xcb_rectangle_t rect = { 0, 0, width, height }; - - xcb_create_pixmap (surface->dpy, 8, pixmap, surface->drawable, - width <= 0 ? 1 : width, - height <= 0 ? 1 : height); - xcb_render_create_picture (surface->dpy, picture, pixmap, format->id, mask, values); - xcb_render_fill_rectangles (surface->dpy, XCB_RENDER_PICT_OP_SRC, picture, *color, 1, &rect); - xcb_free_pixmap (surface->dpy, pixmap); - - return picture; -} - -/* Creates a temporary mask for the trapezoids covering the area - * [@dst_x, @dst_y, @width, @height] of the destination surface. - */ -static cairo_status_t -_create_trapezoid_mask (cairo_xcb_surface_t *dst, - cairo_trapezoid_t *traps, - int num_traps, - int dst_x, - int dst_y, - int width, - int height, - xcb_render_pictforminfo_t *pict_format, - xcb_render_picture_t *mask_picture_out) -{ - xcb_render_color_t transparent = { 0, 0, 0, 0 }; - xcb_render_color_t solid = { 0xffff, 0xffff, 0xffff, 0xffff }; - xcb_render_picture_t mask_picture, solid_picture; - xcb_render_trapezoid_t *offset_traps; - int i; - - /* This would be considerably simpler using XRenderAddTraps(), but since - * we are only using this in the unbounded-operator case, we stick with - * XRenderCompositeTrapezoids, which is available on older versions - * of RENDER rather than conditionalizing. We should still hit an - * optimization that avoids creating another intermediate surface on - * the servers that have XRenderAddTraps(). - */ - mask_picture = _create_a8_picture (dst, &transparent, width, height, FALSE); - solid_picture = _create_a8_picture (dst, &solid, width, height, TRUE); - - offset_traps = _cairo_malloc_ab (num_traps, sizeof (xcb_render_trapezoid_t)); - if (offset_traps == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - for (i = 0; i < num_traps; i++) { - offset_traps[i].top = _cairo_fixed_to_16_16(traps[i].top) - 0x10000 * dst_y; - offset_traps[i].bottom = _cairo_fixed_to_16_16(traps[i].bottom) - 0x10000 * dst_y; - offset_traps[i].left.p1.x = _cairo_fixed_to_16_16(traps[i].left.p1.x) - 0x10000 * dst_x; - offset_traps[i].left.p1.y = _cairo_fixed_to_16_16(traps[i].left.p1.y) - 0x10000 * dst_y; - offset_traps[i].left.p2.x = _cairo_fixed_to_16_16(traps[i].left.p2.x) - 0x10000 * dst_x; - offset_traps[i].left.p2.y = _cairo_fixed_to_16_16(traps[i].left.p2.y) - 0x10000 * dst_y; - offset_traps[i].right.p1.x = _cairo_fixed_to_16_16(traps[i].right.p1.x) - 0x10000 * dst_x; - offset_traps[i].right.p1.y = _cairo_fixed_to_16_16(traps[i].right.p1.y) - 0x10000 * dst_y; - offset_traps[i].right.p2.x = _cairo_fixed_to_16_16(traps[i].right.p2.x) - 0x10000 * dst_x; - offset_traps[i].right.p2.y = _cairo_fixed_to_16_16(traps[i].right.p2.y) - 0x10000 * dst_y; - } - - xcb_render_trapezoids (dst->dpy, XCB_RENDER_PICT_OP_ADD, - solid_picture, mask_picture, - pict_format->id, - 0, 0, - num_traps, offset_traps); - - xcb_render_free_picture (dst->dpy, solid_picture); - free (offset_traps); - - *mask_picture_out = mask_picture; - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_xcb_surface_composite_trapezoids (cairo_operator_t op, - cairo_pattern_t *pattern, - void *abstract_dst, - cairo_antialias_t antialias, - int src_x, - int src_y, - int dst_x, - int dst_y, - unsigned int width, - unsigned int height, - cairo_trapezoid_t *traps, - int num_traps) -{ - cairo_surface_attributes_t attributes; - cairo_xcb_surface_t *dst = abstract_dst; - cairo_xcb_surface_t *src; - cairo_int_status_t status; - composite_operation_t operation; - int render_reference_x, render_reference_y; - int render_src_x, render_src_y; - int cairo_format; - xcb_render_pictforminfo_t *render_format; - - if (!CAIRO_SURFACE_RENDER_HAS_TRAPEZOIDS (dst)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - operation = _categorize_composite_operation (dst, op, pattern, TRUE); - if (operation == DO_UNSUPPORTED) - return CAIRO_INT_STATUS_UNSUPPORTED; - - status = _cairo_pattern_acquire_surface (pattern, &dst->base, - src_x, src_y, width, height, - (cairo_surface_t **) &src, - &attributes); - if (status) - return status; - - operation = _recategorize_composite_operation (dst, op, src, &attributes, TRUE); - if (operation == DO_UNSUPPORTED) { - status = CAIRO_INT_STATUS_UNSUPPORTED; - goto BAIL; - } - - switch (antialias) { - case CAIRO_ANTIALIAS_NONE: - cairo_format = CAIRO_FORMAT_A1; - break; - case CAIRO_ANTIALIAS_GRAY: - case CAIRO_ANTIALIAS_SUBPIXEL: - case CAIRO_ANTIALIAS_DEFAULT: - default: - cairo_format = CAIRO_FORMAT_A8; - break; - } - render_format = _CAIRO_FORMAT_TO_XRENDER_FORMAT (dst->dpy, cairo_format); - /* XXX: what to do if render_format is null? */ - - if (traps[0].left.p1.y < traps[0].left.p2.y) { - render_reference_x = _cairo_fixed_integer_floor (traps[0].left.p1.x); - render_reference_y = _cairo_fixed_integer_floor (traps[0].left.p1.y); - } else { - render_reference_x = _cairo_fixed_integer_floor (traps[0].left.p2.x); - render_reference_y = _cairo_fixed_integer_floor (traps[0].left.p2.y); - } - - render_src_x = src_x + render_reference_x - dst_x; - render_src_y = src_y + render_reference_y - dst_y; - - _cairo_xcb_surface_ensure_dst_picture (dst); - status = _cairo_xcb_surface_set_attributes (src, &attributes); - if (status) - goto BAIL; - - if (!_cairo_operator_bounded_by_mask (op)) { - /* xcb_render_composite+trapezoids() creates a mask only large enough for the - * trapezoids themselves, but if the operator is unbounded, then we need - * to actually composite all the way out to the bounds, so we create - * the mask and composite ourselves. There actually would - * be benefit to doing this in all cases, since RENDER implementations - * will frequently create a too temporary big mask, ignoring destination - * bounds and clip. (xcb_render_add_traps() could be used to make creating - * the mask somewhat cheaper.) - */ - xcb_render_picture_t mask_picture = 0; /* silence compiler */ - - status = _create_trapezoid_mask (dst, traps, num_traps, - dst_x, dst_y, width, height, - render_format, - &mask_picture); - if (status) - goto BAIL; - - xcb_render_composite (dst->dpy, - _render_operator (op), - src->src_picture, - mask_picture, - dst->dst_picture, - src_x + attributes.x_offset, - src_y + attributes.y_offset, - 0, 0, - dst_x, dst_y, - width, height); - - xcb_render_free_picture (dst->dpy, mask_picture); - - status = _cairo_surface_composite_shape_fixup_unbounded (&dst->base, - &attributes, src->width, src->height, - width, height, - src_x, src_y, - 0, 0, - dst_x, dst_y, width, height); - - } else { - xcb_render_trapezoid_t xtraps_stack[16]; - xcb_render_trapezoid_t *xtraps = xtraps_stack; - int i; - - if (num_traps > ARRAY_LENGTH(xtraps_stack)) { - xtraps = _cairo_malloc_ab (num_traps, sizeof(xcb_render_trapezoid_t)); - if (xtraps == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto BAIL; - } - } - - for (i = 0; i < num_traps; i++) { - xtraps[i].top = _cairo_fixed_to_16_16(traps[i].top); - xtraps[i].bottom = _cairo_fixed_to_16_16(traps[i].bottom); - xtraps[i].left.p1.x = _cairo_fixed_to_16_16(traps[i].left.p1.x); - xtraps[i].left.p1.y = _cairo_fixed_to_16_16(traps[i].left.p1.y); - xtraps[i].left.p2.x = _cairo_fixed_to_16_16(traps[i].left.p2.x); - xtraps[i].left.p2.y = _cairo_fixed_to_16_16(traps[i].left.p2.y); - xtraps[i].right.p1.x = _cairo_fixed_to_16_16(traps[i].right.p1.x); - xtraps[i].right.p1.y = _cairo_fixed_to_16_16(traps[i].right.p1.y); - xtraps[i].right.p2.x = _cairo_fixed_to_16_16(traps[i].right.p2.x); - xtraps[i].right.p2.y = _cairo_fixed_to_16_16(traps[i].right.p2.y); - } - - xcb_render_trapezoids (dst->dpy, - _render_operator (op), - src->src_picture, dst->dst_picture, - render_format->id, - render_src_x + attributes.x_offset, - render_src_y + attributes.y_offset, - num_traps, xtraps); - - if (xtraps != xtraps_stack) - free(xtraps); - } - - BAIL: - _cairo_pattern_release_surface (pattern, &src->base, &attributes); - - return status; -} - -static cairo_int_status_t -_cairo_xcb_surface_set_clip_region (void *abstract_surface, - cairo_region_t *region) -{ - cairo_xcb_surface_t *surface = abstract_surface; - - if (surface->clip_rects) { - free (surface->clip_rects); - surface->clip_rects = NULL; - } - - surface->have_clip_rects = FALSE; - surface->num_clip_rects = 0; - - if (region == NULL) { - uint32_t none[] = { XCB_NONE }; - if (surface->gc) - xcb_change_gc (surface->dpy, surface->gc, XCB_GC_CLIP_MASK, none); - - if (surface->xrender_format.id != XCB_NONE && surface->dst_picture) - xcb_render_change_picture (surface->dpy, surface->dst_picture, - XCB_RENDER_CP_CLIP_MASK, none); - } else { - cairo_box_int_t *boxes; - cairo_status_t status; - xcb_rectangle_t *rects = NULL; - int n_boxes, i; - - status = _cairo_region_get_boxes (region, &n_boxes, &boxes); - if (status) - return status; - - if (n_boxes > 0) { - rects = _cairo_malloc_ab (n_boxes, sizeof(xcb_rectangle_t)); - if (rects == NULL) { - _cairo_region_boxes_fini (region, boxes); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - } else { - rects = NULL; - } - - for (i = 0; i < n_boxes; i++) { - rects[i].x = boxes[i].p1.x; - rects[i].y = boxes[i].p1.y; - rects[i].width = boxes[i].p2.x - boxes[i].p1.x; - rects[i].height = boxes[i].p2.y - boxes[i].p1.y; - } - - _cairo_region_boxes_fini (region, boxes); - - surface->have_clip_rects = TRUE; - surface->clip_rects = rects; - surface->num_clip_rects = n_boxes; - - if (surface->gc) - _cairo_xcb_surface_set_gc_clip_rects (surface); - - if (surface->dst_picture) - _cairo_xcb_surface_set_picture_clip_rects (surface); - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_xcb_surface_get_extents (void *abstract_surface, - cairo_rectangle_int_t *rectangle) -{ - cairo_xcb_surface_t *surface = abstract_surface; - - rectangle->x = 0; - rectangle->y = 0; - - rectangle->width = surface->width; - rectangle->height = surface->height; - - return CAIRO_STATUS_SUCCESS; -} - -/* XXX: _cairo_xcb_surface_get_font_options */ - -static void -_cairo_xcb_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font); - -static void -_cairo_xcb_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph, - cairo_scaled_font_t *scaled_font); - -static cairo_int_status_t -_cairo_xcb_surface_show_glyphs (void *abstract_dst, - cairo_operator_t op, - cairo_pattern_t *src_pattern, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font, - int *remaining_glyphs); - -static cairo_bool_t -_cairo_xcb_surface_is_similar (void *surface_a, - void *surface_b, - cairo_content_t content) -{ - cairo_xcb_surface_t *a = surface_a; - cairo_xcb_surface_t *b = surface_b; - xcb_render_pictforminfo_t *xrender_format; - - /* XXX: disable caching by the solid pattern cache until we implement - * display notification to avoid issuing xcb calls from the wrong thread - * or accessing the surface after the Display has been closed. - */ - return FALSE; - - if (! _cairo_xcb_surface_same_screen (a, b)) - return FALSE; - - /* now check that the target is a similar format */ - xrender_format = _CAIRO_FORMAT_TO_XRENDER_FORMAT (b->dpy, - _cairo_format_from_content (content)); - - return a->xrender_format.id == xrender_format->id; -} - -static cairo_status_t -_cairo_xcb_surface_reset (void *abstract_surface) -{ - cairo_xcb_surface_t *surface = abstract_surface; - cairo_status_t status; - - status = _cairo_xcb_surface_set_clip_region (surface, NULL); - if (status) - return status; - - return CAIRO_STATUS_SUCCESS; -} - - -/* XXX: move this to the bottom of the file, XCB and Xlib */ - -static const cairo_surface_backend_t cairo_xcb_surface_backend = { - CAIRO_SURFACE_TYPE_XCB, - _cairo_xcb_surface_create_similar, - _cairo_xcb_surface_finish, - _cairo_xcb_surface_acquire_source_image, - _cairo_xcb_surface_release_source_image, - _cairo_xcb_surface_acquire_dest_image, - _cairo_xcb_surface_release_dest_image, - _cairo_xcb_surface_clone_similar, - _cairo_xcb_surface_composite, - _cairo_xcb_surface_fill_rectangles, - _cairo_xcb_surface_composite_trapezoids, - NULL, /* copy_page */ - NULL, /* show_page */ - _cairo_xcb_surface_set_clip_region, - NULL, /* intersect_clip_path */ - _cairo_xcb_surface_get_extents, - NULL, /* old_show_glyphs */ - NULL, /* get_font_options */ - NULL, /* flush */ - NULL, /* mark_dirty_rectangle */ - _cairo_xcb_surface_scaled_font_fini, - _cairo_xcb_surface_scaled_glyph_fini, - - NULL, /* paint */ - NULL, /* mask */ - NULL, /* stroke */ - NULL, /* fill */ - _cairo_xcb_surface_show_glyphs, - NULL, /* snapshot */ - - _cairo_xcb_surface_is_similar, - - _cairo_xcb_surface_reset -}; - -/** - * _cairo_surface_is_xcb: - * @surface: a #cairo_surface_t - * - * Checks if a surface is a #cairo_xcb_surface_t - * - * Return value: True if the surface is an xcb surface - **/ -static cairo_bool_t -_cairo_surface_is_xcb (cairo_surface_t *surface) -{ - return surface->backend == &cairo_xcb_surface_backend; -} - -static cairo_surface_t * -_cairo_xcb_surface_create_internal (xcb_connection_t *dpy, - xcb_drawable_t drawable, - xcb_screen_t *screen, - xcb_visualtype_t *visual, - xcb_render_pictforminfo_t *xrender_format, - int width, - int height, - int depth) -{ - cairo_xcb_surface_t *surface; - const xcb_render_query_version_reply_t *r; - - surface = malloc (sizeof (cairo_xcb_surface_t)); - if (surface == NULL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - if (xrender_format) { - depth = xrender_format->depth; - } else if (visual) { - xcb_depth_iterator_t depths; - xcb_visualtype_iterator_t visuals; - - /* This is ugly, but we have to walk over all visuals - * for the screen to find the depth. - */ - depths = xcb_screen_allowed_depths_iterator(screen); - for(; depths.rem; xcb_depth_next(&depths)) - { - visuals = xcb_depth_visuals_iterator(depths.data); - for(; visuals.rem; xcb_visualtype_next(&visuals)) - { - if(visuals.data->visual_id == visual->visual_id) - { - depth = depths.data->depth; - goto found; - } - } - } - found: - ; - } - - r = xcb_render_util_query_version(dpy); - if (r) { - surface->render_major = r->major_version; - surface->render_minor = r->minor_version; - } else { - surface->render_major = -1; - surface->render_minor = -1; - } - - if (CAIRO_SURFACE_RENDER_HAS_CREATE_PICTURE (surface)) { - if (!xrender_format) { - if (visual) { - const xcb_render_query_pict_formats_reply_t *formats; - xcb_render_pictvisual_t *pict_visual; - formats = xcb_render_util_query_formats (dpy); - pict_visual = xcb_render_util_find_visual_format (formats, visual->visual_id); - if (pict_visual) { - xcb_render_pictforminfo_t template; - template.id = pict_visual->format; - xrender_format = xcb_render_util_find_format (formats, XCB_PICT_FORMAT_ID, &template, 0); - } - } else if (depth == 1) { - xrender_format = _CAIRO_FORMAT_TO_XRENDER_FORMAT (dpy, CAIRO_FORMAT_A1); - } - } - } else { - xrender_format = NULL; - } - - _cairo_surface_init (&surface->base, &cairo_xcb_surface_backend, - _xcb_render_format_to_content (xrender_format)); - - surface->dpy = dpy; - - surface->gc = XCB_NONE; - surface->drawable = drawable; - surface->screen = screen; - surface->owns_pixmap = FALSE; - surface->use_pixmap = 0; - surface->width = width; - surface->height = height; - - /* XXX: set buggy_repeat based on ServerVendor and VendorRelease */ - - surface->dst_picture = XCB_NONE; - surface->src_picture = XCB_NONE; - - surface->visual = visual; - surface->xrender_format.id = XCB_NONE; - if (xrender_format) surface->xrender_format = *xrender_format; - surface->depth = depth; - - surface->have_clip_rects = FALSE; - surface->clip_rects = NULL; - surface->num_clip_rects = 0; - - return (cairo_surface_t *) surface; -} - -static xcb_screen_t * -_cairo_xcb_screen_from_visual (xcb_connection_t *c, xcb_visualtype_t *visual) -{ - xcb_depth_iterator_t d; - xcb_screen_iterator_t s = xcb_setup_roots_iterator(xcb_get_setup(c)); - for (; s.rem; xcb_screen_next(&s)) - { - if (s.data->root_visual == visual->visual_id) - return s.data; - - d = xcb_screen_allowed_depths_iterator(s.data); - for (; d.rem; xcb_depth_next(&d)) - { - xcb_visualtype_iterator_t v = xcb_depth_visuals_iterator(d.data); - for (; v.rem; xcb_visualtype_next(&v)) - { - if (v.data->visual_id == visual->visual_id) - return s.data; - } - } - } - return NULL; -} - -/** - * cairo_xcb_surface_create: - * @c: an XCB connection - * @drawable: an XCB drawable - * @visual: the visual to use for drawing to @drawable. The depth - * of the visual must match the depth of the drawable. - * Currently, only TrueColor visuals are fully supported. - * @width: the current width of @drawable. - * @height: the current height of @drawable. - * - * Creates an XCB surface that draws to the given drawable. - * The way that colors are represented in the drawable is specified - * by the provided visual. - * - * Note: If @drawable is a window, then the function - * cairo_xcb_surface_set_size() must be called whenever the size of the - * window changes. - * - * Return value: the newly created surface - **/ -cairo_surface_t * -cairo_xcb_surface_create (xcb_connection_t *c, - xcb_drawable_t drawable, - xcb_visualtype_t *visual, - int width, - int height) -{ - xcb_screen_t *screen = _cairo_xcb_screen_from_visual (c, visual); - - if (screen == NULL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL)); - - return _cairo_xcb_surface_create_internal (c, drawable, screen, - visual, NULL, - width, height, 0); -} - -/** - * cairo_xcb_surface_create_for_bitmap: - * @c: an XCB connection - * @bitmap: an XCB Pixmap (a depth-1 pixmap) - * @screen: an XCB Screen - * @width: the current width of @bitmap - * @height: the current height of @bitmap - * - * Creates an XCB surface that draws to the given bitmap. - * This will be drawn to as a %CAIRO_FORMAT_A1 object. - * - * Return value: the newly created surface - **/ -cairo_surface_t * -cairo_xcb_surface_create_for_bitmap (xcb_connection_t *c, - xcb_pixmap_t bitmap, - xcb_screen_t *screen, - int width, - int height) -{ - return _cairo_xcb_surface_create_internal (c, bitmap, screen, - NULL, NULL, - width, height, 1); -} - -/** - * cairo_xcb_surface_create_with_xrender_format: - * @c: an XCB connection - * @drawable: an XCB drawable - * @screen: the XCB screen associated with @drawable - * @format: the picture format to use for drawing to @drawable. The - * depth of @format mush match the depth of the drawable. - * @width: the current width of @drawable - * @height: the current height of @drawable - * - * Creates an XCB surface that draws to the given drawable. - * The way that colors are represented in the drawable is specified - * by the provided picture format. - * - * Note: If @drawable is a Window, then the function - * cairo_xcb_surface_set_size() must be called whenever the size of the - * window changes. - * - * Return value: the newly created surface. - **/ -cairo_surface_t * -cairo_xcb_surface_create_with_xrender_format (xcb_connection_t *c, - xcb_drawable_t drawable, - xcb_screen_t *screen, - xcb_render_pictforminfo_t *format, - int width, - int height) -{ - return _cairo_xcb_surface_create_internal (c, drawable, screen, - NULL, format, - width, height, 0); -} -slim_hidden_def (cairo_xcb_surface_create_with_xrender_format); - -/** - * cairo_xcb_surface_set_size: - * @surface: a #cairo_surface_t for the XCB backend - * @width: the new width of the surface - * @height: the new height of the surface - * - * Informs cairo of the new size of the XCB drawable underlying the - * surface. For a surface created for a window (rather than a pixmap), - * this function must be called each time the size of the window - * changes. (For a subwindow, you are normally resizing the window - * yourself, but for a toplevel window, it is necessary to listen for - * ConfigureNotify events.) - * - * A pixmap can never change size, so it is never necessary to call - * this function on a surface created for a pixmap. - **/ -void -cairo_xcb_surface_set_size (cairo_surface_t *abstract_surface, - int width, - int height) -{ - cairo_xcb_surface_t *surface = (cairo_xcb_surface_t *) abstract_surface; - cairo_status_t status_ignored; - - if (! _cairo_surface_is_xcb (abstract_surface)) { - status_ignored = _cairo_surface_set_error (abstract_surface, - CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - return; - } - - surface->width = width; - surface->height = height; -} - -/* - * Glyph rendering support - */ - -typedef struct _cairo_xcb_surface_font_private { - xcb_connection_t *dpy; - xcb_render_glyphset_t glyphset; - cairo_format_t format; - xcb_render_pictforminfo_t *xrender_format; -} cairo_xcb_surface_font_private_t; - -static cairo_status_t -_cairo_xcb_surface_font_init (xcb_connection_t *dpy, - cairo_scaled_font_t *scaled_font, - cairo_format_t format) -{ - cairo_xcb_surface_font_private_t *font_private; - - font_private = malloc (sizeof (cairo_xcb_surface_font_private_t)); - if (!font_private) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - font_private->dpy = dpy; - font_private->format = format; - font_private->xrender_format = _CAIRO_FORMAT_TO_XRENDER_FORMAT(dpy, format); - font_private->glyphset = xcb_generate_id(dpy); - xcb_render_create_glyph_set (dpy, font_private->glyphset, font_private->xrender_format->id); - - scaled_font->surface_private = font_private; - scaled_font->surface_backend = &cairo_xcb_surface_backend; - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_xcb_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font) -{ - cairo_xcb_surface_font_private_t *font_private = scaled_font->surface_private; - - if (font_private) { - xcb_render_free_glyph_set (font_private->dpy, font_private->glyphset); - free (font_private); - } -} - -static void -_cairo_xcb_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph, - cairo_scaled_font_t *scaled_font) -{ - cairo_xcb_surface_font_private_t *font_private = scaled_font->surface_private; - - if (font_private != NULL && scaled_glyph->surface_private != NULL) { - xcb_render_glyph_t glyph_index = _cairo_scaled_glyph_index(scaled_glyph); - xcb_render_free_glyphs (font_private->dpy, - font_private->glyphset, - 1, &glyph_index); - } -} - -static cairo_bool_t -_native_byte_order_lsb (void) -{ - int x = 1; - - return *((char *) &x) == 1; -} - -static cairo_status_t -_cairo_xcb_surface_add_glyph (xcb_connection_t *dpy, - cairo_scaled_font_t *scaled_font, - cairo_scaled_glyph_t *scaled_glyph) -{ - xcb_render_glyphinfo_t glyph_info; - xcb_render_glyph_t glyph_index; - unsigned char *data; - cairo_status_t status = CAIRO_STATUS_SUCCESS; - cairo_xcb_surface_font_private_t *font_private; - cairo_image_surface_t *glyph_surface = scaled_glyph->surface; - - if (scaled_font->surface_private == NULL) { - status = _cairo_xcb_surface_font_init (dpy, scaled_font, - glyph_surface->format); - if (status) - return status; - } - font_private = scaled_font->surface_private; - - /* If the glyph format does not match the font format, then we - * create a temporary surface for the glyph image with the font's - * format. - */ - if (glyph_surface->format != font_private->format) { - cairo_t *cr; - cairo_surface_t *tmp_surface; - double x_offset, y_offset; - - tmp_surface = cairo_image_surface_create (font_private->format, - glyph_surface->width, - glyph_surface->height); - cr = cairo_create (tmp_surface); - cairo_surface_get_device_offset (&glyph_surface->base, &x_offset, &y_offset); - cairo_set_source_surface (cr, &glyph_surface->base, x_offset, y_offset); - cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); - cairo_paint (cr); - - status = cairo_status (cr); - - cairo_destroy (cr); - - tmp_surface->device_transform = glyph_surface->base.device_transform; - tmp_surface->device_transform_inverse = glyph_surface->base.device_transform_inverse; - - glyph_surface = (cairo_image_surface_t *) tmp_surface; - - if (status) - goto BAIL; - } - - /* XXX: FRAGILE: We're ignore device_transform scaling here. A bug? */ - glyph_info.x = _cairo_lround (glyph_surface->base.device_transform.x0); - glyph_info.y = _cairo_lround (glyph_surface->base.device_transform.y0); - glyph_info.width = glyph_surface->width; - glyph_info.height = glyph_surface->height; - glyph_info.x_off = 0; - glyph_info.y_off = 0; - - data = glyph_surface->data; - - /* flip formats around */ - switch (scaled_glyph->surface->format) { - case CAIRO_FORMAT_A1: - /* local bitmaps are always stored with bit == byte */ - if (_native_byte_order_lsb() != (xcb_get_setup(dpy)->bitmap_format_bit_order == XCB_IMAGE_ORDER_LSB_FIRST)) { - int c = glyph_surface->stride * glyph_surface->height; - unsigned char *d; - unsigned char *new, *n; - - new = malloc (c); - if (!new) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto BAIL; - } - n = new; - d = data; - while (c--) - { - char b = *d++; - b = ((b << 1) & 0xaa) | ((b >> 1) & 0x55); - b = ((b << 2) & 0xcc) | ((b >> 2) & 0x33); - b = ((b << 4) & 0xf0) | ((b >> 4) & 0x0f); - *n++ = b; - } - data = new; - } - break; - case CAIRO_FORMAT_A8: - break; - case CAIRO_FORMAT_ARGB32: - if (_native_byte_order_lsb() != (xcb_get_setup(dpy)->image_byte_order == XCB_IMAGE_ORDER_LSB_FIRST)) { - unsigned int c = glyph_surface->stride * glyph_surface->height; - unsigned char *d; - unsigned char *new, *n; - - new = malloc (c); - if (new == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto BAIL; - } - n = new; - d = data; - while (c >= 4) - { - n[3] = d[0]; - n[2] = d[1]; - n[1] = d[2]; - n[0] = d[3]; - d += 4; - n += 4; - c -= 4; - } - data = new; - } - break; - case CAIRO_FORMAT_RGB24: - default: - ASSERT_NOT_REACHED; - break; - } - /* XXX assume X server wants pixman padding. Xft assumes this as well */ - - glyph_index = _cairo_scaled_glyph_index (scaled_glyph); - - xcb_render_add_glyphs (dpy, font_private->glyphset, - 1, &glyph_index, &glyph_info, - glyph_surface->stride * glyph_surface->height, - data); - - if (data != glyph_surface->data) - free (data); - - BAIL: - if (glyph_surface != scaled_glyph->surface) - cairo_surface_destroy (&glyph_surface->base); - - return status; -} - -#define N_STACK_BUF 1024 - -static cairo_status_t -_cairo_xcb_surface_show_glyphs_8 (cairo_xcb_surface_t *dst, - cairo_operator_t op, - cairo_xcb_surface_t *src, - int src_x_offset, int src_y_offset, - const cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font) -{ - cairo_xcb_surface_font_private_t *font_private = scaled_font->surface_private; - xcb_render_util_composite_text_stream_t *stream; - int i; - int thisX, thisY; - int lastX = 0, lastY = 0; - uint8_t glyph; - - stream = xcb_render_util_composite_text_stream (font_private->glyphset, num_glyphs, 0); - - for (i = 0; i < num_glyphs; ++i) { - thisX = _cairo_lround (glyphs[i].x); - thisY = _cairo_lround (glyphs[i].y); - glyph = glyphs[i].index; - xcb_render_util_glyphs_8 (stream, thisX - lastX, thisY - lastY, 1, &glyph); - lastX = thisX; - lastY = thisY; - } - - xcb_render_util_composite_text (dst->dpy, - _render_operator (op), - src->src_picture, - dst->dst_picture, - font_private->xrender_format->id, - src_x_offset + _cairo_lround (glyphs[0].x), - src_y_offset + _cairo_lround (glyphs[0].y), - stream); - - xcb_render_util_composite_text_free (stream); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_xcb_surface_show_glyphs_16 (cairo_xcb_surface_t *dst, - cairo_operator_t op, - cairo_xcb_surface_t *src, - int src_x_offset, int src_y_offset, - const cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font) -{ - cairo_xcb_surface_font_private_t *font_private = scaled_font->surface_private; - xcb_render_util_composite_text_stream_t *stream; - int i; - int thisX, thisY; - int lastX = 0, lastY = 0; - uint16_t glyph; - - stream = xcb_render_util_composite_text_stream (font_private->glyphset, num_glyphs, 0); - - for (i = 0; i < num_glyphs; ++i) { - thisX = _cairo_lround (glyphs[i].x); - thisY = _cairo_lround (glyphs[i].y); - glyph = glyphs[i].index; - xcb_render_util_glyphs_16 (stream, thisX - lastX, thisY - lastY, 1, &glyph); - lastX = thisX; - lastY = thisY; - } - - xcb_render_util_composite_text (dst->dpy, - _render_operator (op), - src->src_picture, - dst->dst_picture, - font_private->xrender_format->id, - src_x_offset + _cairo_lround (glyphs[0].x), - src_y_offset + _cairo_lround (glyphs[0].y), - stream); - - xcb_render_util_composite_text_free (stream); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_xcb_surface_show_glyphs_32 (cairo_xcb_surface_t *dst, - cairo_operator_t op, - cairo_xcb_surface_t *src, - int src_x_offset, int src_y_offset, - const cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font) -{ - cairo_xcb_surface_font_private_t *font_private = scaled_font->surface_private; - xcb_render_util_composite_text_stream_t *stream; - int i; - int thisX, thisY; - int lastX = 0, lastY = 0; - uint32_t glyph; - - stream = xcb_render_util_composite_text_stream (font_private->glyphset, num_glyphs, 0); - - for (i = 0; i < num_glyphs; ++i) { - thisX = _cairo_lround (glyphs[i].x); - thisY = _cairo_lround (glyphs[i].y); - glyph = glyphs[i].index; - xcb_render_util_glyphs_32 (stream, thisX - lastX, thisY - lastY, 1, &glyph); - lastX = thisX; - lastY = thisY; - } - - xcb_render_util_composite_text (dst->dpy, - _render_operator (op), - src->src_picture, - dst->dst_picture, - font_private->xrender_format->id, - src_x_offset + _cairo_lround (glyphs[0].x), - src_y_offset + _cairo_lround (glyphs[0].y), - stream); - - xcb_render_util_composite_text_free (stream); - - return CAIRO_STATUS_SUCCESS; -} - -typedef cairo_status_t (*cairo_xcb_surface_show_glyphs_func_t) - (cairo_xcb_surface_t *, cairo_operator_t, cairo_xcb_surface_t *, int, int, - const cairo_glyph_t *, int, cairo_scaled_font_t *); - -static cairo_bool_t -_cairo_xcb_surface_owns_font (cairo_xcb_surface_t *dst, - cairo_scaled_font_t *scaled_font) -{ - cairo_xcb_surface_font_private_t *font_private; - - font_private = scaled_font->surface_private; - if ((scaled_font->surface_backend != NULL && - scaled_font->surface_backend != &cairo_xcb_surface_backend) || - (font_private != NULL && font_private->dpy != dst->dpy)) - { - return FALSE; - } - - return TRUE; -} - - - -static cairo_status_t -_cairo_xcb_surface_emit_glyphs (cairo_xcb_surface_t *dst, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font, - cairo_operator_t op, - cairo_xcb_surface_t *src, - cairo_surface_attributes_t *attributes, - int *remaining_glyphs) -{ - cairo_scaled_glyph_t *scaled_glyph; - int i, o; - unsigned long max_index = 0; - cairo_status_t status; - cairo_glyph_t *output_glyphs; - const cairo_glyph_t *glyphs_chunk; - int glyphs_remaining, chunk_size, max_chunk_size; - cairo_xcb_surface_show_glyphs_func_t show_glyphs_func; - - /* We make a copy of the glyphs so that we can elide any size-zero - * glyphs to workaround an X server bug, (present in at least Xorg - * 7.1 without EXA). */ - output_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t)); - if (output_glyphs == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - for (i = 0, o = 0; i < num_glyphs; i++) { - if (glyphs[i].index > max_index) - max_index = glyphs[i].index; - status = _cairo_scaled_glyph_lookup (scaled_font, - glyphs[i].index, - CAIRO_SCALED_GLYPH_INFO_SURFACE, - &scaled_glyph); - if (status) { - free (output_glyphs); - return status; - } - - /* Don't put any size-zero glyphs into output_glyphs to avoid - * an X server bug which stops rendering glyphs after the - * first size-zero glyph. */ - if (scaled_glyph->surface->width && scaled_glyph->surface->height) { - output_glyphs[o++] = glyphs[i]; - if (scaled_glyph->surface_private == NULL) { - _cairo_xcb_surface_add_glyph (dst->dpy, scaled_font, scaled_glyph); - scaled_glyph->surface_private = (void *) 1; - } - } - } - num_glyphs = o; - - _cairo_xcb_surface_ensure_dst_picture (dst); - - max_chunk_size = xcb_get_maximum_request_length (dst->dpy); - if (max_index < 256) { - /* XXX: these are all the same size! (28) */ - max_chunk_size -= sizeof(xcb_render_composite_glyphs_8_request_t); - show_glyphs_func = _cairo_xcb_surface_show_glyphs_8; - } else if (max_index < 65536) { - max_chunk_size -= sizeof(xcb_render_composite_glyphs_16_request_t); - show_glyphs_func = _cairo_xcb_surface_show_glyphs_16; - } else { - max_chunk_size -= sizeof(xcb_render_composite_glyphs_32_request_t); - show_glyphs_func = _cairo_xcb_surface_show_glyphs_32; - } - /* XXX: I think this is wrong; this is only the header size (2 longs) */ - /* but should also include the glyph (1 long) */ - /* max_chunk_size /= sz_xGlyphElt; */ - max_chunk_size /= 3*sizeof(uint32_t); - - for (glyphs_remaining = num_glyphs, glyphs_chunk = output_glyphs; - glyphs_remaining; - glyphs_remaining -= chunk_size, glyphs_chunk += chunk_size) - { - chunk_size = MIN (glyphs_remaining, max_chunk_size); - - status = show_glyphs_func (dst, op, src, - attributes->x_offset, attributes->y_offset, - glyphs_chunk, chunk_size, scaled_font); - if (status) { - free (output_glyphs); - return status; - } - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_xcb_surface_show_glyphs (void *abstract_dst, - cairo_operator_t op, - cairo_pattern_t *src_pattern, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font, - int *remaining_glyphs) -{ - cairo_int_status_t status = CAIRO_STATUS_SUCCESS; - cairo_xcb_surface_t *dst = abstract_dst; - - composite_operation_t operation; - cairo_surface_attributes_t attributes; - cairo_xcb_surface_t *src = NULL; - - cairo_solid_pattern_t solid_pattern; - - if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT (dst) || dst->xrender_format.id == XCB_NONE) - return CAIRO_INT_STATUS_UNSUPPORTED; - - /* Just let unbounded operators go through the fallback code - * instead of trying to do the fixups here */ - if (!_cairo_operator_bounded_by_mask (op)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - /* Render <= 0.10 seems to have a bug with PictOpSrc and glyphs -- - * the solid source seems to be multiplied by the glyph mask, and - * then the entire thing is copied to the destination surface, - * including the fully transparent "background" of the rectangular - * glyph surface. */ - if (op == CAIRO_OPERATOR_SOURCE && - !CAIRO_SURFACE_RENDER_AT_LEAST(dst, 0, 11)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - /* We can only use our code if we either have no clip or - * have a real native clip region set. If we're using - * fallback clip masking, we have to go through the full - * fallback path. - */ - if (dst->base.clip && - (dst->base.clip->mode != CAIRO_CLIP_MODE_REGION || - dst->base.clip->surface != NULL)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - operation = _categorize_composite_operation (dst, op, src_pattern, TRUE); - if (operation == DO_UNSUPPORTED) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (! _cairo_xcb_surface_owns_font (dst, scaled_font)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - /* After passing all those tests, we're now committed to rendering - * these glyphs or to fail trying. We first upload any glyphs to - * the X server that it doesn't have already, then we draw - * them. We tie into the scaled_font's glyph cache and remove - * glyphs from the X server when they are ejected from the - * scaled_font cache. - */ - - /* PictOpClear doesn't seem to work with CompositeText; it seems to ignore - * the mask (the glyphs). This code below was executed as a side effect - * of going through the _clip_and_composite fallback code for old_show_glyphs, - * so PictOpClear was never used with CompositeText before. - */ - if (op == CAIRO_OPERATOR_CLEAR) { - _cairo_pattern_init_solid (&solid_pattern, CAIRO_COLOR_WHITE, - CAIRO_CONTENT_COLOR); - src_pattern = &solid_pattern.base; - op = CAIRO_OPERATOR_DEST_OUT; - } - - if (src_pattern->type == CAIRO_PATTERN_TYPE_SOLID) { - status = _cairo_pattern_acquire_surface (src_pattern, &dst->base, - 0, 0, 1, 1, - (cairo_surface_t **) &src, - &attributes); - } else { - cairo_rectangle_int_t glyph_extents; - - status = _cairo_scaled_font_glyph_device_extents (scaled_font, - glyphs, - num_glyphs, - &glyph_extents); - if (status) - goto BAIL; - - status = _cairo_pattern_acquire_surface (src_pattern, &dst->base, - glyph_extents.x, glyph_extents.y, - glyph_extents.width, glyph_extents.height, - (cairo_surface_t **) &src, - &attributes); - } - - if (status) - goto BAIL; - - operation = _recategorize_composite_operation (dst, op, src, &attributes, TRUE); - if (operation == DO_UNSUPPORTED) { - status = CAIRO_INT_STATUS_UNSUPPORTED; - goto BAIL; - } - - status = _cairo_xcb_surface_set_attributes (src, &attributes); - if (status) - goto BAIL; - - /* Send all unsent glyphs to the server, and count the max of the glyph indices */ - _cairo_scaled_font_freeze_cache (scaled_font); - - if (_cairo_xcb_surface_owns_font (dst, scaled_font)) - status = _cairo_xcb_surface_emit_glyphs (dst, - glyphs, num_glyphs, - scaled_font, - op, - src, - &attributes, - remaining_glyphs); - else - status = CAIRO_INT_STATUS_UNSUPPORTED; - _cairo_scaled_font_thaw_cache (scaled_font); - - BAIL: - if (src) - _cairo_pattern_release_surface (src_pattern, &src->base, &attributes); - if (src_pattern == &solid_pattern.base) - _cairo_pattern_fini (&solid_pattern.base); - - return status; -} diff --git a/uppdev/plugin/cairo/lib/cairo-xcb-xrender.h b/uppdev/plugin/cairo/lib/cairo-xcb-xrender.h deleted file mode 100644 index 09c609738..000000000 --- a/uppdev/plugin/cairo/lib/cairo-xcb-xrender.h +++ /dev/null @@ -1,63 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - */ - -#ifndef CAIRO_XCB_XRENDER_H -#define CAIRO_XCB_XRENDER_H - -#include "cairo.h" - -#if CAIRO_HAS_XCB_SURFACE - -#include -#include - -CAIRO_BEGIN_DECLS - -cairo_public cairo_surface_t * -cairo_xcb_surface_create_with_xrender_format (xcb_connection_t *c, - xcb_drawable_t drawable, - xcb_screen_t *screen, - xcb_render_pictforminfo_t *format, - int width, - int height); - -CAIRO_END_DECLS - -#else /* CAIRO_HAS_XCB_SURFACE */ -# error Cairo was not compiled with support for the xcb backend -#endif /* CAIRO_HAS_XCB_SURFACE */ - -#endif /* CAIRO_XCB_XRENDER_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-xcb.h b/uppdev/plugin/cairo/lib/cairo-xcb.h deleted file mode 100644 index 1b6d2e69f..000000000 --- a/uppdev/plugin/cairo/lib/cairo-xcb.h +++ /dev/null @@ -1,73 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - */ - -#ifndef CAIRO_XCB_H -#define CAIRO_XCB_H - -#include "cairo.h" - -#if CAIRO_HAS_XCB_SURFACE - -#include - -CAIRO_BEGIN_DECLS - -cairo_public cairo_surface_t * -cairo_xcb_surface_create (xcb_connection_t *c, - xcb_drawable_t drawable, - xcb_visualtype_t *visual, - int width, - int height); - -cairo_public cairo_surface_t * -cairo_xcb_surface_create_for_bitmap (xcb_connection_t *c, - xcb_pixmap_t bitmap, - xcb_screen_t *screen, - int width, - int height); - -cairo_public void -cairo_xcb_surface_set_size (cairo_surface_t *surface, - int width, - int height); - -CAIRO_END_DECLS - -#else /* CAIRO_HAS_XCB_SURFACE */ -# error Cairo was not compiled with support for the xcb backend -#endif /* CAIRO_HAS_XCB_SURFACE */ - -#endif /* CAIRO_XCB_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-xlib-display.c b/uppdev/plugin/cairo/lib/cairo-xlib-display.c deleted file mode 100644 index b2e2755d3..000000000 --- a/uppdev/plugin/cairo/lib/cairo-xlib-display.c +++ /dev/null @@ -1,525 +0,0 @@ -/* Cairo - a vector graphics library with display and print output - * - * Copyright © 2007 Chris Wilson - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Chris Wilson. - * - * Contributor(s): - * Karl Tomlinson , Mozilla Corporation - */ - -#include "cairoint.h" - -#include "cairo-xlib-private.h" -#include "cairo-xlib-xrender-private.h" - -#include - -#include /* For XESetCloseDisplay */ - -typedef int (*cairo_xlib_error_func_t) (Display *display, - XErrorEvent *event); - -struct _cairo_xlib_job { - cairo_xlib_job_t *next; - enum { - RESOURCE, - WORK - } type; - union { - struct { - cairo_xlib_notify_resource_func notify; - XID xid; - } resource; - struct { - cairo_xlib_notify_func notify; - void *data; - void (*destroy) (void *); - } work; - } func; -}; - -static cairo_xlib_display_t *_cairo_xlib_display_list; - -static void -_cairo_xlib_remove_close_display_hook_internal (cairo_xlib_display_t *display, - cairo_xlib_hook_t *hook); - -static void -_cairo_xlib_call_close_display_hooks (cairo_xlib_display_t *display) -{ - cairo_xlib_screen_info_t *screen; - cairo_xlib_hook_t *hook; - - /* call all registered shutdown routines */ - CAIRO_MUTEX_LOCK (display->mutex); - - for (screen = display->screens; screen != NULL; screen = screen->next) - _cairo_xlib_screen_info_close_display (screen); - - while (TRUE) { - hook = display->close_display_hooks; - if (hook == NULL) - break; - - _cairo_xlib_remove_close_display_hook_internal (display, hook); - - CAIRO_MUTEX_UNLOCK (display->mutex); - hook->func (display, hook); - CAIRO_MUTEX_LOCK (display->mutex); - } - display->closed = TRUE; - - CAIRO_MUTEX_UNLOCK (display->mutex); -} - -static void -_cairo_xlib_display_discard_screens (cairo_xlib_display_t *display) -{ - cairo_xlib_screen_info_t *screens; - - CAIRO_MUTEX_LOCK (display->mutex); - screens = display->screens; - display->screens = NULL; - CAIRO_MUTEX_UNLOCK (display->mutex); - - while (screens != NULL) { - cairo_xlib_screen_info_t *screen = screens; - screens = screen->next; - - _cairo_xlib_screen_info_destroy (screen); - } -} - -cairo_xlib_display_t * -_cairo_xlib_display_reference (cairo_xlib_display_t *display) -{ - assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&display->ref_count)); - - _cairo_reference_count_inc (&display->ref_count); - - return display; -} - -void -_cairo_xlib_display_destroy (cairo_xlib_display_t *display) -{ - assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&display->ref_count)); - - if (! _cairo_reference_count_dec_and_test (&display->ref_count)) - return; - - /* destroy all outstanding notifies */ - while (display->workqueue != NULL) { - cairo_xlib_job_t *job = display->workqueue; - display->workqueue = job->next; - - if (job->type == WORK && job->func.work.destroy != NULL) - job->func.work.destroy (job->func.work.data); - - _cairo_freelist_free (&display->wq_freelist, job); - } - _cairo_freelist_fini (&display->wq_freelist); - - CAIRO_MUTEX_FINI (display->mutex); - - free (display); -} - -static int -_noop_error_handler (Display *display, - XErrorEvent *event) -{ - return False; /* return value is ignored */ -} -static int -_cairo_xlib_close_display (Display *dpy, XExtCodes *codes) -{ - cairo_xlib_display_t *display, **prev, *next; - cairo_xlib_error_func_t old_handler; - - CAIRO_MUTEX_LOCK (_cairo_xlib_display_mutex); - for (display = _cairo_xlib_display_list; display; display = display->next) - if (display->display == dpy) - break; - CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex); - if (display == NULL) - return 0; - - /* protect the notifies from triggering XErrors */ - XSync (dpy, False); - old_handler = XSetErrorHandler (_noop_error_handler); - - _cairo_xlib_display_notify (display); - _cairo_xlib_call_close_display_hooks (display); - _cairo_xlib_display_discard_screens (display); - - /* catch any that arrived before marking the display as closed */ - _cairo_xlib_display_notify (display); - - XSync (dpy, False); - XSetErrorHandler (old_handler); - - /* - * Unhook from the global list - */ - CAIRO_MUTEX_LOCK (_cairo_xlib_display_mutex); - prev = &_cairo_xlib_display_list; - for (display = _cairo_xlib_display_list; display; display = next) { - next = display->next; - if (display->display == dpy) { - *prev = next; - break; - } else - prev = &display->next; - } - CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex); - - assert (display != NULL); - _cairo_xlib_display_destroy (display); - - /* Return value in accordance with requirements of - * XESetCloseDisplay */ - return 0; -} - -cairo_xlib_display_t * -_cairo_xlib_display_get (Display *dpy) -{ - cairo_xlib_display_t *display; - cairo_xlib_display_t **prev; - XExtCodes *codes; - int major_unused, minor_unused; - - /* There is an apparent deadlock between this mutex and the - * mutex for the display, but it's actually safe. For the - * app to call XCloseDisplay() while any other thread is - * inside this function would be an error in the logic - * app, and the CloseDisplay hook is the only other place we - * acquire this mutex. - */ - CAIRO_MUTEX_LOCK (_cairo_xlib_display_mutex); - - for (prev = &_cairo_xlib_display_list; (display = *prev); prev = &(*prev)->next) - { - if (display->display == dpy) { - /* - * MRU the list - */ - if (prev != &_cairo_xlib_display_list) { - *prev = display->next; - display->next = _cairo_xlib_display_list; - _cairo_xlib_display_list = display; - } - break; - } - } - - if (display != NULL) { - display = _cairo_xlib_display_reference (display); - goto UNLOCK; - } - - display = malloc (sizeof (cairo_xlib_display_t)); - if (display == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - goto UNLOCK; - } - - /* Xlib calls out to the extension close_display hooks in LIFO - * order. So we have to ensure that all extensions that we depend - * on in our close_display hook are properly initialized before we - * add our hook. For now, that means Render, so we call into its - * QueryVersion function to ensure it gets initialized. - */ - XRenderQueryVersion (dpy, &major_unused, &minor_unused); - - codes = XAddExtension (dpy); - if (codes == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - free (display); - display = NULL; - goto UNLOCK; - } - - XESetCloseDisplay (dpy, codes->extension, _cairo_xlib_close_display); - - _cairo_freelist_init (&display->wq_freelist, sizeof (cairo_xlib_job_t)); - - CAIRO_REFERENCE_COUNT_INIT (&display->ref_count, 2); /* add one for the CloseDisplay */ - CAIRO_MUTEX_INIT (display->mutex); - display->display = dpy; - display->screens = NULL; - display->workqueue = NULL; - display->close_display_hooks = NULL; - display->closed = FALSE; - - memset (display->cached_xrender_formats, 0, - sizeof (display->cached_xrender_formats)); - - display->buggy_repeat = FALSE; - - /* This buggy_repeat condition is very complicated because there - * are multiple X server code bases (with multiple versioning - * schemes within a code base), and multiple bugs. - * - * The X servers: - * - * 1. The Vendor=="XFree86" code base with release numbers such - * as 4.7.0 (VendorRelease==40700000). - * - * 2. The Vendor=="X.Org" code base (a descendant of the - * XFree86 code base). It originally had things like - * VendorRelease==60700000 for release 6.7.0 but then changed - * its versioning scheme so that, for example, - * VendorRelease==10400000 for the 1.4.0 X server within the - * X.Org 7.3 release. - * - * The bugs: - * - * 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 - * servers. Confirmed X servers with this bug include: - * - * "XFree86" <= 40500000 - * "X.Org" <= 60802000 (only with old numbering >= 60700000) - * - * 2. A separate bug resulting in a crash of the X server when - * using cairo's extend-reflect test case, (which, surprisingly - * enough was not passing RepeatReflect to the X server, but - * instead using RepeatNormal in a workaround). Nobody to date - * has understood the bug well, but it appears to be gone as of - * the X.Org 1.4.0 server. This bug is coincidentally avoided - * by using the same buggy_repeat workaround. Confirmed X - * servers with this bug include: - * - * "X.org" == 60900000 (old versioning scheme) - * "X.org" < 10400000 (new numbering scheme) - * - * For the old-versioning-scheme X servers we don't know - * exactly when second the bug started, but since bug 1 is - * present through 6.8.2 and bug 2 is present in 6.9.0 it seems - * safest to just blacklist all old-versioning-scheme X servers, - * (just using VendorRelase < 70000000), as buggy_repeat=TRUE. - */ - if (strstr (ServerVendor (dpy), "X.Org") != NULL) { - if (VendorRelease (dpy) >= 60700000 && VendorRelease (dpy) < 70000000) - display->buggy_repeat = TRUE; - if (VendorRelease (dpy) < 10400000) - display->buggy_repeat = TRUE; - } else if (strstr (ServerVendor (dpy), "XFree86") != NULL) { - if (VendorRelease (dpy) <= 40500000) - display->buggy_repeat = TRUE; - } - - display->next = _cairo_xlib_display_list; - _cairo_xlib_display_list = display; - -UNLOCK: - CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex); - return display; -} - -void -_cairo_xlib_add_close_display_hook (cairo_xlib_display_t *display, - cairo_xlib_hook_t *hook) -{ - CAIRO_MUTEX_LOCK (display->mutex); - hook->prev = NULL; - hook->next = display->close_display_hooks; - if (hook->next != NULL) - hook->next->prev = hook; - display->close_display_hooks = hook; - CAIRO_MUTEX_UNLOCK (display->mutex); -} - -/* display->mutex must be held */ -static void -_cairo_xlib_remove_close_display_hook_internal (cairo_xlib_display_t *display, - cairo_xlib_hook_t *hook) -{ - if (display->close_display_hooks == hook) - display->close_display_hooks = hook->next; - else if (hook->prev != NULL) - hook->prev->next = hook->next; - - if (hook->next != NULL) - hook->next->prev = hook->prev; - - hook->prev = NULL; - hook->next = NULL; -} - -void -_cairo_xlib_remove_close_display_hook (cairo_xlib_display_t *display, - cairo_xlib_hook_t *hook) -{ - CAIRO_MUTEX_LOCK (display->mutex); - _cairo_xlib_remove_close_display_hook_internal (display, hook); - CAIRO_MUTEX_UNLOCK (display->mutex); -} - -cairo_status_t -_cairo_xlib_display_queue_resource (cairo_xlib_display_t *display, - cairo_xlib_notify_resource_func notify, - XID xid) -{ - cairo_xlib_job_t *job; - cairo_status_t status = CAIRO_STATUS_NO_MEMORY; - - CAIRO_MUTEX_LOCK (display->mutex); - if (display->closed == FALSE) { - job = _cairo_freelist_alloc (&display->wq_freelist); - if (job != NULL) { - job->type = RESOURCE; - job->func.resource.xid = xid; - job->func.resource.notify = notify; - - job->next = display->workqueue; - display->workqueue = job; - - status = CAIRO_STATUS_SUCCESS; - } - } - CAIRO_MUTEX_UNLOCK (display->mutex); - - return status; -} - -cairo_status_t -_cairo_xlib_display_queue_work (cairo_xlib_display_t *display, - cairo_xlib_notify_func notify, - void *data, - void (*destroy) (void *)) -{ - cairo_xlib_job_t *job; - cairo_status_t status = CAIRO_STATUS_NO_MEMORY; - - CAIRO_MUTEX_LOCK (display->mutex); - if (display->closed == FALSE) { - job = _cairo_freelist_alloc (&display->wq_freelist); - if (job != NULL) { - job->type = WORK; - job->func.work.data = data; - job->func.work.notify = notify; - job->func.work.destroy = destroy; - - job->next = display->workqueue; - display->workqueue = job; - - status = CAIRO_STATUS_SUCCESS; - } - } - CAIRO_MUTEX_UNLOCK (display->mutex); - - return status; -} - -void -_cairo_xlib_display_notify (cairo_xlib_display_t *display) -{ - cairo_xlib_job_t *jobs, *job, *freelist; - Display *dpy = display->display; - - CAIRO_MUTEX_LOCK (display->mutex); - jobs = display->workqueue; - while (jobs != NULL) { - display->workqueue = NULL; - CAIRO_MUTEX_UNLOCK (display->mutex); - - /* reverse the list to obtain FIFO order */ - job = NULL; - do { - cairo_xlib_job_t *next = jobs->next; - jobs->next = job; - job = jobs; - jobs = next; - } while (jobs != NULL); - freelist = jobs = job; - - do { - job = jobs; - jobs = job->next; - - switch (job->type){ - case WORK: - job->func.work.notify (dpy, job->func.work.data); - if (job->func.work.destroy != NULL) - job->func.work.destroy (job->func.work.data); - break; - - case RESOURCE: - job->func.resource.notify (dpy, job->func.resource.xid); - break; - } - } while (jobs != NULL); - - CAIRO_MUTEX_LOCK (display->mutex); - do { - job = freelist; - freelist = job->next; - _cairo_freelist_free (&display->wq_freelist, job); - } while (freelist != NULL); - - jobs = display->workqueue; - } - CAIRO_MUTEX_UNLOCK (display->mutex); -} - -XRenderPictFormat * -_cairo_xlib_display_get_xrender_format (cairo_xlib_display_t *display, - cairo_format_t format) -{ - XRenderPictFormat *xrender_format; - - CAIRO_MUTEX_LOCK (display->mutex); - xrender_format = display->cached_xrender_formats[format]; - if (xrender_format == NULL) { - int pict_format; - - switch (format) { - case CAIRO_FORMAT_A1: - pict_format = PictStandardA1; break; - case CAIRO_FORMAT_A8: - pict_format = PictStandardA8; break; - case CAIRO_FORMAT_RGB24: - pict_format = PictStandardRGB24; break; - default: - ASSERT_NOT_REACHED; - case CAIRO_FORMAT_ARGB32: - pict_format = PictStandardARGB32; break; - } - xrender_format = XRenderFindStandardFormat (display->display, - pict_format); - display->cached_xrender_formats[format] = xrender_format; - } - CAIRO_MUTEX_UNLOCK (display->mutex); - - return xrender_format; -} diff --git a/uppdev/plugin/cairo/lib/cairo-xlib-private.h b/uppdev/plugin/cairo/lib/cairo-xlib-private.h deleted file mode 100644 index e381e584d..000000000 --- a/uppdev/plugin/cairo/lib/cairo-xlib-private.h +++ /dev/null @@ -1,168 +0,0 @@ -/* Cairo - a vector graphics library with display and print output - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributors(s): - * Chris Wilson - * Karl Tomlinson , Mozilla Corporation - */ - -#ifndef CAIRO_XLIB_PRIVATE_H -#define CAIRO_XLIB_PRIVATE_H - -#include "cairo-xlib.h" -#include "cairo-xlib-xrender-private.h" - -#include "cairo-compiler-private.h" -#include "cairo-freelist-private.h" -#include "cairo-mutex-private.h" -#include "cairo-reference-count-private.h" - -typedef struct _cairo_xlib_display cairo_xlib_display_t; -typedef struct _cairo_xlib_hook cairo_xlib_hook_t; -typedef struct _cairo_xlib_job cairo_xlib_job_t; -typedef void (*cairo_xlib_notify_func) (Display *, void *); -typedef void (*cairo_xlib_notify_resource_func) (Display *, XID); - -struct _cairo_xlib_hook { - cairo_xlib_hook_t *prev, *next; /* private */ - void (*func) (cairo_xlib_display_t *display, void *data); -}; - -struct _cairo_xlib_display { - cairo_xlib_display_t *next; - cairo_reference_count_t ref_count; - cairo_mutex_t mutex; - - Display *display; - cairo_xlib_screen_info_t *screens; - - XRenderPictFormat *cached_xrender_formats[CAIRO_FORMAT_A1 + 1]; - - cairo_xlib_job_t *workqueue; - cairo_freelist_t wq_freelist; - - cairo_xlib_hook_t *close_display_hooks; - unsigned int buggy_repeat :1; - unsigned int closed :1; -}; - -/* size of color cube */ -#define CUBE_SIZE 6 -/* size of gray ramp */ -#define RAMP_SIZE 16 - -typedef struct _cairo_xlib_visual_info { - VisualID visualid; - struct { uint8_t a, r, g, b; } colors[256]; - uint8_t cube_to_pseudocolor[CUBE_SIZE][CUBE_SIZE][CUBE_SIZE]; - uint8_t field8_to_cube[256]; - int8_t dither8_to_cube[256]; - uint8_t gray8_to_pseudocolor[256]; -} cairo_xlib_visual_info_t; - -struct _cairo_xlib_screen_info { - cairo_xlib_screen_info_t *next; - cairo_reference_count_t ref_count; - cairo_mutex_t mutex; - - cairo_xlib_display_t *display; - Screen *screen; - cairo_bool_t has_render; - - cairo_font_options_t font_options; - - GC gc[9]; - unsigned int gc_needs_clip_reset; - - cairo_array_t visuals; -}; - -cairo_private cairo_xlib_display_t * -_cairo_xlib_display_get (Display *display); - -cairo_private cairo_xlib_display_t * -_cairo_xlib_display_reference (cairo_xlib_display_t *info); -cairo_private void -_cairo_xlib_display_destroy (cairo_xlib_display_t *info); - -cairo_private void -_cairo_xlib_add_close_display_hook (cairo_xlib_display_t *display, cairo_xlib_hook_t *hook); - -cairo_private void -_cairo_xlib_remove_close_display_hook (cairo_xlib_display_t *display, cairo_xlib_hook_t *hook); - -cairo_private cairo_status_t -_cairo_xlib_display_queue_work (cairo_xlib_display_t *display, - cairo_xlib_notify_func notify, - void *data, - void (*destroy)(void *)); -cairo_private cairo_status_t -_cairo_xlib_display_queue_resource (cairo_xlib_display_t *display, - cairo_xlib_notify_resource_func notify, - XID resource); -cairo_private void -_cairo_xlib_display_notify (cairo_xlib_display_t *display); - -cairo_private XRenderPictFormat * -_cairo_xlib_display_get_xrender_format (cairo_xlib_display_t *display, - cairo_format_t format); - -cairo_private cairo_xlib_screen_info_t * -_cairo_xlib_screen_info_get (cairo_xlib_display_t *display, Screen *screen); - -cairo_private cairo_xlib_screen_info_t * -_cairo_xlib_screen_info_reference (cairo_xlib_screen_info_t *info); -cairo_private void -_cairo_xlib_screen_info_destroy (cairo_xlib_screen_info_t *info); - -cairo_private void -_cairo_xlib_screen_info_close_display (cairo_xlib_screen_info_t *info); - -cairo_private GC -_cairo_xlib_screen_get_gc (cairo_xlib_screen_info_t *info, int depth); -cairo_private cairo_status_t -_cairo_xlib_screen_put_gc (cairo_xlib_screen_info_t *info, int depth, GC gc, cairo_bool_t reset_clip); - -cairo_private cairo_status_t -_cairo_xlib_screen_get_visual_info (cairo_xlib_screen_info_t *info, - Visual *visual, - cairo_xlib_visual_info_t **out); - -cairo_private cairo_status_t -_cairo_xlib_visual_info_create (Display *dpy, - int screen, - VisualID visualid, - cairo_xlib_visual_info_t **out); - -cairo_private void -_cairo_xlib_visual_info_destroy (Display *dpy, cairo_xlib_visual_info_t *info); - -#endif /* CAIRO_XLIB_PRIVATE_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-xlib-screen.c b/uppdev/plugin/cairo/lib/cairo-xlib-screen.c deleted file mode 100644 index f670b8ae7..000000000 --- a/uppdev/plugin/cairo/lib/cairo-xlib-screen.c +++ /dev/null @@ -1,504 +0,0 @@ -/* Cairo - a vector graphics library with display and print output - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * 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-xlib-private.h" -#include "cairo-xlib-xrender-private.h" - -#include - -static int -parse_boolean (const char *v) -{ - char c0, c1; - - c0 = *v; - if (c0 == 't' || c0 == 'T' || c0 == 'y' || c0 == 'Y' || c0 == '1') - return 1; - if (c0 == 'f' || c0 == 'F' || c0 == 'n' || c0 == 'N' || c0 == '0') - return 0; - if (c0 == 'o') - { - c1 = v[1]; - if (c1 == 'n' || c1 == 'N') - return 1; - if (c1 == 'f' || c1 == 'F') - return 0; - } - - return -1; -} - -static cairo_bool_t -get_boolean_default (Display *dpy, - const char *option, - cairo_bool_t *value) -{ - char *v; - int i; - - v = XGetDefault (dpy, "Xft", option); - if (v) { - i = parse_boolean (v); - if (i >= 0) { - *value = i; - return TRUE; - } - } - - return FALSE; -} - -static cairo_bool_t -get_integer_default (Display *dpy, - const char *option, - int *value) -{ - char *v, *e; - - v = XGetDefault (dpy, "Xft", option); - if (v) { -#if CAIRO_HAS_FT_FONT - if (FcNameConstant ((FcChar8 *) v, value)) - return TRUE; -#endif - - *value = strtol (v, &e, 0); - if (e != v) - return TRUE; - } - - return FALSE; -} - -/* Old versions of fontconfig didn't have these options */ -#ifndef FC_HINT_NONE -#define FC_HINT_NONE 0 -#define FC_HINT_SLIGHT 1 -#define FC_HINT_MEDIUM 2 -#define FC_HINT_FULL 3 -#endif - -/* Fontconfig version older than 2.6 didn't have these options */ -#ifndef FC_LCD_FILTER -#define FC_LCD_FILTER "lcdfilter" -#endif -/* Some Ubuntu versions defined FC_LCD_FILTER without defining the following */ -#ifndef FC_LCD_NONE -#define FC_LCD_NONE 0 -#define FC_LCD_DEFAULT 1 -#define FC_LCD_LIGHT 2 -#define FC_LCD_LEGACY 3 -#endif - -static void -_cairo_xlib_init_screen_font_options (Display *dpy, cairo_xlib_screen_info_t *info) -{ - cairo_bool_t xft_hinting; - cairo_bool_t xft_antialias; - int xft_hintstyle; - int xft_rgba; - cairo_antialias_t antialias; - cairo_subpixel_order_t subpixel_order; - cairo_hint_style_t hint_style; - - if (!get_boolean_default (dpy, "antialias", &xft_antialias)) - xft_antialias = TRUE; - - if (!get_boolean_default (dpy, "hinting", &xft_hinting)) - xft_hinting = TRUE; - - if (!get_integer_default (dpy, "hintstyle", &xft_hintstyle)) - xft_hintstyle = FC_HINT_FULL; - - if (!get_integer_default (dpy, "rgba", &xft_rgba)) - { - xft_rgba = FC_RGBA_UNKNOWN; - -#if RENDER_MAJOR > 0 || RENDER_MINOR >= 6 - if (info->has_render) - { - int render_order = XRenderQuerySubpixelOrder (dpy, - XScreenNumberOfScreen (info->screen)); - - switch (render_order) - { - default: - case SubPixelUnknown: - xft_rgba = FC_RGBA_UNKNOWN; - break; - case SubPixelHorizontalRGB: - xft_rgba = FC_RGBA_RGB; - break; - case SubPixelHorizontalBGR: - xft_rgba = FC_RGBA_BGR; - break; - case SubPixelVerticalRGB: - xft_rgba = FC_RGBA_VRGB; - break; - case SubPixelVerticalBGR: - xft_rgba = FC_RGBA_VBGR; - break; - case SubPixelNone: - xft_rgba = FC_RGBA_NONE; - break; - } - } -#endif - } - - if (xft_hinting) { - switch (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 (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; - } - - if (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 (&info->font_options, hint_style); - cairo_font_options_set_antialias (&info->font_options, antialias); - cairo_font_options_set_subpixel_order (&info->font_options, subpixel_order); - cairo_font_options_set_hint_metrics (&info->font_options, CAIRO_HINT_METRICS_ON); -} - -cairo_xlib_screen_info_t * -_cairo_xlib_screen_info_reference (cairo_xlib_screen_info_t *info) -{ - assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&info->ref_count)); - - _cairo_reference_count_inc (&info->ref_count); - - return info; -} - -void -_cairo_xlib_screen_info_close_display (cairo_xlib_screen_info_t *info) -{ - cairo_xlib_visual_info_t **visuals; - int i; - - CAIRO_MUTEX_LOCK (info->mutex); - for (i = 0; i < ARRAY_LENGTH (info->gc); i++) { - if (info->gc[i] != NULL) { - XFreeGC (info->display->display, info->gc[i]); - info->gc[i] = NULL; - } - } - - visuals = _cairo_array_index (&info->visuals, 0); - for (i = 0; i < _cairo_array_num_elements (&info->visuals); i++) - _cairo_xlib_visual_info_destroy (info->display->display, visuals[i]); - _cairo_array_truncate (&info->visuals, 0); - - CAIRO_MUTEX_UNLOCK (info->mutex); -} - -void -_cairo_xlib_screen_info_destroy (cairo_xlib_screen_info_t *info) -{ - cairo_xlib_screen_info_t **prev; - cairo_xlib_screen_info_t *list; - - assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&info->ref_count)); - - if (! _cairo_reference_count_dec_and_test (&info->ref_count)) - return; - - CAIRO_MUTEX_LOCK (info->display->mutex); - for (prev = &info->display->screens; (list = *prev); prev = &list->next) { - if (list == info) { - *prev = info->next; - break; - } - } - CAIRO_MUTEX_UNLOCK (info->display->mutex); - - _cairo_xlib_screen_info_close_display (info); - - _cairo_xlib_display_destroy (info->display); - - _cairo_array_fini (&info->visuals); - - CAIRO_MUTEX_FINI (info->mutex); - - free (info); -} - -cairo_xlib_screen_info_t * -_cairo_xlib_screen_info_get (cairo_xlib_display_t *display, Screen *screen) -{ - cairo_xlib_screen_info_t *info = NULL, **prev; - - CAIRO_MUTEX_LOCK (display->mutex); - if (display->closed) { - CAIRO_MUTEX_UNLOCK (display->mutex); - return NULL; - } - - for (prev = &display->screens; (info = *prev); prev = &(*prev)->next) { - if (info->screen == screen) { - /* - * MRU the list - */ - if (prev != &display->screens) { - *prev = info->next; - info->next = display->screens; - display->screens = info; - } - break; - } - } - CAIRO_MUTEX_UNLOCK (display->mutex); - - if (info != NULL) { - info = _cairo_xlib_screen_info_reference (info); - } else { - info = malloc (sizeof (cairo_xlib_screen_info_t)); - if (info != NULL) { - CAIRO_REFERENCE_COUNT_INIT (&info->ref_count, 2); /* Add one for display cache */ - CAIRO_MUTEX_INIT (info->mutex); - info->display = _cairo_xlib_display_reference (display); - info->screen = screen; - info->has_render = FALSE; - _cairo_font_options_init_default (&info->font_options); - memset (info->gc, 0, sizeof (info->gc)); - info->gc_needs_clip_reset = 0; - - _cairo_array_init (&info->visuals, - sizeof (cairo_xlib_visual_info_t*)); - - if (screen) { - Display *dpy = display->display; - int event_base, error_base; - - info->has_render = (XRenderQueryExtension (dpy, &event_base, &error_base) && - (XRenderFindVisualFormat (dpy, DefaultVisual (dpy, DefaultScreen (dpy))) != 0)); - _cairo_xlib_init_screen_font_options (dpy, info); - } - - CAIRO_MUTEX_LOCK (display->mutex); - info->next = display->screens; - display->screens = info; - CAIRO_MUTEX_UNLOCK (display->mutex); - } - } - - return info; -} - -static int -depth_to_index (int depth) -{ - switch(depth){ - case 1: return 1; - case 8: return 2; - case 12: return 3; - case 15: return 4; - case 16: return 5; - case 24: return 6; - case 30: return 7; - case 32: return 8; - } - return 0; -} - -GC -_cairo_xlib_screen_get_gc (cairo_xlib_screen_info_t *info, int depth) -{ - GC gc; - cairo_bool_t needs_reset; - - depth = depth_to_index (depth); - - CAIRO_MUTEX_LOCK (info->mutex); - gc = info->gc[depth]; - info->gc[depth] = NULL; - needs_reset = info->gc_needs_clip_reset & (1 << depth); - info->gc_needs_clip_reset &= ~(1 << depth); - CAIRO_MUTEX_UNLOCK (info->mutex); - - if (needs_reset) - XSetClipMask(info->display->display, gc, None); - - return gc; -} - -cairo_status_t -_cairo_xlib_screen_put_gc (cairo_xlib_screen_info_t *info, int depth, GC gc, cairo_bool_t reset_clip) -{ - cairo_status_t status = CAIRO_STATUS_SUCCESS; - GC oldgc; - - depth = depth_to_index (depth); - - CAIRO_MUTEX_LOCK (info->mutex); - oldgc = info->gc[depth]; - info->gc[depth] = gc; - if (reset_clip) - info->gc_needs_clip_reset |= 1 << depth; - else - info->gc_needs_clip_reset &= ~(1 << depth); - CAIRO_MUTEX_UNLOCK (info->mutex); - - if (oldgc != NULL) { - status = _cairo_xlib_display_queue_work (info->display, - (cairo_xlib_notify_func) XFreeGC, - oldgc, - NULL); - } - - return status; -} - -cairo_status_t -_cairo_xlib_screen_get_visual_info (cairo_xlib_screen_info_t *info, - Visual *visual, - cairo_xlib_visual_info_t **out) -{ - Display *dpy = info->display->display; - cairo_xlib_visual_info_t **visuals, *ret = NULL; - cairo_status_t status; - int i, n_visuals; - - CAIRO_MUTEX_LOCK (info->mutex); - visuals = _cairo_array_index (&info->visuals, 0); - n_visuals = _cairo_array_num_elements (&info->visuals); - for (i = 0; i < n_visuals; i++) { - if (visuals[i]->visualid == visual->visualid) { - ret = visuals[i]; - break; - } - } - CAIRO_MUTEX_UNLOCK (info->mutex); - - if (ret != NULL) { - *out = ret; - return CAIRO_STATUS_SUCCESS; - } - - status = _cairo_xlib_visual_info_create (dpy, - XScreenNumberOfScreen (info->screen), - visual->visualid, - &ret); - if (status) - return status; - - CAIRO_MUTEX_LOCK (info->mutex); - if (n_visuals != _cairo_array_num_elements (&info->visuals)) { - /* check that another thread has not added our visual */ - int new_visuals = _cairo_array_num_elements (&info->visuals); - visuals = _cairo_array_index (&info->visuals, 0); - for (i = n_visuals; i < new_visuals; i++) { - if (visuals[i]->visualid == visual->visualid) { - _cairo_xlib_visual_info_destroy (dpy, ret); - ret = visuals[i]; - break; - } - } - if (i == new_visuals) - status = _cairo_array_append (&info->visuals, &ret); - } else - status = _cairo_array_append (&info->visuals, &ret); - CAIRO_MUTEX_UNLOCK (info->mutex); - - if (status) { - _cairo_xlib_visual_info_destroy (dpy, ret); - return status; - } - - *out = ret; - return CAIRO_STATUS_SUCCESS; -} diff --git a/uppdev/plugin/cairo/lib/cairo-xlib-surface-private.h b/uppdev/plugin/cairo/lib/cairo-xlib-surface-private.h deleted file mode 100644 index e06fd978c..000000000 --- a/uppdev/plugin/cairo/lib/cairo-xlib-surface-private.h +++ /dev/null @@ -1,109 +0,0 @@ -/* Cairo - a vector graphics library with display and print output - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - */ - -#ifndef CAIRO_XLIB_SURFACE_PRIVATE_H -#define CAIRO_XLIB_SURFACE_PRIVATE_H - -#include "cairo-xlib.h" -#include "cairo-xlib-private.h" -#include "cairo-xlib-xrender-private.h" - -#include "cairo-surface-private.h" - -typedef struct _cairo_xlib_surface cairo_xlib_surface_t; - -struct _cairo_xlib_surface { - cairo_surface_t base; - - Display *dpy; - cairo_xlib_display_t *display; - cairo_xlib_screen_info_t *screen_info; - cairo_xlib_hook_t close_display_hook; - - GC gc; - Drawable drawable; - Screen *screen; - cairo_bool_t owns_pixmap; - Visual *visual; - - int use_pixmap; - - int render_major; - int render_minor; - - /* TRUE if the server has a bug with repeating pictures - * - * https://bugs.freedesktop.org/show_bug.cgi?id=3566 - * - * We can't test for this because it depends on whether the - * picture is in video memory or not. - * - * We also use this variable as a guard against a second - * independent bug with transformed repeating pictures: - * - * http://lists.freedesktop.org/archives/cairo/2004-September/001839.html - * - * Both are fixed in xorg >= 6.9 and hopefully in > 6.8.2, so - * we can reuse the test for now. - */ - cairo_bool_t buggy_repeat; - - int width; - int height; - int depth; - - Picture dst_picture, src_picture; - - unsigned int clip_dirty; - cairo_bool_t have_clip_rects; - XRectangle embedded_clip_rects[4]; - XRectangle *clip_rects; - int num_clip_rects; - - XRenderPictFormat *xrender_format; - cairo_filter_t filter; - int repeat; - XTransform xtransform; - - uint32_t a_mask; - uint32_t r_mask; - uint32_t g_mask; - uint32_t b_mask; -}; - -enum { - CAIRO_XLIB_SURFACE_CLIP_DIRTY_GC = 0x01, - CAIRO_XLIB_SURFACE_CLIP_DIRTY_PICTURE = 0x02, - CAIRO_XLIB_SURFACE_CLIP_DIRTY_ALL = 0x03 -}; - -#endif /* CAIRO_XLIB_SURFACE_PRIVATE_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-xlib-surface.c b/uppdev/plugin/cairo/lib/cairo-xlib-surface.c deleted file mode 100644 index ba38f5d8b..000000000 --- a/uppdev/plugin/cairo/lib/cairo-xlib-surface.c +++ /dev/null @@ -1,4075 +0,0 @@ -/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - * Behdad Esfahbod - * Chris Wilson - * Karl Tomlinson , Mozilla Corporation - */ - -#include "cairoint.h" - -#include "cairo-xlib-private.h" -#include "cairo-xlib-surface-private.h" -#include "cairo-clip-private.h" -#include "cairo-scaled-font-private.h" - -#include /* for XDestroyImage */ - -#define XLIB_COORD_MAX 32767 - -/* Xlib doesn't define a typedef, so define one ourselves */ -typedef int (*cairo_xlib_error_func_t) (Display *display, - XErrorEvent *event); - -static cairo_surface_t * -_cairo_xlib_surface_create_internal (Display *dpy, - Drawable drawable, - Screen *screen, - Visual *visual, - XRenderPictFormat *xrender_format, - int width, - int height, - int depth); - -static cairo_status_t -_cairo_xlib_surface_ensure_gc (cairo_xlib_surface_t *surface); - -static void -_cairo_xlib_surface_ensure_src_picture (cairo_xlib_surface_t *surface); - -static void -_cairo_xlib_surface_ensure_dst_picture (cairo_xlib_surface_t *surface); - -static cairo_bool_t -_cairo_surface_is_xlib (cairo_surface_t *surface); - -static cairo_bool_t -_native_byte_order_lsb (void); - -static cairo_int_status_t -_cairo_xlib_surface_show_glyphs (void *abstract_dst, - cairo_operator_t op, - cairo_pattern_t *src_pattern, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font, - int *remaining_glyphs); - -/* - * Instead of taking two round trips for each blending request, - * assume that if a particular drawable fails GetImage that it will - * fail for a "while"; use temporary pixmaps to avoid the errors - */ - -#define CAIRO_ASSUME_PIXMAP 20 - -static const XTransform identity = { { - { 1 << 16, 0x00000, 0x00000 }, - { 0x00000, 1 << 16, 0x00000 }, - { 0x00000, 0x00000, 1 << 16 }, -} }; - -#define CAIRO_SURFACE_RENDER_AT_LEAST(surface, major, minor) \ - (((surface)->render_major > major) || \ - (((surface)->render_major == major) && ((surface)->render_minor >= minor))) - -#define CAIRO_SURFACE_RENDER_HAS_CREATE_PICTURE(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 0) -#define CAIRO_SURFACE_RENDER_HAS_COMPOSITE(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 0) -#define CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 0) - -#define CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLES(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 1) - -#define CAIRO_SURFACE_RENDER_HAS_DISJOINT(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 2) -#define CAIRO_SURFACE_RENDER_HAS_CONJOINT(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 2) - -#define CAIRO_SURFACE_RENDER_HAS_TRAPEZOIDS(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 4) -#define CAIRO_SURFACE_RENDER_HAS_TRIANGLES(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 4) -#define CAIRO_SURFACE_RENDER_HAS_TRISTRIP(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 4) -#define CAIRO_SURFACE_RENDER_HAS_TRIFAN(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 4) - -#define CAIRO_SURFACE_RENDER_HAS_PICTURE_TRANSFORM(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 6) -#define CAIRO_SURFACE_RENDER_HAS_FILTERS(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 6) - -static cairo_surface_t * -_cairo_xlib_surface_create_similar_with_format (void *abstract_src, - cairo_format_t format, - int width, - int height) -{ - cairo_xlib_surface_t *src = abstract_src; - Display *dpy = src->dpy; - Pixmap pix; - cairo_xlib_surface_t *surface; - XRenderPictFormat *xrender_format; - - if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX) - return NULL; - - /* As a good first approximation, if the display doesn't have even - * the most elementary RENDER operation, then we're better off - * using image surfaces for all temporary operations, so return NULL - * and let the fallback code happen. - */ - if (! CAIRO_SURFACE_RENDER_HAS_COMPOSITE (src)) - return NULL; - - xrender_format = _cairo_xlib_display_get_xrender_format ( - src->display, - format); - if (xrender_format == NULL) - return NULL; - - pix = XCreatePixmap (dpy, src->drawable, - width <= 0 ? 1 : width, height <= 0 ? 1 : height, - xrender_format->depth); - - surface = (cairo_xlib_surface_t *) - _cairo_xlib_surface_create_internal (dpy, pix, - src->screen, NULL, - xrender_format, - width, height, - xrender_format->depth); - if (surface->base.status) { - XFreePixmap (dpy, pix); - return &surface->base; - } - - surface->owns_pixmap = TRUE; - - return &surface->base; -} - -static cairo_content_t -_xrender_format_to_content (XRenderPictFormat *xrender_format) -{ - cairo_bool_t xrender_format_has_alpha; - cairo_bool_t xrender_format_has_color; - - /* This only happens when using a non-Render server. Let's punt - * and say there's no alpha here. */ - if (xrender_format == NULL) - return CAIRO_CONTENT_COLOR; - - xrender_format_has_alpha = (xrender_format->direct.alphaMask != 0); - xrender_format_has_color = (xrender_format->direct.redMask != 0 || - xrender_format->direct.greenMask != 0 || - xrender_format->direct.blueMask != 0); - - if (xrender_format_has_alpha) - if (xrender_format_has_color) - return CAIRO_CONTENT_COLOR_ALPHA; - else - return CAIRO_CONTENT_ALPHA; - else - return CAIRO_CONTENT_COLOR; -} - -static cairo_surface_t * -_cairo_xlib_surface_create_similar (void *abstract_src, - cairo_content_t content, - int width, - int height) -{ - cairo_xlib_surface_t *src = abstract_src; - XRenderPictFormat *xrender_format = src->xrender_format; - cairo_xlib_surface_t *surface; - Pixmap pix; - - if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX) - return _cairo_surface_create_in_error (_cairo_error(CAIRO_STATUS_NO_MEMORY)); - - _cairo_xlib_display_notify (src->display); - - /* Start by examining the surface's XRenderFormat, or if it - * doesn't have one, then look one up through its visual (in the - * case of a bitmap, it won't even have that). */ - if (xrender_format == NULL && src->visual != NULL) - xrender_format = XRenderFindVisualFormat (src->dpy, src->visual); - - /* If we never found an XRenderFormat or if it isn't compatible - * with the content being requested, then we fallback to just - * constructing a cairo_format_t instead, (which will fairly - * arbitrarily pick a visual/depth for the similar surface. - */ - if (xrender_format == NULL || - _xrender_format_to_content (xrender_format) != content) - { - return _cairo_xlib_surface_create_similar_with_format (abstract_src, - _cairo_format_from_content (content), - width, height); - } - - /* We've got a compatible XRenderFormat now, which means the - * similar surface will match the existing surface as closely in - * visual/depth etc. as possible. */ - pix = XCreatePixmap (src->dpy, src->drawable, - width <= 0 ? 1 : width, height <= 0 ? 1 : height, - xrender_format->depth); - - surface = (cairo_xlib_surface_t *) - _cairo_xlib_surface_create_internal (src->dpy, pix, - src->screen, src->visual, - xrender_format, - width, height, - xrender_format->depth); - if (surface->base.status != CAIRO_STATUS_SUCCESS) { - XFreePixmap (src->dpy, pix); - return &surface->base; - } - - surface->owns_pixmap = TRUE; - - return &surface->base; -} - -static cairo_status_t -_cairo_xlib_surface_finish (void *abstract_surface) -{ - cairo_xlib_surface_t *surface = abstract_surface; - cairo_xlib_display_t *display = surface->display; - cairo_status_t status = CAIRO_STATUS_SUCCESS; - - if (surface->owns_pixmap) { - cairo_status_t status2; - - if (surface->dst_picture != None) { - status2 = _cairo_xlib_display_queue_resource (display, - XRenderFreePicture, - surface->dst_picture); - if (status2 == CAIRO_STATUS_SUCCESS) - surface->dst_picture = None; - else if (status == CAIRO_STATUS_SUCCESS) - status = status2; - } - - if (surface->src_picture != None) { - status2 = _cairo_xlib_display_queue_resource (display, - XRenderFreePicture, - surface->src_picture); - if (status2 == CAIRO_STATUS_SUCCESS) - surface->src_picture = None; - else if (status == CAIRO_STATUS_SUCCESS) - status = status2; - } - - status2 = _cairo_xlib_display_queue_resource (display, - (cairo_xlib_notify_resource_func) XFreePixmap, - surface->drawable); - if (status2 == CAIRO_STATUS_SUCCESS) { - surface->owns_pixmap = FALSE; - surface->drawable = None; - } else if (status == CAIRO_STATUS_SUCCESS) - status = status2; - } else { - if (surface->dst_picture != None) - XRenderFreePicture (surface->dpy, surface->dst_picture); - - if (surface->src_picture != None) - XRenderFreePicture (surface->dpy, surface->src_picture); - } - - if (surface->gc != NULL) { - cairo_status_t status2; - status2 = _cairo_xlib_screen_put_gc (surface->screen_info, - surface->depth, - surface->gc, - surface->have_clip_rects); - surface->gc = NULL; - if (status == CAIRO_STATUS_SUCCESS) - status = status2; - } - - if (surface->clip_rects != surface->embedded_clip_rects) - free (surface->clip_rects); - - if (surface->screen_info != NULL) - _cairo_xlib_screen_info_destroy (surface->screen_info); - - if (surface->display != NULL) { - _cairo_xlib_remove_close_display_hook (surface->display, - &surface->close_display_hook); - _cairo_xlib_display_destroy (surface->display); - } - - surface->dpy = NULL; - - return status; -} - -static int -_noop_error_handler (Display *display, - XErrorEvent *event) -{ - return False; /* return value is ignored */ -} - -static void -_swap_ximage_2bytes (XImage *ximage) -{ - int i, j; - char *line = ximage->data; - - for (j = ximage->height; j; j--) { - uint16_t *p = (uint16_t *) line; - for (i = ximage->width; i; i--) { - *p = bswap_16 (*p); - p++; - } - - line += ximage->bytes_per_line; - } -} - -static void -_swap_ximage_3bytes (XImage *ximage) -{ - int i, j; - char *line = ximage->data; - - for (j = ximage->height; j; j--) { - uint8_t *p = (uint8_t *) line; - for (i = ximage->width; i; i--) { - uint8_t tmp; - tmp = p[2]; - p[2] = p[0]; - p[0] = tmp; - p += 3; - } - - line += ximage->bytes_per_line; - } -} - -static void -_swap_ximage_4bytes (XImage *ximage) -{ - int i, j; - char *line = ximage->data; - - for (j = ximage->height; j; j--) { - uint32_t *p = (uint32_t *) line; - for (i = ximage->width; i; i--) { - *p = bswap_32 (*p); - p++; - } - - line += ximage->bytes_per_line; - } -} - -static void -_swap_ximage_nibbles (XImage *ximage) -{ - int i, j; - char *line = ximage->data; - - for (j = ximage->height; j; j--) { - uint8_t *p = (uint8_t *) line; - for (i = (ximage->width + 1) / 2; i; i--) { - *p = ((*p >> 4) & 0xf) | ((*p << 4) & ~0xf); - p++; - } - - line += ximage->bytes_per_line; - } -} - -static void -_swap_ximage_bits (XImage *ximage) -{ - int i, j; - char *line = ximage->data; - int unit = ximage->bitmap_unit; - int line_bytes = ((ximage->width + unit - 1) & ~(unit - 1)) / 8; - - for (j = ximage->height; j; j--) { - char *p = line; - - for (i = line_bytes; i; i--) { - char b = *p; - b = ((b << 1) & 0xaa) | ((b >> 1) & 0x55); - b = ((b << 2) & 0xcc) | ((b >> 2) & 0x33); - b = ((b << 4) & 0xf0) | ((b >> 4) & 0x0f); - *p = b; - - p++; - } - - line += ximage->bytes_per_line; - } -} - -static void -_swap_ximage_to_native (XImage *ximage) -{ - int unit_bytes = 0; - int native_byte_order = _native_byte_order_lsb () ? LSBFirst : MSBFirst; - - if (ximage->bits_per_pixel == 1 && - ximage->bitmap_bit_order != native_byte_order) - { - _swap_ximage_bits (ximage); - if (ximage->bitmap_bit_order == ximage->byte_order) - return; - } - - if (ximage->byte_order == native_byte_order) - return; - - switch (ximage->bits_per_pixel) { - case 1: - unit_bytes = ximage->bitmap_unit / 8; - break; - case 4: - _swap_ximage_nibbles (ximage); - /* fall-through */ - case 8: - case 16: - case 20: - case 24: - case 28: - case 30: - case 32: - unit_bytes = (ximage->bits_per_pixel + 7) / 8; - break; - default: - /* This could be hit on some rare but possible cases. */ - ASSERT_NOT_REACHED; - } - - switch (unit_bytes) { - case 1: - break; - case 2: - _swap_ximage_2bytes (ximage); - break; - case 3: - _swap_ximage_3bytes (ximage); - break; - case 4: - _swap_ximage_4bytes (ximage); - break; - default: - ASSERT_NOT_REACHED; - } -} - - -/* Given a mask, (with a single sequence of contiguous 1 bits), return - * the number of 1 bits in 'width' and the number of 0 bits to its - * right in 'shift'. */ -static void -_characterize_field (uint32_t mask, int *width, int *shift) -{ - *width = _cairo_popcount (mask); - /* The final '& 31' is to force a 0 mask to result in 0 shift. */ - *shift = _cairo_popcount ((mask - 1) & ~mask) & 31; -} - - -/* Convert a field of 'width' bits to 'new_width' bits with correct - * rounding. */ -static inline uint32_t -_resize_field (uint32_t field, int width, int new_width) -{ - if (width == 0) - return 0; - - if (width >= new_width) { - return field >> (width - new_width); - } else { - uint32_t result = field << (new_width - width); - - while (width < new_width) { - result |= result >> width; - width <<= 1; - } - return result; - } -} - -static inline uint32_t -_adjust_field (uint32_t field, int adjustment) -{ - return MIN (255, MAX(0, (int)field + adjustment)); -} - -/* Given a shifted field value, (described by 'width' and 'shift), - * resize it 8-bits and return that value. - * - * Note that the original field value must not have any non-field bits - * set. - */ -static inline uint32_t -_field_to_8 (uint32_t field, int width, int shift) -{ - return _resize_field (field >> shift, width, 8); -} - -static inline uint32_t -_field_to_8_undither (uint32_t field, int width, int shift, - int dither_adjustment) -{ - return _adjust_field (_field_to_8 (field, width, shift), - dither_adjustment>>width); -} - -/* Given an 8-bit value, convert it to a field of 'width', shift it up - * to 'shift, and return it. */ -static inline uint32_t -_field_from_8 (uint32_t field, int width, int shift) -{ - return _resize_field (field, 8, width) << shift; -} - -static inline uint32_t -_field_from_8_dither (uint32_t field, int width, int shift, - int8_t dither_adjustment) -{ - return _field_from_8 (_adjust_field (field, dither_adjustment>>width), width, shift); -} - -static inline uint32_t -_pseudocolor_from_rgb888_dither (cairo_xlib_visual_info_t *visual_info, - uint32_t r, uint32_t g, uint32_t b, - int8_t dither_adjustment) -{ - if (r == g && g == b) { - dither_adjustment /= RAMP_SIZE; - return visual_info->gray8_to_pseudocolor[_adjust_field (r, dither_adjustment)]; - } else { - dither_adjustment = visual_info->dither8_to_cube[dither_adjustment+128]; - return visual_info->cube_to_pseudocolor[visual_info->field8_to_cube[_adjust_field (r, dither_adjustment)]] - [visual_info->field8_to_cube[_adjust_field (g, dither_adjustment)]] - [visual_info->field8_to_cube[_adjust_field (b, dither_adjustment)]]; - } -} - -static inline uint32_t -_pseudocolor_to_rgb888 (cairo_xlib_visual_info_t *visual_info, - uint32_t pixel) -{ - uint32_t r, g, b; - pixel &= 0xff; - r = visual_info->colors[pixel].r; - g = visual_info->colors[pixel].g; - b = visual_info->colors[pixel].b; - return (r << 16) | - (g << 8) | - (b ); -} - - -/* should range from -128 to 127 */ -#define X 16 -static const int8_t dither_pattern[4][4] = { - {-8*X, +0*X, -6*X, +2*X}, - {+4*X, -4*X, +6*X, -2*X}, - {-5*X, +4*X, -7*X, +1*X}, - {+7*X, -1*X, +5*X, -3*X} -}; -#undef X - - -static cairo_status_t -_get_image_surface (cairo_xlib_surface_t *surface, - cairo_rectangle_int_t *interest_rect, - cairo_image_surface_t **image_out, - cairo_rectangle_int_t *image_rect) -{ - cairo_int_status_t status; - cairo_image_surface_t *image = NULL; - XImage *ximage; - cairo_rectangle_int_t extents; - pixman_format_code_t pixman_format; - cairo_format_masks_t xlib_masks; - - extents.x = 0; - extents.y = 0; - extents.width = surface->width; - extents.height = surface->height; - - if (interest_rect) { - if (! _cairo_rectangle_intersect (&extents, interest_rect)) { - *image_out = NULL; - return CAIRO_STATUS_SUCCESS; - } - } - - if (image_rect) - *image_rect = extents; - - /* XXX: This should try to use the XShm extension if available */ - - if (surface->use_pixmap == 0) - { - cairo_xlib_error_func_t old_handler; - - old_handler = XSetErrorHandler (_noop_error_handler); - - ximage = XGetImage (surface->dpy, - surface->drawable, - extents.x, extents.y, - extents.width, extents.height, - AllPlanes, ZPixmap); - - XSetErrorHandler (old_handler); - - /* If we get an error, the surface must have been a window, - * so retry with the safe code path. - */ - if (!ximage) - surface->use_pixmap = CAIRO_ASSUME_PIXMAP; - } - else - { - surface->use_pixmap--; - ximage = NULL; - } - - if (!ximage) - { - - /* XGetImage from a window is dangerous because it can - * produce errors if the window is unmapped or partially - * outside the screen. We could check for errors and - * retry, but to keep things simple, we just create a - * temporary pixmap - */ - Pixmap pixmap; - cairo_status_t status = _cairo_xlib_surface_ensure_gc (surface); - if (status) - return status; - - pixmap = XCreatePixmap (surface->dpy, - surface->drawable, - extents.width, extents.height, - surface->depth); - if (pixmap) { - XCopyArea (surface->dpy, surface->drawable, pixmap, surface->gc, - extents.x, extents.y, - extents.width, extents.height, - 0, 0); - - ximage = XGetImage (surface->dpy, - pixmap, - 0, 0, - extents.width, extents.height, - AllPlanes, ZPixmap); - - XFreePixmap (surface->dpy, pixmap); - } - } - if (!ximage) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - _swap_ximage_to_native (ximage); - - xlib_masks.bpp = ximage->bits_per_pixel; - xlib_masks.alpha_mask = surface->a_mask; - xlib_masks.red_mask = surface->r_mask; - xlib_masks.green_mask = surface->g_mask; - xlib_masks.blue_mask = surface->b_mask; - - if (_pixman_format_from_masks (&xlib_masks, &pixman_format) && - xlib_masks.bpp >= 24 && - ximage->bitmap_unit == 32 && - ximage->bitmap_pad == 32) - { - image = (cairo_image_surface_t*) - _cairo_image_surface_create_with_pixman_format ((unsigned char *) ximage->data, - pixman_format, - ximage->width, - ximage->height, - ximage->bytes_per_line); - status = image->base.status; - if (status) - goto BAIL; - - /* Let the surface take ownership of the data */ - _cairo_image_surface_assume_ownership_of_data (image); - ximage->data = NULL; - } else { - /* The visual we are dealing with is not supported by the - * standard pixman formats. So we must first convert the data - * to a supported format. */ - - cairo_format_t format; - unsigned char *data; - uint32_t *row; - uint32_t in_pixel, out_pixel; - unsigned int rowstride; - uint32_t a_mask=0, r_mask=0, g_mask=0, b_mask=0; - int a_width=0, r_width=0, g_width=0, b_width=0; - int a_shift=0, r_shift=0, g_shift=0, b_shift=0; - int x, y, x0, y0, x_off, y_off; - cairo_xlib_visual_info_t *visual_info; - - if (surface->visual == NULL || surface->visual->class == TrueColor) { - cairo_bool_t has_alpha; - cairo_bool_t has_color; - - has_alpha = surface->a_mask; - has_color = (surface->r_mask || - surface->g_mask || - surface->b_mask); - - if (has_color) { - if (has_alpha) { - format = CAIRO_FORMAT_ARGB32; - } else { - format = CAIRO_FORMAT_RGB24; - } - } else { - /* XXX: Using CAIRO_FORMAT_A8 here would be more - * efficient, but would require slightly different code in - * the image conversion to put the alpha channel values - * into the right place. */ - format = CAIRO_FORMAT_ARGB32; - } - - a_mask = surface->a_mask; - r_mask = surface->r_mask; - g_mask = surface->g_mask; - b_mask = surface->b_mask; - - _characterize_field (a_mask, &a_width, &a_shift); - _characterize_field (r_mask, &r_width, &r_shift); - _characterize_field (g_mask, &g_width, &g_shift); - _characterize_field (b_mask, &b_width, &b_shift); - - } else { - format = CAIRO_FORMAT_RGB24; - - status = _cairo_xlib_screen_get_visual_info (surface->screen_info, - surface->visual, - &visual_info); - if (status) - goto BAIL; - } - - image = (cairo_image_surface_t *) cairo_image_surface_create - (format, ximage->width, ximage->height); - status = image->base.status; - if (status) - goto BAIL; - - data = cairo_image_surface_get_data (&image->base); - rowstride = cairo_image_surface_get_stride (&image->base) >> 2; - row = (uint32_t *) data; - x0 = extents.x + surface->base.device_transform.x0; - y0 = extents.y + surface->base.device_transform.y0; - for (y = 0, y_off = y0 % ARRAY_LENGTH (dither_pattern); - y < ximage->height; - y++, y_off = (y_off+1) % ARRAY_LENGTH (dither_pattern)) { - const int8_t *dither_row = dither_pattern[y_off]; - for (x = 0, x_off = x0 % ARRAY_LENGTH (dither_pattern[0]); - x < ximage->width; - x++, x_off = (x_off+1) % ARRAY_LENGTH (dither_pattern[0])) { - int dither_adjustment = dither_row[x_off]; - - in_pixel = XGetPixel (ximage, x, y); - if (surface->visual == NULL || surface->visual->class == TrueColor) { - out_pixel = ( - _field_to_8 (in_pixel & a_mask, a_width, a_shift) << 24 | - _field_to_8_undither (in_pixel & r_mask, r_width, r_shift, dither_adjustment) << 16 | - _field_to_8_undither (in_pixel & g_mask, g_width, g_shift, dither_adjustment) << 8 | - _field_to_8_undither (in_pixel & b_mask, b_width, b_shift, dither_adjustment)); - } else { - /* Undithering pseudocolor does not look better */ - out_pixel = _pseudocolor_to_rgb888 (visual_info, in_pixel); - } - row[x] = out_pixel; - } - row += rowstride; - } - } - - BAIL: - XDestroyImage (ximage); - - if (status) { - if (image) { - cairo_surface_destroy (&image->base); - image = NULL; - } - } - *image_out = image; - return status; -} - -static void -_cairo_xlib_surface_ensure_src_picture (cairo_xlib_surface_t *surface) -{ - if (!surface->src_picture) - { - XRenderPictureAttributes pa; - int mask = 0; - - pa.subwindow_mode = IncludeInferiors; - mask |= CPSubwindowMode; - - surface->src_picture = XRenderCreatePicture (surface->dpy, - surface->drawable, - surface->xrender_format, - mask, &pa); - } -} - -static void -_cairo_xlib_surface_set_picture_clip_rects (cairo_xlib_surface_t *surface) -{ - if (surface->have_clip_rects) { - XRenderSetPictureClipRectangles (surface->dpy, surface->dst_picture, - 0, 0, - surface->clip_rects, - surface->num_clip_rects); - } else { - XRenderPictureAttributes pa; - pa.clip_mask = None; - XRenderChangePicture (surface->dpy, surface->dst_picture, - CPClipMask, &pa); - } - - surface->clip_dirty &= ~CAIRO_XLIB_SURFACE_CLIP_DIRTY_PICTURE; -} - -static void -_cairo_xlib_surface_set_gc_clip_rects (cairo_xlib_surface_t *surface) -{ - if (surface->have_clip_rects) { - XSetClipRectangles(surface->dpy, surface->gc, - 0, 0, - surface->clip_rects, - surface->num_clip_rects, YXSorted); - } else - XSetClipMask (surface->dpy, surface->gc, None); - - surface->clip_dirty &= ~CAIRO_XLIB_SURFACE_CLIP_DIRTY_GC; -} - -static void -_cairo_xlib_surface_ensure_dst_picture (cairo_xlib_surface_t *surface) -{ - if (!surface->dst_picture) { - surface->dst_picture = XRenderCreatePicture (surface->dpy, - surface->drawable, - surface->xrender_format, - 0, NULL); - _cairo_xlib_surface_set_picture_clip_rects (surface); - } else if (surface->clip_dirty & CAIRO_XLIB_SURFACE_CLIP_DIRTY_PICTURE) - _cairo_xlib_surface_set_picture_clip_rects (surface); -} - -static cairo_status_t -_cairo_xlib_surface_ensure_gc (cairo_xlib_surface_t *surface) -{ - XGCValues gcv; - - if (surface->gc == NULL) { - surface->gc = _cairo_xlib_screen_get_gc (surface->screen_info, - surface->depth); - if (surface->gc == NULL) { - gcv.graphics_exposures = False; - surface->gc = XCreateGC (surface->dpy, surface->drawable, - GCGraphicsExposures, &gcv); - if (!surface->gc) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - _cairo_xlib_surface_set_gc_clip_rects (surface); - } else if (surface->clip_dirty & CAIRO_XLIB_SURFACE_CLIP_DIRTY_GC) - _cairo_xlib_surface_set_gc_clip_rects (surface); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_draw_image_surface (cairo_xlib_surface_t *surface, - cairo_image_surface_t *image, - int src_x, - int src_y, - int width, - int height, - int dst_x, - int dst_y) -{ - XImage ximage; - cairo_format_masks_t image_masks; - int native_byte_order = _native_byte_order_lsb () ? LSBFirst : MSBFirst; - cairo_status_t status; - cairo_bool_t own_data; - - _pixman_format_to_masks (image->pixman_format, &image_masks); - - ximage.width = image->width; - ximage.height = image->height; - ximage.format = ZPixmap; - ximage.byte_order = native_byte_order; - ximage.bitmap_unit = 32; /* always for libpixman */ - ximage.bitmap_bit_order = native_byte_order; - ximage.bitmap_pad = 32; /* always for libpixman */ - ximage.depth = surface->depth; - ximage.red_mask = surface->r_mask; - ximage.green_mask = surface->g_mask; - ximage.blue_mask = surface->b_mask; - ximage.xoffset = 0; - - if (image_masks.red_mask == surface->r_mask && - image_masks.green_mask == surface->g_mask && - image_masks.blue_mask == surface->b_mask) - { - int ret; - - ximage.bits_per_pixel = image_masks.bpp; - ximage.bytes_per_line = image->stride; - ximage.data = (char *)image->data; - own_data = FALSE; - - ret = XInitImage (&ximage); - assert (ret != 0); - } else { - unsigned int stride, rowstride; - int x, y, x0, y0, x_off, y_off; - uint32_t in_pixel, out_pixel, *row; - int i_a_width=0, i_r_width=0, i_g_width=0, i_b_width=0; - int i_a_shift=0, i_r_shift=0, i_g_shift=0, i_b_shift=0; - int o_a_width=0, o_r_width=0, o_g_width=0, o_b_width=0; - int o_a_shift=0, o_r_shift=0, o_g_shift=0, o_b_shift=0; - cairo_xlib_visual_info_t *visual_info = NULL; - cairo_bool_t true_color; - int ret; - - if (surface->depth > 16) { - ximage.bits_per_pixel = 32; - } else if (surface->depth > 8) { - ximage.bits_per_pixel = 16; - } else if (surface->depth > 1) { - ximage.bits_per_pixel = 8; - } else { - ximage.bits_per_pixel = 1; - } - stride = CAIRO_STRIDE_FOR_WIDTH_BPP (ximage.width, - ximage.bits_per_pixel); - ximage.bytes_per_line = stride; - ximage.data = _cairo_malloc_ab (stride, ximage.height); - if (ximage.data == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - own_data = TRUE; - - ret = XInitImage (&ximage); - assert (ret != 0); - - _characterize_field (image_masks.alpha_mask, &i_a_width, &i_a_shift); - _characterize_field (image_masks.red_mask , &i_r_width, &i_r_shift); - _characterize_field (image_masks.green_mask, &i_g_width, &i_g_shift); - _characterize_field (image_masks.blue_mask , &i_b_width, &i_b_shift); - - true_color = surface->visual == NULL || - surface->visual->class == TrueColor; - if (true_color) { - _characterize_field (surface->a_mask, &o_a_width, &o_a_shift); - _characterize_field (surface->r_mask, &o_r_width, &o_r_shift); - _characterize_field (surface->g_mask, &o_g_width, &o_g_shift); - _characterize_field (surface->b_mask, &o_b_width, &o_b_shift); - } else { - status = _cairo_xlib_screen_get_visual_info (surface->screen_info, - surface->visual, - &visual_info); - if (status) - goto BAIL; - } - - rowstride = cairo_image_surface_get_stride (&image->base) >> 2; - row = (uint32_t *) cairo_image_surface_get_data (&image->base); - x0 = dst_x + surface->base.device_transform.x0; - y0 = dst_y + surface->base.device_transform.y0; - for (y = 0, y_off = y0 % ARRAY_LENGTH (dither_pattern); - y < ximage.height; - y++, y_off = (y_off+1) % ARRAY_LENGTH (dither_pattern)) - { - const int8_t *dither_row = dither_pattern[y_off]; - - for (x = 0, x_off = x0 % ARRAY_LENGTH (dither_pattern[0]); - x < ximage.width; - x++, x_off = (x_off+1) % ARRAY_LENGTH (dither_pattern[0])) - { - int dither_adjustment = dither_row[x_off]; - int a, r, g, b; - - if (image_masks.bpp <= 8) - in_pixel = ((uint8_t*)row)[x]; - else if (image_masks.bpp <= 16) - in_pixel = ((uint16_t*)row)[x]; - else - in_pixel = row[x]; - - /* If the incoming image has no alpha channel, then the input - * is opaque and the output should have the maximum alpha value. - * For all other channels, their absence implies 0. - */ - if (image_masks.alpha_mask == 0x0) - a = 0xff; - else - a = _field_to_8 (in_pixel & image_masks.alpha_mask, i_a_width, i_a_shift); - r = _field_to_8 (in_pixel & image_masks.red_mask , i_r_width, i_r_shift); - g = _field_to_8 (in_pixel & image_masks.green_mask, i_g_width, i_g_shift); - b = _field_to_8 (in_pixel & image_masks.blue_mask , i_b_width, i_b_shift); - - if (true_color) { - out_pixel = _field_from_8 (a, o_a_width, o_a_shift) | - _field_from_8_dither (r, o_r_width, o_r_shift, dither_adjustment) | - _field_from_8_dither (g, o_g_width, o_g_shift, dither_adjustment) | - _field_from_8_dither (b, o_b_width, o_b_shift, dither_adjustment); - } else { - out_pixel = _pseudocolor_from_rgb888_dither (visual_info, r, g, b, dither_adjustment); - } - - XPutPixel (&ximage, x, y, out_pixel); - } - - row += rowstride; - } - } - - status = _cairo_xlib_surface_ensure_gc (surface); - if (status) - goto BAIL; - - XPutImage(surface->dpy, surface->drawable, surface->gc, - &ximage, src_x, src_y, dst_x, dst_y, - width, height); - - BAIL: - if (own_data) - free (ximage.data); - - return status; -} - -static cairo_status_t -_cairo_xlib_surface_acquire_source_image (void *abstract_surface, - cairo_image_surface_t **image_out, - void **image_extra) -{ - cairo_xlib_surface_t *surface = abstract_surface; - cairo_image_surface_t *image; - cairo_status_t status; - - _cairo_xlib_display_notify (surface->display); - - status = _get_image_surface (surface, NULL, &image, NULL); - if (status) - return status; - - *image_out = image; - *image_extra = NULL; - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_xlib_surface_release_source_image (void *abstract_surface, - cairo_image_surface_t *image, - void *image_extra) -{ - cairo_surface_destroy (&image->base); -} - -static cairo_status_t -_cairo_xlib_surface_acquire_dest_image (void *abstract_surface, - cairo_rectangle_int_t *interest_rect, - cairo_image_surface_t **image_out, - cairo_rectangle_int_t *image_rect_out, - void **image_extra) -{ - cairo_xlib_surface_t *surface = abstract_surface; - cairo_image_surface_t *image; - cairo_status_t status; - - _cairo_xlib_display_notify (surface->display); - - status = _get_image_surface (surface, interest_rect, &image, image_rect_out); - if (status) - return status; - - *image_out = image; - *image_extra = NULL; - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_xlib_surface_release_dest_image (void *abstract_surface, - cairo_rectangle_int_t *interest_rect, - cairo_image_surface_t *image, - cairo_rectangle_int_t *image_rect, - void *image_extra) -{ - cairo_xlib_surface_t *surface = abstract_surface; - cairo_status_t status; - - status = _draw_image_surface (surface, image, - 0, 0, image->width, image->height, - image_rect->x, image_rect->y); - status = _cairo_surface_set_error (&surface->base, status); - - cairo_surface_destroy (&image->base); -} - -/* - * Return whether two xlib surfaces share the same - * screen. Both core and Render drawing require this - * when using multiple drawables in an operation. - */ -static cairo_bool_t -_cairo_xlib_surface_same_screen (cairo_xlib_surface_t *dst, - cairo_xlib_surface_t *src) -{ - return dst->dpy == src->dpy && dst->screen == src->screen; -} - -static cairo_status_t -_cairo_xlib_surface_clone_similar (void *abstract_surface, - cairo_surface_t *src, - int src_x, - int src_y, - int width, - int height, - int *clone_offset_x, - int *clone_offset_y, - cairo_surface_t **clone_out) -{ - cairo_xlib_surface_t *surface = abstract_surface; - cairo_xlib_surface_t *clone; - cairo_status_t status; - - _cairo_xlib_display_notify (surface->display); - - if (src->backend == surface->base.backend ) { - cairo_xlib_surface_t *xlib_src = (cairo_xlib_surface_t *)src; - - if (_cairo_xlib_surface_same_screen (surface, xlib_src)) { - *clone_offset_x = 0; - *clone_offset_y = 0; - *clone_out = cairo_surface_reference (src); - - return CAIRO_STATUS_SUCCESS; - } - } else if (_cairo_surface_is_image (src)) { - cairo_image_surface_t *image_src = (cairo_image_surface_t *)src; - - if (! CAIRO_FORMAT_VALID (image_src->format)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - clone = (cairo_xlib_surface_t *) - _cairo_xlib_surface_create_similar_with_format (surface, - image_src->format, - width, height); - if (clone == NULL) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (clone->base.status) - return clone->base.status; - - status = _draw_image_surface (clone, image_src, - src_x, src_y, - width, height, - 0, 0); - if (status) { - cairo_surface_destroy (&clone->base); - return status; - } - - *clone_offset_x = src_x; - *clone_offset_y = src_y; - *clone_out = &clone->base; - - return CAIRO_STATUS_SUCCESS; - } - - return CAIRO_INT_STATUS_UNSUPPORTED; -} - -static cairo_surface_t * -_cairo_xlib_surface_create_solid_pattern_surface (void *abstract_surface, - cairo_solid_pattern_t *solid_pattern) -{ - /* This function's only responsibility is to create a proper surface - * for when XRender is not available. The proper surface is a xlib - * surface (as opposed to image surface which is what create_similar - * returns in those cases) and the size of the dithering pattern, not - * 1x1. This surface can then be used in - * _cairo_xlib_surface_solid_fill_rectangles() to do dithered "solid" - * fills using core protocol */ - - cairo_xlib_surface_t *other = abstract_surface; - cairo_image_surface_t *image; - cairo_xlib_surface_t *surface = NULL; - cairo_status_t status = CAIRO_STATUS_SUCCESS; - - int width = ARRAY_LENGTH (dither_pattern[0]); - int height = ARRAY_LENGTH (dither_pattern); - - Pixmap pixmap = None; - - if (CAIRO_SURFACE_RENDER_HAS_COMPOSITE (other)) - return NULL; - - if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX) - return NULL; - - image = (cairo_image_surface_t *) - _cairo_image_surface_create_with_content (solid_pattern->content, - width, height); - status = image->base.status; - if (status) - goto BAIL; - - pixmap = XCreatePixmap (other->dpy, - other->drawable, - width, height, - other->depth); - - surface = (cairo_xlib_surface_t *) - _cairo_xlib_surface_create_internal (other->dpy, - pixmap, - other->screen, other->visual, - other->xrender_format, - width, height, - other->depth); - status = surface->base.status; - if (status) - goto BAIL; - - status = _cairo_surface_paint (&image->base, - CAIRO_OPERATOR_SOURCE, - &solid_pattern->base); - if (status) - goto BAIL; - - status = _draw_image_surface (surface, image, - 0, 0, - width, height, - 0, 0); - if (status) - goto BAIL; - - BAIL: - cairo_surface_destroy (&image->base); - - if (status) { - if (pixmap != None) - XFreePixmap (other->dpy, pixmap); - cairo_surface_destroy (&surface->base); - - return _cairo_surface_create_in_error (status); - } - - surface->owns_pixmap = TRUE; - return &surface->base; -} - -static cairo_status_t -_cairo_xlib_surface_set_matrix (cairo_xlib_surface_t *surface, - cairo_matrix_t *matrix) -{ - XTransform xtransform; - - if (!surface->src_picture) - return CAIRO_STATUS_SUCCESS; - - /* Casting between pixman_transform_t and XTransform is safe because - * they happen to be the exact same type. - */ - _cairo_matrix_to_pixman_matrix (matrix, (pixman_transform_t *)&xtransform); - - if (memcmp (&xtransform, &surface->xtransform, sizeof (XTransform)) == 0) - return CAIRO_STATUS_SUCCESS; - - if (!CAIRO_SURFACE_RENDER_HAS_PICTURE_TRANSFORM (surface)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - XRenderSetPictureTransform (surface->dpy, surface->src_picture, &xtransform); - surface->xtransform = xtransform; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_xlib_surface_set_filter (cairo_xlib_surface_t *surface, - cairo_filter_t filter) -{ - const char *render_filter; - - if (!surface->src_picture) - return CAIRO_STATUS_SUCCESS; - - if (surface->filter == filter) - return CAIRO_STATUS_SUCCESS; - - if (!CAIRO_SURFACE_RENDER_HAS_FILTERS (surface)) - { - if (filter == CAIRO_FILTER_FAST || filter == CAIRO_FILTER_NEAREST) - return CAIRO_STATUS_SUCCESS; - - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - switch (filter) { - case CAIRO_FILTER_FAST: - render_filter = FilterFast; - break; - case CAIRO_FILTER_GOOD: - render_filter = FilterGood; - break; - case CAIRO_FILTER_BEST: - render_filter = FilterBest; - break; - case CAIRO_FILTER_NEAREST: - render_filter = FilterNearest; - break; - case CAIRO_FILTER_BILINEAR: - render_filter = FilterBilinear; - break; - case CAIRO_FILTER_GAUSSIAN: - /* XXX: The GAUSSIAN value has no implementation in cairo - * whatsoever, so it was really a mistake to have it in the - * API. We could fix this by officially deprecating it, or - * else inventing semantics and providing an actual - * implementation for it. */ - default: - render_filter = FilterBest; - break; - } - - XRenderSetPictureFilter (surface->dpy, surface->src_picture, - (char *) render_filter, NULL, 0); - surface->filter = filter; - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_xlib_surface_set_repeat (cairo_xlib_surface_t *surface, int repeat) -{ - XRenderPictureAttributes pa; - unsigned long mask; - - if (!surface->src_picture) - return; - - if (surface->repeat == repeat) - return; - - mask = CPRepeat; - pa.repeat = repeat; - - XRenderChangePicture (surface->dpy, surface->src_picture, mask, &pa); - surface->repeat = repeat; -} - -static cairo_int_status_t -_cairo_xlib_surface_set_attributes (cairo_xlib_surface_t *surface, - cairo_surface_attributes_t *attributes) -{ - cairo_int_status_t status; - - _cairo_xlib_surface_ensure_src_picture (surface); - - status = _cairo_xlib_surface_set_matrix (surface, &attributes->matrix); - if (status) - return status; - - switch (attributes->extend) { - case CAIRO_EXTEND_NONE: - _cairo_xlib_surface_set_repeat (surface, RepeatNone); - break; - case CAIRO_EXTEND_REPEAT: - _cairo_xlib_surface_set_repeat (surface, RepeatNormal); - break; - case CAIRO_EXTEND_REFLECT: - case CAIRO_EXTEND_PAD: - default: - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - status = _cairo_xlib_surface_set_filter (surface, attributes->filter); - if (status) - return status; - - return CAIRO_STATUS_SUCCESS; -} - -/* Checks whether we can can directly draw from src to dst with - * the core protocol: either with CopyArea or using src as a - * a tile in a GC. - */ -static cairo_bool_t -_surfaces_compatible (cairo_xlib_surface_t *dst, - cairo_xlib_surface_t *src) -{ - /* same screen */ - if (!_cairo_xlib_surface_same_screen (dst, src)) - return FALSE; - - /* same depth (for core) */ - if (src->depth != dst->depth) - return FALSE; - - /* if Render is supported, match picture formats */ - if (src->xrender_format != dst->xrender_format) - return FALSE; - else if (src->xrender_format != NULL) - return TRUE; - - /* Without Render, match visuals instead */ - if (src->visual == dst->visual) - return TRUE; - - return FALSE; -} - -static cairo_bool_t -_surface_has_alpha (cairo_xlib_surface_t *surface) -{ - if (surface->xrender_format) { - if (surface->xrender_format->type == PictTypeDirect && - surface->xrender_format->direct.alphaMask != 0) - return TRUE; - else - return FALSE; - } else { - - /* In the no-render case, we never have alpha */ - return FALSE; - } -} - -/* Returns true if the given operator and source-alpha combination - * requires alpha compositing to complete. - */ -static cairo_bool_t -_operator_needs_alpha_composite (cairo_operator_t op, - cairo_bool_t surface_has_alpha) -{ - if (op == CAIRO_OPERATOR_SOURCE || - (!surface_has_alpha && - (op == CAIRO_OPERATOR_OVER || - op == CAIRO_OPERATOR_ATOP || - op == CAIRO_OPERATOR_IN))) - return FALSE; - - return TRUE; -} - -/* There is a bug in most older X servers with compositing using a - * untransformed repeating source pattern when the source is in off-screen - * video memory, and another with repeated transformed images using a - * general transform matrix. When these bugs could be triggered, we need a - * fallback: in the common case where we have no transformation and the - * source and destination have the same format/visual, we can do the - * operation using the core protocol for the first bug, otherwise, we need - * a software fallback. - * - * We can also often optimize a compositing operation by calling XCopyArea - * for some common cases where there is no alpha compositing to be done. - * We figure that out here as well. - */ -typedef enum { - DO_RENDER, /* use render */ - DO_XCOPYAREA, /* core protocol XCopyArea optimization/fallback */ - DO_XTILE, /* core protocol XSetTile optimization/fallback */ - DO_UNSUPPORTED /* software fallback */ -} composite_operation_t; - -/* Initial check for the render bugs; we need to recheck for the - * offscreen-memory bug after we turn patterns into surfaces, since that - * may introduce a repeating pattern for gradient patterns. We don't need - * to check for the repeat+transform bug because gradient surfaces aren't - * transformed. - * - * All we do here is reject cases where we *know* are going to - * hit the bug and won't be able to use a core protocol fallback. - */ -static composite_operation_t -_categorize_composite_operation (cairo_xlib_surface_t *dst, - cairo_operator_t op, - cairo_pattern_t *src_pattern, - cairo_bool_t have_mask) - -{ - if (!dst->buggy_repeat) - return DO_RENDER; - - if (src_pattern->type == CAIRO_PATTERN_TYPE_SURFACE) - { - cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *)src_pattern; - - if (_cairo_matrix_is_integer_translation (&src_pattern->matrix, NULL, NULL) && - src_pattern->extend == CAIRO_EXTEND_REPEAT) - { - /* This is the case where we have the bug involving - * untransformed repeating source patterns with off-screen - * video memory; reject some cases where a core protocol - * fallback is impossible. - */ - if (have_mask || - !(op == CAIRO_OPERATOR_SOURCE || op == CAIRO_OPERATOR_OVER)) - return DO_UNSUPPORTED; - - if (_cairo_surface_is_xlib (surface_pattern->surface)) { - cairo_xlib_surface_t *src = (cairo_xlib_surface_t *)surface_pattern->surface; - - if (op == CAIRO_OPERATOR_OVER && _surface_has_alpha (src)) - return DO_UNSUPPORTED; - - /* If these are on the same screen but otherwise incompatible, - * make a copy as core drawing can't cross depths and doesn't - * work right across visuals of the same depth - */ - if (_cairo_xlib_surface_same_screen (dst, src) && - !_surfaces_compatible (dst, src)) - return DO_UNSUPPORTED; - } - } - - /* Check for the other bug involving repeat patterns with general - * transforms. */ - if (!_cairo_matrix_is_integer_translation (&src_pattern->matrix, NULL, NULL) && - src_pattern->extend == CAIRO_EXTEND_REPEAT) - return DO_UNSUPPORTED; - } - - return DO_RENDER; -} - -/* Recheck for composite-repeat once we've turned patterns into Xlib surfaces - * If we end up returning DO_UNSUPPORTED here, we're throwing away work we - * did to turn gradients into a pattern, but most of the time we can handle - * that case with core protocol fallback. - * - * Also check here if we can just use XCopyArea, instead of going through - * Render. - */ -static composite_operation_t -_recategorize_composite_operation (cairo_xlib_surface_t *dst, - cairo_operator_t op, - cairo_xlib_surface_t *src, - cairo_surface_attributes_t *src_attr, - cairo_bool_t have_mask) -{ - cairo_bool_t is_integer_translation = - _cairo_matrix_is_integer_translation (&src_attr->matrix, NULL, NULL); - cairo_bool_t needs_alpha_composite; - - if (! _cairo_surface_is_xlib (&src->base)) - return DO_UNSUPPORTED; - - needs_alpha_composite = - _operator_needs_alpha_composite (op, _surface_has_alpha (src)); - - if (! have_mask && - is_integer_translation && - src_attr->extend == CAIRO_EXTEND_NONE && - ! needs_alpha_composite && - _surfaces_compatible (src, dst)) - { - return DO_XCOPYAREA; - } - - if (dst->buggy_repeat && - is_integer_translation && - src_attr->extend == CAIRO_EXTEND_REPEAT && - (src->width != 1 || src->height != 1)) - { - if (! have_mask && - ! needs_alpha_composite && - _surfaces_compatible (dst, src)) - { - return DO_XTILE; - } - - return DO_UNSUPPORTED; - } - - if (! CAIRO_SURFACE_RENDER_HAS_COMPOSITE (src)) - return DO_UNSUPPORTED; - - if (! CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst)) - return DO_UNSUPPORTED; - - return DO_RENDER; -} - -static int -_render_operator (cairo_operator_t op) -{ - switch (op) { - case CAIRO_OPERATOR_CLEAR: - return PictOpClear; - - case CAIRO_OPERATOR_SOURCE: - return PictOpSrc; - case CAIRO_OPERATOR_OVER: - return PictOpOver; - case CAIRO_OPERATOR_IN: - return PictOpIn; - case CAIRO_OPERATOR_OUT: - return PictOpOut; - case CAIRO_OPERATOR_ATOP: - return PictOpAtop; - - case CAIRO_OPERATOR_DEST: - return PictOpDst; - case CAIRO_OPERATOR_DEST_OVER: - return PictOpOverReverse; - case CAIRO_OPERATOR_DEST_IN: - return PictOpInReverse; - case CAIRO_OPERATOR_DEST_OUT: - return PictOpOutReverse; - case CAIRO_OPERATOR_DEST_ATOP: - return PictOpAtopReverse; - - case CAIRO_OPERATOR_XOR: - return PictOpXor; - case CAIRO_OPERATOR_ADD: - return PictOpAdd; - case CAIRO_OPERATOR_SATURATE: - return PictOpSaturate; - default: - return PictOpOver; - } -} - -static cairo_int_status_t -_cairo_xlib_surface_composite (cairo_operator_t op, - cairo_pattern_t *src_pattern, - cairo_pattern_t *mask_pattern, - void *abstract_dst, - 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_surface_attributes_t src_attr, mask_attr; - cairo_xlib_surface_t *dst = abstract_dst; - cairo_xlib_surface_t *src; - cairo_xlib_surface_t *mask; - cairo_int_status_t status; - composite_operation_t operation; - int itx, ity; - cairo_bool_t is_integer_translation; - - _cairo_xlib_display_notify (dst->display); - - operation = _categorize_composite_operation (dst, op, src_pattern, - mask_pattern != NULL); - if (operation == DO_UNSUPPORTED) - return CAIRO_INT_STATUS_UNSUPPORTED; - - status = _cairo_pattern_acquire_surfaces (src_pattern, mask_pattern, - &dst->base, - src_x, src_y, - mask_x, mask_y, - width, height, - (cairo_surface_t **) &src, - (cairo_surface_t **) &mask, - &src_attr, &mask_attr); - if (status) - return status; - - /* check for fallback surfaces that we cannot handle ... */ - if (!_cairo_surface_is_xlib (&src->base)) { - status = CAIRO_INT_STATUS_UNSUPPORTED; - goto BAIL; - } - if (mask != NULL && - (! _cairo_surface_is_xlib (&mask->base) || - ! CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst))) - { - status = CAIRO_INT_STATUS_UNSUPPORTED; - goto BAIL; - } - - operation = _recategorize_composite_operation (dst, op, src, &src_attr, - mask_pattern != NULL); - if (operation == DO_UNSUPPORTED) { - status = CAIRO_INT_STATUS_UNSUPPORTED; - goto BAIL; - } - - switch (operation) - { - case DO_RENDER: - status = _cairo_xlib_surface_set_attributes (src, &src_attr); - if (status) - goto BAIL; - - _cairo_xlib_surface_ensure_dst_picture (dst); - if (mask) { - status = _cairo_xlib_surface_set_attributes (mask, &mask_attr); - if (status) - goto BAIL; - - XRenderComposite (dst->dpy, - _render_operator (op), - src->src_picture, - mask->src_picture, - dst->dst_picture, - src_x + src_attr.x_offset, - src_y + src_attr.y_offset, - mask_x + mask_attr.x_offset, - mask_y + mask_attr.y_offset, - dst_x, dst_y, - width, height); - } else { - XRenderComposite (dst->dpy, - _render_operator (op), - src->src_picture, - 0, - dst->dst_picture, - src_x + src_attr.x_offset, - src_y + src_attr.y_offset, - 0, 0, - dst_x, dst_y, - width, height); - } - - break; - - case DO_XCOPYAREA: - status = _cairo_xlib_surface_ensure_gc (dst); - if (status) - goto BAIL; - - is_integer_translation = _cairo_matrix_is_integer_translation (&src_attr.matrix, - &itx, &ity); - /* This is a pre-condition for DO_XCOPYAREA. */ - assert (is_integer_translation); - - XCopyArea (dst->dpy, - src->drawable, - dst->drawable, - dst->gc, - src_x + src_attr.x_offset + itx, - src_y + src_attr.y_offset + ity, - width, height, - dst_x, dst_y); - break; - - case DO_XTILE: - /* This case is only used for bug fallbacks, though we also use it for - * the case where we don't have the RENDER extension, by forcing - * buggy_repeat to TRUE. - * - * We've checked that we have a repeating unscaled source in - * _recategorize_composite_operation. - */ - - status = _cairo_xlib_surface_ensure_gc (dst); - if (status) - goto BAIL; - is_integer_translation = _cairo_matrix_is_integer_translation (&src_attr.matrix, - &itx, &ity); - /* This is a pre-condition for DO_XTILE. */ - assert (is_integer_translation); - - XSetTSOrigin (dst->dpy, dst->gc, - - (itx + src_attr.x_offset), - (ity + src_attr.y_offset)); - XSetTile (dst->dpy, dst->gc, src->drawable); - XSetFillStyle (dst->dpy, dst->gc, FillTiled); - - XFillRectangle (dst->dpy, dst->drawable, dst->gc, - dst_x, dst_y, width, height); - break; - - case DO_UNSUPPORTED: - default: - ASSERT_NOT_REACHED; - } - - if (!_cairo_operator_bounded_by_source (op)) - status = _cairo_surface_composite_fixup_unbounded (&dst->base, - &src_attr, src->width, src->height, - mask ? &mask_attr : NULL, - mask ? mask->width : 0, - mask ? mask->height : 0, - src_x, src_y, - mask_x, mask_y, - dst_x, dst_y, width, height); - - BAIL: - if (mask) - _cairo_pattern_release_surface (mask_pattern, &mask->base, &mask_attr); - - _cairo_pattern_release_surface (src_pattern, &src->base, &src_attr); - - return status; -} - -static cairo_int_status_t -_cairo_xlib_surface_solid_fill_rectangles (cairo_xlib_surface_t *surface, - const cairo_color_t *color, - cairo_rectangle_int_t *rects, - int num_rects) -{ - cairo_status_t status; - cairo_solid_pattern_t solid; - cairo_surface_t *solid_surface = NULL; - cairo_surface_attributes_t attrs; - int i; - - _cairo_pattern_init_solid (&solid, color, CAIRO_CONTENT_COLOR); - - status = _cairo_xlib_surface_ensure_gc (surface); - if (status) - return status; - - status = _cairo_pattern_acquire_surface (&solid.base, &surface->base, - 0, 0, - ARRAY_LENGTH (dither_pattern[0]), - ARRAY_LENGTH (dither_pattern), - &solid_surface, - &attrs); - if (status) - return status; - - if (! _cairo_surface_is_xlib (solid_surface)) { - status = CAIRO_INT_STATUS_UNSUPPORTED; - goto BAIL; - } - - XSetTSOrigin (surface->dpy, surface->gc, - - (surface->base.device_transform.x0 + attrs.x_offset), - - (surface->base.device_transform.y0 + attrs.y_offset)); - XSetTile (surface->dpy, surface->gc, - ((cairo_xlib_surface_t *) solid_surface)->drawable); - XSetFillStyle (surface->dpy, surface->gc, FillTiled); - - for (i = 0; i < num_rects; i++) { - XFillRectangle (surface->dpy, surface->drawable, surface->gc, - rects[i].x, rects[i].y, - rects[i].width, rects[i].height); - } - - BAIL: - _cairo_pattern_release_surface (&solid.base, solid_surface, &attrs); - - return status; -} - -static cairo_int_status_t -_cairo_xlib_surface_fill_rectangles (void *abstract_surface, - cairo_operator_t op, - const cairo_color_t *color, - cairo_rectangle_int_t *rects, - int num_rects) -{ - cairo_xlib_surface_t *surface = abstract_surface; - XRenderColor render_color; - XRectangle static_xrects[CAIRO_STACK_ARRAY_LENGTH (XRectangle)]; - XRectangle *xrects = static_xrects; - int i; - - _cairo_xlib_display_notify (surface->display); - - if (! CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLES (surface)) { - if (op == CAIRO_OPERATOR_CLEAR || - ((op == CAIRO_OPERATOR_SOURCE || op == CAIRO_OPERATOR_OVER) && - CAIRO_COLOR_IS_OPAQUE (color))) - { - return _cairo_xlib_surface_solid_fill_rectangles (surface, color, - rects, num_rects); - } - - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - render_color.red = color->red_short; - render_color.green = color->green_short; - render_color.blue = color->blue_short; - render_color.alpha = color->alpha_short; - - if (num_rects > ARRAY_LENGTH (static_xrects)) { - xrects = _cairo_malloc_ab (num_rects, sizeof (XRectangle)); - if (xrects == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - for (i = 0; i < num_rects; i++) { - xrects[i].x = rects[i].x; - xrects[i].y = rects[i].y; - xrects[i].width = rects[i].width; - xrects[i].height = rects[i].height; - } - - _cairo_xlib_surface_ensure_dst_picture (surface); - XRenderFillRectangles (surface->dpy, - _render_operator (op), - surface->dst_picture, - &render_color, xrects, num_rects); - - if (xrects != static_xrects) - free (xrects); - - return CAIRO_STATUS_SUCCESS; -} - -/* Creates an A8 picture of size @width x @height, initialized with @color - */ -static Picture -_create_a8_picture (cairo_xlib_surface_t *surface, - XRenderColor *color, - int width, - int height, - cairo_bool_t repeat) -{ - XRenderPictureAttributes pa; - unsigned long mask = 0; - - Pixmap pixmap; - Picture picture; - XRenderPictFormat *xrender_format; - - if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX) - return None; - - xrender_format = - _cairo_xlib_display_get_xrender_format (surface->display, - CAIRO_FORMAT_A8); - if (xrender_format == NULL) - return None; - - pixmap = XCreatePixmap (surface->dpy, surface->drawable, - width <= 0 ? 1 : width, - height <= 0 ? 1 : height, - 8); - - if (repeat) { - pa.repeat = TRUE; - mask = CPRepeat; - } - - picture = XRenderCreatePicture (surface->dpy, pixmap, - xrender_format, mask, &pa); - XRenderFillRectangle (surface->dpy, PictOpSrc, picture, color, - 0, 0, width, height); - XFreePixmap (surface->dpy, pixmap); - - return picture; -} - -/* Creates a temporary mask for the trapezoids covering the area - * [@dst_x, @dst_y, @width, @height] of the destination surface. - */ -static Picture -_create_trapezoid_mask (cairo_xlib_surface_t *dst, - cairo_trapezoid_t *traps, - int num_traps, - int dst_x, - int dst_y, - int width, - int height, - XRenderPictFormat *pict_format) -{ - XRenderColor transparent = { 0, 0, 0, 0 }; - XRenderColor solid = { 0xffff, 0xffff, 0xffff, 0xffff }; - Picture mask_picture, solid_picture; - XTrapezoid *offset_traps; - int i; - - /* This would be considerably simpler using XRenderAddTraps(), but since - * we are only using this in the unbounded-operator case, we stick with - * XRenderCompositeTrapezoids, which is available on older versions - * of RENDER rather than conditionalizing. We should still hit an - * optimization that avoids creating another intermediate surface on - * the servers that have XRenderAddTraps(). - */ - mask_picture = _create_a8_picture (dst, &transparent, width, height, FALSE); - if (mask_picture == None || num_traps == 0) - return mask_picture; - - offset_traps = _cairo_malloc_ab (num_traps, sizeof (XTrapezoid)); - if (!offset_traps) { - XRenderFreePicture (dst->dpy, mask_picture); - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return None; - } - - for (i = 0; i < num_traps; i++) { - offset_traps[i].top = _cairo_fixed_to_16_16(traps[i].top) - 0x10000 * dst_y; - offset_traps[i].bottom = _cairo_fixed_to_16_16(traps[i].bottom) - 0x10000 * dst_y; - offset_traps[i].left.p1.x = _cairo_fixed_to_16_16(traps[i].left.p1.x) - 0x10000 * dst_x; - offset_traps[i].left.p1.y = _cairo_fixed_to_16_16(traps[i].left.p1.y) - 0x10000 * dst_y; - offset_traps[i].left.p2.x = _cairo_fixed_to_16_16(traps[i].left.p2.x) - 0x10000 * dst_x; - offset_traps[i].left.p2.y = _cairo_fixed_to_16_16(traps[i].left.p2.y) - 0x10000 * dst_y; - offset_traps[i].right.p1.x = _cairo_fixed_to_16_16(traps[i].right.p1.x) - 0x10000 * dst_x; - offset_traps[i].right.p1.y = _cairo_fixed_to_16_16(traps[i].right.p1.y) - 0x10000 * dst_y; - offset_traps[i].right.p2.x = _cairo_fixed_to_16_16(traps[i].right.p2.x) - 0x10000 * dst_x; - offset_traps[i].right.p2.y = _cairo_fixed_to_16_16(traps[i].right.p2.y) - 0x10000 * dst_y; - } - - solid_picture = _create_a8_picture (dst, &solid, width, height, TRUE); - if (solid_picture == None) { - XRenderFreePicture (dst->dpy, mask_picture); - free (offset_traps); - return None; - } - - XRenderCompositeTrapezoids (dst->dpy, PictOpAdd, - solid_picture, mask_picture, - pict_format, - 0, 0, - offset_traps, num_traps); - - XRenderFreePicture (dst->dpy, solid_picture); - free (offset_traps); - - return mask_picture; -} - -static cairo_int_status_t -_cairo_xlib_surface_composite_trapezoids (cairo_operator_t op, - cairo_pattern_t *pattern, - void *abstract_dst, - cairo_antialias_t antialias, - int src_x, - int src_y, - int dst_x, - int dst_y, - unsigned int width, - unsigned int height, - cairo_trapezoid_t *traps, - int num_traps) -{ - cairo_surface_attributes_t attributes; - cairo_xlib_surface_t *dst = abstract_dst; - cairo_xlib_surface_t *src; - cairo_int_status_t status; - composite_operation_t operation; - int render_reference_x, render_reference_y; - int render_src_x, render_src_y; - XRenderPictFormat *pict_format; - - _cairo_xlib_display_notify (dst->display); - - if (!CAIRO_SURFACE_RENDER_HAS_TRAPEZOIDS (dst)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - operation = _categorize_composite_operation (dst, op, pattern, TRUE); - if (operation == DO_UNSUPPORTED) - return CAIRO_INT_STATUS_UNSUPPORTED; - - status = _cairo_pattern_acquire_surface (pattern, &dst->base, - src_x, src_y, width, height, - (cairo_surface_t **) &src, - &attributes); - if (status) - return status; - - operation = _recategorize_composite_operation (dst, op, src, - &attributes, TRUE); - if (operation == DO_UNSUPPORTED) { - status = CAIRO_INT_STATUS_UNSUPPORTED; - goto BAIL; - } - - switch (antialias) { - case CAIRO_ANTIALIAS_NONE: - pict_format = - _cairo_xlib_display_get_xrender_format (dst->display, - CAIRO_FORMAT_A1); - break; - case CAIRO_ANTIALIAS_GRAY: - case CAIRO_ANTIALIAS_SUBPIXEL: - case CAIRO_ANTIALIAS_DEFAULT: - default: - pict_format = - _cairo_xlib_display_get_xrender_format (dst->display, - CAIRO_FORMAT_A8); - break; - } - - if (traps[0].left.p1.y < traps[0].left.p2.y) { - render_reference_x = _cairo_fixed_integer_floor (traps[0].left.p1.x); - render_reference_y = _cairo_fixed_integer_floor (traps[0].left.p1.y); - } else { - render_reference_x = _cairo_fixed_integer_floor (traps[0].left.p2.x); - render_reference_y = _cairo_fixed_integer_floor (traps[0].left.p2.y); - } - - render_src_x = src_x + render_reference_x - dst_x; - render_src_y = src_y + render_reference_y - dst_y; - - _cairo_xlib_surface_ensure_dst_picture (dst); - status = _cairo_xlib_surface_set_attributes (src, &attributes); - if (status) - goto BAIL; - - if (!_cairo_operator_bounded_by_mask (op)) { - /* XRenderCompositeTrapezoids() creates a mask only large enough for the - * trapezoids themselves, but if the operator is unbounded, then we need - * to actually composite all the way out to the bounds, so we create - * the mask and composite ourselves. There actually would - * be benefit to doing this in all cases, since RENDER implementations - * will frequently create a too temporary big mask, ignoring destination - * bounds and clip. (XRenderAddTraps() could be used to make creating - * the mask somewhat cheaper.) - */ - Picture mask_picture = _create_trapezoid_mask (dst, traps, num_traps, - dst_x, dst_y, width, height, - pict_format); - if (!mask_picture) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto BAIL; - } - - XRenderComposite (dst->dpy, - _render_operator (op), - src->src_picture, - mask_picture, - dst->dst_picture, - src_x + attributes.x_offset, - src_y + attributes.y_offset, - 0, 0, - dst_x, dst_y, - width, height); - - XRenderFreePicture (dst->dpy, mask_picture); - - status = _cairo_surface_composite_shape_fixup_unbounded (&dst->base, - &attributes, src->width, src->height, - width, height, - src_x, src_y, - 0, 0, - dst_x, dst_y, width, height); - - } else { - XTrapezoid xtraps_stack[CAIRO_STACK_ARRAY_LENGTH (XTrapezoid)]; - XTrapezoid *xtraps = xtraps_stack; - int i; - - if (num_traps > ARRAY_LENGTH (xtraps_stack)) { - xtraps = _cairo_malloc_ab (num_traps, sizeof (XTrapezoid)); - if (xtraps == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto BAIL; - } - } - - for (i = 0; i < num_traps; i++) { - xtraps[i].top = _cairo_fixed_to_16_16(traps[i].top); - xtraps[i].bottom = _cairo_fixed_to_16_16(traps[i].bottom); - xtraps[i].left.p1.x = _cairo_fixed_to_16_16(traps[i].left.p1.x); - xtraps[i].left.p1.y = _cairo_fixed_to_16_16(traps[i].left.p1.y); - xtraps[i].left.p2.x = _cairo_fixed_to_16_16(traps[i].left.p2.x); - xtraps[i].left.p2.y = _cairo_fixed_to_16_16(traps[i].left.p2.y); - xtraps[i].right.p1.x = _cairo_fixed_to_16_16(traps[i].right.p1.x); - xtraps[i].right.p1.y = _cairo_fixed_to_16_16(traps[i].right.p1.y); - xtraps[i].right.p2.x = _cairo_fixed_to_16_16(traps[i].right.p2.x); - xtraps[i].right.p2.y = _cairo_fixed_to_16_16(traps[i].right.p2.y); - } - - XRenderCompositeTrapezoids (dst->dpy, - _render_operator (op), - src->src_picture, dst->dst_picture, - pict_format, - render_src_x + attributes.x_offset, - render_src_y + attributes.y_offset, - xtraps, num_traps); - - if (xtraps != xtraps_stack) - free(xtraps); - } - - BAIL: - _cairo_pattern_release_surface (pattern, &src->base, &attributes); - - return status; -} - -static cairo_int_status_t -_cairo_xlib_surface_set_clip_region (void *abstract_surface, - cairo_region_t *region) -{ - cairo_xlib_surface_t *surface = abstract_surface; - cairo_bool_t had_clip_rects = surface->have_clip_rects; - - if (had_clip_rects == FALSE && region == NULL) - return CAIRO_STATUS_SUCCESS; - - if (surface->clip_rects != surface->embedded_clip_rects) { - free (surface->clip_rects); - surface->clip_rects = surface->embedded_clip_rects; - } - - surface->have_clip_rects = FALSE; - surface->num_clip_rects = 0; - - if (region != NULL) { - cairo_box_int_t *boxes; - cairo_status_t status; - XRectangle *rects = NULL; - int n_boxes, i; - cairo_rectangle_int_t rect; - cairo_region_t bound, bounded; - - rect.x = rect.y = 0; - rect.width = surface->width; - rect.height = surface->height; - - /* Intersect the region with the bounds of the surface. This - * is necessary so we don't wrap around when we convert cairo's - * 32 bit region into 16 bit rectangles. - */ - _cairo_region_init_rect (&bound, &rect); - _cairo_region_init (&bounded); - status = _cairo_region_intersect (&bounded, &bound, region); - if (status) { - _cairo_region_fini (&bound); - _cairo_region_fini (&bounded); - return status; - } - - status = _cairo_region_get_boxes (&bounded, &n_boxes, &boxes); - if (status) { - _cairo_region_fini (&bound); - _cairo_region_fini (&bounded); - return status; - } - - if (n_boxes > ARRAY_LENGTH (surface->embedded_clip_rects)) { - rects = _cairo_malloc_ab (n_boxes, sizeof (XRectangle)); - if (rects == NULL) { - _cairo_region_boxes_fini (&bounded, boxes); - _cairo_region_fini (&bound); - _cairo_region_fini (&bounded); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - } else { - rects = surface->embedded_clip_rects; - } - - for (i = 0; i < n_boxes; i++) { - rects[i].x = boxes[i].p1.x; - rects[i].y = boxes[i].p1.y; - rects[i].width = boxes[i].p2.x - boxes[i].p1.x; - rects[i].height = boxes[i].p2.y - boxes[i].p1.y; - } - - _cairo_region_boxes_fini (&bounded, boxes); - _cairo_region_fini (&bounded); - _cairo_region_fini (&bound); - - surface->have_clip_rects = TRUE; - surface->clip_rects = rects; - surface->num_clip_rects = n_boxes; - - /* Discard the trivial clip rectangle that covers the entire surface */ - if (n_boxes == 1 && - rects[0].x == 0 && - rects[0].y == 0 && - rects[0].width == surface->width && - rects[0].height == surface->height) - { - surface->have_clip_rects = FALSE; - surface->num_clip_rects = 0; - - if (! had_clip_rects) - goto DONE; - } - } - - surface->clip_dirty = CAIRO_XLIB_SURFACE_CLIP_DIRTY_ALL; - DONE: - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_xlib_surface_get_extents (void *abstract_surface, - cairo_rectangle_int_t *rectangle) -{ - cairo_xlib_surface_t *surface = abstract_surface; - - rectangle->x = 0; - rectangle->y = 0; - - rectangle->width = surface->width; - rectangle->height = surface->height; - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_xlib_surface_get_font_options (void *abstract_surface, - cairo_font_options_t *options) -{ - cairo_xlib_surface_t *surface = abstract_surface; - - *options = surface->screen_info->font_options; -} - -static void -_cairo_xlib_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font); - -static void -_cairo_xlib_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph, - cairo_scaled_font_t *scaled_font); - -static cairo_bool_t -_cairo_xlib_surface_is_similar (void *surface_a, - void *surface_b, - cairo_content_t content) -{ - cairo_xlib_surface_t *a = surface_a; - cairo_xlib_surface_t *b = surface_b; - XRenderPictFormat *xrender_format = b->xrender_format; - - if (!_cairo_xlib_surface_same_screen (a, b)) - return FALSE; - - /* now inspect the content to check that a is similar to b */ - if (xrender_format == NULL && b->visual != NULL) - xrender_format = XRenderFindVisualFormat (b->dpy, b->visual); - - if (xrender_format == NULL || - _xrender_format_to_content (xrender_format) != content) - { - xrender_format = _cairo_xlib_display_get_xrender_format ( - b->display, - _cairo_format_from_content (content)); - } - - - return a->xrender_format == xrender_format; -} - -static cairo_status_t -_cairo_xlib_surface_reset (void *abstract_surface) -{ - cairo_xlib_surface_t *surface = abstract_surface; - cairo_status_t status; - - status = _cairo_xlib_surface_set_clip_region (surface, NULL); - if (status) - return status; - - return CAIRO_STATUS_SUCCESS; -} - -static const cairo_surface_backend_t cairo_xlib_surface_backend = { - CAIRO_SURFACE_TYPE_XLIB, - _cairo_xlib_surface_create_similar, - _cairo_xlib_surface_finish, - _cairo_xlib_surface_acquire_source_image, - _cairo_xlib_surface_release_source_image, - _cairo_xlib_surface_acquire_dest_image, - _cairo_xlib_surface_release_dest_image, - _cairo_xlib_surface_clone_similar, - _cairo_xlib_surface_composite, - _cairo_xlib_surface_fill_rectangles, - _cairo_xlib_surface_composite_trapezoids, - NULL, /* copy_page */ - NULL, /* show_page */ - _cairo_xlib_surface_set_clip_region, - NULL, /* intersect_clip_path */ - _cairo_xlib_surface_get_extents, - NULL, /* old_show_glyphs */ - _cairo_xlib_surface_get_font_options, - NULL, /* flush */ - NULL, /* mark_dirty_rectangle */ - _cairo_xlib_surface_scaled_font_fini, - _cairo_xlib_surface_scaled_glyph_fini, - - NULL, /* paint */ - NULL, /* mask */ - NULL, /* stroke */ - NULL, /* fill */ - _cairo_xlib_surface_show_glyphs, - NULL, /* snapshot */ - _cairo_xlib_surface_is_similar, - _cairo_xlib_surface_reset, - NULL, /* fill_stroke */ - _cairo_xlib_surface_create_solid_pattern_surface -}; - -/** - * _cairo_surface_is_xlib: - * @surface: a #cairo_surface_t - * - * Checks if a surface is a #cairo_xlib_surface_t - * - * Return value: True if the surface is an xlib surface - **/ -static cairo_bool_t -_cairo_surface_is_xlib (cairo_surface_t *surface) -{ - return surface->backend == &cairo_xlib_surface_backend; -} - -/* callback from CloseDisplay */ -static void -_cairo_xlib_surface_detach_display (cairo_xlib_display_t *display, void *data) -{ - cairo_xlib_surface_t *surface = cairo_container_of (data, - cairo_xlib_surface_t, - close_display_hook); - Display *dpy; - - dpy = surface->dpy; - surface->dpy = NULL; - - if (surface->dst_picture != None) { - XRenderFreePicture (dpy, surface->dst_picture); - surface->dst_picture = None; - } - - if (surface->src_picture != None) { - XRenderFreePicture (dpy, surface->src_picture); - surface->src_picture = None; - } - - if (surface->owns_pixmap) { - XFreePixmap (dpy, surface->drawable); - surface->drawable = None; - surface->owns_pixmap = FALSE; - } - - if (surface->gc != NULL) { - XFreeGC (dpy, surface->gc); - surface->gc = NULL; - } -} - -static cairo_surface_t * -_cairo_xlib_surface_create_internal (Display *dpy, - Drawable drawable, - Screen *screen, - Visual *visual, - XRenderPictFormat *xrender_format, - int width, - int height, - int depth) -{ - cairo_xlib_surface_t *surface; - cairo_xlib_display_t *display; - cairo_xlib_screen_info_t *screen_info; - - CAIRO_MUTEX_INITIALIZE (); - - if (xrender_format) { - depth = xrender_format->depth; - - /* XXX find matching visual for core/dithering fallbacks? */ - } else if (visual) { - int j, k; - - /* This is ugly, but we have to walk over all visuals - * for the display to find the correct depth. - */ - depth = 0; - for (j = 0; j < screen->ndepths; j++) { - Depth *d = &screen->depths[j]; - for (k = 0; k < d->nvisuals; k++) { - if (&d->visuals[k] == visual) { - depth = d->depth; - goto found; - } - } - } - found: - ; - } - - if (depth == 0) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL)); - - display = _cairo_xlib_display_get (dpy); - if (display == NULL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - screen_info = _cairo_xlib_screen_info_get (display, screen); - if (screen_info == NULL) { - _cairo_xlib_display_destroy (display); - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - } - - surface = malloc (sizeof (cairo_xlib_surface_t)); - if (surface == NULL) { - _cairo_xlib_screen_info_destroy (screen_info); - _cairo_xlib_display_destroy (display); - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - } - - /* initialize and hook into the CloseDisplay callback */ - surface->close_display_hook.func = _cairo_xlib_surface_detach_display; - _cairo_xlib_add_close_display_hook (display, &surface->close_display_hook); - - if (! XRenderQueryVersion (dpy, &surface->render_major, &surface->render_minor)) { - surface->render_major = -1; - surface->render_minor = -1; - } - - if (CAIRO_SURFACE_RENDER_HAS_CREATE_PICTURE (surface)) { - if (!xrender_format) { - if (visual) { - xrender_format = XRenderFindVisualFormat (dpy, visual); - } else if (depth == 1) { - xrender_format = - _cairo_xlib_display_get_xrender_format (display, - CAIRO_FORMAT_A1); - } - } - } else { - xrender_format = NULL; - } - - /* we cannot use XRender for this surface, so ensure we don't try */ - if (xrender_format == NULL) { - surface->render_major = -1; - surface->render_minor = -1; - } - - _cairo_surface_init (&surface->base, &cairo_xlib_surface_backend, - _xrender_format_to_content (xrender_format)); - - surface->dpy = dpy; - surface->display = display; - surface->screen_info = screen_info; - - surface->gc = NULL; - surface->drawable = drawable; - surface->screen = screen; - surface->owns_pixmap = FALSE; - surface->use_pixmap = 0; - surface->width = width; - surface->height = height; - - surface->buggy_repeat = screen_info->display->buggy_repeat; - if (!CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLES (surface)) { - /* so we can use the XTile fallback */ - surface->buggy_repeat = TRUE; - } - - surface->dst_picture = None; - surface->src_picture = None; - - surface->visual = visual; - surface->xrender_format = xrender_format; - surface->depth = depth; - surface->filter = CAIRO_FILTER_NEAREST; - surface->repeat = FALSE; - surface->xtransform = identity; - - surface->have_clip_rects = FALSE; - surface->clip_rects = surface->embedded_clip_rects; - surface->num_clip_rects = 0; - - /* - * Compute the pixel format masks from either a XrenderFormat or - * else from a visual; failing that we assume the drawable is an - * alpha-only pixmap as it could only have been created that way - * through the cairo_xlib_surface_create_for_bitmap function. - */ - if (xrender_format) { - surface->a_mask = (unsigned long) - surface->xrender_format->direct.alphaMask - << surface->xrender_format->direct.alpha; - surface->r_mask = (unsigned long) - surface->xrender_format->direct.redMask - << surface->xrender_format->direct.red; - surface->g_mask = (unsigned long) - surface->xrender_format->direct.greenMask - << surface->xrender_format->direct.green; - surface->b_mask = (unsigned long) - surface->xrender_format->direct.blueMask - << surface->xrender_format->direct.blue; - } else if (visual) { - surface->a_mask = 0; - surface->r_mask = visual->red_mask; - surface->g_mask = visual->green_mask; - surface->b_mask = visual->blue_mask; - } else { - if (depth < 32) - surface->a_mask = (1 << depth) - 1; - else - surface->a_mask = 0xffffffff; - surface->r_mask = 0; - surface->g_mask = 0; - surface->b_mask = 0; - } - - return (cairo_surface_t *) surface; -} - -static Screen * -_cairo_xlib_screen_from_visual (Display *dpy, Visual *visual) -{ - int s; - int d; - int v; - Screen *screen; - Depth *depth; - - for (s = 0; s < ScreenCount (dpy); s++) { - screen = ScreenOfDisplay (dpy, s); - if (visual == DefaultVisualOfScreen (screen)) - return screen; - for (d = 0; d < screen->ndepths; d++) { - depth = &screen->depths[d]; - for (v = 0; v < depth->nvisuals; v++) - if (visual == &depth->visuals[v]) - return screen; - } - } - return NULL; -} - -/** - * cairo_xlib_surface_create: - * @dpy: an X Display - * @drawable: an X Drawable, (a Pixmap or a Window) - * @visual: the visual to use for drawing to @drawable. The depth - * of the visual must match the depth of the drawable. - * Currently, only TrueColor visuals are fully supported. - * @width: the current width of @drawable. - * @height: the current height of @drawable. - * - * Creates an Xlib surface that draws to the given drawable. - * The way that colors are represented in the drawable is specified - * by the provided visual. - * - * Note: If @drawable is a Window, then the function - * cairo_xlib_surface_set_size() must be called whenever the size of the - * window changes. - * - * When @drawable is a Window containing child windows then drawing to - * the created surface will be clipped by those child windows. When - * the created surface is used as a source, the contents of the - * children will be included. - * - * Return value: the newly created surface - **/ -cairo_surface_t * -cairo_xlib_surface_create (Display *dpy, - Drawable drawable, - Visual *visual, - int width, - int height) -{ - Screen *screen = _cairo_xlib_screen_from_visual (dpy, visual); - - if (screen == NULL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL)); - - return _cairo_xlib_surface_create_internal (dpy, drawable, screen, - visual, NULL, width, height, 0); -} - -/** - * cairo_xlib_surface_create_for_bitmap: - * @dpy: an X Display - * @bitmap: an X Drawable, (a depth-1 Pixmap) - * @screen: the X Screen associated with @bitmap - * @width: the current width of @bitmap. - * @height: the current height of @bitmap. - * - * Creates an Xlib surface that draws to the given bitmap. - * This will be drawn to as a %CAIRO_FORMAT_A1 object. - * - * Return value: the newly created surface - **/ -cairo_surface_t * -cairo_xlib_surface_create_for_bitmap (Display *dpy, - Pixmap bitmap, - Screen *screen, - int width, - int height) -{ - return _cairo_xlib_surface_create_internal (dpy, bitmap, screen, - NULL, NULL, width, height, 1); -} - -#if CAIRO_HAS_XLIB_XRENDER_SURFACE -/** - * cairo_xlib_surface_create_with_xrender_format: - * @dpy: an X Display - * @drawable: an X Drawable, (a Pixmap or a Window) - * @screen: the X Screen associated with @drawable - * @format: the picture format to use for drawing to @drawable. The depth - * of @format must match the depth of the drawable. - * @width: the current width of @drawable. - * @height: the current height of @drawable. - * - * Creates an Xlib surface that draws to the given drawable. - * The way that colors are represented in the drawable is specified - * by the provided picture format. - * - * Note: If @drawable is a Window, then the function - * cairo_xlib_surface_set_size() must be called whenever the size of the - * window changes. - * - * Return value: the newly created surface - **/ -cairo_surface_t * -cairo_xlib_surface_create_with_xrender_format (Display *dpy, - Drawable drawable, - Screen *screen, - XRenderPictFormat *format, - int width, - int height) -{ - return _cairo_xlib_surface_create_internal (dpy, drawable, screen, - NULL, format, width, height, 0); -} - -/** - * cairo_xlib_surface_get_xrender_format: - * @surface: an xlib surface - * - * Gets the X Render picture format that @surface uses for rendering with the - * X Render extension. If the surface was created by - * cairo_xlib_surface_create_with_xrender_format() originally, the return - * value is the format passed to that constructor. - * - * Return value: the XRenderPictFormat* associated with @surface, - * or %NULL if the surface is not an xlib surface - * or if the X Render extension is not available. - * - * Since: 1.6 - **/ -XRenderPictFormat * -cairo_xlib_surface_get_xrender_format (cairo_surface_t *surface) -{ - cairo_xlib_surface_t *xlib_surface = (cairo_xlib_surface_t *) surface; - - /* Throw an error for a non-xlib surface */ - if (! _cairo_surface_is_xlib (surface)) { - _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - return NULL; - } - - return xlib_surface->xrender_format; -} -#endif - -/** - * cairo_xlib_surface_set_size: - * @surface: a #cairo_surface_t for the XLib backend - * @width: the new width of the surface - * @height: the new height of the surface - * - * Informs cairo of the new size of the X Drawable underlying the - * surface. For a surface created for a Window (rather than a Pixmap), - * this function must be called each time the size of the window - * changes. (For a subwindow, you are normally resizing the window - * yourself, but for a toplevel window, it is necessary to listen for - * ConfigureNotify events.) - * - * A Pixmap can never change size, so it is never necessary to call - * this function on a surface created for a Pixmap. - **/ -void -cairo_xlib_surface_set_size (cairo_surface_t *abstract_surface, - int width, - int height) -{ - cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface; - cairo_status_t status; - - if (! _cairo_surface_is_xlib (abstract_surface)) { - status = _cairo_surface_set_error (abstract_surface, - CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - return; - } - - surface->width = width; - surface->height = height; -} -/** - * cairo_xlib_surface_set_drawable: - * @surface: a #cairo_surface_t for the XLib backend - * @drawable: the new drawable for the surface - * @width: the width of the new drawable - * @height: the height of the new drawable - * - * Informs cairo of a new X Drawable underlying the - * surface. The drawable must match the display, screen - * and format of the existing drawable or the application - * will get X protocol errors and will probably terminate. - * No checks are done by this function to ensure this - * compatibility. - **/ -void -cairo_xlib_surface_set_drawable (cairo_surface_t *abstract_surface, - Drawable drawable, - int width, - int height) -{ - cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *)abstract_surface; - cairo_status_t status; - - if (! _cairo_surface_is_xlib (abstract_surface)) { - status = _cairo_surface_set_error (abstract_surface, - CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - return; - } - - /* XXX: and what about this case? */ - if (surface->owns_pixmap) - return; - - if (surface->drawable != drawable) { - if (surface->dst_picture != None) { - status = _cairo_xlib_display_queue_resource ( - surface->display, - XRenderFreePicture, - surface->dst_picture); - if (status) { - status = _cairo_surface_set_error (&surface->base, status); - return; - } - - surface->dst_picture = None; - } - - if (surface->src_picture != None) { - status = _cairo_xlib_display_queue_resource ( - surface->display, - XRenderFreePicture, - surface->src_picture); - if (status) { - status = _cairo_surface_set_error (&surface->base, status); - return; - } - - surface->src_picture = None; - } - - surface->drawable = drawable; - } - surface->width = width; - surface->height = height; -} - -/** - * cairo_xlib_surface_get_display: - * @surface: a #cairo_xlib_surface_t - * - * Get the X Display for the underlying X Drawable. - * - * Return value: the display. - * - * Since: 1.2 - **/ -Display * -cairo_xlib_surface_get_display (cairo_surface_t *abstract_surface) -{ - cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface; - - if (! _cairo_surface_is_xlib (abstract_surface)) { - _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - return NULL; - } - - return surface->dpy; -} - -/** - * cairo_xlib_surface_get_drawable: - * @surface: a #cairo_xlib_surface_t - * - * Get the underlying X Drawable used for the surface. - * - * Return value: the drawable. - * - * Since: 1.2 - **/ -Drawable -cairo_xlib_surface_get_drawable (cairo_surface_t *abstract_surface) -{ - cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface; - - if (! _cairo_surface_is_xlib (abstract_surface)) { - _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - return 0; - } - - return surface->drawable; -} - -/** - * cairo_xlib_surface_get_screen: - * @surface: a #cairo_xlib_surface_t - * - * Get the X Screen for the underlying X Drawable. - * - * Return value: the screen. - * - * Since: 1.2 - **/ -Screen * -cairo_xlib_surface_get_screen (cairo_surface_t *abstract_surface) -{ - cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface; - - if (! _cairo_surface_is_xlib (abstract_surface)) { - _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - return NULL; - } - - return surface->screen; -} - -/** - * cairo_xlib_surface_get_visual: - * @surface: a #cairo_xlib_surface_t - * - * Get the X Visual used for underlying X Drawable. - * - * Return value: the visual. - * - * Since: 1.2 - **/ -Visual * -cairo_xlib_surface_get_visual (cairo_surface_t *abstract_surface) -{ - cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface; - - if (! _cairo_surface_is_xlib (abstract_surface)) { - _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - return NULL; - } - - return surface->visual; -} - -/** - * cairo_xlib_surface_get_depth: - * @surface: a #cairo_xlib_surface_t - * - * Get the number of bits used to represent each pixel value. - * - * Return value: the depth of the surface in bits. - * - * Since: 1.2 - **/ -int -cairo_xlib_surface_get_depth (cairo_surface_t *abstract_surface) -{ - cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface; - - if (! _cairo_surface_is_xlib (abstract_surface)) { - _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - return 0; - } - - return surface->depth; -} - -/** - * cairo_xlib_surface_get_width: - * @surface: a #cairo_xlib_surface_t - * - * Get the width of the X Drawable underlying the surface in pixels. - * - * Return value: the width of the surface in pixels. - * - * Since: 1.2 - **/ -int -cairo_xlib_surface_get_width (cairo_surface_t *abstract_surface) -{ - cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface; - - if (! _cairo_surface_is_xlib (abstract_surface)) { - _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - return -1; - } - - return surface->width; -} - -/** - * cairo_xlib_surface_get_height: - * @surface: a #cairo_xlib_surface_t - * - * Get the height of the X Drawable underlying the surface in pixels. - * - * Return value: the height of the surface in pixels. - * - * Since: 1.2 - **/ -int -cairo_xlib_surface_get_height (cairo_surface_t *abstract_surface) -{ - cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface; - - if (! _cairo_surface_is_xlib (abstract_surface)) { - _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - return -1; - } - - return surface->height; -} - -enum { - GLYPHSET_INDEX_ARGB32, - GLYPHSET_INDEX_A8, - GLYPHSET_INDEX_A1, - NUM_GLYPHSETS -}; - -typedef struct _cairo_xlib_font_glyphset_free_glyphs { - GlyphSet glyphset; - int glyph_count; - unsigned long glyph_indices[128]; -} cairo_xlib_font_glyphset_free_glyphs_t; - -typedef struct _cairo_xlib_font_glyphset_info { - GlyphSet glyphset; - cairo_format_t format; - XRenderPictFormat *xrender_format; - cairo_xlib_font_glyphset_free_glyphs_t *pending_free_glyphs; -} cairo_xlib_font_glyphset_info_t; - -typedef struct _cairo_xlib_surface_font_private { - cairo_scaled_font_t *scaled_font; - cairo_xlib_hook_t close_display_hook; - cairo_xlib_display_t *display; - cairo_xlib_font_glyphset_info_t glyphset_info[NUM_GLYPHSETS]; -} cairo_xlib_surface_font_private_t; - -/* callback from CloseDisplay */ -static void -_cairo_xlib_surface_remove_scaled_font (cairo_xlib_display_t *display, - void *data) -{ - cairo_xlib_surface_font_private_t *font_private; - cairo_scaled_font_t *scaled_font; - - font_private = cairo_container_of (data, - cairo_xlib_surface_font_private_t, - close_display_hook); - scaled_font = font_private->scaled_font; - - CAIRO_MUTEX_LOCK (scaled_font->mutex); - font_private = scaled_font->surface_private; - scaled_font->surface_private = NULL; - - _cairo_scaled_font_reset_cache (scaled_font); - CAIRO_MUTEX_UNLOCK (scaled_font->mutex); - - if (font_private != NULL) { - Display *dpy; - int i; - - dpy = display->display; - for (i = 0; i < NUM_GLYPHSETS; i++) { - cairo_xlib_font_glyphset_info_t *glyphset_info; - - glyphset_info = &font_private->glyphset_info[i]; - if (glyphset_info->glyphset) - XRenderFreeGlyphSet (dpy, glyphset_info->glyphset); - - if (glyphset_info->pending_free_glyphs != NULL) - free (glyphset_info->pending_free_glyphs); - } - - _cairo_xlib_display_destroy (font_private->display); - free (font_private); - } -} - -static cairo_status_t -_cairo_xlib_surface_font_init (Display *dpy, - cairo_scaled_font_t *scaled_font) -{ - cairo_xlib_surface_font_private_t *font_private; - int i; - - font_private = malloc (sizeof (cairo_xlib_surface_font_private_t)); - if (font_private == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - font_private->scaled_font = scaled_font; - font_private->display = _cairo_xlib_display_get (dpy); - if (font_private->display == NULL) { - free (font_private); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - /* initialize and hook into the CloseDisplay callback */ - font_private->close_display_hook.func = - _cairo_xlib_surface_remove_scaled_font; - _cairo_xlib_add_close_display_hook (font_private->display, - &font_private->close_display_hook); - - - for (i = 0; i < NUM_GLYPHSETS; i++) { - cairo_xlib_font_glyphset_info_t *glyphset_info = &font_private->glyphset_info[i]; - switch (i) { - case GLYPHSET_INDEX_ARGB32: glyphset_info->format = CAIRO_FORMAT_ARGB32; break; - case GLYPHSET_INDEX_A8: glyphset_info->format = CAIRO_FORMAT_A8; break; - case GLYPHSET_INDEX_A1: glyphset_info->format = CAIRO_FORMAT_A1; break; - default: ASSERT_NOT_REACHED; break; - } - glyphset_info->xrender_format = NULL; - glyphset_info->glyphset = None; - glyphset_info->pending_free_glyphs = NULL; - } - - scaled_font->surface_private = font_private; - scaled_font->surface_backend = &cairo_xlib_surface_backend; - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_xlib_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font) -{ - cairo_xlib_surface_font_private_t *font_private; - - font_private = scaled_font->surface_private; - if (font_private != NULL) { - cairo_xlib_display_t *display; - int i; - - display = font_private->display; - _cairo_xlib_remove_close_display_hook (display, - &font_private->close_display_hook); - - for (i = 0; i < NUM_GLYPHSETS; i++) { - cairo_xlib_font_glyphset_info_t *glyphset_info; - - glyphset_info = &font_private->glyphset_info[i]; - - if (glyphset_info->pending_free_glyphs != NULL) - free (glyphset_info->pending_free_glyphs); - - if (glyphset_info->glyphset) { - cairo_status_t status; - - status = _cairo_xlib_display_queue_resource (display, - XRenderFreeGlyphSet, - glyphset_info->glyphset); - (void) status; /* XXX cannot propagate failure */ - } - } - - _cairo_xlib_display_destroy (display); - free (font_private); - } -} - -static void -_cairo_xlib_render_free_glyphs (Display *dpy, - cairo_xlib_font_glyphset_free_glyphs_t *to_free) -{ - XRenderFreeGlyphs (dpy, - to_free->glyphset, - to_free->glyph_indices, - to_free->glyph_count); -} - -static cairo_xlib_font_glyphset_info_t * -_cairo_xlib_scaled_glyph_get_glyphset_info (cairo_scaled_glyph_t *scaled_glyph) -{ - return scaled_glyph->surface_private; -} - -static void -_cairo_xlib_scaled_glyph_set_glyphset_info (cairo_scaled_glyph_t *scaled_glyph, - cairo_xlib_font_glyphset_info_t *glyphset_info) -{ - scaled_glyph->surface_private = glyphset_info; -} - -static void -_cairo_xlib_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph, - cairo_scaled_font_t *scaled_font) -{ - cairo_xlib_surface_font_private_t *font_private; - cairo_xlib_font_glyphset_info_t *glyphset_info; - - if (scaled_font->finished) - return; - - font_private = scaled_font->surface_private; - glyphset_info = _cairo_xlib_scaled_glyph_get_glyphset_info (scaled_glyph); - if (font_private != NULL && glyphset_info != NULL) { - cairo_xlib_font_glyphset_free_glyphs_t *to_free; - cairo_status_t status; - - to_free = glyphset_info->pending_free_glyphs; - if (to_free != NULL && - to_free->glyph_count == ARRAY_LENGTH (to_free->glyph_indices)) - { - status = _cairo_xlib_display_queue_work (font_private->display, - (cairo_xlib_notify_func) _cairo_xlib_render_free_glyphs, - to_free, - free); - /* XXX cannot propagate failure */ - if (status) - free (to_free); - - to_free = glyphset_info->pending_free_glyphs = NULL; - } - - if (to_free == NULL) { - to_free = malloc (sizeof (cairo_xlib_font_glyphset_free_glyphs_t)); - if (to_free == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return; /* XXX cannot propagate failure */ - } - - to_free->glyphset = glyphset_info->glyphset; - to_free->glyph_count = 0; - glyphset_info->pending_free_glyphs = to_free; - } - - to_free->glyph_indices[to_free->glyph_count++] = - _cairo_scaled_glyph_index (scaled_glyph); - } -} - -static cairo_bool_t -_native_byte_order_lsb (void) -{ - int x = 1; - - return *((char *) &x) == 1; -} - -static cairo_xlib_font_glyphset_info_t * -_cairo_xlib_scaled_font_get_glyphset_info_for_format (cairo_scaled_font_t *scaled_font, - cairo_format_t format) -{ - cairo_xlib_surface_font_private_t *font_private; - cairo_xlib_font_glyphset_info_t *glyphset_info; - int glyphset_index; - - switch (format) { - default: - case CAIRO_FORMAT_RGB24: - case CAIRO_FORMAT_ARGB32: glyphset_index = GLYPHSET_INDEX_ARGB32; break; - case CAIRO_FORMAT_A8: glyphset_index = GLYPHSET_INDEX_A8; break; - case CAIRO_FORMAT_A1: glyphset_index = GLYPHSET_INDEX_A1; break; - } - - font_private = scaled_font->surface_private; - glyphset_info = &font_private->glyphset_info[glyphset_index]; - if (glyphset_info->glyphset == None) { - cairo_xlib_display_t *display = font_private->display; - - glyphset_info->xrender_format = - _cairo_xlib_display_get_xrender_format (display, - glyphset_info->format); - glyphset_info->glyphset = XRenderCreateGlyphSet (display->display, - glyphset_info->xrender_format); - } - - return glyphset_info; -} - -static cairo_bool_t -_cairo_xlib_glyphset_info_has_pending_free_glyph ( - cairo_xlib_font_glyphset_info_t *glyphset_info, - unsigned long glyph_index) -{ - if (glyphset_info->pending_free_glyphs != NULL) { - cairo_xlib_font_glyphset_free_glyphs_t *to_free; - int i; - - to_free = glyphset_info->pending_free_glyphs; - for (i = 0; i < to_free->glyph_count; i++) { - if (to_free->glyph_indices[i] == glyph_index) { - to_free->glyph_count--; - memmove (&to_free->glyph_indices[i], - &to_free->glyph_indices[i+1], - (to_free->glyph_count - i) * sizeof (to_free->glyph_indices[0])); - return TRUE; - } - } - } - - return FALSE; -} - -static cairo_xlib_font_glyphset_info_t * -_cairo_xlib_scaled_font_get_glyphset_info_for_pending_free_glyph ( - cairo_scaled_font_t *scaled_font, - unsigned long glyph_index, - cairo_image_surface_t *surface) -{ - cairo_xlib_surface_font_private_t *font_private; - int i; - - font_private = scaled_font->surface_private; - if (font_private == NULL) - return NULL; - - if (surface != NULL) { - switch (surface->format) { - default: - case CAIRO_FORMAT_RGB24: - case CAIRO_FORMAT_ARGB32: i = GLYPHSET_INDEX_ARGB32; break; - case CAIRO_FORMAT_A8: i = GLYPHSET_INDEX_A8; break; - case CAIRO_FORMAT_A1: i = GLYPHSET_INDEX_A1; break; - } - if (_cairo_xlib_glyphset_info_has_pending_free_glyph ( - &font_private->glyphset_info[i], - glyph_index)) - { - return &font_private->glyphset_info[i]; - } - } else { - for (i = 0; i < NUM_GLYPHSETS; i++) { - if (_cairo_xlib_glyphset_info_has_pending_free_glyph ( - &font_private->glyphset_info[i], - glyph_index)) - { - return &font_private->glyphset_info[i]; - } - } - } - - return NULL; -} - -static cairo_status_t -_cairo_xlib_surface_add_glyph (Display *dpy, - cairo_scaled_font_t *scaled_font, - cairo_scaled_glyph_t **pscaled_glyph) -{ - XGlyphInfo glyph_info; - unsigned long glyph_index; - unsigned char *data; - cairo_status_t status = CAIRO_STATUS_SUCCESS; - cairo_scaled_glyph_t *scaled_glyph = *pscaled_glyph; - cairo_image_surface_t *glyph_surface = scaled_glyph->surface; - cairo_bool_t already_had_glyph_surface; - cairo_xlib_font_glyphset_info_t *glyphset_info; - - glyph_index = _cairo_scaled_glyph_index (scaled_glyph); - - /* check to see if we have a pending XRenderFreeGlyph for this glyph */ - glyphset_info = _cairo_xlib_scaled_font_get_glyphset_info_for_pending_free_glyph (scaled_font, glyph_index, glyph_surface); - if (glyphset_info != NULL) { - _cairo_xlib_scaled_glyph_set_glyphset_info (scaled_glyph, glyphset_info); - return CAIRO_STATUS_SUCCESS; - } - - if (!glyph_surface) { - status = _cairo_scaled_glyph_lookup (scaled_font, - glyph_index, - CAIRO_SCALED_GLYPH_INFO_METRICS | - CAIRO_SCALED_GLYPH_INFO_SURFACE, - pscaled_glyph); - if (status) - return status; - - scaled_glyph = *pscaled_glyph; - glyph_surface = scaled_glyph->surface; - already_had_glyph_surface = FALSE; - } else { - already_had_glyph_surface = TRUE; - } - - if (scaled_font->surface_private == NULL) { - status = _cairo_xlib_surface_font_init (dpy, scaled_font); - if (status) - return status; - } - - glyphset_info = _cairo_xlib_scaled_font_get_glyphset_info_for_format (scaled_font, - glyph_surface->format); - - /* XRenderAddGlyph does not handle a glyph surface larger than the extended maximum XRequest size. */ - { - int len = cairo_format_stride_for_width (glyphset_info->format, glyph_surface->width) * glyph_surface->height; - int max_request_size = (XExtendedMaxRequestSize (dpy) ? XExtendedMaxRequestSize (dpy) : XMaxRequestSize (dpy)) * 4 - - sz_xRenderAddGlyphsReq - - sz_xGlyphInfo - - 8; - if (len >= max_request_size) - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - /* If the glyph surface has zero height or width, we create - * a clear 1x1 surface, to avoid various X server bugs. - */ - if (glyph_surface->width == 0 || glyph_surface->height == 0) { - cairo_t *cr; - cairo_surface_t *tmp_surface; - - tmp_surface = cairo_image_surface_create (glyphset_info->format, 1, 1); - status = tmp_surface->status; - if (status) - goto BAIL; - - cr = cairo_create (tmp_surface); - cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); - cairo_paint (cr); - status = cairo_status (cr); - cairo_destroy (cr); - - tmp_surface->device_transform = glyph_surface->base.device_transform; - tmp_surface->device_transform_inverse = glyph_surface->base.device_transform_inverse; - - glyph_surface = (cairo_image_surface_t *) tmp_surface; - - if (status) - goto BAIL; - } - - /* If the glyph format does not match the font format, then we - * create a temporary surface for the glyph image with the font's - * format. - */ - if (glyph_surface->format != glyphset_info->format) { - cairo_t *cr; - cairo_surface_t *tmp_surface; - - tmp_surface = cairo_image_surface_create (glyphset_info->format, - glyph_surface->width, - glyph_surface->height); - status = tmp_surface->status; - if (status) - goto BAIL; - - tmp_surface->device_transform = glyph_surface->base.device_transform; - tmp_surface->device_transform_inverse = glyph_surface->base.device_transform_inverse; - - cr = cairo_create (tmp_surface); - cairo_set_source_surface (cr, &glyph_surface->base, 0, 0); - cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); - cairo_paint (cr); - status = cairo_status (cr); - cairo_destroy (cr); - - glyph_surface = (cairo_image_surface_t *) tmp_surface; - - if (status) - goto BAIL; - } - - /* XXX: FRAGILE: We're ignore device_transform scaling here. A bug? */ - glyph_info.x = _cairo_lround (glyph_surface->base.device_transform.x0); - glyph_info.y = _cairo_lround (glyph_surface->base.device_transform.y0); - glyph_info.width = glyph_surface->width; - glyph_info.height = glyph_surface->height; - glyph_info.xOff = scaled_glyph->x_advance; - glyph_info.yOff = scaled_glyph->y_advance; - - data = glyph_surface->data; - - /* flip formats around */ - switch (scaled_glyph->surface->format) { - case CAIRO_FORMAT_A1: - /* local bitmaps are always stored with bit == byte */ - if (_native_byte_order_lsb() != (BitmapBitOrder (dpy) == LSBFirst)) { - int c = glyph_surface->stride * glyph_surface->height; - unsigned char *d; - unsigned char *new, *n; - - new = malloc (c); - if (!new) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto BAIL; - } - n = new; - d = data; - while (c--) - { - char b = *d++; - b = ((b << 1) & 0xaa) | ((b >> 1) & 0x55); - b = ((b << 2) & 0xcc) | ((b >> 2) & 0x33); - b = ((b << 4) & 0xf0) | ((b >> 4) & 0x0f); - *n++ = b; - } - data = new; - } - break; - case CAIRO_FORMAT_A8: - break; - case CAIRO_FORMAT_ARGB32: - if (_native_byte_order_lsb() != (ImageByteOrder (dpy) == LSBFirst)) { - unsigned int c = glyph_surface->stride * glyph_surface->height; - unsigned char *d; - unsigned char *new, *n; - - new = malloc (c); - if (new == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto BAIL; - } - n = new; - d = data; - while (c >= 4) - { - n[3] = d[0]; - n[2] = d[1]; - n[1] = d[2]; - n[0] = d[3]; - d += 4; - n += 4; - c -= 4; - } - data = new; - } - break; - case CAIRO_FORMAT_RGB24: - default: - ASSERT_NOT_REACHED; - break; - } - /* XXX assume X server wants pixman padding. Xft assumes this as well */ - - XRenderAddGlyphs (dpy, glyphset_info->glyphset, - &glyph_index, &glyph_info, 1, - (char *) data, - glyph_surface->stride * glyph_surface->height); - - if (data != glyph_surface->data) - free (data); - - _cairo_xlib_scaled_glyph_set_glyphset_info (scaled_glyph, glyphset_info); - - BAIL: - if (glyph_surface != scaled_glyph->surface) - cairo_surface_destroy (&glyph_surface->base); - - /* if the scaled glyph didn't already have a surface attached - * to it, release the created surface now that we have it - * uploaded to the X server. If the surface has already been - * there (eg. because image backend requested it), leave it in - * the cache - */ - if (!already_had_glyph_surface) - _cairo_scaled_glyph_set_surface (scaled_glyph, scaled_font, NULL); - - return status; -} - -typedef void (*cairo_xrender_composite_text_func_t) - (Display *dpy, - int op, - Picture src, - Picture dst, - _Xconst XRenderPictFormat *maskFormat, - int xSrc, - int ySrc, - int xDst, - int yDst, - _Xconst XGlyphElt8 *elts, - int nelt); - -/* Build a struct of the same size of #cairo_glyph_t that can be used both as - * an input glyph with double coordinates, and as "working" glyph with - * integer from-current-point offsets. */ -typedef union { - cairo_glyph_t d; - unsigned long index; - struct { - unsigned long index; - int x; - int y; - } i; -} cairo_xlib_glyph_t; - -/* compile-time assert that #cairo_xlib_glyph_t is the same size as #cairo_glyph_t */ -COMPILE_TIME_ASSERT (sizeof (cairo_xlib_glyph_t) == sizeof (cairo_glyph_t)); - -/* Start a new element for the first glyph, - * or for any glyph that has unexpected position, - * or if current element has too many glyphs - * (Xrender limits each element to 252 glyphs, we limit them to 128) - * - * These same conditions need to be mirrored between - * _cairo_xlib_surface_emit_glyphs and _emit_glyph_chunks - */ -#define _start_new_glyph_elt(count, glyph) \ - (((count) & 127) == 0 || (glyph)->i.x || (glyph)->i.y) - -static cairo_status_t -_emit_glyphs_chunk (cairo_xlib_surface_t *dst, - cairo_xlib_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font, - cairo_operator_t op, - cairo_xlib_surface_t *src, - cairo_surface_attributes_t *attributes, - /* info for this chunk */ - int num_elts, - int width, - cairo_xlib_font_glyphset_info_t *glyphset_info) -{ - /* Which XRenderCompositeText function to use */ - cairo_xrender_composite_text_func_t composite_text_func; - int size; - - /* Element buffer stuff */ - XGlyphElt8 *elts; - XGlyphElt8 stack_elts[CAIRO_STACK_ARRAY_LENGTH (XGlyphElt8)]; - - /* Reuse the input glyph array for output char generation */ - char *char8 = (char *) glyphs; - unsigned short *char16 = (unsigned short *) glyphs; - unsigned int *char32 = (unsigned int *) glyphs; - - int i; - int nelt; /* Element index */ - int n; /* Num output glyphs in current element */ - int j; /* Num output glyphs so far */ - - switch (width) { - case 1: - /* don't cast the 8-variant, to catch possible mismatches */ - composite_text_func = XRenderCompositeText8; - size = sizeof (char); - break; - case 2: - composite_text_func = (cairo_xrender_composite_text_func_t) XRenderCompositeText16; - size = sizeof (unsigned short); - break; - default: - case 4: - composite_text_func = (cairo_xrender_composite_text_func_t) XRenderCompositeText32; - size = sizeof (unsigned int); - } - - /* Allocate element array */ - if (num_elts <= ARRAY_LENGTH (stack_elts)) { - elts = stack_elts; - } else { - elts = _cairo_malloc_ab (num_elts, sizeof (XGlyphElt8)); - if (elts == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - /* Fill them in */ - nelt = 0; - n = 0; - j = 0; - for (i = 0; i < num_glyphs; i++) { - - /* Start a new element for first output glyph, - * or for any glyph that has unexpected position, - * or if current element has too many glyphs. - * - * These same conditions are mirrored in _cairo_xlib_surface_emit_glyphs() - */ - if (_start_new_glyph_elt (j, &glyphs[i])) { - if (j) { - elts[nelt].nchars = n; - nelt++; - n = 0; - } - elts[nelt].chars = char8 + size * j; - elts[nelt].glyphset = glyphset_info->glyphset; - elts[nelt].xOff = glyphs[i].i.x; - elts[nelt].yOff = glyphs[i].i.y; - } - - switch (width) { - case 1: char8 [j] = (char) glyphs[i].index; break; - case 2: char16[j] = (unsigned short) glyphs[i].index; break; - default: - case 4: char32[j] = (unsigned int) glyphs[i].index; break; - } - - n++; - j++; - } - - if (n) { - elts[nelt].nchars = n; - nelt++; - n = 0; - } - - /* Check that we agree with _cairo_xlib_surface_emit_glyphs() on the - * expected number of xGlyphElts. */ - assert (nelt == num_elts); - - composite_text_func (dst->dpy, - _render_operator (op), - src->src_picture, - dst->dst_picture, - glyphset_info->xrender_format, - attributes->x_offset + elts[0].xOff, - attributes->y_offset + elts[0].yOff, - elts[0].xOff, elts[0].yOff, - (XGlyphElt8 *) elts, nelt); - - if (elts != stack_elts) - free (elts); - - return CAIRO_STATUS_SUCCESS; -} - - -/* sz_xGlyphtElt required alignment to a 32-bit boundary, so ensure we have - * enough room for padding */ -#define _cairo_sz_xGlyphElt (sz_xGlyphElt + 4) - -static cairo_status_t -_cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst, - cairo_xlib_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font, - cairo_operator_t op, - cairo_xlib_surface_t *src, - cairo_surface_attributes_t *attributes, - int *remaining_glyphs) -{ - int i; - cairo_status_t status = CAIRO_STATUS_SUCCESS; - cairo_scaled_glyph_t *scaled_glyph; - cairo_fixed_t x = 0, y = 0; - cairo_xlib_font_glyphset_info_t *glyphset_info = NULL, *this_glyphset_info; - - unsigned long max_index = 0; - int width = 1; - int num_elts = 0; - int num_out_glyphs = 0; - - int max_request_size = XMaxRequestSize (dst->dpy) * 4 - - MAX (sz_xRenderCompositeGlyphs8Req, - MAX(sz_xRenderCompositeGlyphs16Req, - sz_xRenderCompositeGlyphs32Req)); - int request_size = 0; - - _cairo_xlib_surface_ensure_dst_picture (dst); - _cairo_xlib_display_notify (dst->display); - - for (i = 0; i < num_glyphs; i++) { - int this_x, this_y; - int old_width; - - status = _cairo_scaled_glyph_lookup (scaled_font, - glyphs[i].index, - CAIRO_SCALED_GLYPH_INFO_METRICS, - &scaled_glyph); - if (status != CAIRO_STATUS_SUCCESS) - return status; - - this_x = _cairo_lround (glyphs[i].d.x); - this_y = _cairo_lround (glyphs[i].d.y); - - /* Glyph skipping: - * - * We skip any glyphs that have troublesome coordinates. We want - * to make sure that (glyph2.x - (glyph1.x + glyph1.width)) fits in - * a signed 16bit integer, otherwise it will overflow in the render - * protocol. - * To ensure this, we'll make sure that (glyph2.x - glyph1.x) fits in - * a signed 15bit integer. The trivial option would be to allow - * coordinates -8192..8192, but that's kinda dull. It probably will - * take a decade or so to get monitors 8192x4096 or something. A - * negative value of -8192 on the other hand, is absolutely useless. - * Note that we do want to allow some negative positions. The glyph - * may start off the screen but part of it make it to the screen. - * Anyway, we will allow positions in the range -4096..122887. That - * will buy us a few more years before this stops working. - * - * Update: upon seeing weird glyphs, we just return and let fallback - * code do the job. - */ - if (((this_x+4096)|(this_y+4096))&~0x3fffu) - break; - - /* Send unsent glyphs to the server */ - if (_cairo_xlib_scaled_glyph_get_glyphset_info (scaled_glyph) == NULL) { - status = _cairo_xlib_surface_add_glyph (dst->dpy, - scaled_font, - &scaled_glyph); - if (status) { - if (status == CAIRO_INT_STATUS_UNSUPPORTED) - /* Break so we flush glyphs so far and let fallback code - * handle the rest */ - break; - - return status; - } - } - - this_glyphset_info = _cairo_xlib_scaled_glyph_get_glyphset_info (scaled_glyph); - if (!glyphset_info) - glyphset_info = this_glyphset_info; - - /* The invariant here is that we can always flush the glyphs - * accumulated before this one, using old_width, and they - * would fit in the request. - */ - old_width = width; - - /* Update max glyph index */ - if (glyphs[i].index > max_index) { - max_index = glyphs[i].index; - if (max_index >= 65536) - width = 4; - else if (max_index >= 256) - width = 2; - if (width != old_width) - request_size += (width - old_width) * num_out_glyphs; - } - - /* If we will pass the max request size by adding this glyph, - * flush current glyphs. Note that we account for a - * possible element being added below. - * - * Also flush if changing glyphsets, as Xrender limits one mask - * format per request, so we can either break up, or use a - * wide-enough mask format. We do the former. One reason to - * prefer the latter is the fact that Xserver ADDs all glyphs - * to the mask first, and then composes that to final surface, - * though it's not a big deal. - */ - if (request_size + width > max_request_size - _cairo_sz_xGlyphElt || - (this_glyphset_info != glyphset_info)) { - status = _emit_glyphs_chunk (dst, glyphs, i, - scaled_font, op, src, attributes, - num_elts, old_width, glyphset_info); - if (status != CAIRO_STATUS_SUCCESS) - return status; - - glyphs += i; - num_glyphs -= i; - i = 0; - max_index = glyphs[i].index; - width = max_index < 256 ? 1 : max_index < 65536 ? 2 : 4; - request_size = 0; - num_elts = 0; - num_out_glyphs = 0; - x = y = 0; - glyphset_info = this_glyphset_info; - } - - /* Convert absolute glyph position to relative-to-current-point - * position */ - glyphs[i].i.x = this_x - x; - glyphs[i].i.y = this_y - y; - - /* Start a new element for the first glyph, - * or for any glyph that has unexpected position, - * or if current element has too many glyphs. - * - * These same conditions are mirrored in _emit_glyphs_chunk(). - */ - if (_start_new_glyph_elt (num_out_glyphs, &glyphs[i])) { - num_elts++; - request_size += _cairo_sz_xGlyphElt; - } - - /* adjust current-position */ - x = this_x + scaled_glyph->x_advance; - y = this_y + scaled_glyph->y_advance; - - num_out_glyphs++; - request_size += width; - } - - if (num_elts) - status = _emit_glyphs_chunk (dst, glyphs, i, - scaled_font, op, src, attributes, - num_elts, width, glyphset_info); - - *remaining_glyphs = num_glyphs - i; - if (*remaining_glyphs && status == CAIRO_STATUS_SUCCESS) - status = CAIRO_INT_STATUS_UNSUPPORTED; - - return status; -} - -static cairo_bool_t -_cairo_xlib_surface_owns_font (cairo_xlib_surface_t *dst, - cairo_scaled_font_t *scaled_font) -{ - cairo_xlib_surface_font_private_t *font_private; - - font_private = scaled_font->surface_private; - if ((scaled_font->surface_backend != NULL && - scaled_font->surface_backend != &cairo_xlib_surface_backend) || - (font_private != NULL && font_private->display != dst->display)) - { - return FALSE; - } - - return TRUE; -} - -static cairo_int_status_t -_cairo_xlib_surface_show_glyphs (void *abstract_dst, - cairo_operator_t op, - cairo_pattern_t *src_pattern, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font, - int *remaining_glyphs) -{ - cairo_int_status_t status = CAIRO_STATUS_SUCCESS; - cairo_xlib_surface_t *dst = (cairo_xlib_surface_t*) abstract_dst; - - composite_operation_t operation; - cairo_surface_attributes_t attributes; - cairo_xlib_surface_t *src = NULL; - - cairo_solid_pattern_t solid_pattern; - - if (! CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT (dst)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - /* Just let unbounded operators go through the fallback code - * instead of trying to do the fixups here */ - if (!_cairo_operator_bounded_by_mask (op)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - /* Render <= 0.10 seems to have a bug with PictOpSrc and glyphs -- - * the solid source seems to be multiplied by the glyph mask, and - * then the entire thing is copied to the destination surface, - * including the fully transparent "background" of the rectangular - * glyph surface. */ - if (op == CAIRO_OPERATOR_SOURCE && - !CAIRO_SURFACE_RENDER_AT_LEAST(dst, 0, 11)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - /* We can only use our code if we either have no clip or - * have a real native clip region set. If we're using - * fallback clip masking, we have to go through the full - * fallback path. - */ - if (dst->base.clip && - (dst->base.clip->mode != CAIRO_CLIP_MODE_REGION || - dst->base.clip->surface != NULL)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - operation = _categorize_composite_operation (dst, op, src_pattern, TRUE); - if (operation == DO_UNSUPPORTED) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (! _cairo_xlib_surface_owns_font (dst, scaled_font)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - /* After passing all those tests, we're now committed to rendering - * these glyphs or to fail trying. We first upload any glyphs to - * the X server that it doesn't have already, then we draw - * them. - */ - - /* PictOpClear doesn't seem to work with CompositeText; it seems to ignore - * the mask (the glyphs). This code below was executed as a side effect - * of going through the _clip_and_composite fallback code for old_show_glyphs, - * so PictOpClear was never used with CompositeText before. - */ - if (op == CAIRO_OPERATOR_CLEAR) { - _cairo_pattern_init_solid (&solid_pattern, CAIRO_COLOR_WHITE, - CAIRO_CONTENT_COLOR); - src_pattern = &solid_pattern.base; - op = CAIRO_OPERATOR_DEST_OUT; - } - - if (src_pattern->type == CAIRO_PATTERN_TYPE_SOLID) { - status = _cairo_pattern_acquire_surface (src_pattern, &dst->base, - 0, 0, 1, 1, - (cairo_surface_t **) &src, - &attributes); - if (status) - goto BAIL0; - } else { - cairo_rectangle_int_t glyph_extents; - - status = _cairo_scaled_font_glyph_device_extents (scaled_font, - glyphs, - num_glyphs, - &glyph_extents); - if (status) - goto BAIL0; - - status = _cairo_pattern_acquire_surface (src_pattern, &dst->base, - glyph_extents.x, glyph_extents.y, - glyph_extents.width, glyph_extents.height, - (cairo_surface_t **) &src, - &attributes); - if (status) - goto BAIL0; - } - - operation = _recategorize_composite_operation (dst, op, src, - &attributes, TRUE); - if (operation == DO_UNSUPPORTED) { - status = CAIRO_INT_STATUS_UNSUPPORTED; - goto BAIL1; - } - - status = _cairo_xlib_surface_set_attributes (src, &attributes); - if (status) - goto BAIL1; - - _cairo_scaled_font_freeze_cache (scaled_font); - if (_cairo_xlib_surface_owns_font (dst, scaled_font)) { - status = _cairo_xlib_surface_emit_glyphs (dst, - (cairo_xlib_glyph_t *) glyphs, - num_glyphs, - scaled_font, - op, - src, - &attributes, - remaining_glyphs); - } else - status = CAIRO_INT_STATUS_UNSUPPORTED; - _cairo_scaled_font_thaw_cache (scaled_font); - - BAIL1: - if (src) - _cairo_pattern_release_surface (src_pattern, &src->base, &attributes); - if (src_pattern == &solid_pattern.base) - _cairo_pattern_fini (&solid_pattern.base); - BAIL0: - _cairo_xlib_display_notify (dst->display); - - return status; -} diff --git a/uppdev/plugin/cairo/lib/cairo-xlib-visual.c b/uppdev/plugin/cairo/lib/cairo-xlib-visual.c deleted file mode 100644 index f6eb1ee9b..000000000 --- a/uppdev/plugin/cairo/lib/cairo-xlib-visual.c +++ /dev/null @@ -1,185 +0,0 @@ -/* Cairo - a vector graphics library with display and print output - * - * Copyright © 2008 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Carl D. Worth - */ - -#include "cairoint.h" - -#include "cairo-xlib-private.h" - -/* A perceptual distance metric between two colors. No sqrt needed - * since the square of the distance is still a valid metric. */ - -/* XXX: This is currently using linear distance in RGB space which is - * decidedly not perceptually linear. If someone cared a lot about the - * quality, they might choose something else here. Then again, they - * might also choose not to use a PseudoColor visual... */ -static inline int -_color_distance (unsigned short r1, unsigned short g1, unsigned short b1, - unsigned short r2, unsigned short g2, unsigned short b2) -{ - r1 >>= 8; g1 >>= 8; b1 >>= 8; - r2 >>= 8; g2 >>= 8; b2 >>= 8; - - return ((r2 - r1) * (r2 - r1) + - (g2 - g1) * (g2 - g1) + - (b2 - b1) * (b2 - b1)); -} - -cairo_status_t -_cairo_xlib_visual_info_create (Display *dpy, - int screen, - VisualID visualid, - cairo_xlib_visual_info_t **out) -{ - cairo_xlib_visual_info_t *info; - Colormap colormap = DefaultColormap (dpy, screen); - XColor color; - int gray, red, green, blue; - int i, j, distance, min_distance = 0; - XColor colors[256]; - unsigned short cube_index_to_short[CUBE_SIZE]; - unsigned short ramp_index_to_short[RAMP_SIZE]; - unsigned char gray_to_pseudocolor[RAMP_SIZE]; - - for (i = 0; i < CUBE_SIZE; i++) - cube_index_to_short[i] = (0xffff * i + ((CUBE_SIZE-1)>>1)) / (CUBE_SIZE-1); - for (i = 0; i < RAMP_SIZE; i++) - ramp_index_to_short[i] = (0xffff * i + ((RAMP_SIZE-1)>>1)) / (RAMP_SIZE-1); - - info = malloc (sizeof (cairo_xlib_visual_info_t)); - if (info == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - info->visualid = visualid; - - /* Allocate a gray ramp and a color cube. - * Give up as soon as failures start. */ - - for (gray = 0; gray < RAMP_SIZE; gray++) { - color.red = color.green = color.blue = ramp_index_to_short[gray]; - if (! XAllocColor (dpy, colormap, &color)) - goto DONE_ALLOCATE; - } - - /* XXX: Could do this in a more clever order to have the best - * possible results from early failure. Could also choose a cube - * uniformly distributed in a better space than RGB. */ - for (red = 0; red < CUBE_SIZE; red++) { - for (green = 0; green < CUBE_SIZE; green++) { - for (blue = 0; blue < CUBE_SIZE; blue++) { - color.red = cube_index_to_short[red]; - color.green = cube_index_to_short[green]; - color.blue = cube_index_to_short[blue]; - color.pixel = 0; - color.flags = 0; - color.pad = 0; - if (! XAllocColor (dpy, colormap, &color)) - goto DONE_ALLOCATE; - } - } - } - DONE_ALLOCATE: - - for (i = 0; i < ARRAY_LENGTH (colors); i++) - colors[i].pixel = i; - XQueryColors (dpy, colormap, colors, ARRAY_LENGTH (colors)); - - /* Search for nearest colors within allocated colormap. */ - for (gray = 0; gray < RAMP_SIZE; gray++) { - for (i = 0; i < 256; i++) { - distance = _color_distance (ramp_index_to_short[gray], - ramp_index_to_short[gray], - ramp_index_to_short[gray], - colors[i].red, - colors[i].green, - colors[i].blue); - if (i == 0 || distance < min_distance) { - gray_to_pseudocolor[gray] = colors[i].pixel; - min_distance = distance; - if (!min_distance) - break; - } - } - } - for (red = 0; red < CUBE_SIZE; red++) { - for (green = 0; green < CUBE_SIZE; green++) { - for (blue = 0; blue < CUBE_SIZE; blue++) { - for (i = 0; i < 256; i++) { - distance = _color_distance (cube_index_to_short[red], - cube_index_to_short[green], - cube_index_to_short[blue], - colors[i].red, - colors[i].green, - colors[i].blue); - if (i == 0 || distance < min_distance) { - info->cube_to_pseudocolor[red][green][blue] = colors[i].pixel; - min_distance = distance; - if (!min_distance) - break; - } - } - } - } - } - - for (i = 0, j = 0; i < 256; i++) { - if (j < CUBE_SIZE - 1 && (((i<<8)+i) - (int)cube_index_to_short[j]) > ((int)cube_index_to_short[j+1] - ((i<<8)+i))) - j++; - info->field8_to_cube[i] = j; - - info->dither8_to_cube[i] = ((int)i - 128) / (CUBE_SIZE - 1); - } - for (i = 0, j = 0; i < 256; i++) { - if (j < RAMP_SIZE - 1 && (((i<<8)+i) - (int)ramp_index_to_short[j]) > ((int)ramp_index_to_short[j+1] - ((i<<8)+i))) - j++; - info->gray8_to_pseudocolor[i] = gray_to_pseudocolor[j]; - } - - for (i = 0; i < 256; i++) { - info->colors[i].a = 0xff; - info->colors[i].r = colors[i].red >> 8; - info->colors[i].g = colors[i].green >> 8; - info->colors[i].b = colors[i].blue >> 8; - } - - *out = info; - return CAIRO_STATUS_SUCCESS; -} - -void -_cairo_xlib_visual_info_destroy (Display *dpy, cairo_xlib_visual_info_t *info) -{ - /* No need for XFreeColors() whilst using DefaultColormap */ - free (info); -} diff --git a/uppdev/plugin/cairo/lib/cairo-xlib-xrender-private.h b/uppdev/plugin/cairo/lib/cairo-xlib-xrender-private.h deleted file mode 100644 index eee585cc4..000000000 --- a/uppdev/plugin/cairo/lib/cairo-xlib-xrender-private.h +++ /dev/null @@ -1,1090 +0,0 @@ -/* Cairo - a vector graphics library with display and print output - * - * Copyright © 2007 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - */ - -#ifndef CAIRO_XLIB_XRENDER_PRIVATE_H -#define CAIRO_XLIB_XRENDER_PRIVATE_H - -#include "cairo-features.h" -#include "cairo-compiler-private.h" - -#include - -#if CAIRO_HAS_XLIB_XRENDER_SURFACE - -#include "cairo-xlib-xrender.h" - -#include -#include - -/* We require Render >= 0.6. The following defines were only added in - * 0.10. Make sure they are defined. - */ - -/* Filters included in 0.10 */ -#ifndef FilterConvolution -#define FilterConvolution "convolution" -#endif - -/* Extended repeat attributes included in 0.10 */ -#ifndef RepeatNone -#define RepeatNone 0 -#define RepeatNormal 1 -#define RepeatPad 2 -#define RepeatReflect 3 -#endif - - -#else /* !CAIRO_HAS_XLIB_XRENDER_SURFACE */ - -/* Provide dummy symbols and macros to get it compile and take the fallback - * route, just like as if Xrender is not available in the server at run-time. */ - - -/* Functions */ - -/* As it happens, it is the case that, all libxrender functions - * take a pointer as first argument */ - -__attribute__((__unused__)) static void _void_consume (void *p, ...) { } -__attribute__((__unused__)) static void * _voidp_consume (void *p, ...) { return (void *)0; } -__attribute__((__unused__)) static int _int_consume (void *p, ...) { return 0; } -__attribute__((__unused__)) static void _void_consume_free (Display *p, XID n) { } - -#define XRenderQueryExtension _int_consume -#define XRenderQueryVersion _int_consume -#define XRenderQueryFormats _int_consume -#define XRenderQuerySubpixelOrder _int_consume -#define XRenderSetSubpixelOrder _int_consume -#define XRenderFindVisualFormat _voidp_consume -#define XRenderFindFormat _voidp_consume -#define XRenderFindStandardFormat _voidp_consume -#define XRenderQueryPictIndexValues _voidp_consume -#define XRenderCreatePicture _int_consume -#define XRenderChangePicture _void_consume -#define XRenderSetPictureClipRectangles _void_consume -#define XRenderSetPictureClipRegion _void_consume -#define XRenderSetPictureTransform _void_consume -#define XRenderFreePicture _void_consume_free -#define XRenderComposite _void_consume -#define XRenderCreateGlyphSet _int_consume -#define XRenderReferenceGlyphSet _int_consume -#define XRenderFreeGlyphSet _void_consume_free -#define XRenderAddGlyphs _void_consume -#define XRenderFreeGlyphs _void_consume -#define XRenderCompositeString8 _void_consume -#define XRenderCompositeString16 _void_consume -#define XRenderCompositeString32 _void_consume -#define XRenderCompositeText8 (cairo_xrender_composite_text_func_t) _void_consume -#define XRenderCompositeText16 _void_consume -#define XRenderCompositeText32 _void_consume -#define XRenderFillRectangle _void_consume -#define XRenderFillRectangles _void_consume -#define XRenderCompositeTrapezoids _void_consume -#define XRenderCompositeTriangles _void_consume -#define XRenderCompositeTriStrip _void_consume -#define XRenderCompositeTriFan _void_consume -#define XRenderCompositeDoublePoly _void_consume -#define XRenderParseColor _int_consume -#define XRenderCreateCursor _int_consume -#define XRenderQueryFilters _voidp_consume -#define XRenderSetPictureFilter _void_consume -#define XRenderCreateAnimCursor _int_consume -#define XRenderAddTraps _void_consume -#define XRenderCreateSolidFill _int_consume -#define XRenderCreateLinearGradient _int_consume -#define XRenderCreateRadialGradient _int_consume -#define XRenderCreateConicalGradient _int_consume - -#define cairo_xlib_surface_create_with_xrender_format _voidp_consume - - - -/* The rest of this file is copied from various Xrender header files, with - * the following copyright/license information: - * - * Copyright © 2000 SuSE, Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of SuSE not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. SuSE makes no representations about the - * suitability of this software for any purpose. It is provided "as is" - * without express or implied warranty. - * - * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE - * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Author: Keith Packard, SuSE, Inc. - */ - - -/* Copied from X11/extensions/render.h */ - -typedef unsigned long Glyph; -typedef unsigned long GlyphSet; -typedef unsigned long Picture; -typedef unsigned long PictFormat; - -#define BadPictFormat 0 -#define BadPicture 1 -#define BadPictOp 2 -#define BadGlyphSet 3 -#define BadGlyph 4 -#define RenderNumberErrors (BadGlyph+1) - -#define PictTypeIndexed 0 -#define PictTypeDirect 1 - -#define PictOpMinimum 0 -#define PictOpClear 0 -#define PictOpSrc 1 -#define PictOpDst 2 -#define PictOpOver 3 -#define PictOpOverReverse 4 -#define PictOpIn 5 -#define PictOpInReverse 6 -#define PictOpOut 7 -#define PictOpOutReverse 8 -#define PictOpAtop 9 -#define PictOpAtopReverse 10 -#define PictOpXor 11 -#define PictOpAdd 12 -#define PictOpSaturate 13 -#define PictOpMaximum 13 - -/* - * Operators only available in version 0.2 - */ -#define PictOpDisjointMinimum 0x10 -#define PictOpDisjointClear 0x10 -#define PictOpDisjointSrc 0x11 -#define PictOpDisjointDst 0x12 -#define PictOpDisjointOver 0x13 -#define PictOpDisjointOverReverse 0x14 -#define PictOpDisjointIn 0x15 -#define PictOpDisjointInReverse 0x16 -#define PictOpDisjointOut 0x17 -#define PictOpDisjointOutReverse 0x18 -#define PictOpDisjointAtop 0x19 -#define PictOpDisjointAtopReverse 0x1a -#define PictOpDisjointXor 0x1b -#define PictOpDisjointMaximum 0x1b - -#define PictOpConjointMinimum 0x20 -#define PictOpConjointClear 0x20 -#define PictOpConjointSrc 0x21 -#define PictOpConjointDst 0x22 -#define PictOpConjointOver 0x23 -#define PictOpConjointOverReverse 0x24 -#define PictOpConjointIn 0x25 -#define PictOpConjointInReverse 0x26 -#define PictOpConjointOut 0x27 -#define PictOpConjointOutReverse 0x28 -#define PictOpConjointAtop 0x29 -#define PictOpConjointAtopReverse 0x2a -#define PictOpConjointXor 0x2b -#define PictOpConjointMaximum 0x2b - -#define PolyEdgeSharp 0 -#define PolyEdgeSmooth 1 - -#define PolyModePrecise 0 -#define PolyModeImprecise 1 - -#define CPRepeat (1 << 0) -#define CPAlphaMap (1 << 1) -#define CPAlphaXOrigin (1 << 2) -#define CPAlphaYOrigin (1 << 3) -#define CPClipXOrigin (1 << 4) -#define CPClipYOrigin (1 << 5) -#define CPClipMask (1 << 6) -#define CPGraphicsExposure (1 << 7) -#define CPSubwindowMode (1 << 8) -#define CPPolyEdge (1 << 9) -#define CPPolyMode (1 << 10) -#define CPDither (1 << 11) -#define CPComponentAlpha (1 << 12) -#define CPLastBit 12 - -/* Filters included in 0.6 */ -#define FilterNearest "nearest" -#define FilterBilinear "bilinear" -/* Filters included in 0.10 */ -#define FilterConvolution "convolution" - -#define FilterFast "fast" -#define FilterGood "good" -#define FilterBest "best" - -#define FilterAliasNone -1 - -/* Subpixel orders included in 0.6 */ -#define SubPixelUnknown 0 -#define SubPixelHorizontalRGB 1 -#define SubPixelHorizontalBGR 2 -#define SubPixelVerticalRGB 3 -#define SubPixelVerticalBGR 4 -#define SubPixelNone 5 - -/* Extended repeat attributes included in 0.10 */ -#define RepeatNone 0 -#define RepeatNormal 1 -#define RepeatPad 2 -#define RepeatReflect 3 - - - -/* Copied from X11/extensions/Xrender.h */ - -typedef struct { - short red; - short redMask; - short green; - short greenMask; - short blue; - short blueMask; - short alpha; - short alphaMask; -} XRenderDirectFormat; - -typedef struct { - PictFormat id; - int type; - int depth; - XRenderDirectFormat direct; - Colormap colormap; -} XRenderPictFormat; - -#define PictFormatID (1 << 0) -#define PictFormatType (1 << 1) -#define PictFormatDepth (1 << 2) -#define PictFormatRed (1 << 3) -#define PictFormatRedMask (1 << 4) -#define PictFormatGreen (1 << 5) -#define PictFormatGreenMask (1 << 6) -#define PictFormatBlue (1 << 7) -#define PictFormatBlueMask (1 << 8) -#define PictFormatAlpha (1 << 9) -#define PictFormatAlphaMask (1 << 10) -#define PictFormatColormap (1 << 11) - -typedef struct _XRenderPictureAttributes { - int repeat; - Picture alpha_map; - int alpha_x_origin; - int alpha_y_origin; - int clip_x_origin; - int clip_y_origin; - Pixmap clip_mask; - Bool graphics_exposures; - int subwindow_mode; - int poly_edge; - int poly_mode; - Atom dither; - Bool component_alpha; -} XRenderPictureAttributes; - -typedef struct { - unsigned short red; - unsigned short green; - unsigned short blue; - unsigned short alpha; -} XRenderColor; - -typedef struct _XGlyphInfo { - unsigned short width; - unsigned short height; - short x; - short y; - short xOff; - short yOff; -} XGlyphInfo; - -typedef struct _XGlyphElt8 { - GlyphSet glyphset; - _Xconst char *chars; - int nchars; - int xOff; - int yOff; -} XGlyphElt8; - -typedef struct _XGlyphElt16 { - GlyphSet glyphset; - _Xconst unsigned short *chars; - int nchars; - int xOff; - int yOff; -} XGlyphElt16; - -typedef struct _XGlyphElt32 { - GlyphSet glyphset; - _Xconst unsigned int *chars; - int nchars; - int xOff; - int yOff; -} XGlyphElt32; - -typedef double XDouble; - -typedef struct _XPointDouble { - XDouble x, y; -} XPointDouble; - -#define XDoubleToFixed(f) ((XFixed) ((f) * 65536)) -#define XFixedToDouble(f) (((XDouble) (f)) / 65536) - -typedef int XFixed; - -typedef struct _XPointFixed { - XFixed x, y; -} XPointFixed; - -typedef struct _XLineFixed { - XPointFixed p1, p2; -} XLineFixed; - -typedef struct _XTriangle { - XPointFixed p1, p2, p3; -} XTriangle; - -typedef struct _XCircle { - XFixed x; - XFixed y; - XFixed radius; -} XCircle; - -typedef struct _XTrapezoid { - XFixed top, bottom; - XLineFixed left, right; -} XTrapezoid; - -typedef struct _XTransform { - XFixed matrix[3][3]; -} XTransform; - -typedef struct _XFilters { - int nfilter; - char **filter; - int nalias; - short *alias; -} XFilters; - -typedef struct _XIndexValue { - unsigned long pixel; - unsigned short red, green, blue, alpha; -} XIndexValue; - -typedef struct _XAnimCursor { - Cursor cursor; - unsigned long delay; -} XAnimCursor; - -typedef struct _XSpanFix { - XFixed left, right, y; -} XSpanFix; - -typedef struct _XTrap { - XSpanFix top, bottom; -} XTrap; - -typedef struct _XLinearGradient { - XPointFixed p1; - XPointFixed p2; -} XLinearGradient; - -typedef struct _XRadialGradient { - XCircle inner; - XCircle outer; -} XRadialGradient; - -typedef struct _XConicalGradient { - XPointFixed center; - XFixed angle; /* in degrees */ -} XConicalGradient; - -#define PictStandardARGB32 0 -#define PictStandardRGB24 1 -#define PictStandardA8 2 -#define PictStandardA4 3 -#define PictStandardA1 4 -#define PictStandardNUM 5 - - - -/* Copied from X11/extensions/renderproto.h */ - -#include - -#define Window CARD32 -#define Drawable CARD32 -#define Font CARD32 -#define Pixmap CARD32 -#define Cursor CARD32 -#define Colormap CARD32 -#define GContext CARD32 -#define Atom CARD32 -#define VisualID CARD32 -#define Time CARD32 -#define KeyCode CARD8 -#define KeySym CARD32 - -#define Picture CARD32 -#define PictFormat CARD32 -#define Fixed INT32 -#define Glyphset CARD32 -#define Glyph CARD32 - -/* - * data structures - */ - -typedef struct { - CARD16 red B16; - CARD16 redMask B16; - CARD16 green B16; - CARD16 greenMask B16; - CARD16 blue B16; - CARD16 blueMask B16; - CARD16 alpha B16; - CARD16 alphaMask B16; -} xDirectFormat; - -#define sz_xDirectFormat 16 - -typedef struct { - PictFormat id B32; - CARD8 type; - CARD8 depth; - CARD16 pad1 B16; - xDirectFormat direct; - Colormap colormap; -} xPictFormInfo; - -#define sz_xPictFormInfo 28 - -typedef struct { - VisualID visual; - PictFormat format; -} xPictVisual; - -#define sz_xPictVisual 8 - -typedef struct { - CARD8 depth; - CARD8 pad1; - CARD16 nPictVisuals B16; - CARD32 pad2 B32; -} xPictDepth; - -#define sz_xPictDepth 8 - -typedef struct { - CARD32 nDepth B32; - PictFormat fallback B32; -} xPictScreen; - -#define sz_xPictScreen 8 - -typedef struct { - CARD32 pixel B32; - CARD16 red B16; - CARD16 green B16; - CARD16 blue B16; - CARD16 alpha B16; -} xIndexValue; - -#define sz_xIndexValue 12 - -typedef struct { - CARD16 red B16; - CARD16 green B16; - CARD16 blue B16; - CARD16 alpha B16; -} xRenderColor; - -#define sz_xRenderColor 8 - -typedef struct { - Fixed x B32; - Fixed y B32; -} xPointFixed; - -#define sz_xPointFixed 8 - -typedef struct { - xPointFixed p1; - xPointFixed p2; -} xLineFixed; - -#define sz_xLineFixed 16 - -typedef struct { - xPointFixed p1, p2, p3; -} xTriangle; - -#define sz_xTriangle 24 - -typedef struct { - Fixed top B32; - Fixed bottom B32; - xLineFixed left; - xLineFixed right; -} xTrapezoid; - -#define sz_xTrapezoid 40 - -typedef struct { - CARD16 width B16; - CARD16 height B16; - INT16 x B16; - INT16 y B16; - INT16 xOff B16; - INT16 yOff B16; -} xGlyphInfo; - -#define sz_xGlyphInfo 12 - -typedef struct { - CARD8 len; - CARD8 pad1; - CARD16 pad2; - INT16 deltax; - INT16 deltay; -} xGlyphElt; - -#define sz_xGlyphElt 8 - -typedef struct { - Fixed l, r, y; -} xSpanFix; - -#define sz_xSpanFix 12 - -typedef struct { - xSpanFix top, bot; -} xTrap; - -#define sz_xTrap 24 - -/* - * requests and replies - */ -typedef struct { - CARD8 reqType; - CARD8 renderReqType; - CARD16 length B16; - CARD32 majorVersion B32; - CARD32 minorVersion B32; -} xRenderQueryVersionReq; - -#define sz_xRenderQueryVersionReq 12 - -typedef struct { - BYTE type; /* X_Reply */ - BYTE pad1; - CARD16 sequenceNumber B16; - CARD32 length B32; - CARD32 majorVersion B32; - CARD32 minorVersion B32; - CARD32 pad2 B32; - CARD32 pad3 B32; - CARD32 pad4 B32; - CARD32 pad5 B32; -} xRenderQueryVersionReply; - -#define sz_xRenderQueryVersionReply 32 - -typedef struct { - CARD8 reqType; - CARD8 renderReqType; - CARD16 length B16; -} xRenderQueryPictFormatsReq; - -#define sz_xRenderQueryPictFormatsReq 4 - -typedef struct { - BYTE type; /* X_Reply */ - BYTE pad1; - CARD16 sequenceNumber B16; - CARD32 length B32; - CARD32 numFormats B32; - CARD32 numScreens B32; - CARD32 numDepths B32; - CARD32 numVisuals B32; - CARD32 numSubpixel B32; /* Version 0.6 */ - CARD32 pad5 B32; -} xRenderQueryPictFormatsReply; - -#define sz_xRenderQueryPictFormatsReply 32 - -typedef struct { - CARD8 reqType; - CARD8 renderReqType; - CARD16 length B16; - PictFormat format B32; -} xRenderQueryPictIndexValuesReq; - -#define sz_xRenderQueryPictIndexValuesReq 8 - -typedef struct { - BYTE type; /* X_Reply */ - BYTE pad1; - CARD16 sequenceNumber B16; - CARD32 length B32; - CARD32 numIndexValues; - CARD32 pad2 B32; - CARD32 pad3 B32; - CARD32 pad4 B32; - CARD32 pad5 B32; - CARD32 pad6 B32; -} xRenderQueryPictIndexValuesReply; - -#define sz_xRenderQueryPictIndexValuesReply 32 - -typedef struct { - CARD8 reqType; - CARD8 renderReqType; - CARD16 length B16; - Picture pid B32; - Drawable drawable B32; - PictFormat format B32; - CARD32 mask B32; -} xRenderCreatePictureReq; - -#define sz_xRenderCreatePictureReq 20 - -typedef struct { - CARD8 reqType; - CARD8 renderReqType; - CARD16 length B16; - Picture picture B32; - CARD32 mask B32; -} xRenderChangePictureReq; - -#define sz_xRenderChangePictureReq 12 - -typedef struct { - CARD8 reqType; - CARD8 renderReqType; - CARD16 length B16; - Picture picture B32; - INT16 xOrigin B16; - INT16 yOrigin B16; -} xRenderSetPictureClipRectanglesReq; - -#define sz_xRenderSetPictureClipRectanglesReq 12 - -typedef struct { - CARD8 reqType; - CARD8 renderReqType; - CARD16 length B16; - Picture picture B32; -} xRenderFreePictureReq; - -#define sz_xRenderFreePictureReq 8 - -typedef struct { - CARD8 reqType; - CARD8 renderReqType; - CARD16 length B16; - CARD8 op; - CARD8 pad1; - CARD16 pad2 B16; - Picture src B32; - Picture mask B32; - Picture dst B32; - INT16 xSrc B16; - INT16 ySrc B16; - INT16 xMask B16; - INT16 yMask B16; - INT16 xDst B16; - INT16 yDst B16; - CARD16 width B16; - CARD16 height B16; -} xRenderCompositeReq; - -#define sz_xRenderCompositeReq 36 - -typedef struct { - CARD8 reqType; - CARD8 renderReqType; - CARD16 length B16; - Picture src B32; - Picture dst B32; - CARD32 colorScale B32; - CARD32 alphaScale B32; - INT16 xSrc B16; - INT16 ySrc B16; - INT16 xDst B16; - INT16 yDst B16; - CARD16 width B16; - CARD16 height B16; -} xRenderScaleReq; - -#define sz_xRenderScaleReq 32 - -typedef struct { - CARD8 reqType; - CARD8 renderReqType; - CARD16 length B16; - CARD8 op; - CARD8 pad1; - CARD16 pad2 B16; - Picture src B32; - Picture dst B32; - PictFormat maskFormat B32; - INT16 xSrc B16; - INT16 ySrc B16; -} xRenderTrapezoidsReq; - -#define sz_xRenderTrapezoidsReq 24 - -typedef struct { - CARD8 reqType; - CARD8 renderReqType; - CARD16 length B16; - CARD8 op; - CARD8 pad1; - CARD16 pad2 B16; - Picture src B32; - Picture dst B32; - PictFormat maskFormat B32; - INT16 xSrc B16; - INT16 ySrc B16; -} xRenderTrianglesReq; - -#define sz_xRenderTrianglesReq 24 - -typedef struct { - CARD8 reqType; - CARD8 renderReqType; - CARD16 length B16; - CARD8 op; - CARD8 pad1; - CARD16 pad2 B16; - Picture src B32; - Picture dst B32; - PictFormat maskFormat B32; - INT16 xSrc B16; - INT16 ySrc B16; -} xRenderTriStripReq; - -#define sz_xRenderTriStripReq 24 - -typedef struct { - CARD8 reqType; - CARD8 renderReqType; - CARD16 length B16; - CARD8 op; - CARD8 pad1; - CARD16 pad2 B16; - Picture src B32; - Picture dst B32; - PictFormat maskFormat B32; - INT16 xSrc B16; - INT16 ySrc B16; -} xRenderTriFanReq; - -#define sz_xRenderTriFanReq 24 - -typedef struct { - CARD8 reqType; - CARD8 renderReqType; - CARD16 length B16; - Glyphset gsid B32; - PictFormat format B32; -} xRenderCreateGlyphSetReq; - -#define sz_xRenderCreateGlyphSetReq 12 - -typedef struct { - CARD8 reqType; - CARD8 renderReqType; - CARD16 length B16; - Glyphset gsid B32; - Glyphset existing B32; -} xRenderReferenceGlyphSetReq; - -#define sz_xRenderReferenceGlyphSetReq 24 - -typedef struct { - CARD8 reqType; - CARD8 renderReqType; - CARD16 length B16; - Glyphset glyphset B32; -} xRenderFreeGlyphSetReq; - -#define sz_xRenderFreeGlyphSetReq 8 - -typedef struct { - CARD8 reqType; - CARD8 renderReqType; - CARD16 length B16; - Glyphset glyphset B32; - CARD32 nglyphs; -} xRenderAddGlyphsReq; - -#define sz_xRenderAddGlyphsReq 12 - -typedef struct { - CARD8 reqType; - CARD8 renderReqType; - CARD16 length B16; - Glyphset glyphset B32; -} xRenderFreeGlyphsReq; - -#define sz_xRenderFreeGlyphsReq 8 - -typedef struct { - CARD8 reqType; - CARD8 renderReqType; - CARD16 length B16; - CARD8 op; - CARD8 pad1; - CARD16 pad2 B16; - Picture src B32; - Picture dst B32; - PictFormat maskFormat B32; - Glyphset glyphset B32; - INT16 xSrc B16; - INT16 ySrc B16; -} xRenderCompositeGlyphsReq, xRenderCompositeGlyphs8Req, -xRenderCompositeGlyphs16Req, xRenderCompositeGlyphs32Req; - -#define sz_xRenderCompositeGlyphs8Req 28 -#define sz_xRenderCompositeGlyphs16Req 28 -#define sz_xRenderCompositeGlyphs32Req 28 - -/* 0.1 and higher */ - -typedef struct { - CARD8 reqType; - CARD8 renderReqType; - CARD16 length B16; - CARD8 op; - CARD8 pad1; - CARD16 pad2 B16; - Picture dst B32; - xRenderColor color; -} xRenderFillRectanglesReq; - -#define sz_xRenderFillRectanglesReq 20 - -/* 0.5 and higher */ - -typedef struct { - CARD8 reqType; - CARD8 renderReqType; - CARD16 length B16; - Cursor cid B32; - Picture src B32; - CARD16 x B16; - CARD16 y B16; -} xRenderCreateCursorReq; - -#define sz_xRenderCreateCursorReq 16 - -/* 0.6 and higher */ - -/* - * This can't use an array because 32-bit values may be in bitfields - */ -typedef struct { - Fixed matrix11 B32; - Fixed matrix12 B32; - Fixed matrix13 B32; - Fixed matrix21 B32; - Fixed matrix22 B32; - Fixed matrix23 B32; - Fixed matrix31 B32; - Fixed matrix32 B32; - Fixed matrix33 B32; -} xRenderTransform; - -#define sz_xRenderTransform 36 - -typedef struct { - CARD8 reqType; - CARD8 renderReqType; - CARD16 length B16; - Picture picture B32; - xRenderTransform transform; -} xRenderSetPictureTransformReq; - -#define sz_xRenderSetPictureTransformReq 44 - -typedef struct { - CARD8 reqType; - CARD8 renderReqType; - CARD16 length B16; - Drawable drawable B32; -} xRenderQueryFiltersReq; - -#define sz_xRenderQueryFiltersReq 8 - -typedef struct { - BYTE type; /* X_Reply */ - BYTE pad1; - CARD16 sequenceNumber B16; - CARD32 length B32; - CARD32 numAliases B32; /* LISTofCARD16 */ - CARD32 numFilters B32; /* LISTofSTRING8 */ - CARD32 pad2 B32; - CARD32 pad3 B32; - CARD32 pad4 B32; - CARD32 pad5 B32; -} xRenderQueryFiltersReply; - -#define sz_xRenderQueryFiltersReply 32 - -typedef struct { - CARD8 reqType; - CARD8 renderReqType; - CARD16 length B16; - Picture picture B32; - CARD16 nbytes B16; /* number of bytes in name */ - CARD16 pad B16; -} xRenderSetPictureFilterReq; - -#define sz_xRenderSetPictureFilterReq 12 - -/* 0.8 and higher */ - -typedef struct { - Cursor cursor B32; - CARD32 delay B32; -} xAnimCursorElt; - -#define sz_xAnimCursorElt 8 - -typedef struct { - CARD8 reqType; - CARD8 renderReqType; - CARD16 length B16; - Cursor cid B32; -} xRenderCreateAnimCursorReq; - -#define sz_xRenderCreateAnimCursorReq 8 - -/* 0.9 and higher */ - -typedef struct { - CARD8 reqType; - CARD8 renderReqType; - CARD16 length B16; - Picture picture; - INT16 xOff B16; - INT16 yOff B16; -} xRenderAddTrapsReq; - -#define sz_xRenderAddTrapsReq 12 - -/* 0.10 and higher */ - -typedef struct { - CARD8 reqType; - CARD8 renderReqType; - CARD16 length B16; - Picture pid B32; - xRenderColor color; -} xRenderCreateSolidFillReq; - -#define sz_xRenderCreateSolidFillReq 16 - -typedef struct { - CARD8 reqType; - CARD8 renderReqType; - CARD16 length B16; - Picture pid B32; - xPointFixed p1; - xPointFixed p2; - CARD32 nStops; -} xRenderCreateLinearGradientReq; - -#define sz_xRenderCreateLinearGradientReq 28 - -typedef struct { - CARD8 reqType; - CARD8 renderReqType; - CARD16 length B16; - Picture pid B32; - xPointFixed inner; - xPointFixed outer; - Fixed inner_radius; - Fixed outer_radius; - CARD32 nStops; -} xRenderCreateRadialGradientReq; - -#define sz_xRenderCreateRadialGradientReq 36 - -typedef struct { - CARD8 reqType; - CARD8 renderReqType; - CARD16 length B16; - Picture pid B32; - xPointFixed center; - Fixed angle; /* in degrees */ - CARD32 nStops; -} xRenderCreateConicalGradientReq; - -#define sz_xRenderCreateConicalGradientReq 24 - -#undef Window -#undef Drawable -#undef Font -#undef Pixmap -#undef Cursor -#undef Colormap -#undef GContext -#undef Atom -#undef VisualID -#undef Time -#undef KeyCode -#undef KeySym - -#undef Picture -#undef PictFormat -#undef Fixed -#undef Glyphset -#undef Glyph - - -#endif /* CAIRO_HAS_XLIB_XRENDER_SURFACE */ - -#endif /* CAIRO_XLIB_XRENDER_PRIVATE_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-xlib-xrender.h b/uppdev/plugin/cairo/lib/cairo-xlib-xrender.h deleted file mode 100644 index c1c4c6217..000000000 --- a/uppdev/plugin/cairo/lib/cairo-xlib-xrender.h +++ /dev/null @@ -1,66 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - */ - -#ifndef CAIRO_XLIB_XRENDER_H -#define CAIRO_XLIB_XRENDER_H - -#include "cairo.h" - -#if CAIRO_HAS_XLIB_XRENDER_SURFACE - -#include -#include - -CAIRO_BEGIN_DECLS - -cairo_public cairo_surface_t * -cairo_xlib_surface_create_with_xrender_format (Display *dpy, - Drawable drawable, - Screen *screen, - XRenderPictFormat *format, - int width, - int height); - -cairo_public XRenderPictFormat * -cairo_xlib_surface_get_xrender_format (cairo_surface_t *surface); - -CAIRO_END_DECLS - -#else /* CAIRO_HAS_XLIB_XRENDER_SURFACE */ -# error Cairo was not compiled with support for the xlib XRender backend -#endif /* CAIRO_HAS_XLIB_XRENDER_SURFACE */ - -#endif /* CAIRO_XLIB_XRENDER_H */ diff --git a/uppdev/plugin/cairo/lib/cairo-xlib.h b/uppdev/plugin/cairo/lib/cairo-xlib.h deleted file mode 100644 index 29e9f100e..000000000 --- a/uppdev/plugin/cairo/lib/cairo-xlib.h +++ /dev/null @@ -1,100 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - */ - -#ifndef CAIRO_XLIB_H -#define CAIRO_XLIB_H - -#include "cairo.h" - -#if CAIRO_HAS_XLIB_SURFACE - -#include - -CAIRO_BEGIN_DECLS - -cairo_public cairo_surface_t * -cairo_xlib_surface_create (Display *dpy, - Drawable drawable, - Visual *visual, - int width, - int height); - -cairo_public cairo_surface_t * -cairo_xlib_surface_create_for_bitmap (Display *dpy, - Pixmap bitmap, - Screen *screen, - int width, - int height); - -cairo_public void -cairo_xlib_surface_set_size (cairo_surface_t *surface, - int width, - int height); - -cairo_public void -cairo_xlib_surface_set_drawable (cairo_surface_t *surface, - Drawable drawable, - int width, - int height); - -cairo_public Display * -cairo_xlib_surface_get_display (cairo_surface_t *surface); - -cairo_public Drawable -cairo_xlib_surface_get_drawable (cairo_surface_t *surface); - -cairo_public Screen * -cairo_xlib_surface_get_screen (cairo_surface_t *surface); - -cairo_public Visual * -cairo_xlib_surface_get_visual (cairo_surface_t *surface); - -cairo_public int -cairo_xlib_surface_get_depth (cairo_surface_t *surface); - -cairo_public int -cairo_xlib_surface_get_width (cairo_surface_t *surface); - -cairo_public int -cairo_xlib_surface_get_height (cairo_surface_t *surface); - -CAIRO_END_DECLS - -#else /* CAIRO_HAS_XLIB_SURFACE */ -# error Cairo was not compiled with support for the xlib backend -#endif /* CAIRO_HAS_XLIB_SURFACE */ - -#endif /* CAIRO_XLIB_H */ diff --git a/uppdev/plugin/cairo/lib/cairo.c b/uppdev/plugin/cairo/lib/cairo.c deleted file mode 100644 index cefc92538..000000000 --- a/uppdev/plugin/cairo/lib/cairo.c +++ /dev/null @@ -1,3833 +0,0 @@ -/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - */ - -#include "cairoint.h" -#include "cairo-private.h" - -#include "cairo-arc-private.h" -#include "cairo-path-private.h" - -#define CAIRO_TOLERANCE_MINIMUM _cairo_fixed_to_double(1) - -static const cairo_t _cairo_nil = { - CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */ - CAIRO_STATUS_NO_MEMORY, /* status */ - { 0, 0, 0, NULL }, /* user_data */ - NULL, /* gstate */ - {{ /* gstate_tail */ - 0 - }}, - NULL, /* gstate_freelist */ - {{ /* path */ - { 0, 0 }, /* last_move_point */ - { 0, 0 }, /* current point */ - FALSE, /* has_current_point */ - FALSE, /* has_curve_to */ - NULL, {{NULL}} /* buf_tail, buf_head */ - }} -}; - -#include - -/** - * _cairo_error: - * @status: a status value indicating an error, (eg. not - * %CAIRO_STATUS_SUCCESS) - * - * Checks that status is an error status, but does nothing else. - * - * All assignments of an error status to any user-visible object - * within the cairo application should result in a call to - * _cairo_error(). - * - * The purpose of this function is to allow the user to set a - * breakpoint in _cairo_error() to generate a stack trace for when the - * user causes cairo to detect an error. - * - * Return value: the error status. - **/ -cairo_status_t -_cairo_error (cairo_status_t status) -{ - assert (_cairo_status_is_error (status)); - - return status; -} - -/** - * _cairo_set_error: - * @cr: a cairo context - * @status: a status value indicating an error - * - * Atomically sets cr->status to @status and calls _cairo_error; - * Does nothing if status is %CAIRO_STATUS_SUCCESS. - * - * All assignments of an error status to cr->status should happen - * through _cairo_set_error(). Note that due to the nature of the atomic - * operation, it is not safe to call this function on the nil objects. - * - * The purpose of this function is to allow the user to set a - * breakpoint in _cairo_error() to generate a stack trace for when the - * user causes cairo to detect an error. - **/ -static void -_cairo_set_error (cairo_t *cr, cairo_status_t status) -{ - if (status == CAIRO_STATUS_SUCCESS) - return; - - /* Don't overwrite an existing error. This preserves the first - * error, which is the most significant. */ - _cairo_status_set_error (&cr->status, status); - - status = _cairo_error (status); -} - -/** - * cairo_create: - * @target: target surface for the context - * - * Creates a new #cairo_t with all graphics state parameters set to - * default values and with @target as a target surface. The target - * surface should be constructed with a backend-specific function such - * as cairo_image_surface_create() (or any other - * cairo_backend_surface_create() variant). - * - * This function references @target, so you can immediately - * call cairo_surface_destroy() on it if you don't need to - * maintain a separate reference to it. - * - * Return value: a newly allocated #cairo_t with a reference - * count of 1. The initial reference count should be released - * with cairo_destroy() when you are done using the #cairo_t. - * This function never returns %NULL. If memory cannot be - * allocated, a special #cairo_t object will be returned on - * which cairo_status() returns %CAIRO_STATUS_NO_MEMORY. - * You can use this object normally, but no drawing will - * be done. - **/ -cairo_t * -cairo_create (cairo_surface_t *target) -{ - cairo_t *cr; - cairo_status_t status; - - /* special case OOM in order to avoid another allocation */ - if (target && target->status == CAIRO_STATUS_NO_MEMORY) - return (cairo_t *) &_cairo_nil; - - cr = malloc (sizeof (cairo_t)); - if (cr == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - return (cairo_t *) &_cairo_nil; - } - - CAIRO_REFERENCE_COUNT_INIT (&cr->ref_count, 1); - - cr->status = CAIRO_STATUS_SUCCESS; - - _cairo_user_data_array_init (&cr->user_data); - _cairo_path_fixed_init (cr->path); - - cr->gstate = cr->gstate_tail; - cr->gstate_freelist = NULL; - status = _cairo_gstate_init (cr->gstate, target); - - if (status) - _cairo_set_error (cr, status); - - return cr; -} -slim_hidden_def (cairo_create); - -/** - * cairo_reference: - * @cr: a #cairo_t - * - * Increases the reference count on @cr by one. This prevents - * @cr from being destroyed until a matching call to cairo_destroy() - * is made. - * - * The number of references to a #cairo_t can be get using - * cairo_get_reference_count(). - * - * Return value: the referenced #cairo_t. - **/ -cairo_t * -cairo_reference (cairo_t *cr) -{ - if (cr == NULL || CAIRO_REFERENCE_COUNT_IS_INVALID (&cr->ref_count)) - return cr; - - assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&cr->ref_count)); - - _cairo_reference_count_inc (&cr->ref_count); - - return cr; -} - -/** - * cairo_destroy: - * @cr: a #cairo_t - * - * Decreases the reference count on @cr by one. If the result - * is zero, then @cr and all associated resources are freed. - * See cairo_reference(). - **/ -void -cairo_destroy (cairo_t *cr) -{ - if (cr == NULL || CAIRO_REFERENCE_COUNT_IS_INVALID (&cr->ref_count)) - return; - - assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&cr->ref_count)); - - if (! _cairo_reference_count_dec_and_test (&cr->ref_count)) - return; - - while (cr->gstate != cr->gstate_tail) { - if (_cairo_gstate_restore (&cr->gstate, &cr->gstate_freelist)) - break; - } - - _cairo_gstate_fini (cr->gstate); - while (cr->gstate_freelist != NULL) { - cairo_gstate_t *gstate = cr->gstate_freelist; - cr->gstate_freelist = gstate->next; - free (gstate); - } - - _cairo_path_fixed_fini (cr->path); - - _cairo_user_data_array_fini (&cr->user_data); - - free (cr); -} -slim_hidden_def (cairo_destroy); - -/** - * cairo_get_user_data: - * @cr: a #cairo_t - * @key: the address of the #cairo_user_data_key_t the user data was - * attached to - * - * Return user data previously attached to @cr using the specified - * key. If no user data has been attached with the given key this - * function returns %NULL. - * - * Return value: the user data previously attached or %NULL. - * - * Since: 1.4 - **/ -void * -cairo_get_user_data (cairo_t *cr, - const cairo_user_data_key_t *key) -{ - return _cairo_user_data_array_get_data (&cr->user_data, - key); -} - -/** - * cairo_set_user_data: - * @cr: a #cairo_t - * @key: the address of a #cairo_user_data_key_t to attach the user data to - * @user_data: the user data to attach to the #cairo_t - * @destroy: a #cairo_destroy_func_t which will be called when the - * #cairo_t is destroyed or when new user data is attached using the - * same key. - * - * Attach user data to @cr. To remove user data from a surface, - * call this function with the key that was used to set it and %NULL - * for @data. - * - * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a - * slot could not be allocated for the user data. - * - * Since: 1.4 - **/ -cairo_status_t -cairo_set_user_data (cairo_t *cr, - const cairo_user_data_key_t *key, - void *user_data, - cairo_destroy_func_t destroy) -{ - if (CAIRO_REFERENCE_COUNT_IS_INVALID (&cr->ref_count)) - return cr->status; - - return _cairo_user_data_array_set_data (&cr->user_data, - key, user_data, destroy); -} - -/** - * cairo_get_reference_count: - * @cr: a #cairo_t - * - * Returns the current reference count of @cr. - * - * Return value: the current reference count of @cr. If the - * object is a nil object, 0 will be returned. - * - * Since: 1.4 - **/ -unsigned int -cairo_get_reference_count (cairo_t *cr) -{ - if (cr == NULL || CAIRO_REFERENCE_COUNT_IS_INVALID (&cr->ref_count)) - return 0; - - return CAIRO_REFERENCE_COUNT_GET_VALUE (&cr->ref_count); -} - -/** - * cairo_save: - * @cr: a #cairo_t - * - * Makes a copy of the current state of @cr and saves it - * on an internal stack of saved states for @cr. When - * cairo_restore() is called, @cr will be restored to - * the saved state. Multiple calls to cairo_save() and - * cairo_restore() can be nested; each call to cairo_restore() - * restores the state from the matching paired cairo_save(). - * - * It isn't necessary to clear all saved states before - * a #cairo_t is freed. If the reference count of a #cairo_t - * drops to zero in response to a call to cairo_destroy(), - * any saved states will be freed along with the #cairo_t. - **/ -void -cairo_save (cairo_t *cr) -{ - cairo_status_t status; - - if (cr->status) - return; - - status = _cairo_gstate_save (&cr->gstate, &cr->gstate_freelist); - if (status) - _cairo_set_error (cr, status); -} -slim_hidden_def(cairo_save); - -/** - * cairo_restore: - * @cr: a #cairo_t - * - * Restores @cr to the state saved by a preceding call to - * cairo_save() and removes that state from the stack of - * saved states. - **/ -void -cairo_restore (cairo_t *cr) -{ - cairo_status_t status; - - if (cr->status) - return; - - status = _cairo_gstate_restore (&cr->gstate, &cr->gstate_freelist); - if (status) - _cairo_set_error (cr, status); -} -slim_hidden_def(cairo_restore); - -/** - * cairo_push_group: - * @cr: a cairo context - * - * Temporarily redirects drawing to an intermediate surface known as a - * group. The redirection lasts until the group is completed by a call - * to cairo_pop_group() or cairo_pop_group_to_source(). These calls - * provide the result of any drawing to the group as a pattern, - * (either as an explicit object, or set as the source pattern). - * - * This group functionality can be convenient for performing - * intermediate compositing. One common use of a group is to render - * objects as opaque within the group, (so that they occlude each - * other), and then blend the result with translucence onto the - * destination. - * - * Groups can be nested arbitrarily deep by making balanced calls to - * cairo_push_group()/cairo_pop_group(). Each call pushes/pops the new - * target group onto/from a stack. - * - * The cairo_push_group() function calls cairo_save() so that any - * changes to the graphics state will not be visible outside the - * group, (the pop_group functions call cairo_restore()). - * - * By default the intermediate group will have a content type of - * %CAIRO_CONTENT_COLOR_ALPHA. Other content types can be chosen for - * the group by using cairo_push_group_with_content() instead. - * - * As an example, here is how one might fill and stroke a path with - * translucence, but without any portion of the fill being visible - * under the stroke: - * - * - * cairo_push_group (cr); - * cairo_set_source (cr, fill_pattern); - * cairo_fill_preserve (cr); - * cairo_set_source (cr, stroke_pattern); - * cairo_stroke (cr); - * cairo_pop_group_to_source (cr); - * cairo_paint_with_alpha (cr, alpha); - * - * - * Since: 1.2 - */ -void -cairo_push_group (cairo_t *cr) -{ - cairo_push_group_with_content (cr, CAIRO_CONTENT_COLOR_ALPHA); -} -slim_hidden_def(cairo_push_group); - -/** - * cairo_push_group_with_content: - * @cr: a cairo context - * @content: a %#cairo_content_t indicating the type of group that - * will be created - * - * Temporarily redirects drawing to an intermediate surface known as a - * group. The redirection lasts until the group is completed by a call - * to cairo_pop_group() or cairo_pop_group_to_source(). These calls - * provide the result of any drawing to the group as a pattern, - * (either as an explicit object, or set as the source pattern). - * - * The group will have a content type of @content. The ability to - * control this content type is the only distinction between this - * function and cairo_push_group() which you should see for a more - * detailed description of group rendering. - * - * Since: 1.2 - */ -void -cairo_push_group_with_content (cairo_t *cr, cairo_content_t content) -{ - cairo_status_t status; - cairo_rectangle_int_t extents; - cairo_surface_t *parent_surface, *group_surface = NULL; - - if (cr->status) - return; - - parent_surface = _cairo_gstate_get_target (cr->gstate); - /* Get the extents that we'll use in creating our new group surface */ - status = _cairo_surface_get_extents (parent_surface, &extents); - if (status) - goto bail; - status = _cairo_clip_intersect_to_rectangle (_cairo_gstate_get_clip (cr->gstate), &extents); - if (status) - goto bail; - - group_surface = cairo_surface_create_similar (_cairo_gstate_get_target (cr->gstate), - content, - extents.width, - extents.height); - status = cairo_surface_status (group_surface); - if (status) - goto bail; - - /* Set device offsets on the new surface so that logically it appears at - * the same location on the parent surface -- when we pop_group this, - * the source pattern will get fixed up for the appropriate target surface - * device offsets, so we want to set our own surface offsets from /that/, - * and not from the device origin. */ - cairo_surface_set_device_offset (group_surface, - parent_surface->device_transform.x0 - extents.x, - parent_surface->device_transform.y0 - extents.y); - - /* create a new gstate for the redirect */ - cairo_save (cr); - if (cr->status) - goto bail; - - status = _cairo_gstate_redirect_target (cr->gstate, group_surface); - -bail: - cairo_surface_destroy (group_surface); - if (status) - _cairo_set_error (cr, status); -} -slim_hidden_def(cairo_push_group_with_content); - -/** - * cairo_pop_group: - * @cr: a cairo context - * - * Terminates the redirection begun by a call to cairo_push_group() or - * cairo_push_group_with_content() and returns a new pattern - * containing the results of all drawing operations performed to the - * group. - * - * The cairo_pop_group() function calls cairo_restore(), (balancing a - * call to cairo_save() by the push_group function), so that any - * changes to the graphics state will not be visible outside the - * group. - * - * Return value: a newly created (surface) pattern containing the - * results of all drawing operations performed to the group. The - * caller owns the returned object and should call - * cairo_pattern_destroy() when finished with it. - * - * Since: 1.2 - **/ -cairo_pattern_t * -cairo_pop_group (cairo_t *cr) -{ - cairo_surface_t *group_surface, *parent_target; - cairo_pattern_t *group_pattern = (cairo_pattern_t*) &_cairo_pattern_nil.base; - cairo_matrix_t group_matrix; - - if (cr->status) - return group_pattern; - - /* Grab the active surfaces */ - group_surface = _cairo_gstate_get_target (cr->gstate); - parent_target = _cairo_gstate_get_parent_target (cr->gstate); - - /* Verify that we are at the right nesting level */ - if (parent_target == NULL) { - _cairo_set_error (cr, CAIRO_STATUS_INVALID_POP_GROUP); - return group_pattern; - } - - /* We need to save group_surface before we restore; we don't need - * to reference parent_target and original_target, since the - * gstate will still hold refs to them once we restore. */ - group_surface = cairo_surface_reference (group_surface); - - cairo_restore (cr); - - if (cr->status) - goto done; - - group_pattern = cairo_pattern_create_for_surface (group_surface); - if (cairo_pattern_status (group_pattern)) { - _cairo_set_error (cr, cairo_pattern_status (group_pattern)); - 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); - } - -done: - cairo_surface_destroy (group_surface); - - return group_pattern; -} -slim_hidden_def(cairo_pop_group); - -/** - * cairo_pop_group_to_source: - * @cr: a cairo context - * - * Terminates the redirection begun by a call to cairo_push_group() or - * cairo_push_group_with_content() and installs the resulting pattern - * as the source pattern in the given cairo context. - * - * The behavior of this function is equivalent to the sequence of - * operations: - * - * - * #cairo_pattern_t *group = cairo_pop_group (cr); - * cairo_set_source (cr, group); - * cairo_pattern_destroy (group); - * - * - * but is more convenient as their is no need for a variable to store - * the short-lived pointer to the pattern. - * - * The cairo_pop_group() function calls cairo_restore(), (balancing a - * call to cairo_save() by the push_group function), so that any - * changes to the graphics state will not be visible outside the - * group. - * - * Since: 1.2 - **/ -void -cairo_pop_group_to_source (cairo_t *cr) -{ - cairo_pattern_t *group_pattern; - - group_pattern = cairo_pop_group (cr); - cairo_set_source (cr, group_pattern); - cairo_pattern_destroy (group_pattern); -} -slim_hidden_def(cairo_pop_group_to_source); - -/** - * cairo_set_operator: - * @cr: a #cairo_t - * @op: a compositing operator, specified as a #cairo_operator_t - * - * Sets the compositing operator to be used for all drawing - * operations. See #cairo_operator_t for details on the semantics of - * each available compositing operator. - * - * The default operator is %CAIRO_OPERATOR_OVER. - **/ -void -cairo_set_operator (cairo_t *cr, cairo_operator_t op) -{ - cairo_status_t status; - - if (cr->status) - return; - - status = _cairo_gstate_set_operator (cr->gstate, op); - if (status) - _cairo_set_error (cr, status); -} -slim_hidden_def (cairo_set_operator); - -/** - * cairo_set_source_rgb - * @cr: a cairo context - * @red: red component of color - * @green: green component of color - * @blue: blue component of color - * - * Sets the source pattern within @cr to an opaque color. This opaque - * color will then be used for any subsequent drawing operation until - * a new source pattern is set. - * - * The color components are floating point numbers in the range 0 to - * 1. If the values passed in are outside that range, they will be - * clamped. - * - * The default source pattern is opaque black, (that is, it is - * equivalent to cairo_set_source_rgb(cr, 0.0, 0.0, 0.0)). - **/ -void -cairo_set_source_rgb (cairo_t *cr, double red, double green, double blue) -{ - cairo_pattern_t *pattern; - - if (cr->status) - return; - - /* push the current pattern to the freed lists */ - cairo_set_source (cr, (cairo_pattern_t *) &_cairo_pattern_none); - - pattern = cairo_pattern_create_rgb (red, green, blue); - cairo_set_source (cr, pattern); - cairo_pattern_destroy (pattern); -} - -/** - * cairo_set_source_rgba: - * @cr: a cairo context - * @red: red component of color - * @green: green component of color - * @blue: blue component of color - * @alpha: alpha component of color - * - * Sets the source pattern within @cr to a translucent color. This - * color will then be used for any subsequent drawing operation until - * a new source pattern is set. - * - * The color and alpha components are floating point numbers in the - * range 0 to 1. If the values passed in are outside that range, they - * will be clamped. - * - * The default source pattern is opaque black, (that is, it is - * equivalent to cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0)). - **/ -void -cairo_set_source_rgba (cairo_t *cr, - double red, double green, double blue, - double alpha) -{ - cairo_pattern_t *pattern; - - if (cr->status) - return; - - /* push the current pattern to the freed lists */ - cairo_set_source (cr, (cairo_pattern_t *) &_cairo_pattern_none); - - pattern = cairo_pattern_create_rgba (red, green, blue, alpha); - cairo_set_source (cr, pattern); - cairo_pattern_destroy (pattern); -} - -/** - * cairo_set_source_surface: - * @cr: a cairo context - * @surface: a surface to be used to set the source pattern - * @x: User-space X coordinate for surface origin - * @y: User-space Y coordinate for surface origin - * - * This is a convenience function for creating a pattern from @surface - * and setting it as the source in @cr with cairo_set_source(). - * - * The @x and @y parameters give the user-space coordinate at which - * the surface origin should appear. (The surface origin is its - * upper-left corner before any transformation has been applied.) The - * @x and @y patterns are negated and then set as translation values - * in the pattern matrix. - * - * Other than the initial translation pattern matrix, as described - * above, all other pattern attributes, (such as its extend mode), are - * set to the default values as in cairo_pattern_create_for_surface(). - * The resulting pattern can be queried with cairo_get_source() so - * that these attributes can be modified if desired, (eg. to create a - * repeating pattern with cairo_pattern_set_extend()). - **/ -void -cairo_set_source_surface (cairo_t *cr, - cairo_surface_t *surface, - double x, - double y) -{ - cairo_pattern_t *pattern; - cairo_matrix_t matrix; - - if (cr->status) - return; - - /* push the current pattern to the freed lists */ - cairo_set_source (cr, (cairo_pattern_t *) &_cairo_pattern_none); - - pattern = cairo_pattern_create_for_surface (surface); - - cairo_matrix_init_translate (&matrix, -x, -y); - cairo_pattern_set_matrix (pattern, &matrix); - - cairo_set_source (cr, pattern); - cairo_pattern_destroy (pattern); -} -slim_hidden_def (cairo_set_source_surface); - -/** - * cairo_set_source - * @cr: a cairo context - * @source: a #cairo_pattern_t to be used as the source for - * subsequent drawing operations. - * - * Sets the source pattern within @cr to @source. This pattern - * will then be used for any subsequent drawing operation until a new - * source pattern is set. - * - * Note: The pattern's transformation matrix will be locked to the - * user space in effect at the time of cairo_set_source(). This means - * that further modifications of the current transformation matrix - * will not affect the source pattern. See cairo_pattern_set_matrix(). - * - * The default source pattern is a solid pattern that is opaque black, - * (that is, it is equivalent to cairo_set_source_rgb(cr, 0.0, 0.0, - * 0.0)). - **/ -void -cairo_set_source (cairo_t *cr, cairo_pattern_t *source) -{ - cairo_status_t status; - - if (cr->status) - return; - - if (source == NULL) { - _cairo_set_error (cr, CAIRO_STATUS_NULL_POINTER); - return; - } - - if (source->status) { - _cairo_set_error (cr, source->status); - return; - } - - status = _cairo_gstate_set_source (cr->gstate, source); - if (status) - _cairo_set_error (cr, status); -} -slim_hidden_def (cairo_set_source); - -/** - * cairo_get_source: - * @cr: a cairo context - * - * Gets the current source pattern for @cr. - * - * Return value: the current source pattern. This object is owned by - * cairo. To keep a reference to it, you must call - * cairo_pattern_reference(). - **/ -cairo_pattern_t * -cairo_get_source (cairo_t *cr) -{ - if (cr->status) - return (cairo_pattern_t*) &_cairo_pattern_nil.base; - - return _cairo_gstate_get_source (cr->gstate); -} - -/** - * cairo_set_tolerance: - * @cr: a #cairo_t - * @tolerance: the tolerance, in device units (typically pixels) - * - * Sets the tolerance used when converting paths into trapezoids. - * Curved segments of the path will be subdivided until the maximum - * deviation between the original path and the polygonal approximation - * is less than @tolerance. The default value is 0.1. A larger - * value will give better performance, a smaller value, better - * appearance. (Reducing the value from the default value of 0.1 - * is unlikely to improve appearance significantly.) - **/ -void -cairo_set_tolerance (cairo_t *cr, double tolerance) -{ - cairo_status_t status; - - if (cr->status) - return; - - _cairo_restrict_value (&tolerance, CAIRO_TOLERANCE_MINIMUM, tolerance); - - status = _cairo_gstate_set_tolerance (cr->gstate, tolerance); - if (status) - _cairo_set_error (cr, status); -} - -/** - * cairo_set_antialias: - * @cr: a #cairo_t - * @antialias: the new antialiasing mode - * - * Set the antialiasing mode of the rasterizer used for drawing shapes. - * This value is a hint, and a particular backend may or may not support - * a particular value. At the current time, no backend supports - * %CAIRO_ANTIALIAS_SUBPIXEL when drawing shapes. - * - * Note that this option does not affect text rendering, instead see - * cairo_font_options_set_antialias(). - **/ -void -cairo_set_antialias (cairo_t *cr, cairo_antialias_t antialias) -{ - cairo_status_t status; - - if (cr->status) - return; - - status = _cairo_gstate_set_antialias (cr->gstate, antialias); - if (status) - _cairo_set_error (cr, status); -} - -/** - * cairo_set_fill_rule: - * @cr: a #cairo_t - * @fill_rule: a fill rule, specified as a #cairo_fill_rule_t - * - * Set the current fill rule within the cairo context. The fill rule - * is used to determine which regions are inside or outside a complex - * (potentially self-intersecting) path. The current fill rule affects - * both cairo_fill() and cairo_clip(). See #cairo_fill_rule_t for details - * on the semantics of each available fill rule. - * - * The default fill rule is %CAIRO_FILL_RULE_WINDING. - **/ -void -cairo_set_fill_rule (cairo_t *cr, cairo_fill_rule_t fill_rule) -{ - cairo_status_t status; - - if (cr->status) - return; - - status = _cairo_gstate_set_fill_rule (cr->gstate, fill_rule); - if (status) - _cairo_set_error (cr, status); -} - -/** - * cairo_set_line_width: - * @cr: a #cairo_t - * @width: a line width - * - * Sets the current line width within the cairo context. The line - * width value specifies the diameter of a pen that is circular in - * user space, (though device-space pen may be an ellipse in general - * due to scaling/shear/rotation of the CTM). - * - * Note: When the description above refers to user space and CTM it - * refers to the user space and CTM in effect at the time of the - * stroking operation, not the user space and CTM in effect at the - * time of the call to cairo_set_line_width(). The simplest usage - * makes both of these spaces identical. That is, if there is no - * change to the CTM between a call to cairo_set_line_with() and the - * stroking operation, then one can just pass user-space values to - * cairo_set_line_width() and ignore this note. - * - * As with the other stroke parameters, the current line width is - * examined by cairo_stroke(), cairo_stroke_extents(), and - * cairo_stroke_to_path(), but does not have any effect during path - * construction. - * - * The default line width value is 2.0. - **/ -void -cairo_set_line_width (cairo_t *cr, double width) -{ - cairo_status_t status; - - if (cr->status) - return; - - _cairo_restrict_value (&width, 0.0, width); - - status = _cairo_gstate_set_line_width (cr->gstate, width); - if (status) - _cairo_set_error (cr, status); -} -slim_hidden_def (cairo_set_line_width); - -/** - * cairo_set_line_cap: - * @cr: a cairo context - * @line_cap: a line cap style - * - * Sets the current line cap style within the cairo context. See - * #cairo_line_cap_t for details about how the available line cap - * styles are drawn. - * - * As with the other stroke parameters, the current line cap style is - * examined by cairo_stroke(), cairo_stroke_extents(), and - * cairo_stroke_to_path(), but does not have any effect during path - * construction. - * - * The default line cap style is %CAIRO_LINE_CAP_BUTT. - **/ -void -cairo_set_line_cap (cairo_t *cr, cairo_line_cap_t line_cap) -{ - cairo_status_t status; - - if (cr->status) - return; - - status = _cairo_gstate_set_line_cap (cr->gstate, line_cap); - if (status) - _cairo_set_error (cr, status); -} -slim_hidden_def (cairo_set_line_cap); - -/** - * cairo_set_line_join: - * @cr: a cairo context - * @line_join: a line join style - * - * Sets the current line join style within the cairo context. See - * #cairo_line_join_t for details about how the available line join - * styles are drawn. - * - * As with the other stroke parameters, the current line join style is - * examined by cairo_stroke(), cairo_stroke_extents(), and - * cairo_stroke_to_path(), but does not have any effect during path - * construction. - * - * The default line join style is %CAIRO_LINE_JOIN_MITER. - **/ -void -cairo_set_line_join (cairo_t *cr, cairo_line_join_t line_join) -{ - cairo_status_t status; - - if (cr->status) - return; - - status = _cairo_gstate_set_line_join (cr->gstate, line_join); - if (status) - _cairo_set_error (cr, status); -} -slim_hidden_def (cairo_set_line_join); - -/** - * cairo_set_dash: - * @cr: a cairo context - * @dashes: an array specifying alternate lengths of on and off stroke portions - * @num_dashes: the length of the dashes array - * @offset: an offset into the dash pattern at which the stroke should start - * - * Sets the dash pattern to be used by cairo_stroke(). A dash pattern - * is specified by @dashes, an array of positive values. Each value - * provides the length of alternate "on" and "off" portions of the - * stroke. The @offset specifies an offset into the pattern at which - * the stroke begins. - * - * Each "on" segment will have caps applied as if the segment were a - * separate sub-path. In particular, it is valid to use an "on" length - * of 0.0 with %CAIRO_LINE_CAP_ROUND or %CAIRO_LINE_CAP_SQUARE in order - * to distributed dots or squares along a path. - * - * Note: The length values are in user-space units as evaluated at the - * time of stroking. This is not necessarily the same as the user - * space at the time of cairo_set_dash(). - * - * If @num_dashes is 0 dashing is disabled. - * - * If @num_dashes is 1 a symmetric pattern is assumed with alternating - * on and off portions of the size specified by the single value in - * @dashes. - * - * If any value in @dashes is negative, or if all values are 0, then - * @cr will be put into an error state with a status of - * #%CAIRO_STATUS_INVALID_DASH. - **/ -void -cairo_set_dash (cairo_t *cr, - const double *dashes, - int num_dashes, - double offset) -{ - cairo_status_t status; - - if (cr->status) - return; - - status = _cairo_gstate_set_dash (cr->gstate, - dashes, num_dashes, offset); - if (status) - _cairo_set_error (cr, status); -} - -/** - * cairo_get_dash_count: - * @cr: a #cairo_t - * - * This function returns the length of the dash array in @cr (0 if dashing - * is not currently in effect). - * - * See also cairo_set_dash() and cairo_get_dash(). - * - * Return value: the length of the dash array, or 0 if no dash array set. - * - * Since: 1.4 - */ -int -cairo_get_dash_count (cairo_t *cr) -{ - int num_dashes; - - if (cr->status) - return 0; - - _cairo_gstate_get_dash (cr->gstate, NULL, &num_dashes, NULL); - - return num_dashes; -} - -/** - * cairo_get_dash: - * @cr: a #cairo_t - * @dashes: return value for the dash array, or %NULL - * @offset: return value for the current dash offset, or %NULL - * - * Gets the current dash array. If not %NULL, @dashes should be big - * enough to hold at least the number of values returned by - * cairo_get_dash_count(). - * - * Since: 1.4 - **/ -void -cairo_get_dash (cairo_t *cr, - double *dashes, - double *offset) -{ - if (cr->status) - return; - - _cairo_gstate_get_dash (cr->gstate, dashes, NULL, offset); -} - -/** - * cairo_set_miter_limit: - * @cr: a cairo context - * @limit: miter limit to set - * - * Sets the current miter limit within the cairo context. - * - * If the current line join style is set to %CAIRO_LINE_JOIN_MITER - * (see cairo_set_line_join()), the miter limit is used to determine - * whether the lines should be joined with a bevel instead of a miter. - * Cairo divides the length of the miter by the line width. - * If the result is greater than the miter limit, the style is - * converted to a bevel. - * - * As with the other stroke parameters, the current line miter limit is - * examined by cairo_stroke(), cairo_stroke_extents(), and - * cairo_stroke_to_path(), but does not have any effect during path - * construction. - * - * The default miter limit value is 10.0, which will convert joins - * with interior angles less than 11 degrees to bevels instead of - * miters. For reference, a miter limit of 2.0 makes the miter cutoff - * at 60 degrees, and a miter limit of 1.414 makes the cutoff at 90 - * degrees. - * - * A miter limit for a desired angle can be computed as: miter limit = - * 1/sin(angle/2) - **/ -void -cairo_set_miter_limit (cairo_t *cr, double limit) -{ - cairo_status_t status; - - if (cr->status) - return; - - status = _cairo_gstate_set_miter_limit (cr->gstate, limit); - if (status) - _cairo_set_error (cr, status); -} - -/** - * cairo_translate: - * @cr: a cairo context - * @tx: amount to translate in the X direction - * @ty: amount to translate in the Y direction - * - * Modifies the current transformation matrix (CTM) by translating the - * user-space origin by (@tx, @ty). This offset is interpreted as a - * user-space coordinate according to the CTM in place before the new - * call to cairo_translate(). In other words, the translation of the - * user-space origin takes place after any existing transformation. - **/ -void -cairo_translate (cairo_t *cr, double tx, double ty) -{ - cairo_status_t status; - - if (cr->status) - return; - - status = _cairo_gstate_translate (cr->gstate, tx, ty); - if (status) - _cairo_set_error (cr, status); -} - -/** - * cairo_scale: - * @cr: a cairo context - * @sx: scale factor for the X dimension - * @sy: scale factor for the Y dimension - * - * Modifies the current transformation matrix (CTM) by scaling the X - * and Y user-space axes by @sx and @sy respectively. The scaling of - * the axes takes place after any existing transformation of user - * space. - **/ -void -cairo_scale (cairo_t *cr, double sx, double sy) -{ - cairo_status_t status; - - if (cr->status) - return; - - status = _cairo_gstate_scale (cr->gstate, sx, sy); - if (status) - _cairo_set_error (cr, status); -} -slim_hidden_def (cairo_scale); - -/** - * cairo_rotate: - * @cr: a cairo context - * @angle: angle (in radians) by which the user-space axes will be - * rotated - * - * Modifies the current transformation matrix (CTM) by rotating the - * user-space axes by @angle radians. The rotation of the axes takes - * places after any existing transformation of user space. The - * rotation direction for positive angles is from the positive X axis - * toward the positive Y axis. - **/ -void -cairo_rotate (cairo_t *cr, double angle) -{ - cairo_status_t status; - - if (cr->status) - return; - - status = _cairo_gstate_rotate (cr->gstate, angle); - if (status) - _cairo_set_error (cr, status); -} - -/** - * cairo_transform: - * @cr: a cairo context - * @matrix: a transformation to be applied to the user-space axes - * - * Modifies the current transformation matrix (CTM) by applying - * @matrix as an additional transformation. The new transformation of - * user space takes place after any existing transformation. - **/ -void -cairo_transform (cairo_t *cr, - const cairo_matrix_t *matrix) -{ - cairo_status_t status; - - if (cr->status) - return; - - status = _cairo_gstate_transform (cr->gstate, matrix); - if (status) - _cairo_set_error (cr, status); -} - -/** - * cairo_set_matrix: - * @cr: a cairo context - * @matrix: a transformation matrix from user space to device space - * - * Modifies the current transformation matrix (CTM) by setting it - * equal to @matrix. - **/ -void -cairo_set_matrix (cairo_t *cr, - const cairo_matrix_t *matrix) -{ - cairo_status_t status; - - if (cr->status) - return; - - status = _cairo_gstate_set_matrix (cr->gstate, matrix); - if (status) - _cairo_set_error (cr, status); -} -slim_hidden_def (cairo_set_matrix); - -/** - * cairo_identity_matrix: - * @cr: a cairo context - * - * Resets the current transformation matrix (CTM) by setting it equal - * to the identity matrix. That is, the user-space and device-space - * axes will be aligned and one user-space unit will transform to one - * device-space unit. - **/ -void -cairo_identity_matrix (cairo_t *cr) -{ - if (cr->status) - return; - - _cairo_gstate_identity_matrix (cr->gstate); -} - -/** - * cairo_user_to_device: - * @cr: a cairo context - * @x: X value of coordinate (in/out parameter) - * @y: Y value of coordinate (in/out parameter) - * - * Transform a coordinate from user space to device space by - * multiplying the given point by the current transformation matrix - * (CTM). - **/ -void -cairo_user_to_device (cairo_t *cr, double *x, double *y) -{ - if (cr->status) - return; - - _cairo_gstate_user_to_device (cr->gstate, x, y); -} - -/** - * cairo_user_to_device_distance: - * @cr: a cairo context - * @dx: X component of a distance vector (in/out parameter) - * @dy: Y component of a distance vector (in/out parameter) - * - * Transform a distance vector from user space to device space. This - * function is similar to cairo_user_to_device() except that the - * translation components of the CTM will be ignored when transforming - * (@dx,@dy). - **/ -void -cairo_user_to_device_distance (cairo_t *cr, double *dx, double *dy) -{ - if (cr->status) - return; - - _cairo_gstate_user_to_device_distance (cr->gstate, dx, dy); -} - -/** - * cairo_device_to_user: - * @cr: a cairo - * @x: X value of coordinate (in/out parameter) - * @y: Y value of coordinate (in/out parameter) - * - * Transform a coordinate from device space to user space by - * multiplying the given point by the inverse of the current - * transformation matrix (CTM). - **/ -void -cairo_device_to_user (cairo_t *cr, double *x, double *y) -{ - if (cr->status) - return; - - _cairo_gstate_device_to_user (cr->gstate, x, y); -} - -/** - * cairo_device_to_user_distance: - * @cr: a cairo context - * @dx: X component of a distance vector (in/out parameter) - * @dy: Y component of a distance vector (in/out parameter) - * - * Transform a distance vector from device space to user space. This - * function is similar to cairo_device_to_user() except that the - * translation components of the inverse CTM will be ignored when - * transforming (@dx,@dy). - **/ -void -cairo_device_to_user_distance (cairo_t *cr, double *dx, double *dy) -{ - if (cr->status) - return; - - _cairo_gstate_device_to_user_distance (cr->gstate, dx, dy); -} - -/** - * cairo_new_path: - * @cr: a cairo context - * - * Clears the current path. After this call there will be no path and - * no current point. - **/ -void -cairo_new_path (cairo_t *cr) -{ - if (cr->status) - return; - - _cairo_path_fixed_fini (cr->path); -} -slim_hidden_def(cairo_new_path); - -/** - * cairo_move_to: - * @cr: a cairo context - * @x: the X coordinate of the new position - * @y: the Y coordinate of the new position - * - * Begin a new sub-path. After this call the current point will be (@x, - * @y). - **/ -void -cairo_move_to (cairo_t *cr, double x, double y) -{ - cairo_status_t status; - cairo_fixed_t x_fixed, y_fixed; - - if (cr->status) - return; - - _cairo_gstate_user_to_backend (cr->gstate, &x, &y); - x_fixed = _cairo_fixed_from_double (x); - y_fixed = _cairo_fixed_from_double (y); - - status = _cairo_path_fixed_move_to (cr->path, x_fixed, y_fixed); - if (status) - _cairo_set_error (cr, status); -} -slim_hidden_def(cairo_move_to); - -/** - * cairo_new_sub_path: - * @cr: a cairo context - * - * Begin a new sub-path. Note that the existing path is not - * affected. After this call there will be no current point. - * - * In many cases, this call is not needed since new sub-paths are - * frequently started with cairo_move_to(). - * - * A call to cairo_new_sub_path() is particularly useful when - * beginning a new sub-path with one of the cairo_arc() calls. This - * makes things easier as it is no longer necessary to manually - * compute the arc's initial coordinates for a call to - * cairo_move_to(). - * - * Since: 1.2 - **/ -void -cairo_new_sub_path (cairo_t *cr) -{ - if (cr->status) - return; - - _cairo_path_fixed_new_sub_path (cr->path); -} - -/** - * cairo_line_to: - * @cr: a cairo context - * @x: the X coordinate of the end of the new line - * @y: the Y coordinate of the end of the new line - * - * Adds a line to the path from the current point to position (@x, @y) - * in user-space coordinates. After this call the current point - * will be (@x, @y). - * - * If there is no current point before the call to cairo_line_to() - * this function will behave as cairo_move_to(@cr, @x, @y). - **/ -void -cairo_line_to (cairo_t *cr, double x, double y) -{ - cairo_status_t status; - cairo_fixed_t x_fixed, y_fixed; - - if (cr->status) - return; - - _cairo_gstate_user_to_backend (cr->gstate, &x, &y); - x_fixed = _cairo_fixed_from_double (x); - y_fixed = _cairo_fixed_from_double (y); - - status = _cairo_path_fixed_line_to (cr->path, x_fixed, y_fixed); - if (status) - _cairo_set_error (cr, status); -} -slim_hidden_def (cairo_line_to); - -/** - * cairo_curve_to: - * @cr: a cairo context - * @x1: the X coordinate of the first control point - * @y1: the Y coordinate of the first control point - * @x2: the X coordinate of the second control point - * @y2: the Y coordinate of the second control point - * @x3: the X coordinate of the end of the curve - * @y3: the Y coordinate of the end of the curve - * - * Adds a cubic Bézier spline to the path from the current point to - * position (@x3, @y3) in user-space coordinates, using (@x1, @y1) and - * (@x2, @y2) as the control points. After this call the current point - * will be (@x3, @y3). - * - * If there is no current point before the call to cairo_curve_to() - * this function will behave as if preceded by a call to - * cairo_move_to(@cr, @x1, @y1). - **/ -void -cairo_curve_to (cairo_t *cr, - double x1, double y1, - double x2, double y2, - double x3, double y3) -{ - cairo_status_t status; - cairo_fixed_t x1_fixed, y1_fixed; - cairo_fixed_t x2_fixed, y2_fixed; - cairo_fixed_t x3_fixed, y3_fixed; - - if (cr->status) - return; - - _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); - - x1_fixed = _cairo_fixed_from_double (x1); - y1_fixed = _cairo_fixed_from_double (y1); - - x2_fixed = _cairo_fixed_from_double (x2); - y2_fixed = _cairo_fixed_from_double (y2); - - x3_fixed = _cairo_fixed_from_double (x3); - y3_fixed = _cairo_fixed_from_double (y3); - - status = _cairo_path_fixed_curve_to (cr->path, - x1_fixed, y1_fixed, - x2_fixed, y2_fixed, - x3_fixed, y3_fixed); - if (status) - _cairo_set_error (cr, status); -} -slim_hidden_def (cairo_curve_to); - -/** - * cairo_arc: - * @cr: a cairo context - * @xc: X position of the center of the arc - * @yc: Y position of the center of the arc - * @radius: the radius of the arc - * @angle1: the start angle, in radians - * @angle2: the end angle, in radians - * - * Adds a circular arc of the given @radius to the current path. The - * arc is centered at (@xc, @yc), begins at @angle1 and proceeds in - * the direction of increasing angles to end at @angle2. If @angle2 is - * less than @angle1 it will be progressively increased by 2*M_PI - * until it is greater than @angle1. - * - * If there is a current point, an initial line segment will be added - * to the path to connect the current point to the beginning of the - * arc. If this initial line is undesired, it can be avoided by - * calling cairo_new_sub_path() before calling cairo_arc(). - * - * Angles are measured in radians. An angle of 0.0 is in the direction - * of the positive X axis (in user space). An angle of %M_PI/2.0 radians - * (90 degrees) is in the direction of the positive Y axis (in - * user space). Angles increase in the direction from the positive X - * axis toward the positive Y axis. So with the default transformation - * matrix, angles increase in a clockwise direction. - * - * (To convert from degrees to radians, use degrees * (M_PI / - * 180.).) - * - * This function gives the arc in the direction of increasing angles; - * see cairo_arc_negative() to get the arc in the direction of - * decreasing angles. - * - * The arc is circular in user space. To achieve an elliptical arc, - * you can scale the current transformation matrix by different - * amounts in the X and Y directions. For example, to draw an ellipse - * in the box given by @x, @y, @width, @height: - * - * - * cairo_save (cr); - * cairo_translate (cr, x + width / 2., y + height / 2.); - * cairo_scale (cr, width / 2., height / 2.); - * cairo_arc (cr, 0., 0., 1., 0., 2 * M_PI); - * cairo_restore (cr); - * - **/ -void -cairo_arc (cairo_t *cr, - double xc, double yc, - double radius, - double angle1, double angle2) -{ - if (cr->status) - return; - - /* Do nothing, successfully, if radius is <= 0 */ - if (radius <= 0.0) - return; - - while (angle2 < angle1) - angle2 += 2 * M_PI; - - cairo_line_to (cr, - xc + radius * cos (angle1), - yc + radius * sin (angle1)); - - _cairo_arc_path (cr, xc, yc, radius, - angle1, angle2); -} - -/** - * cairo_arc_negative: - * @cr: a cairo context - * @xc: X position of the center of the arc - * @yc: Y position of the center of the arc - * @radius: the radius of the arc - * @angle1: the start angle, in radians - * @angle2: the end angle, in radians - * - * Adds a circular arc of the given @radius to the current path. The - * arc is centered at (@xc, @yc), begins at @angle1 and proceeds in - * the direction of decreasing angles to end at @angle2. If @angle2 is - * greater than @angle1 it will be progressively decreased by 2*M_PI - * until it is less than @angle1. - * - * See cairo_arc() for more details. This function differs only in the - * direction of the arc between the two angles. - **/ -void -cairo_arc_negative (cairo_t *cr, - double xc, double yc, - double radius, - double angle1, double angle2) -{ - if (cr->status) - return; - - /* Do nothing, successfully, if radius is <= 0 */ - if (radius <= 0.0) - return; - - while (angle2 > angle1) - angle2 -= 2 * M_PI; - - cairo_line_to (cr, - xc + radius * cos (angle1), - yc + radius * sin (angle1)); - - _cairo_arc_path_negative (cr, xc, yc, radius, - angle1, angle2); -} - -/* XXX: NYI -void -cairo_arc_to (cairo_t *cr, - double x1, double y1, - double x2, double y2, - double radius) -{ - cairo_status_t status; - - if (cr->status) - return; - - status = _cairo_gstate_arc_to (cr->gstate, - x1, y1, - x2, y2, - radius); - if (status) - _cairo_set_error (cr, status); -} -*/ - -/** - * cairo_rel_move_to: - * @cr: a cairo context - * @dx: the X offset - * @dy: the Y offset - * - * Begin a new sub-path. After this call the current point will offset - * by (@x, @y). - * - * Given a current point of (x, y), cairo_rel_move_to(@cr, @dx, @dy) - * is logically equivalent to cairo_move_to(@cr, x + @dx, y + @dy). - * - * It is an error to call this function with no current point. Doing - * so will cause @cr to shutdown with a status of - * %CAIRO_STATUS_NO_CURRENT_POINT. - **/ -void -cairo_rel_move_to (cairo_t *cr, double dx, double dy) -{ - cairo_fixed_t dx_fixed, dy_fixed; - cairo_status_t status; - - if (cr->status) - return; - - _cairo_gstate_user_to_device_distance (cr->gstate, &dx, &dy); - - dx_fixed = _cairo_fixed_from_double (dx); - dy_fixed = _cairo_fixed_from_double (dy); - - status = _cairo_path_fixed_rel_move_to (cr->path, dx_fixed, dy_fixed); - if (status) - _cairo_set_error (cr, status); -} - -/** - * cairo_rel_line_to: - * @cr: a cairo context - * @dx: the X offset to the end of the new line - * @dy: the Y offset to the end of the new line - * - * Relative-coordinate version of cairo_line_to(). Adds a line to the - * path from the current point to a point that is offset from the - * current point by (@dx, @dy) in user space. After this call the - * current point will be offset by (@dx, @dy). - * - * Given a current point of (x, y), cairo_rel_line_to(@cr, @dx, @dy) - * is logically equivalent to cairo_line_to(@cr, x + @dx, y + @dy). - * - * It is an error to call this function with no current point. Doing - * so will cause @cr to shutdown with a status of - * %CAIRO_STATUS_NO_CURRENT_POINT. - **/ -void -cairo_rel_line_to (cairo_t *cr, double dx, double dy) -{ - cairo_fixed_t dx_fixed, dy_fixed; - cairo_status_t status; - - if (cr->status) - return; - - _cairo_gstate_user_to_device_distance (cr->gstate, &dx, &dy); - - dx_fixed = _cairo_fixed_from_double (dx); - dy_fixed = _cairo_fixed_from_double (dy); - - status = _cairo_path_fixed_rel_line_to (cr->path, dx_fixed, dy_fixed); - if (status) - _cairo_set_error (cr, status); -} -slim_hidden_def(cairo_rel_line_to); - -/** - * cairo_rel_curve_to: - * @cr: a cairo context - * @dx1: the X offset to the first control point - * @dy1: the Y offset to the first control point - * @dx2: the X offset to the second control point - * @dy2: the Y offset to the second control point - * @dx3: the X offset to the end of the curve - * @dy3: the Y offset to the end of the curve - * - * Relative-coordinate version of cairo_curve_to(). All offsets are - * relative to the current point. Adds a cubic Bézier spline to the - * path from the current point to a point offset from the current - * point by (@dx3, @dy3), using points offset by (@dx1, @dy1) and - * (@dx2, @dy2) as the control points. After this call the current - * point will be offset by (@dx3, @dy3). - * - * Given a current point of (x, y), cairo_rel_curve_to(@cr, @dx1, - * @dy1, @dx2, @dy2, @dx3, @dy3) is logically equivalent to - * cairo_curve_to(@cr, x+@dx1, y+@dy1, x+@dx2, y+@dy2, x+@dx3, y+@dy3). - * - * It is an error to call this function with no current point. Doing - * so will cause @cr to shutdown with a status of - * %CAIRO_STATUS_NO_CURRENT_POINT. - **/ -void -cairo_rel_curve_to (cairo_t *cr, - double dx1, double dy1, - double dx2, double dy2, - double dx3, double dy3) -{ - cairo_fixed_t dx1_fixed, dy1_fixed; - cairo_fixed_t dx2_fixed, dy2_fixed; - cairo_fixed_t dx3_fixed, dy3_fixed; - cairo_status_t status; - - if (cr->status) - return; - - _cairo_gstate_user_to_device_distance (cr->gstate, &dx1, &dy1); - _cairo_gstate_user_to_device_distance (cr->gstate, &dx2, &dy2); - _cairo_gstate_user_to_device_distance (cr->gstate, &dx3, &dy3); - - dx1_fixed = _cairo_fixed_from_double (dx1); - dy1_fixed = _cairo_fixed_from_double (dy1); - - dx2_fixed = _cairo_fixed_from_double (dx2); - dy2_fixed = _cairo_fixed_from_double (dy2); - - dx3_fixed = _cairo_fixed_from_double (dx3); - dy3_fixed = _cairo_fixed_from_double (dy3); - - status = _cairo_path_fixed_rel_curve_to (cr->path, - dx1_fixed, dy1_fixed, - dx2_fixed, dy2_fixed, - dx3_fixed, dy3_fixed); - if (status) - _cairo_set_error (cr, status); -} - -/** - * cairo_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 - * - * Adds a closed sub-path rectangle of the given size to the current - * path at position (@x, @y) in user-space coordinates. - * - * This function is logically equivalent to: - * - * cairo_move_to (cr, x, y); - * cairo_rel_line_to (cr, width, 0); - * cairo_rel_line_to (cr, 0, height); - * cairo_rel_line_to (cr, -width, 0); - * cairo_close_path (cr); - * - **/ -void -cairo_rectangle (cairo_t *cr, - double x, double y, - double width, double height) -{ - if (cr->status) - return; - - cairo_move_to (cr, x, y); - cairo_rel_line_to (cr, width, 0); - cairo_rel_line_to (cr, 0, height); - cairo_rel_line_to (cr, -width, 0); - cairo_close_path (cr); -} - -#if 0 -/* XXX: NYI */ -void -cairo_stroke_to_path (cairo_t *cr) -{ - cairo_status_t status; - - if (cr->status) - return; - - /* The code in _cairo_meta_surface_get_path has a poorman's stroke_to_path */ - - status = _cairo_gstate_stroke_path (cr->gstate); - if (status) - _cairo_set_error (cr, status); -} -#endif - -/** - * cairo_close_path: - * @cr: a cairo context - * - * Adds a line segment to the path from the current point to the - * beginning of the current sub-path, (the most recent point passed to - * cairo_move_to()), and closes this sub-path. After this call the - * current point will be at the joined endpoint of the sub-path. - * - * The behavior of cairo_close_path() is distinct from simply calling - * cairo_line_to() with the equivalent coordinate in the case of - * stroking. When a closed sub-path is stroked, there are no caps on - * the ends of the sub-path. Instead, there is a line join connecting - * the final and initial segments of the sub-path. - * - * If there is no current point before the call to cairo_close_path(), - * this function will have no effect. - * - * Note: As of cairo version 1.2.4 any call to cairo_close_path() will - * place an explicit MOVE_TO element into the path immediately after - * the CLOSE_PATH element, (which can be seen in cairo_copy_path() for - * example). This can simplify path processing in some cases as it may - * not be necessary to save the "last move_to point" during processing - * as the MOVE_TO immediately after the CLOSE_PATH will provide that - * point. - **/ -void -cairo_close_path (cairo_t *cr) -{ - cairo_status_t status; - - if (cr->status) - return; - - status = _cairo_path_fixed_close_path (cr->path); - if (status) - _cairo_set_error (cr, status); -} -slim_hidden_def(cairo_close_path); - -/** - * cairo_path_extents: - * @cr: a cairo context - * @x1: left of the resulting extents - * @y1: top of the resulting extents - * @x2: right of the resulting extents - * @y2: bottom of the resulting extents - * - * Computes a bounding box in user-space coordinates covering the - * points on the current path. If the current path is empty, returns - * an empty rectangle ((0,0), (0,0)). Stroke parameters, fill rule, - * surface dimensions and clipping are not taken into account. - * - * Contrast with cairo_fill_extents() and cairo_stroke_extents() which - * return the extents of only the area that would be "inked" by - * the corresponding drawing operations. - * - * The result of cairo_path_extents() is defined as equivalent to the - * limit of cairo_stroke_extents() with %CAIRO_LINE_CAP_ROUND as the - * line width approaches 0.0, (but never reaching the empty-rectangle - * returned by cairo_stroke_extents() for a line width of 0.0). - * - * Specifically, this means that zero-area sub-paths such as - * cairo_move_to();cairo_line_to() segments, (even degenerate cases - * where the coordinates to both calls are identical), will be - * considered as contributing to the extents. However, a lone - * cairo_move_to() will not contribute to the results of - * cairo_path_extents(). - * - * Since: 1.6 - **/ -void -cairo_path_extents (cairo_t *cr, - double *x1, double *y1, double *x2, double *y2) -{ - cairo_status_t status; - - if (cr->status) { - if (x1) - *x1 = 0.0; - if (y1) - *y1 = 0.0; - if (x2) - *x2 = 0.0; - if (y2) - *y2 = 0.0; - - return; - } - - status = _cairo_gstate_path_extents (cr->gstate, - cr->path, - x1, y1, x2, y2); - if (status) - _cairo_set_error (cr, status); -} -slim_hidden_def (cairo_path_extents); - -/** - * cairo_paint: - * @cr: a cairo context - * - * A drawing operator that paints the current source everywhere within - * the current clip region. - **/ -void -cairo_paint (cairo_t *cr) -{ - cairo_status_t status; - - if (cr->status) - return; - - status = _cairo_gstate_paint (cr->gstate); - if (status) - _cairo_set_error (cr, status); -} -slim_hidden_def (cairo_paint); - -/** - * cairo_paint_with_alpha: - * @cr: a cairo context - * @alpha: alpha value, between 0 (transparent) and 1 (opaque) - * - * A drawing operator that paints the current source everywhere within - * the current clip region using a mask of constant alpha value - * @alpha. The effect is similar to cairo_paint(), but the drawing - * is faded out using the alpha value. - **/ -void -cairo_paint_with_alpha (cairo_t *cr, - double alpha) -{ - cairo_status_t status; - cairo_color_t color; - cairo_solid_pattern_t pattern; - - if (cr->status) - return; - - if (CAIRO_ALPHA_IS_OPAQUE (alpha)) { - cairo_paint (cr); - return; - } - - if (CAIRO_ALPHA_IS_ZERO (alpha)) { - return; - } - - _cairo_color_init_rgba (&color, 1., 1., 1., alpha); - _cairo_pattern_init_solid (&pattern, &color, CAIRO_CONTENT_ALPHA); - - status = _cairo_gstate_mask (cr->gstate, &pattern.base); - if (status) - _cairo_set_error (cr, status); - - _cairo_pattern_fini (&pattern.base); -} - -/** - * cairo_mask: - * @cr: a cairo context - * @pattern: a #cairo_pattern_t - * - * A drawing operator that paints the current source - * using the alpha channel of @pattern as a mask. (Opaque - * areas of @pattern are painted with the source, transparent - * areas are not painted.) - */ -void -cairo_mask (cairo_t *cr, - cairo_pattern_t *pattern) -{ - cairo_status_t status; - - if (cr->status) - return; - - if (pattern == NULL) { - _cairo_set_error (cr, CAIRO_STATUS_NULL_POINTER); - return; - } - - if (pattern->status) { - _cairo_set_error (cr, pattern->status); - return; - } - - status = _cairo_gstate_mask (cr->gstate, pattern); - if (status) - _cairo_set_error (cr, status); -} -slim_hidden_def (cairo_mask); - -/** - * cairo_mask_surface: - * @cr: a cairo context - * @surface: a #cairo_surface_t - * @surface_x: X coordinate at which to place the origin of @surface - * @surface_y: Y coordinate at which to place the origin of @surface - * - * A drawing operator that paints the current source - * using the alpha channel of @surface as a mask. (Opaque - * areas of @surface are painted with the source, transparent - * areas are not painted.) - */ -void -cairo_mask_surface (cairo_t *cr, - cairo_surface_t *surface, - double surface_x, - double surface_y) -{ - cairo_pattern_t *pattern; - cairo_matrix_t matrix; - - if (cr->status) - return; - - pattern = cairo_pattern_create_for_surface (surface); - - cairo_matrix_init_translate (&matrix, - surface_x, - surface_y); - cairo_pattern_set_matrix (pattern, &matrix); - - cairo_mask (cr, pattern); - - cairo_pattern_destroy (pattern); -} - -/** - * cairo_stroke: - * @cr: a cairo context - * - * A drawing operator that strokes the current path according to the - * current line width, line join, line cap, and dash settings. After - * cairo_stroke(), the current path will be cleared from the cairo - * context. See cairo_set_line_width(), cairo_set_line_join(), - * cairo_set_line_cap(), cairo_set_dash(), and - * cairo_stroke_preserve(). - * - * Note: Degenerate segments and sub-paths are treated specially and - * provide a useful result. These can result in two different - * situations: - * - * 1. Zero-length "on" segments set in cairo_set_dash(). If the cap - * style is %CAIRO_LINE_CAP_ROUND or %CAIRO_LINE_CAP_SQUARE then these - * segments will be drawn as circular dots or squares respectively. In - * the case of %CAIRO_LINE_CAP_SQUARE, the orientation of the squares - * is determined by the direction of the underlying path. - * - * 2. A sub-path created by cairo_move_to() followed by either a - * cairo_close_path() or one or more calls to cairo_line_to() to the - * same coordinate as the cairo_move_to(). If the cap style is - * %CAIRO_LINE_CAP_ROUND then these sub-paths will be drawn as circular - * dots. Note that in the case of %CAIRO_LINE_CAP_SQUARE a degenerate - * sub-path will not be drawn at all, (since the correct orientation - * is indeterminate). - * - * In no case will a cap style of %CAIRO_LINE_CAP_BUTT cause anything - * to be drawn in the case of either degenerate segments or sub-paths. - **/ -void -cairo_stroke (cairo_t *cr) -{ - cairo_stroke_preserve (cr); - - cairo_new_path (cr); -} -slim_hidden_def(cairo_stroke); - -/** - * cairo_stroke_preserve: - * @cr: a cairo context - * - * A drawing operator that strokes the current path according to the - * current line width, line join, line cap, and dash settings. Unlike - * cairo_stroke(), cairo_stroke_preserve() preserves the path within the - * cairo context. - * - * See cairo_set_line_width(), cairo_set_line_join(), - * cairo_set_line_cap(), cairo_set_dash(), and - * cairo_stroke_preserve(). - **/ -void -cairo_stroke_preserve (cairo_t *cr) -{ - cairo_status_t status; - - if (cr->status) - return; - - status = _cairo_gstate_stroke (cr->gstate, cr->path); - if (status) - _cairo_set_error (cr, status); -} -slim_hidden_def(cairo_stroke_preserve); - -/** - * cairo_fill: - * @cr: a cairo context - * - * A drawing operator that fills the current path according to the - * current fill rule, (each sub-path is implicitly closed before being - * filled). After cairo_fill(), the current path will be cleared from - * the cairo context. See cairo_set_fill_rule() and - * cairo_fill_preserve(). - **/ -void -cairo_fill (cairo_t *cr) -{ - cairo_fill_preserve (cr); - - cairo_new_path (cr); -} - -/** - * cairo_fill_preserve: - * @cr: a cairo context - * - * A drawing operator that fills the current path according to the - * current fill rule, (each sub-path is implicitly closed before being - * filled). Unlike cairo_fill(), cairo_fill_preserve() preserves the - * path within the cairo context. - * - * See cairo_set_fill_rule() and cairo_fill(). - **/ -void -cairo_fill_preserve (cairo_t *cr) -{ - cairo_status_t status; - - if (cr->status) - return; - - status = _cairo_gstate_fill (cr->gstate, cr->path); - if (status) - _cairo_set_error (cr, status); -} -slim_hidden_def(cairo_fill_preserve); - -/** - * cairo_copy_page: - * @cr: a cairo context - * - * Emits the current page for backends that support multiple pages, but - * doesn't clear it, so, the contents of the current page will be retained - * for the next page too. Use cairo_show_page() if you want to get an - * empty page after the emission. - * - * This is a convenience function that simply calls - * cairo_surface_copy_page() on @cr's target. - **/ -void -cairo_copy_page (cairo_t *cr) -{ - cairo_status_t status; - - if (cr->status) - return; - - status = _cairo_gstate_copy_page (cr->gstate); - if (status) - _cairo_set_error (cr, status); -} - -/** - * cairo_show_page: - * @cr: a cairo context - * - * Emits and clears the current page for backends that support multiple - * pages. Use cairo_copy_page() if you don't want to clear the page. - * - * This is a convenience function that simply calls - * cairo_surface_show_page() on @cr's target. - **/ -void -cairo_show_page (cairo_t *cr) -{ - cairo_status_t status; - - if (cr->status) - return; - - status = _cairo_gstate_show_page (cr->gstate); - if (status) - _cairo_set_error (cr, status); -} - -/** - * cairo_in_stroke: - * @cr: a cairo context - * @x: X coordinate of the point to test - * @y: Y coordinate of the point to test - * - * Tests whether the given point is inside the area that would be - * affected by a cairo_stroke() operation given the current path and - * stroking parameters. Surface dimensions and clipping are not taken - * into account. - * - * See cairo_stroke(), cairo_set_line_width(), cairo_set_line_join(), - * cairo_set_line_cap(), cairo_set_dash(), and - * cairo_stroke_preserve(). - * - * Return value: A non-zero value if the point is inside, or zero if - * outside. - **/ -cairo_bool_t -cairo_in_stroke (cairo_t *cr, double x, double y) -{ - cairo_status_t status; - cairo_bool_t inside = FALSE; - - if (cr->status) - return 0; - - status = _cairo_gstate_in_stroke (cr->gstate, - cr->path, - x, y, &inside); - if (status) - _cairo_set_error (cr, status); - - return inside; -} - -/** - * cairo_in_fill: - * @cr: a cairo context - * @x: X coordinate of the point to test - * @y: Y coordinate of the point to test - * - * Tests whether the given point is inside the area that would be - * affected by a cairo_fill() operation given the current path and - * filling parameters. Surface dimensions and clipping are not taken - * into account. - * - * See cairo_fill(), cairo_set_fill_rule() and cairo_fill_preserve(). - * - * Return value: A non-zero value if the point is inside, or zero if - * outside. - **/ -cairo_bool_t -cairo_in_fill (cairo_t *cr, double x, double y) -{ - cairo_status_t status; - cairo_bool_t inside = FALSE; - - if (cr->status) - return 0; - - status = _cairo_gstate_in_fill (cr->gstate, - cr->path, - x, y, &inside); - if (status) - _cairo_set_error (cr, status); - - return inside; -} - -/** - * cairo_stroke_extents: - * @cr: a cairo context - * @x1: left of the resulting extents - * @y1: top of the resulting extents - * @x2: right of the resulting extents - * @y2: bottom of the resulting extents - * - * Computes a bounding box in user coordinates covering the area that - * would be affected, (the "inked" area), by a cairo_stroke() - * operation operation given the current path and stroke - * parameters. If the current path is empty, returns an empty - * rectangle ((0,0), (0,0)). Surface dimensions and clipping are not - * taken into account. - * - * Note that if the line width is set to exactly zero, then - * cairo_stroke_extents() will return an empty rectangle. Contrast with - * cairo_path_extents() which can be used to compute the non-empty - * bounds as the line width approaches zero. - * - * Note that cairo_stroke_extents() must necessarily do more work to - * compute the precise inked areas in light of the stroke parameters, - * so cairo_path_extents() may be more desirable for sake of - * performance if non-inked path extents are desired. - * - * See cairo_stroke(), cairo_set_line_width(), cairo_set_line_join(), - * cairo_set_line_cap(), cairo_set_dash(), and - * cairo_stroke_preserve(). - **/ -void -cairo_stroke_extents (cairo_t *cr, - double *x1, double *y1, double *x2, double *y2) -{ - cairo_status_t status; - - if (cr->status) { - if (x1) - *x1 = 0.0; - if (y1) - *y1 = 0.0; - if (x2) - *x2 = 0.0; - if (y2) - *y2 = 0.0; - - return; - } - - status = _cairo_gstate_stroke_extents (cr->gstate, - cr->path, - x1, y1, x2, y2); - if (status) - _cairo_set_error (cr, status); -} - -/** - * cairo_fill_extents: - * @cr: a cairo context - * @x1: left of the resulting extents - * @y1: top of the resulting extents - * @x2: right of the resulting extents - * @y2: bottom of the resulting extents - * - * Computes a bounding box in user coordinates covering the area that - * would be affected, (the "inked" area), by a cairo_fill() operation - * given the current path and fill parameters. If the current path is - * empty, returns an empty rectangle ((0,0), (0,0)). Surface - * dimensions and clipping are not taken into account. - * - * Contrast with cairo_path_extents(), which is similar, but returns - * non-zero extents for some paths with no inked area, (such as a - * simple line segment). - * - * Note that cairo_fill_extents() must necessarily do more work to - * compute the precise inked areas in light of the fill rule, so - * cairo_path_extents() may be more desirable for sake of performance - * if the non-inked path extents are desired. - * - * See cairo_fill(), cairo_set_fill_rule() and cairo_fill_preserve(). - **/ -void -cairo_fill_extents (cairo_t *cr, - double *x1, double *y1, double *x2, double *y2) -{ - cairo_status_t status; - - if (cr->status) { - if (x1) - *x1 = 0.0; - if (y1) - *y1 = 0.0; - if (x2) - *x2 = 0.0; - if (y2) - *y2 = 0.0; - - return; - } - - status = _cairo_gstate_fill_extents (cr->gstate, - cr->path, - x1, y1, x2, y2); - if (status) - _cairo_set_error (cr, status); -} - -/** - * cairo_clip: - * @cr: a cairo context - * - * Establishes a new clip region by intersecting the current clip - * region with the current path as it would be filled by cairo_fill() - * and according to the current fill rule (see cairo_set_fill_rule()). - * - * After cairo_clip(), the current path will be cleared from the cairo - * context. - * - * The current clip region affects all drawing operations by - * effectively masking out any changes to the surface that are outside - * the current clip region. - * - * Calling cairo_clip() can only make the clip region smaller, never - * larger. But the current clip is part of the graphics state, so a - * temporary restriction of the clip region can be achieved by - * calling cairo_clip() within a cairo_save()/cairo_restore() - * pair. The only other means of increasing the size of the clip - * region is cairo_reset_clip(). - **/ -void -cairo_clip (cairo_t *cr) -{ - cairo_clip_preserve (cr); - - cairo_new_path (cr); -} - -/** - * cairo_clip_preserve: - * @cr: a cairo context - * - * Establishes a new clip region by intersecting the current clip - * region with the current path as it would be filled by cairo_fill() - * and according to the current fill rule (see cairo_set_fill_rule()). - * - * Unlike cairo_clip(), cairo_clip_preserve() preserves the path within - * the cairo context. - * - * The current clip region affects all drawing operations by - * effectively masking out any changes to the surface that are outside - * the current clip region. - * - * Calling cairo_clip() can only make the clip region smaller, never - * larger. But the current clip is part of the graphics state, so a - * temporary restriction of the clip region can be achieved by - * calling cairo_clip() within a cairo_save()/cairo_restore() - * pair. The only other means of increasing the size of the clip - * region is cairo_reset_clip(). - **/ -void -cairo_clip_preserve (cairo_t *cr) -{ - cairo_status_t status; - - if (cr->status) - return; - - status = _cairo_gstate_clip (cr->gstate, cr->path); - if (status) - _cairo_set_error (cr, status); -} -slim_hidden_def(cairo_clip_preserve); - -/** - * cairo_reset_clip: - * @cr: a cairo context - * - * Reset the current clip region to its original, unrestricted - * state. That is, set the clip region to an infinitely large shape - * containing the target surface. Equivalently, if infinity is too - * hard to grasp, one can imagine the clip region being reset to the - * exact bounds of the target surface. - * - * Note that code meant to be reusable should not call - * cairo_reset_clip() as it will cause results unexpected by - * higher-level code which calls cairo_clip(). Consider using - * cairo_save() and cairo_restore() around cairo_clip() as a more - * robust means of temporarily restricting the clip region. - **/ -void -cairo_reset_clip (cairo_t *cr) -{ - cairo_status_t status; - - if (cr->status) - return; - - status = _cairo_gstate_reset_clip (cr->gstate); - if (status) - _cairo_set_error (cr, status); -} - -/** - * cairo_clip_extents: - * @cr: a cairo context - * @x1: left of the resulting extents - * @y1: top of the resulting extents - * @x2: right of the resulting extents - * @y2: bottom of the resulting extents - * - * Computes a bounding box in user coordinates covering the area inside the - * current clip. - * - * Since: 1.4 - **/ -void -cairo_clip_extents (cairo_t *cr, - double *x1, double *y1, - double *x2, double *y2) -{ - cairo_status_t status; - - if (cr->status) { - if (x1) - *x1 = 0.0; - if (y1) - *y1 = 0.0; - if (x2) - *x2 = 0.0; - if (y2) - *y2 = 0.0; - - return; - } - - status = _cairo_gstate_clip_extents (cr->gstate, x1, y1, x2, y2); - if (status) - _cairo_set_error (cr, status); -} - -static cairo_rectangle_list_t * -_cairo_rectangle_list_create_in_error (cairo_status_t status) -{ - cairo_rectangle_list_t *list; - - if (status == CAIRO_STATUS_NO_MEMORY) - return (cairo_rectangle_list_t*) &_cairo_rectangles_nil; - - list = malloc (sizeof (cairo_rectangle_list_t)); - if (list == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - return (cairo_rectangle_list_t*) &_cairo_rectangles_nil; - } - - list->status = status; - list->rectangles = NULL; - list->num_rectangles = 0; - return list; -} - -/** - * cairo_copy_clip_rectangle_list: - * @cr: a cairo context - * - * Gets the current clip region as a list of rectangles in user coordinates. - * Never returns %NULL. - * - * The status in the list may be %CAIRO_STATUS_CLIP_NOT_REPRESENTABLE to - * indicate that the clip region cannot be represented as a list of - * user-space rectangles. The status may have other values to indicate - * other errors. - * - * Returns: the current clip region as a list of rectangles in user coordinates, - * which should be destroyed using cairo_rectangle_list_destroy(). - * - * Since: 1.4 - **/ -cairo_rectangle_list_t * -cairo_copy_clip_rectangle_list (cairo_t *cr) -{ - if (cr->status) - return _cairo_rectangle_list_create_in_error (cr->status); - - return _cairo_gstate_copy_clip_rectangle_list (cr->gstate); -} - -/** - * cairo_select_font_face: - * @cr: a #cairo_t - * @family: a font family name, encoded in UTF-8 - * @slant: the slant for the font - * @weight: the weight for the font - * - * Note: The cairo_select_font_face() function call is part of what - * the cairo designers call the "toy" text API. It is convenient for - * short demos and simple programs, but it is not expected to be - * adequate for serious text-using applications. - * - * Selects a family and style of font from a simplified description as - * a family name, slant and weight. Cairo provides no operation to - * list available family names on the system (this is a "toy", - * remember), but the standard CSS2 generic family names, ("serif", - * "sans-serif", "cursive", "fantasy", "monospace"), are likely to - * work as expected. - * - * For "real" font selection, see the font-backend-specific - * font_face_create functions for the font backend you are using. (For - * example, if you are using the freetype-based cairo-ft font backend, - * see cairo_ft_font_face_create_for_ft_face() or - * cairo_ft_font_face_create_for_pattern().) The resulting font face - * could then be used with cairo_scaled_font_create() and - * cairo_set_scaled_font(). - * - * Similarly, when using the "real" font support, you can call - * directly into the underlying font system, (such as fontconfig or - * freetype), for operations such as listing available fonts, etc. - * - * It is expected that most applications will need to use a more - * comprehensive font handling and text layout library, (for example, - * pango), in conjunction with cairo. - * - * If text is drawn without a call to cairo_select_font_face(), (nor - * cairo_set_font_face() nor cairo_set_scaled_font()), the default - * family is platform-specific, but is essentially "sans-serif". - * Default slant is %CAIRO_FONT_SLANT_NORMAL, and default weight is - * %CAIRO_FONT_WEIGHT_NORMAL. - * - * This function is equivalent to a call to cairo_toy_font_face_create() - * followed by cairo_set_font_face(). - **/ -void -cairo_select_font_face (cairo_t *cr, - const char *family, - cairo_font_slant_t slant, - cairo_font_weight_t weight) -{ - cairo_status_t status; - - if (cr->status) - return; - - status = _cairo_gstate_select_font_face (cr->gstate, family, slant, weight); - if (status) - _cairo_set_error (cr, status); -} - -/** - * cairo_font_extents: - * @cr: a #cairo_t - * @extents: a #cairo_font_extents_t object into which the results - * will be stored. - * - * Gets the font extents for the currently selected font. - **/ -void -cairo_font_extents (cairo_t *cr, - cairo_font_extents_t *extents) -{ - cairo_status_t status; - - extents->ascent = 0.0; - extents->descent = 0.0; - extents->height = 0.0; - extents->max_x_advance = 0.0; - extents->max_y_advance = 0.0; - - if (cr->status) - return; - - status = _cairo_gstate_get_font_extents (cr->gstate, extents); - if (status) - _cairo_set_error (cr, status); -} - -/** - * cairo_set_font_face: - * @cr: a #cairo_t - * @font_face: a #cairo_font_face_t, or %NULL to restore to the default font - * - * Replaces the current #cairo_font_face_t object in the #cairo_t with - * @font_face. The replaced font face in the #cairo_t will be - * destroyed if there are no other references to it. - **/ -void -cairo_set_font_face (cairo_t *cr, - cairo_font_face_t *font_face) -{ - cairo_status_t status; - - if (cr->status) - return; - - status = _cairo_gstate_set_font_face (cr->gstate, font_face); - if (status) - _cairo_set_error (cr, status); -} - -/** - * cairo_get_font_face: - * @cr: a #cairo_t - * - * Gets the current font face for a #cairo_t. - * - * Return value: the current font face. This object is owned by - * cairo. To keep a reference to it, you must call - * cairo_font_face_reference(). - * - * This function never returns %NULL. If memory cannot be allocated, a - * special "nil" #cairo_font_face_t object will be returned on which - * cairo_font_face_status() returns %CAIRO_STATUS_NO_MEMORY. Using - * this nil object will cause its error state to propagate to other - * objects it is passed to, (for example, calling - * cairo_set_font_face() with a nil font will trigger an error that - * will shutdown the #cairo_t object). - **/ -cairo_font_face_t * -cairo_get_font_face (cairo_t *cr) -{ - cairo_status_t status; - cairo_font_face_t *font_face; - - if (cr->status) - return (cairo_font_face_t*) &_cairo_font_face_nil; - - status = _cairo_gstate_get_font_face (cr->gstate, &font_face); - if (status) { - _cairo_set_error (cr, status); - return (cairo_font_face_t*) &_cairo_font_face_nil; - } - - return font_face; -} - -/** - * cairo_set_font_size: - * @cr: a #cairo_t - * @size: the new font size, in user space units - * - * Sets the current font matrix to a scale by a factor of @size, replacing - * any font matrix previously set with cairo_set_font_size() or - * cairo_set_font_matrix(). This results in a font size of @size user space - * units. (More precisely, this matrix will result in the font's - * em-square being a @size by @size square in user space.) - * - * If text is drawn without a call to cairo_set_font_size(), (nor - * cairo_set_font_matrix() nor cairo_set_scaled_font()), the default - * font size is 10.0. - **/ -void -cairo_set_font_size (cairo_t *cr, double size) -{ - cairo_status_t status; - - if (cr->status) - return; - - status = _cairo_gstate_set_font_size (cr->gstate, size); - if (status) - _cairo_set_error (cr, status); -} -slim_hidden_def (cairo_set_font_size); - -/** - * cairo_set_font_matrix - * @cr: a #cairo_t - * @matrix: a #cairo_matrix_t describing a transform to be applied to - * the current font. - * - * Sets the current font matrix to @matrix. The font matrix gives a - * transformation from the design space of the font (in this space, - * the em-square is 1 unit by 1 unit) to user space. Normally, a - * simple scale is used (see cairo_set_font_size()), but a more - * complex font matrix can be used to shear the font - * or stretch it unequally along the two axes - **/ -void -cairo_set_font_matrix (cairo_t *cr, - const cairo_matrix_t *matrix) -{ - cairo_status_t status; - - if (cr->status) - return; - - status = _cairo_gstate_set_font_matrix (cr->gstate, matrix); - if (status) - _cairo_set_error (cr, status); -} - -/** - * cairo_get_font_matrix - * @cr: a #cairo_t - * @matrix: return value for the matrix - * - * Stores the current font matrix into @matrix. See - * cairo_set_font_matrix(). - **/ -void -cairo_get_font_matrix (cairo_t *cr, cairo_matrix_t *matrix) -{ - if (cr->status) { - cairo_matrix_init_identity (matrix); - return; - } - - _cairo_gstate_get_font_matrix (cr->gstate, matrix); -} - -/** - * cairo_set_font_options: - * @cr: a #cairo_t - * @options: font options to use - * - * Sets a set of custom font rendering options for the #cairo_t. - * Rendering options are derived by merging these options with the - * options derived from underlying surface; if the value in @options - * has a default value (like %CAIRO_ANTIALIAS_DEFAULT), then the value - * from the surface is used. - **/ -void -cairo_set_font_options (cairo_t *cr, - const cairo_font_options_t *options) -{ - cairo_status_t status; - - if (cr->status) - return; - - status = cairo_font_options_status ((cairo_font_options_t *) options); - if (status) { - _cairo_set_error (cr, status); - return; - } - - _cairo_gstate_set_font_options (cr->gstate, options); -} -slim_hidden_def (cairo_set_font_options); - -/** - * cairo_get_font_options: - * @cr: a #cairo_t - * @options: a #cairo_font_options_t object into which to store - * the retrieved options. All existing values are overwritten - * - * Retrieves font rendering options set via #cairo_set_font_options. - * Note that the returned options do not include any options derived - * from the underlying surface; they are literally the options - * passed to cairo_set_font_options(). - **/ -void -cairo_get_font_options (cairo_t *cr, - cairo_font_options_t *options) -{ - /* check that we aren't trying to overwrite the nil object */ - if (cairo_font_options_status (options)) - return; - - if (cr->status) { - _cairo_font_options_init_default (options); - return; - } - - _cairo_gstate_get_font_options (cr->gstate, options); -} - -/** - * cairo_set_scaled_font: - * @cr: a #cairo_t - * @scaled_font: a #cairo_scaled_font_t - * - * Replaces the current font face, font matrix, and font options in - * the #cairo_t with those of the #cairo_scaled_font_t. Except for - * some translation, the current CTM of the #cairo_t should be the - * same as that of the #cairo_scaled_font_t, which can be accessed - * using cairo_scaled_font_get_ctm(). - * - * Since: 1.2 - **/ -void -cairo_set_scaled_font (cairo_t *cr, - const cairo_scaled_font_t *scaled_font) -{ - cairo_status_t status; - - if (cr->status) - return; - - if (scaled_font == NULL) { - status = CAIRO_STATUS_NULL_POINTER; - goto BAIL; - } - - status = scaled_font->status; - if (status) - goto BAIL; - - status = _cairo_gstate_set_font_face (cr->gstate, scaled_font->font_face); - if (status) - goto BAIL; - - status = _cairo_gstate_set_font_matrix (cr->gstate, &scaled_font->font_matrix); - if (status) - goto BAIL; - - _cairo_gstate_set_font_options (cr->gstate, &scaled_font->options); - - return; - -BAIL: - _cairo_set_error (cr, status); -} - -/** - * cairo_get_scaled_font: - * @cr: a #cairo_t - * - * Gets the current scaled font for a #cairo_t. - * - * Return value: the current scaled font. This object is owned by - * cairo. To keep a reference to it, you must call - * cairo_scaled_font_reference(). - * - * This function never returns %NULL. If memory cannot be allocated, a - * special "nil" #cairo_scaled_font_t object will be returned on which - * cairo_scaled_font_status() returns %CAIRO_STATUS_NO_MEMORY. Using - * this nil object will cause its error state to propagate to other - * objects it is passed to, (for example, calling - * cairo_set_scaled_font() with a nil font will trigger an error that - * will shutdown the #cairo_t object). - * - * Since: 1.4 - **/ -cairo_scaled_font_t * -cairo_get_scaled_font (cairo_t *cr) -{ - cairo_status_t status; - cairo_scaled_font_t *scaled_font; - - if (cr->status) - return _cairo_scaled_font_create_in_error (cr->status); - - status = _cairo_gstate_get_scaled_font (cr->gstate, &scaled_font); - if (status) { - _cairo_set_error (cr, status); - return _cairo_scaled_font_create_in_error (status); - } - - return scaled_font; -} - -/** - * cairo_text_extents: - * @cr: a #cairo_t - * @utf8: a NUL-terminated string of text encoded in UTF-8, or %NULL - * @extents: a #cairo_text_extents_t object into which the results - * will be stored - * - * Gets the extents for a string of text. The extents describe a - * user-space rectangle that encloses the "inked" portion of the text, - * (as it would be drawn by cairo_show_text()). Additionally, the - * x_advance and y_advance values indicate the amount by which the - * current point would be advanced by cairo_show_text(). - * - * Note that whitespace characters do not directly contribute to the - * size of the rectangle (extents.width and extents.height). They do - * contribute indirectly by changing the position of non-whitespace - * characters. In particular, trailing whitespace characters are - * likely to not affect the size of the rectangle, though they will - * affect the x_advance and y_advance values. - **/ -void -cairo_text_extents (cairo_t *cr, - const char *utf8, - cairo_text_extents_t *extents) -{ - cairo_status_t status; - cairo_glyph_t *glyphs = NULL; - int num_glyphs; - double x, y; - - extents->x_bearing = 0.0; - extents->y_bearing = 0.0; - extents->width = 0.0; - extents->height = 0.0; - extents->x_advance = 0.0; - extents->y_advance = 0.0; - - if (cr->status) - return; - - if (utf8 == NULL) - return; - - cairo_get_current_point (cr, &x, &y); - - status = _cairo_gstate_text_to_glyphs (cr->gstate, - x, y, - utf8, strlen (utf8), - &glyphs, &num_glyphs, - NULL, NULL, - NULL); - - if (status == CAIRO_STATUS_SUCCESS) - status = _cairo_gstate_glyph_extents (cr->gstate, - glyphs, num_glyphs, - extents); - cairo_glyph_free (glyphs); - - if (status) - _cairo_set_error (cr, status); -} - -/** - * cairo_glyph_extents: - * @cr: a #cairo_t - * @glyphs: an array of #cairo_glyph_t objects - * @num_glyphs: the number of elements in @glyphs - * @extents: a #cairo_text_extents_t object into which the results - * will be stored - * - * Gets the extents for an array of glyphs. The extents describe a - * user-space rectangle that encloses the "inked" portion of the - * glyphs, (as they would be drawn by cairo_show_glyphs()). - * Additionally, the x_advance and y_advance values indicate the - * amount by which the current point would be advanced by - * cairo_show_glyphs(). - * - * Note that whitespace glyphs do not contribute to the size of the - * rectangle (extents.width and extents.height). - **/ -void -cairo_glyph_extents (cairo_t *cr, - const cairo_glyph_t *glyphs, - int num_glyphs, - cairo_text_extents_t *extents) -{ - cairo_status_t status; - - extents->x_bearing = 0.0; - extents->y_bearing = 0.0; - extents->width = 0.0; - extents->height = 0.0; - extents->x_advance = 0.0; - extents->y_advance = 0.0; - - if (cr->status) - return; - - if (num_glyphs == 0) - return; - - if (num_glyphs < 0) { - _cairo_set_error (cr, CAIRO_STATUS_NEGATIVE_COUNT); - return; - } - - if (glyphs == NULL) { - _cairo_set_error (cr, CAIRO_STATUS_NULL_POINTER); - return; - } - - status = _cairo_gstate_glyph_extents (cr->gstate, glyphs, num_glyphs, - extents); - if (status) - _cairo_set_error (cr, status); -} - -/** - * cairo_show_text: - * @cr: a cairo context - * @utf8: a NUL-terminated string of text encoded in UTF-8, or %NULL - * - * A drawing operator that generates the shape from a string of UTF-8 - * characters, rendered according to the current font_face, font_size - * (font_matrix), and font_options. - * - * This function first computes a set of glyphs for the string of - * text. The first glyph is placed so that its origin is at the - * current point. The origin of each subsequent glyph is offset from - * that of the previous glyph by the advance values of the previous - * glyph. - * - * After this call the current point is moved to the origin of where - * the next glyph would be placed in this same progression. That is, - * the current point will be at the origin of the final glyph offset - * by its advance values. This allows for easy display of a single - * logical string with multiple calls to cairo_show_text(). - * - * Note: The cairo_show_text() function call is part of what the cairo - * designers call the "toy" text API. It is convenient for short demos - * and simple programs, but it is not expected to be adequate for - * serious text-using applications. See cairo_show_glyphs() for the - * "real" text display API in cairo. - **/ -void -cairo_show_text (cairo_t *cr, const char *utf8) -{ - cairo_text_extents_t extents; - cairo_status_t status; - cairo_glyph_t *glyphs = NULL, *last_glyph; - cairo_text_cluster_t *clusters = NULL; - int utf8_len, num_glyphs, num_clusters; - cairo_text_cluster_flags_t cluster_flags; - double x, y; - cairo_bool_t has_show_text_glyphs; - - if (cr->status) - return; - - if (utf8 == NULL) - return; - - cairo_get_current_point (cr, &x, &y); - - utf8_len = strlen (utf8); - - has_show_text_glyphs = - cairo_surface_has_show_text_glyphs (cairo_get_target (cr)); - - status = _cairo_gstate_text_to_glyphs (cr->gstate, - x, y, - utf8, utf8_len, - &glyphs, &num_glyphs, - has_show_text_glyphs ? &clusters : NULL, &num_clusters, - &cluster_flags); - if (status) - goto BAIL; - - if (num_glyphs == 0) - return; - - status = _cairo_gstate_show_text_glyphs (cr->gstate, - utf8, utf8_len, - glyphs, num_glyphs, - clusters, num_clusters, - cluster_flags); - if (status) - goto BAIL; - - last_glyph = &glyphs[num_glyphs - 1]; - status = _cairo_gstate_glyph_extents (cr->gstate, - last_glyph, 1, - &extents); - if (status) - goto BAIL; - - x = last_glyph->x + extents.x_advance; - y = last_glyph->y + extents.y_advance; - cairo_move_to (cr, x, y); - - BAIL: - cairo_glyph_free (glyphs); - cairo_text_cluster_free (clusters); - - if (status) - _cairo_set_error (cr, status); -} - -/** - * cairo_show_glyphs: - * @cr: a cairo context - * @glyphs: array of glyphs to show - * @num_glyphs: number of glyphs to show - * - * A drawing operator that generates the shape from an array of glyphs, - * rendered according to the current font face, font size - * (font matrix), and font options. - **/ -void -cairo_show_glyphs (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs) -{ - cairo_status_t status; - - if (cr->status) - return; - - if (num_glyphs == 0) - return; - - if (num_glyphs < 0) { - _cairo_set_error (cr, CAIRO_STATUS_NEGATIVE_COUNT); - return; - } - - if (glyphs == NULL) { - _cairo_set_error (cr, CAIRO_STATUS_NULL_POINTER); - return; - } - - status = _cairo_gstate_show_text_glyphs (cr->gstate, - NULL, 0, - glyphs, num_glyphs, - NULL, 0, - FALSE); - if (status) - _cairo_set_error (cr, status); -} - -/** - * cairo_show_text_glyphs: - * @cr: a cairo context - * @utf8: a string of text encoded in UTF-8 - * @utf8_len: length of @utf8 in bytes, or -1 if it is NUL-terminated - * @glyphs: array of glyphs to show - * @num_glyphs: number of glyphs to show - * @clusters: array of cluster mapping information - * @num_clusters: number of clusters in the mapping - * @cluster_flags: cluster mapping flags - * - * This operation has rendering effects similar to cairo_show_glyphs() - * but, if the target surface supports it, uses the provided text and - * cluster mapping to embed the text for the glyphs shown in the output. - * If the target does not support the extended attributes, this function - * acts like the basic cairo_show_glyphs() as if it had been passed - * @glyphs and @num_glyphs. - * - * The mapping between @utf8 and @glyphs is provided by an array of - * clusters. Each cluster covers a number of - * text bytes and glyphs, and neighboring clusters cover neighboring - * areas of @utf8 and @glyphs. The clusters should collectively cover @utf8 - * and @glyphs in entirety. - * - * The first cluster always covers bytes from the beginning of @utf8. - * If @cluster_flags do not have the %CAIRO_TEXT_CLUSTER_FLAG_BACKWARD - * set, the first cluster also covers the beginning - * of @glyphs, otherwise it covers the end of the @glyphs array and - * following clusters move backward. - * - * See #cairo_text_cluster_t for constraints on valid clusters. - * - * Since: 1.8 - **/ -void -cairo_show_text_glyphs (cairo_t *cr, - const char *utf8, - int utf8_len, - const cairo_glyph_t *glyphs, - int num_glyphs, - const cairo_text_cluster_t *clusters, - int num_clusters, - cairo_text_cluster_flags_t cluster_flags) -{ - cairo_status_t status; - - if (cr->status) - return; - - /* A slew of sanity checks */ - - /* Special case for NULL and -1 */ - if (utf8 == NULL && utf8_len == -1) - utf8_len = 0; - - /* No NULLs for non-zeros */ - if ((num_glyphs && glyphs == NULL) || - (utf8_len && utf8 == NULL) || - (num_clusters && clusters == NULL)) { - _cairo_set_error (cr, CAIRO_STATUS_NULL_POINTER); - return; - } - - /* A -1 for utf8_len means NUL-terminated */ - if (utf8_len == -1) - utf8_len = strlen (utf8); - - /* Apart from that, no negatives */ - if (num_glyphs < 0 || utf8_len < 0 || num_clusters < 0) { - _cairo_set_error (cr, CAIRO_STATUS_NEGATIVE_COUNT); - return; - } - - /* Make sure clusters cover the entire glyphs and utf8 arrays, - * and that cluster boundaries are UTF-8 boundaries. */ - status = _cairo_validate_text_clusters (utf8, utf8_len, - glyphs, num_glyphs, - clusters, num_clusters, cluster_flags); - if (status == CAIRO_STATUS_INVALID_CLUSTERS) { - /* Either got invalid UTF-8 text, or cluster mapping is bad. - * Differentiate those. */ - - cairo_status_t status2; - - status2 = _cairo_utf8_to_ucs4 (utf8, utf8_len, NULL, NULL); - if (status2) - status = status2; - - _cairo_set_error (cr, status); - return; - } - - if (num_glyphs == 0 && utf8_len == 0) - return; - - status = _cairo_gstate_show_text_glyphs (cr->gstate, - utf8, utf8_len, - glyphs, num_glyphs, - clusters, num_clusters, cluster_flags); - if (status) - _cairo_set_error (cr, status); -} - -/** - * cairo_text_path: - * @cr: a cairo context - * @utf8: a NUL-terminated string of text encoded in UTF-8, or %NULL - * - * Adds closed paths for text to the current path. The generated - * path if filled, achieves an effect similar to that of - * cairo_show_text(). - * - * Text conversion and positioning is done similar to cairo_show_text(). - * - * Like cairo_show_text(), After this call the current point is - * moved to the origin of where the next glyph would be placed in - * this same progression. That is, the current point will be at - * the origin of the final glyph offset by its advance values. - * This allows for chaining multiple calls to to cairo_text_path() - * without having to set current point in between. - * - * Note: The cairo_text_path() function call is part of what the cairo - * designers call the "toy" text API. It is convenient for short demos - * and simple programs, but it is not expected to be adequate for - * serious text-using applications. See cairo_glyph_path() for the - * "real" text path API in cairo. - **/ -void -cairo_text_path (cairo_t *cr, const char *utf8) -{ - cairo_status_t status; - cairo_text_extents_t extents; - cairo_glyph_t *glyphs = NULL, *last_glyph; - int num_glyphs; - double x, y; - - if (cr->status) - return; - - if (utf8 == NULL) - return; - - cairo_get_current_point (cr, &x, &y); - - status = _cairo_gstate_text_to_glyphs (cr->gstate, - x, y, - utf8, strlen (utf8), - &glyphs, &num_glyphs, - NULL, NULL, - NULL); - - if (status) - goto BAIL; - - if (num_glyphs == 0) - return; - - status = _cairo_gstate_glyph_path (cr->gstate, - glyphs, num_glyphs, - cr->path); - - if (status) - goto BAIL; - - last_glyph = &glyphs[num_glyphs - 1]; - status = _cairo_gstate_glyph_extents (cr->gstate, - last_glyph, 1, - &extents); - - if (status) - goto BAIL; - - x = last_glyph->x + extents.x_advance; - y = last_glyph->y + extents.y_advance; - cairo_move_to (cr, x, y); - - BAIL: - cairo_glyph_free (glyphs); - - if (status) - _cairo_set_error (cr, status); -} - -/** - * cairo_glyph_path: - * @cr: a cairo context - * @glyphs: array of glyphs to show - * @num_glyphs: number of glyphs to show - * - * Adds closed paths for the glyphs to the current path. The generated - * path if filled, achieves an effect similar to that of - * cairo_show_glyphs(). - **/ -void -cairo_glyph_path (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs) -{ - cairo_status_t status; - - if (cr->status) - return; - - if (num_glyphs == 0) - return; - - if (num_glyphs < 0) { - _cairo_set_error (cr, CAIRO_STATUS_NEGATIVE_COUNT); - return; - } - - if (glyphs == NULL) { - _cairo_set_error (cr, CAIRO_STATUS_NULL_POINTER); - return; - } - - status = _cairo_gstate_glyph_path (cr->gstate, - glyphs, num_glyphs, - cr->path); - if (status) - _cairo_set_error (cr, status); -} - -/** - * cairo_get_operator: - * @cr: a cairo context - * - * Gets the current compositing operator for a cairo context. - * - * Return value: the current compositing operator. - **/ -cairo_operator_t -cairo_get_operator (cairo_t *cr) -{ - if (cr->status) - return CAIRO_GSTATE_OPERATOR_DEFAULT; - - return _cairo_gstate_get_operator (cr->gstate); -} - -/** - * cairo_get_tolerance: - * @cr: a cairo context - * - * Gets the current tolerance value, as set by cairo_set_tolerance(). - * - * Return value: the current tolerance value. - **/ -double -cairo_get_tolerance (cairo_t *cr) -{ - if (cr->status) - return CAIRO_GSTATE_TOLERANCE_DEFAULT; - - return _cairo_gstate_get_tolerance (cr->gstate); -} -slim_hidden_def (cairo_get_tolerance); - -/** - * cairo_get_antialias: - * @cr: a cairo context - * - * Gets the current shape antialiasing mode, as set by cairo_set_shape_antialias(). - * - * Return value: the current shape antialiasing mode. - **/ -cairo_antialias_t -cairo_get_antialias (cairo_t *cr) -{ - if (cr->status) - return CAIRO_ANTIALIAS_DEFAULT; - - return _cairo_gstate_get_antialias (cr->gstate); -} - -/** - * cairo_has_current_point: - * @cr: a cairo context - * - * Returns whether a current point is defined on the current path. - * See cairo_get_current_point() for details on the current point. - * - * Return value: whether a current point is defined. - * - * Since: 1.6 - **/ -cairo_bool_t -cairo_has_current_point (cairo_t *cr) -{ - if (cr->status) - return FALSE; - - return cr->path->has_current_point; -} - -/** - * cairo_get_current_point: - * @cr: a cairo context - * @x: return value for X coordinate of the current point - * @y: return value for Y coordinate of the current point - * - * Gets the current point of the current path, which is - * conceptually the final point reached by the path so far. - * - * The current point is returned in the user-space coordinate - * system. If there is no defined current point or if @cr is in an - * error status, @x and @y will both be set to 0.0. It is possible to - * check this in advance with cairo_has_current_point(). - * - * Most path construction functions alter the current point. See the - * following for details on how they affect the current point: - * cairo_new_path(), cairo_new_sub_path(), - * cairo_append_path(), cairo_close_path(), - * cairo_move_to(), cairo_line_to(), cairo_curve_to(), - * cairo_rel_move_to(), cairo_rel_line_to(), cairo_rel_curve_to(), - * cairo_arc(), cairo_arc_negative(), cairo_rectangle(), - * cairo_text_path(), cairo_glyph_path(), cairo_stroke_to_path(). - * - * Some functions use and alter the current point but do not - * otherwise change current path: - * cairo_show_text(). - * - * Some functions unset the current path and as a result, current point: - * cairo_fill(), cairo_stroke(). - **/ -void -cairo_get_current_point (cairo_t *cr, double *x_ret, double *y_ret) -{ - cairo_fixed_t x_fixed, y_fixed; - double x, y; - - if (cr->status == CAIRO_STATUS_SUCCESS && - _cairo_path_fixed_get_current_point (cr->path, &x_fixed, &y_fixed)) - { - x = _cairo_fixed_to_double (x_fixed); - y = _cairo_fixed_to_double (y_fixed); - _cairo_gstate_backend_to_user (cr->gstate, &x, &y); - } - else - { - x = 0.0; - y = 0.0; - } - - if (x_ret) - *x_ret = x; - if (y_ret) - *y_ret = y; -} -slim_hidden_def(cairo_get_current_point); - -/** - * cairo_get_fill_rule: - * @cr: a cairo context - * - * Gets the current fill rule, as set by cairo_set_fill_rule(). - * - * Return value: the current fill rule. - **/ -cairo_fill_rule_t -cairo_get_fill_rule (cairo_t *cr) -{ - if (cr->status) - return CAIRO_GSTATE_FILL_RULE_DEFAULT; - - return _cairo_gstate_get_fill_rule (cr->gstate); -} - -/** - * cairo_get_line_width: - * @cr: a cairo context - * - * This function returns the current line width value exactly as set by - * cairo_set_line_width(). Note that the value is unchanged even if - * the CTM has changed between the calls to cairo_set_line_width() and - * cairo_get_line_width(). - * - * Return value: the current line width. - **/ -double -cairo_get_line_width (cairo_t *cr) -{ - if (cr->status) - return CAIRO_GSTATE_LINE_WIDTH_DEFAULT; - - return _cairo_gstate_get_line_width (cr->gstate); -} -slim_hidden_def (cairo_get_line_width); - -/** - * cairo_get_line_cap: - * @cr: a cairo context - * - * Gets the current line cap style, as set by cairo_set_line_cap(). - * - * Return value: the current line cap style. - **/ -cairo_line_cap_t -cairo_get_line_cap (cairo_t *cr) -{ - if (cr->status) - return CAIRO_GSTATE_LINE_CAP_DEFAULT; - - return _cairo_gstate_get_line_cap (cr->gstate); -} - -/** - * cairo_get_line_join: - * @cr: a cairo context - * - * Gets the current line join style, as set by cairo_set_line_join(). - * - * Return value: the current line join style. - **/ -cairo_line_join_t -cairo_get_line_join (cairo_t *cr) -{ - if (cr->status) - return CAIRO_GSTATE_LINE_JOIN_DEFAULT; - - return _cairo_gstate_get_line_join (cr->gstate); -} - -/** - * cairo_get_miter_limit: - * @cr: a cairo context - * - * Gets the current miter limit, as set by cairo_set_miter_limit(). - * - * Return value: the current miter limit. - **/ -double -cairo_get_miter_limit (cairo_t *cr) -{ - if (cr->status) - return CAIRO_GSTATE_MITER_LIMIT_DEFAULT; - - return _cairo_gstate_get_miter_limit (cr->gstate); -} - -/** - * cairo_get_matrix: - * @cr: a cairo context - * @matrix: return value for the matrix - * - * Stores the current transformation matrix (CTM) into @matrix. - **/ -void -cairo_get_matrix (cairo_t *cr, cairo_matrix_t *matrix) -{ - if (cr->status) { - cairo_matrix_init_identity (matrix); - return; - } - - _cairo_gstate_get_matrix (cr->gstate, matrix); -} -slim_hidden_def (cairo_get_matrix); - -/** - * cairo_get_target: - * @cr: a cairo context - * - * Gets the target surface for the cairo context as passed to - * cairo_create(). - * - * This function will always return a valid pointer, but the result - * can be a "nil" surface if @cr is already in an error state, - * (ie. cairo_status() != %CAIRO_STATUS_SUCCESS). - * A nil surface is indicated by cairo_surface_status() - * != %CAIRO_STATUS_SUCCESS. - * - * Return value: the target surface. This object is owned by cairo. To - * keep a reference to it, you must call cairo_surface_reference(). - **/ -cairo_surface_t * -cairo_get_target (cairo_t *cr) -{ - if (cr->status) - return _cairo_surface_create_in_error (cr->status); - - return _cairo_gstate_get_original_target (cr->gstate); -} -slim_hidden_def (cairo_get_target); - -/** - * cairo_get_group_target: - * @cr: a cairo context - * - * Gets the current destination surface for the context. This is either - * the original target surface as passed to cairo_create() or the target - * surface for the current group as started by the most recent call to - * cairo_push_group() or cairo_push_group_with_content(). - * - * This function will always return a valid pointer, but the result - * can be a "nil" surface if @cr is already in an error state, - * (ie. cairo_status() != %CAIRO_STATUS_SUCCESS). - * A nil surface is indicated by cairo_surface_status() - * != %CAIRO_STATUS_SUCCESS. - * - * Return value: the target surface. This object is owned by cairo. To - * keep a reference to it, you must call cairo_surface_reference(). - * - * Since: 1.2 - **/ -cairo_surface_t * -cairo_get_group_target (cairo_t *cr) -{ - if (cr->status) - return _cairo_surface_create_in_error (cr->status); - - return _cairo_gstate_get_target (cr->gstate); -} - -/** - * cairo_copy_path: - * @cr: a cairo context - * - * Creates a copy of the current path and returns it to the user as a - * #cairo_path_t. See #cairo_path_data_t for hints on how to iterate - * over the returned data structure. - * - * This function will always return a valid pointer, but the result - * will have no data (data==%NULL and - * num_data==0), if either of the following - * conditions hold: - * - * - * If there is insufficient memory to copy the path. In this - * case path->status will be set to - * %CAIRO_STATUS_NO_MEMORY. - * If @cr is already in an error state. In this case - * path->status will contain the same status that - * would be returned by cairo_status(). - * - * - * In either case, path->status will be set to - * %CAIRO_STATUS_NO_MEMORY (regardless of what the error status in - * @cr might have been). - * - * Return value: the copy of the current path. The caller owns the - * returned object and should call cairo_path_destroy() when finished - * with it. - **/ -cairo_path_t * -cairo_copy_path (cairo_t *cr) -{ - if (cr->status) - return _cairo_path_create_in_error (cr->status); - - return _cairo_path_create (cr->path, cr->gstate); -} - -/** - * cairo_copy_path_flat: - * @cr: a cairo context - * - * Gets a flattened copy of the current path and returns it to the - * user as a #cairo_path_t. See #cairo_path_data_t for hints on - * how to iterate over the returned data structure. - * - * This function is like cairo_copy_path() except that any curves - * in the path will be approximated with piecewise-linear - * approximations, (accurate to within the current tolerance - * value). That is, the result is guaranteed to not have any elements - * of type %CAIRO_PATH_CURVE_TO which will instead be replaced by a - * series of %CAIRO_PATH_LINE_TO elements. - * - * This function will always return a valid pointer, but the result - * will have no data (data==%NULL and - * num_data==0), if either of the following - * conditions hold: - * - * - * If there is insufficient memory to copy the path. In this - * case path->status will be set to - * %CAIRO_STATUS_NO_MEMORY. - * If @cr is already in an error state. In this case - * path->status will contain the same status that - * would be returned by cairo_status(). - * - * - * Return value: the copy of the current path. The caller owns the - * returned object and should call cairo_path_destroy() when finished - * with it. - **/ -cairo_path_t * -cairo_copy_path_flat (cairo_t *cr) -{ - if (cr->status) - return _cairo_path_create_in_error (cr->status); - - return _cairo_path_create_flat (cr->path, cr->gstate); -} - -/** - * cairo_append_path: - * @cr: a cairo context - * @path: path to be appended - * - * Append the @path onto the current path. The @path may be either the - * return value from one of cairo_copy_path() or - * cairo_copy_path_flat() or it may be constructed manually. See - * #cairo_path_t for details on how the path data structure should be - * initialized, and note that path->status must be - * initialized to %CAIRO_STATUS_SUCCESS. - **/ -void -cairo_append_path (cairo_t *cr, - const cairo_path_t *path) -{ - cairo_status_t status; - - if (cr->status) - return; - - if (path == NULL) { - _cairo_set_error (cr, CAIRO_STATUS_NULL_POINTER); - return; - } - - if (path->status) { - if (path->status > CAIRO_STATUS_SUCCESS && - path->status <= CAIRO_STATUS_LAST_STATUS) - _cairo_set_error (cr, path->status); - else - _cairo_set_error (cr, CAIRO_STATUS_INVALID_STATUS); - return; - } - - if (path->num_data == 0) - return; - - if (path->data == NULL) { - _cairo_set_error (cr, CAIRO_STATUS_NULL_POINTER); - return; - } - - status = _cairo_path_append_to_context (path, cr); - if (status) - _cairo_set_error (cr, status); -} - -/** - * cairo_status: - * @cr: a cairo context - * - * Checks whether an error has previously occurred for this context. - * - * Returns: the current status of this context, see #cairo_status_t - **/ -cairo_status_t -cairo_status (cairo_t *cr) -{ - return cr->status; -} -slim_hidden_def (cairo_status); diff --git a/uppdev/plugin/cairo/lib/cairo.h b/uppdev/plugin/cairo/lib/cairo.h deleted file mode 100644 index cf4bc05b3..000000000 --- a/uppdev/plugin/cairo/lib/cairo.h +++ /dev/null @@ -1,2328 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - */ - -#ifndef CAIRO_H -#define CAIRO_H - -#include "cairo-version.h" -#include "cairo-features.h" -#include "cairo-deprecated.h" - -#ifdef __cplusplus -# define CAIRO_BEGIN_DECLS extern "C" { -# define CAIRO_END_DECLS } -#else -# define CAIRO_BEGIN_DECLS -# define CAIRO_END_DECLS -#endif - -#ifndef cairo_public -# if defined (_MSC_VER) && ! defined (CAIRO_WIN32_STATIC_BUILD) -# define cairo_public __declspec(dllimport) -# else -# define cairo_public -# endif -#endif - -CAIRO_BEGIN_DECLS - -#define CAIRO_VERSION_ENCODE(major, minor, micro) ( \ - ((major) * 10000) \ - + ((minor) * 100) \ - + ((micro) * 1)) - -#define CAIRO_VERSION CAIRO_VERSION_ENCODE( \ - CAIRO_VERSION_MAJOR, \ - CAIRO_VERSION_MINOR, \ - CAIRO_VERSION_MICRO) - - -#define CAIRO_VERSION_STRINGIZE_(major, minor, micro) \ - #major"."#minor"."#micro -#define CAIRO_VERSION_STRINGIZE(major, minor, micro) \ - CAIRO_VERSION_STRINGIZE_(major, minor, micro) - -#define CAIRO_VERSION_STRING CAIRO_VERSION_STRINGIZE( \ - CAIRO_VERSION_MAJOR, \ - CAIRO_VERSION_MINOR, \ - CAIRO_VERSION_MICRO) - - -cairo_public int -cairo_version (void); - -cairo_public const char* -cairo_version_string (void); - -/** - * cairo_bool_t: - * - * #cairo_bool_t is used for boolean values. Returns of type - * #cairo_bool_t will always be either 0 or 1, but testing against - * these values explicitly is not encouraged; just use the - * value as a boolean condition. - * - * - * if (cairo_in_stroke (cr, x, y)) { - * /* do something */ - * } - * - **/ -typedef int cairo_bool_t; - -/** - * cairo_t: - * - * A #cairo_t contains the current state of the rendering device, - * including coordinates of yet to be drawn shapes. - * - * Cairo contexts, as #cairo_t objects are named, are central to - * cairo and all drawing with cairo is always done to a #cairo_t - * object. - * - * Memory management of #cairo_t is done with - * cairo_reference() and cairo_destroy(). - **/ -typedef struct _cairo cairo_t; - -/** - * cairo_surface_t: - * - * A #cairo_surface_t represents an image, either as the destination - * of a drawing operation or as source when drawing onto another - * surface. To draw to a #cairo_surface_t, create a cairo context - * with the surface as the target, using cairo_create(). - * - * There are different subtypes of #cairo_surface_t for - * different drawing backends; for example, cairo_image_surface_create() - * creates a bitmap image in memory. - * The type of a surface can be queried with cairo_surface_get_type(). - * - * Memory management of #cairo_surface_t is done with - * cairo_surface_reference() and cairo_surface_destroy(). - **/ -typedef struct _cairo_surface cairo_surface_t; - -/** - * cairo_matrix_t: - * @xx: xx component of the affine transformation - * @yx: yx component of the affine transformation - * @xy: xy component of the affine transformation - * @yy: yy component of the affine transformation - * @x0: X translation component of the affine transformation - * @y0: Y translation component of the affine transformation - * - * A #cairo_matrix_t holds an affine transformation, such as a scale, - * rotation, shear, or a combination of those. The transformation of - * a point (x, y) is given by: - * - * x_new = xx * x + xy * y + x0; - * y_new = yx * x + yy * y + y0; - * - **/ -typedef struct _cairo_matrix { - double xx; double yx; - double xy; double yy; - double x0; double y0; -} cairo_matrix_t; - -/** - * cairo_pattern_t: - * - * A #cairo_pattern_t represents a source when drawing onto a - * surface. There are different subtypes of #cairo_pattern_t, - * for different types of sources; for example, - * cairo_pattern_create_rgb() creates a pattern for a solid - * opaque color. - * - * Other than various cairo_pattern_create_type() - * functions, some of the pattern types can be implicitly created - * using various cairo_set_source_type() functions; - * for example cairo_set_source_rgb(). - * - * The type of a pattern can be queried with cairo_pattern_get_type(). - * - * Memory management of #cairo_pattern_t is done with - * cairo_pattern_reference() and cairo_pattern_destroy(). - **/ -typedef struct _cairo_pattern cairo_pattern_t; - -/** - * cairo_destroy_func_t: - * @data: The data element being destroyed. - * - * #cairo_destroy_func_t the type of function which is called when a - * data element is destroyed. It is passed the pointer to the data - * element and should free any memory and resources allocated for it. - **/ -typedef void (*cairo_destroy_func_t) (void *data); - -/** - * cairo_user_data_key_t: - * @unused: not used; ignore. - * - * #cairo_user_data_key_t is used for attaching user data to cairo - * data structures. The actual contents of the struct is never used, - * and there is no need to initialize the object; only the unique - * address of a #cairo_data_key_t object is used. Typically, you - * would just use the address of a static #cairo_data_key_t object. - **/ -typedef struct _cairo_user_data_key { - int unused; -} cairo_user_data_key_t; - -/** - * cairo_status_t: - * @CAIRO_STATUS_SUCCESS: no error has occurred - * @CAIRO_STATUS_NO_MEMORY: out of memory - * @CAIRO_STATUS_INVALID_RESTORE: cairo_restore() called without matching cairo_save() - * @CAIRO_STATUS_INVALID_POP_GROUP: no saved group to pop - * @CAIRO_STATUS_NO_CURRENT_POINT: no current point defined - * @CAIRO_STATUS_INVALID_MATRIX: invalid matrix (not invertible) - * @CAIRO_STATUS_INVALID_STATUS: invalid value for an input #cairo_status_t - * @CAIRO_STATUS_NULL_POINTER: %NULL pointer - * @CAIRO_STATUS_INVALID_STRING: input string not valid UTF-8 - * @CAIRO_STATUS_INVALID_PATH_DATA: input path data not valid - * @CAIRO_STATUS_READ_ERROR: error while reading from input stream - * @CAIRO_STATUS_WRITE_ERROR: error while writing to output stream - * @CAIRO_STATUS_SURFACE_FINISHED: target surface has been finished - * @CAIRO_STATUS_SURFACE_TYPE_MISMATCH: the surface type is not appropriate for the operation - * @CAIRO_STATUS_PATTERN_TYPE_MISMATCH: the pattern type is not appropriate for the operation - * @CAIRO_STATUS_INVALID_CONTENT: invalid value for an input #cairo_content_t - * @CAIRO_STATUS_INVALID_FORMAT: invalid value for an input #cairo_format_t - * @CAIRO_STATUS_INVALID_VISUAL: invalid value for an input Visual* - * @CAIRO_STATUS_FILE_NOT_FOUND: file not found - * @CAIRO_STATUS_INVALID_DASH: invalid value for a dash setting - * @CAIRO_STATUS_INVALID_DSC_COMMENT: invalid value for a DSC comment (Since 1.2) - * @CAIRO_STATUS_INVALID_INDEX: invalid index passed to getter (Since 1.4) - * @CAIRO_STATUS_CLIP_NOT_REPRESENTABLE: clip region not representable in desired format (Since 1.4) - * @CAIRO_STATUS_TEMP_FILE_ERROR: error creating or writing to a temporary file (Since 1.6) - * @CAIRO_STATUS_INVALID_STRIDE: invalid value for stride (Since 1.6) - * @CAIRO_STATUS_FONT_TYPE_MISMATCH: the font type is not appropriate for the operation (Since 1.8) - * @CAIRO_STATUS_USER_FONT_IMMUTABLE: the user-font is immutable (Since 1.8) - * @CAIRO_STATUS_USER_FONT_ERROR: error occurred in a user-font callback function (Since 1.8) - * @CAIRO_STATUS_NEGATIVE_COUNT: negative number used where it is not allowed (Since 1.8) - * @CAIRO_STATUS_INVALID_CLUSTERS: input clusters do not represent the accompanying text and glyph array (Since 1.8) - * @CAIRO_STATUS_INVALID_SLANT: invalid value for an input #cairo_font_slant_t (Since 1.8) - * @CAIRO_STATUS_INVALID_WEIGHT: invalid value for an input #cairo_font_weight_t (Since 1.8) - * - * #cairo_status_t is used to indicate errors that can occur when - * using Cairo. In some cases it is returned directly by functions. - * but when using #cairo_t, the last error, if any, is stored in - * the context and can be retrieved with cairo_status(). - * - * New entries may be added in future versions. Use cairo_status_to_string() - * to get a human-readable representation of an error message. - **/ -typedef enum _cairo_status { - CAIRO_STATUS_SUCCESS = 0, - CAIRO_STATUS_NO_MEMORY, - CAIRO_STATUS_INVALID_RESTORE, - CAIRO_STATUS_INVALID_POP_GROUP, - CAIRO_STATUS_NO_CURRENT_POINT, - CAIRO_STATUS_INVALID_MATRIX, - CAIRO_STATUS_INVALID_STATUS, - CAIRO_STATUS_NULL_POINTER, - CAIRO_STATUS_INVALID_STRING, - CAIRO_STATUS_INVALID_PATH_DATA, - CAIRO_STATUS_READ_ERROR, - CAIRO_STATUS_WRITE_ERROR, - CAIRO_STATUS_SURFACE_FINISHED, - CAIRO_STATUS_SURFACE_TYPE_MISMATCH, - CAIRO_STATUS_PATTERN_TYPE_MISMATCH, - CAIRO_STATUS_INVALID_CONTENT, - CAIRO_STATUS_INVALID_FORMAT, - CAIRO_STATUS_INVALID_VISUAL, - CAIRO_STATUS_FILE_NOT_FOUND, - CAIRO_STATUS_INVALID_DASH, - CAIRO_STATUS_INVALID_DSC_COMMENT, - CAIRO_STATUS_INVALID_INDEX, - CAIRO_STATUS_CLIP_NOT_REPRESENTABLE, - CAIRO_STATUS_TEMP_FILE_ERROR, - CAIRO_STATUS_INVALID_STRIDE, - CAIRO_STATUS_FONT_TYPE_MISMATCH, - CAIRO_STATUS_USER_FONT_IMMUTABLE, - CAIRO_STATUS_USER_FONT_ERROR, - CAIRO_STATUS_NEGATIVE_COUNT, - CAIRO_STATUS_INVALID_CLUSTERS, - CAIRO_STATUS_INVALID_SLANT, - CAIRO_STATUS_INVALID_WEIGHT - /* after adding a new error: update CAIRO_STATUS_LAST_STATUS in cairoint.h */ -} cairo_status_t; - -/** - * cairo_content_t: - * @CAIRO_CONTENT_COLOR: The surface will hold color content only. - * @CAIRO_CONTENT_ALPHA: The surface will hold alpha content only. - * @CAIRO_CONTENT_COLOR_ALPHA: The surface will hold color and alpha content. - * - * #cairo_content_t is used to describe the content that a surface will - * contain, whether color information, alpha information (translucence - * vs. opacity), or both. - * - * Note: The large values here are designed to keep #cairo_content_t - * values distinct from #cairo_format_t values so that the - * implementation can detect the error if users confuse the two types. - **/ -typedef enum _cairo_content { - CAIRO_CONTENT_COLOR = 0x1000, - CAIRO_CONTENT_ALPHA = 0x2000, - CAIRO_CONTENT_COLOR_ALPHA = 0x3000 -} cairo_content_t; - -/** - * cairo_write_func_t: - * @closure: the output closure - * @data: the buffer containing the data to write - * @length: the amount of data to write - * - * #cairo_write_func_t is the type of function which is called when a - * backend needs to write data to an output stream. It is passed the - * closure which was specified by the user at the time the write - * function was registered, the data to write and the length of the - * data in bytes. The write function should return - * %CAIRO_STATUS_SUCCESS if all the data was successfully written, - * %CAIRO_STATUS_WRITE_ERROR otherwise. - * - * Returns: the status code of the write operation - **/ -typedef cairo_status_t (*cairo_write_func_t) (void *closure, - const unsigned char *data, - unsigned int length); - -/** - * cairo_read_func_t: - * @closure: the input closure - * @data: the buffer into which to read the data - * @length: the amount of data to read - * - * #cairo_read_func_t is the type of function which is called when a - * backend needs to read data from an input stream. It is passed the - * closure which was specified by the user at the time the read - * function was registered, the buffer to read the data into and the - * length of the data in bytes. The read function should return - * %CAIRO_STATUS_SUCCESS if all the data was successfully read, - * %CAIRO_STATUS_READ_ERROR otherwise. - * - * Returns: the status code of the read operation - **/ -typedef cairo_status_t (*cairo_read_func_t) (void *closure, - unsigned char *data, - unsigned int length); - -/* Functions for manipulating state objects */ -cairo_public cairo_t * -cairo_create (cairo_surface_t *target); - -cairo_public cairo_t * -cairo_reference (cairo_t *cr); - -cairo_public void -cairo_destroy (cairo_t *cr); - -cairo_public unsigned int -cairo_get_reference_count (cairo_t *cr); - -cairo_public void * -cairo_get_user_data (cairo_t *cr, - const cairo_user_data_key_t *key); - -cairo_public cairo_status_t -cairo_set_user_data (cairo_t *cr, - const cairo_user_data_key_t *key, - void *user_data, - cairo_destroy_func_t destroy); - -cairo_public void -cairo_save (cairo_t *cr); - -cairo_public void -cairo_restore (cairo_t *cr); - -cairo_public void -cairo_push_group (cairo_t *cr); - -cairo_public void -cairo_push_group_with_content (cairo_t *cr, cairo_content_t content); - -cairo_public cairo_pattern_t * -cairo_pop_group (cairo_t *cr); - -cairo_public void -cairo_pop_group_to_source (cairo_t *cr); - -/* Modify state */ - -/** - * cairo_operator_t: - * @CAIRO_OPERATOR_CLEAR: clear destination layer (bounded) - * @CAIRO_OPERATOR_SOURCE: replace destination layer (bounded) - * @CAIRO_OPERATOR_OVER: draw source layer on top of destination layer - * (bounded) - * @CAIRO_OPERATOR_IN: draw source where there was destination content - * (unbounded) - * @CAIRO_OPERATOR_OUT: draw source where there was no destination - * content (unbounded) - * @CAIRO_OPERATOR_ATOP: draw source on top of destination content and - * only there - * @CAIRO_OPERATOR_DEST: ignore the source - * @CAIRO_OPERATOR_DEST_OVER: draw destination on top of source - * @CAIRO_OPERATOR_DEST_IN: leave destination only where there was - * source content (unbounded) - * @CAIRO_OPERATOR_DEST_OUT: leave destination only where there was no - * source content - * @CAIRO_OPERATOR_DEST_ATOP: leave destination on top of source content - * and only there (unbounded) - * @CAIRO_OPERATOR_XOR: source and destination are shown where there is only - * one of them - * @CAIRO_OPERATOR_ADD: source and destination layers are accumulated - * @CAIRO_OPERATOR_SATURATE: like over, but assuming source and dest are - * disjoint geometries - * - * #cairo_operator_t is used to set the compositing operator for all cairo - * drawing operations. - * - * The default operator is %CAIRO_OPERATOR_OVER. - * - * The operators marked as unbounded modify their - * destination even outside of the mask layer (that is, their effect is not - * bound by the mask layer). However, their effect can still be limited by - * way of clipping. - * - * To keep things simple, the operator descriptions here - * document the behavior for when both source and destination are either fully - * transparent or fully opaque. The actual implementation works for - * translucent layers too. - * For a more detailed explanation of the effects of each operator, including - * the mathematical definitions, see - * http://cairographics.org/operators/. - **/ -typedef enum _cairo_operator { - CAIRO_OPERATOR_CLEAR, - - CAIRO_OPERATOR_SOURCE, - CAIRO_OPERATOR_OVER, - CAIRO_OPERATOR_IN, - CAIRO_OPERATOR_OUT, - CAIRO_OPERATOR_ATOP, - - CAIRO_OPERATOR_DEST, - CAIRO_OPERATOR_DEST_OVER, - CAIRO_OPERATOR_DEST_IN, - CAIRO_OPERATOR_DEST_OUT, - CAIRO_OPERATOR_DEST_ATOP, - - CAIRO_OPERATOR_XOR, - CAIRO_OPERATOR_ADD, - CAIRO_OPERATOR_SATURATE -} cairo_operator_t; - -cairo_public void -cairo_set_operator (cairo_t *cr, cairo_operator_t op); - -cairo_public void -cairo_set_source (cairo_t *cr, cairo_pattern_t *source); - -cairo_public void -cairo_set_source_rgb (cairo_t *cr, double red, double green, double blue); - -cairo_public void -cairo_set_source_rgba (cairo_t *cr, - double red, double green, double blue, - double alpha); - -cairo_public void -cairo_set_source_surface (cairo_t *cr, - cairo_surface_t *surface, - double x, - double y); - -cairo_public void -cairo_set_tolerance (cairo_t *cr, double tolerance); - -/** - * cairo_antialias_t: - * @CAIRO_ANTIALIAS_DEFAULT: Use the default antialiasing for - * the subsystem and target device - * @CAIRO_ANTIALIAS_NONE: Use a bilevel alpha mask - * @CAIRO_ANTIALIAS_GRAY: Perform single-color antialiasing (using - * shades of gray for black text on a white background, for example). - * @CAIRO_ANTIALIAS_SUBPIXEL: Perform antialiasing by taking - * advantage of the order of subpixel elements on devices - * such as LCD panels - * - * Specifies the type of antialiasing to do when rendering text or shapes. - **/ -typedef enum _cairo_antialias { - CAIRO_ANTIALIAS_DEFAULT, - CAIRO_ANTIALIAS_NONE, - CAIRO_ANTIALIAS_GRAY, - CAIRO_ANTIALIAS_SUBPIXEL -} cairo_antialias_t; - -cairo_public void -cairo_set_antialias (cairo_t *cr, cairo_antialias_t antialias); - -/** - * cairo_fill_rule_t: - * @CAIRO_FILL_RULE_WINDING: If the path crosses the ray from - * left-to-right, counts +1. If the path crosses the ray - * from right to left, counts -1. (Left and right are determined - * from the perspective of looking along the ray from the starting - * point.) If the total count is non-zero, the point will be filled. - * @CAIRO_FILL_RULE_EVEN_ODD: Counts the total number of - * intersections, without regard to the orientation of the contour. If - * the total number of intersections is odd, the point will be - * filled. - * - * #cairo_fill_rule_t is used to select how paths are filled. For both - * fill rules, whether or not a point is included in the fill is - * determined by taking a ray from that point to infinity and looking - * at intersections with the path. The ray can be in any direction, - * as long as it doesn't pass through the end point of a segment - * or have a tricky intersection such as intersecting tangent to the path. - * (Note that filling is not actually implemented in this way. This - * is just a description of the rule that is applied.) - * - * The default fill rule is %CAIRO_FILL_RULE_WINDING. - * - * New entries may be added in future versions. - **/ -typedef enum _cairo_fill_rule { - CAIRO_FILL_RULE_WINDING, - CAIRO_FILL_RULE_EVEN_ODD -} cairo_fill_rule_t; - -cairo_public void -cairo_set_fill_rule (cairo_t *cr, cairo_fill_rule_t fill_rule); - -cairo_public void -cairo_set_line_width (cairo_t *cr, double width); - -/** - * cairo_line_cap_t: - * @CAIRO_LINE_CAP_BUTT: start(stop) the line exactly at the start(end) point - * @CAIRO_LINE_CAP_ROUND: use a round ending, the center of the circle is the end point - * @CAIRO_LINE_CAP_SQUARE: use squared ending, the center of the square is the end point - * - * Specifies how to render the endpoints of the path when stroking. - * - * The default line cap style is %CAIRO_LINE_CAP_BUTT. - **/ -typedef enum _cairo_line_cap { - CAIRO_LINE_CAP_BUTT, - CAIRO_LINE_CAP_ROUND, - CAIRO_LINE_CAP_SQUARE -} cairo_line_cap_t; - -cairo_public void -cairo_set_line_cap (cairo_t *cr, cairo_line_cap_t line_cap); - -/** - * cairo_line_join_t: - * @CAIRO_LINE_JOIN_MITER: use a sharp (angled) corner, see - * cairo_set_miter_limit() - * @CAIRO_LINE_JOIN_ROUND: use a rounded join, the center of the circle is the - * joint point - * @CAIRO_LINE_JOIN_BEVEL: use a cut-off join, the join is cut off at half - * the line width from the joint point - * - * Specifies how to render the junction of two lines when stroking. - * - * The default line join style is %CAIRO_LINE_JOIN_MITER. - **/ -typedef enum _cairo_line_join { - CAIRO_LINE_JOIN_MITER, - CAIRO_LINE_JOIN_ROUND, - CAIRO_LINE_JOIN_BEVEL -} cairo_line_join_t; - -cairo_public void -cairo_set_line_join (cairo_t *cr, cairo_line_join_t line_join); - -cairo_public void -cairo_set_dash (cairo_t *cr, - const double *dashes, - int num_dashes, - double offset); - -cairo_public void -cairo_set_miter_limit (cairo_t *cr, double limit); - -cairo_public void -cairo_translate (cairo_t *cr, double tx, double ty); - -cairo_public void -cairo_scale (cairo_t *cr, double sx, double sy); - -cairo_public void -cairo_rotate (cairo_t *cr, double angle); - -cairo_public void -cairo_transform (cairo_t *cr, - const cairo_matrix_t *matrix); - -cairo_public void -cairo_set_matrix (cairo_t *cr, - const cairo_matrix_t *matrix); - -cairo_public void -cairo_identity_matrix (cairo_t *cr); - -cairo_public void -cairo_user_to_device (cairo_t *cr, double *x, double *y); - -cairo_public void -cairo_user_to_device_distance (cairo_t *cr, double *dx, double *dy); - -cairo_public void -cairo_device_to_user (cairo_t *cr, double *x, double *y); - -cairo_public void -cairo_device_to_user_distance (cairo_t *cr, double *dx, double *dy); - -/* Path creation functions */ -cairo_public void -cairo_new_path (cairo_t *cr); - -cairo_public void -cairo_move_to (cairo_t *cr, double x, double y); - -cairo_public void -cairo_new_sub_path (cairo_t *cr); - -cairo_public void -cairo_line_to (cairo_t *cr, double x, double y); - -cairo_public void -cairo_curve_to (cairo_t *cr, - double x1, double y1, - double x2, double y2, - double x3, double y3); - -cairo_public void -cairo_arc (cairo_t *cr, - double xc, double yc, - double radius, - double angle1, double angle2); - -cairo_public void -cairo_arc_negative (cairo_t *cr, - double xc, double yc, - double radius, - double angle1, double angle2); - -/* XXX: NYI -cairo_public void -cairo_arc_to (cairo_t *cr, - double x1, double y1, - double x2, double y2, - double radius); -*/ - -cairo_public void -cairo_rel_move_to (cairo_t *cr, double dx, double dy); - -cairo_public void -cairo_rel_line_to (cairo_t *cr, double dx, double dy); - -cairo_public void -cairo_rel_curve_to (cairo_t *cr, - double dx1, double dy1, - double dx2, double dy2, - double dx3, double dy3); - -cairo_public void -cairo_rectangle (cairo_t *cr, - double x, double y, - double width, double height); - -/* XXX: NYI -cairo_public void -cairo_stroke_to_path (cairo_t *cr); -*/ - -cairo_public void -cairo_close_path (cairo_t *cr); - -cairo_public void -cairo_path_extents (cairo_t *cr, - double *x1, double *y1, - double *x2, double *y2); - -/* Painting functions */ -cairo_public void -cairo_paint (cairo_t *cr); - -cairo_public void -cairo_paint_with_alpha (cairo_t *cr, - double alpha); - -cairo_public void -cairo_mask (cairo_t *cr, - cairo_pattern_t *pattern); - -cairo_public void -cairo_mask_surface (cairo_t *cr, - cairo_surface_t *surface, - double surface_x, - double surface_y); - -cairo_public void -cairo_stroke (cairo_t *cr); - -cairo_public void -cairo_stroke_preserve (cairo_t *cr); - -cairo_public void -cairo_fill (cairo_t *cr); - -cairo_public void -cairo_fill_preserve (cairo_t *cr); - -cairo_public void -cairo_copy_page (cairo_t *cr); - -cairo_public void -cairo_show_page (cairo_t *cr); - -/* Insideness testing */ -cairo_public cairo_bool_t -cairo_in_stroke (cairo_t *cr, double x, double y); - -cairo_public cairo_bool_t -cairo_in_fill (cairo_t *cr, double x, double y); - -/* Rectangular extents */ -cairo_public void -cairo_stroke_extents (cairo_t *cr, - double *x1, double *y1, - double *x2, double *y2); - -cairo_public void -cairo_fill_extents (cairo_t *cr, - double *x1, double *y1, - double *x2, double *y2); - -/* Clipping */ -cairo_public void -cairo_reset_clip (cairo_t *cr); - -cairo_public void -cairo_clip (cairo_t *cr); - -cairo_public void -cairo_clip_preserve (cairo_t *cr); - -cairo_public void -cairo_clip_extents (cairo_t *cr, - double *x1, double *y1, - double *x2, double *y2); - -/** - * cairo_rectangle_t: - * @x: X coordinate of the left side of the rectangle - * @y: Y coordinate of the the top side of the rectangle - * @width: width of the rectangle - * @height: height of the rectangle - * - * A data structure for holding a rectangle. - * - * Since: 1.4 - **/ -typedef struct _cairo_rectangle { - double x, y, width, height; -} cairo_rectangle_t; - -/** - * cairo_rectangle_list_t: - * @status: Error status of the rectangle list - * @rectangles: Array containing the rectangles - * @num_rectangles: Number of rectangles in this list - * - * A data structure for holding a dynamically allocated - * array of rectangles. - * - * Since: 1.4 - **/ -typedef struct _cairo_rectangle_list { - cairo_status_t status; - cairo_rectangle_t *rectangles; - int num_rectangles; -} cairo_rectangle_list_t; - -cairo_public cairo_rectangle_list_t * -cairo_copy_clip_rectangle_list (cairo_t *cr); - -cairo_public void -cairo_rectangle_list_destroy (cairo_rectangle_list_t *rectangle_list); - -/* Font/Text functions */ - -/** - * cairo_scaled_font_t: - * - * A #cairo_scaled_font_t is a font scaled to a particular size and device - * resolution. A #cairo_scaled_font_t is most useful for low-level font - * usage where a library or application wants to cache a reference - * to a scaled font to speed up the computation of metrics. - * - * There are various types of scaled fonts, depending on the - * font backend they use. The type of a - * scaled font can be queried using cairo_scaled_font_get_type(). - * - * Memory management of #cairo_scaled_font_t is done with - * cairo_scaled_font_reference() and cairo_scaled_font_destroy(). - **/ -typedef struct _cairo_scaled_font cairo_scaled_font_t; - -/** - * cairo_font_face_t: - * - * A #cairo_font_face_t specifies all aspects of a font other - * than the size or font matrix (a font matrix is used to distort - * a font by sheering it or scaling it unequally in the two - * directions) . A font face can be set on a #cairo_t by using - * cairo_set_font_face(); the size and font matrix are set with - * cairo_set_font_size() and cairo_set_font_matrix(). - * - * There are various types of font faces, depending on the - * font backend they use. The type of a - * font face can be queried using cairo_font_face_get_type(). - * - * Memory management of #cairo_font_face_t is done with - * cairo_font_face_reference() and cairo_font_face_destroy(). - **/ -typedef struct _cairo_font_face cairo_font_face_t; - -/** - * cairo_glyph_t: - * @index: glyph index in the font. The exact interpretation of the - * glyph index depends on the font technology being used. - * @x: the offset in the X direction between the origin used for - * drawing or measuring the string and the origin of this glyph. - * @y: the offset in the Y direction between the origin used for - * drawing or measuring the string and the origin of this glyph. - * - * The #cairo_glyph_t structure holds information about a single glyph - * when drawing or measuring text. A font is (in simple terms) a - * collection of shapes used to draw text. A glyph is one of these - * shapes. There can be multiple glyphs for a single character - * (alternates to be used in different contexts, for example), or a - * glyph can be a ligature of multiple - * characters. Cairo doesn't expose any way of converting input text - * into glyphs, so in order to use the Cairo interfaces that take - * arrays of glyphs, you must directly access the appropriate - * underlying font system. - * - * Note that the offsets given by @x and @y are not cumulative. When - * drawing or measuring text, each glyph is individually positioned - * with respect to the overall origin - **/ -typedef struct { - unsigned long index; - double x; - double y; -} cairo_glyph_t; - -cairo_public cairo_glyph_t * -cairo_glyph_allocate (int num_glyphs); - -cairo_public void -cairo_glyph_free (cairo_glyph_t *glyphs); - -/** - * cairo_text_cluster_t: - * @num_bytes: the number of bytes of UTF-8 text covered by cluster - * @num_glyphs: the number of glyphs covered by cluster - * - * The #cairo_text_cluster_t structure holds information about a single - * text cluster. A text cluster is a minimal - * mapping of some glyphs corresponding to some UTF-8 text. - * - * For a cluster to be valid, both @num_bytes and @num_glyphs should - * be non-negative, and at least one should be non-zero. - * Note that clusters with zero glyphs are not as well supported as - * normal clusters. For example, PDF rendering applications typically - * ignore those clusters when PDF text is being selected. - * - * See cairo_show_text_glyphs() for how clusters are used in advanced - * text operations. - * - * Since: 1.8 - **/ -typedef struct { - int num_bytes; - int num_glyphs; -} cairo_text_cluster_t; - -cairo_public cairo_text_cluster_t * -cairo_text_cluster_allocate (int num_clusters); - -cairo_public void -cairo_text_cluster_free (cairo_text_cluster_t *clusters); - -/** - * cairo_text_cluster_flags_t: - * @CAIRO_TEXT_CLUSTER_FLAG_BACKWARD: The clusters in the cluster array - * map to glyphs in the glyph array from end to start. - * - * Specifies properties of a text cluster mapping. - * - * Since: 1.8 - **/ -typedef enum _cairo_text_cluster_flags { - CAIRO_TEXT_CLUSTER_FLAG_BACKWARD = 0x00000001 -} cairo_text_cluster_flags_t; - -/** - * cairo_text_extents_t: - * @x_bearing: the horizontal distance from the origin to the - * leftmost part of the glyphs as drawn. Positive if the - * glyphs lie entirely to the right of the origin. - * @y_bearing: the vertical distance from the origin to the - * topmost part of the glyphs as drawn. Positive only if the - * glyphs lie completely below the origin; will usually be - * negative. - * @width: width of the glyphs as drawn - * @height: height of the glyphs as drawn - * @x_advance:distance to advance in the X direction - * after drawing these glyphs - * @y_advance: distance to advance in the Y direction - * after drawing these glyphs. Will typically be zero except - * for vertical text layout as found in East-Asian languages. - * - * The #cairo_text_extents_t structure stores the extents of a single - * glyph or a string of glyphs in user-space coordinates. Because text - * extents are in user-space coordinates, they are mostly, but not - * entirely, independent of the current transformation matrix. If you call - * cairo_scale(cr, 2.0, 2.0), text will - * be drawn twice as big, but the reported text extents will not be - * doubled. They will change slightly due to hinting (so you can't - * assume that metrics are independent of the transformation matrix), - * but otherwise will remain unchanged. - **/ -typedef struct { - double x_bearing; - double y_bearing; - double width; - double height; - double x_advance; - double y_advance; -} cairo_text_extents_t; - -/** - * cairo_font_extents_t: - * @ascent: the distance that the font extends above the baseline. - * Note that this is not always exactly equal to the maximum - * of the extents of all the glyphs in the font, but rather - * is picked to express the font designer's intent as to - * how the font should align with elements above it. - * @descent: the distance that the font extends below the baseline. - * This value is positive for typical fonts that include - * portions below the baseline. Note that this is not always - * exactly equal to the maximum of the extents of all the - * glyphs in the font, but rather is picked to express the - * font designer's intent as to how the the font should - * align with elements below it. - * @height: the recommended vertical distance between baselines when - * setting consecutive lines of text with the font. This - * is greater than @ascent+@descent by a - * quantity known as the line spacing - * or external leading. When space - * is at a premium, most fonts can be set with only - * a distance of @ascent+@descent between lines. - * @max_x_advance: the maximum distance in the X direction that - * the the origin is advanced for any glyph in the font. - * @max_y_advance: the maximum distance in the Y direction that - * the the origin is advanced for any glyph in the font. - * this will be zero for normal fonts used for horizontal - * writing. (The scripts of East Asia are sometimes written - * vertically.) - * - * The #cairo_font_extents_t structure stores metric information for - * a font. Values are given in the current user-space coordinate - * system. - * - * Because font metrics are in user-space coordinates, they are - * mostly, but not entirely, independent of the current transformation - * matrix. If you call cairo_scale(cr, 2.0, 2.0), - * text will be drawn twice as big, but the reported text extents will - * not be doubled. They will change slightly due to hinting (so you - * can't assume that metrics are independent of the transformation - * matrix), but otherwise will remain unchanged. - **/ -typedef struct { - double ascent; - double descent; - double height; - double max_x_advance; - double max_y_advance; -} cairo_font_extents_t; - -/** - * cairo_font_slant_t: - * @CAIRO_FONT_SLANT_NORMAL: Upright font style - * @CAIRO_FONT_SLANT_ITALIC: Italic font style - * @CAIRO_FONT_SLANT_OBLIQUE: Oblique font style - * - * Specifies variants of a font face based on their slant. - **/ -typedef enum _cairo_font_slant { - CAIRO_FONT_SLANT_NORMAL, - CAIRO_FONT_SLANT_ITALIC, - CAIRO_FONT_SLANT_OBLIQUE -} cairo_font_slant_t; - -/** - * cairo_font_weight_t: - * @CAIRO_FONT_WEIGHT_NORMAL: Normal font weight - * @CAIRO_FONT_WEIGHT_BOLD: Bold font weight - * - * Specifies variants of a font face based on their weight. - **/ -typedef enum _cairo_font_weight { - CAIRO_FONT_WEIGHT_NORMAL, - CAIRO_FONT_WEIGHT_BOLD -} cairo_font_weight_t; - -/** - * cairo_subpixel_order_t: - * @CAIRO_SUBPIXEL_ORDER_DEFAULT: Use the default subpixel order for - * for the target device - * @CAIRO_SUBPIXEL_ORDER_RGB: Subpixel elements are arranged horizontally - * with red at the left - * @CAIRO_SUBPIXEL_ORDER_BGR: Subpixel elements are arranged horizontally - * with blue at the left - * @CAIRO_SUBPIXEL_ORDER_VRGB: Subpixel elements are arranged vertically - * with red at the top - * @CAIRO_SUBPIXEL_ORDER_VBGR: Subpixel elements are arranged vertically - * with blue at the top - * - * The subpixel order specifies the order of color elements within - * each pixel on the display device when rendering with an - * antialiasing mode of %CAIRO_ANTIALIAS_SUBPIXEL. - **/ -typedef enum _cairo_subpixel_order { - CAIRO_SUBPIXEL_ORDER_DEFAULT, - CAIRO_SUBPIXEL_ORDER_RGB, - CAIRO_SUBPIXEL_ORDER_BGR, - CAIRO_SUBPIXEL_ORDER_VRGB, - CAIRO_SUBPIXEL_ORDER_VBGR -} cairo_subpixel_order_t; - -/** - * cairo_hint_style_t: - * @CAIRO_HINT_STYLE_DEFAULT: Use the default hint style for - * font backend and target device - * @CAIRO_HINT_STYLE_NONE: Do not hint outlines - * @CAIRO_HINT_STYLE_SLIGHT: Hint outlines slightly to improve - * contrast while retaining good fidelity to the original - * shapes. - * @CAIRO_HINT_STYLE_MEDIUM: Hint outlines with medium strength - * giving a compromise between fidelity to the original shapes - * and contrast - * @CAIRO_HINT_STYLE_FULL: Hint outlines to maximize contrast - * - * Specifies the type of hinting to do on font outlines. Hinting - * is the process of fitting outlines to the pixel grid in order - * to improve the appearance of the result. Since hinting outlines - * involves distorting them, it also reduces the faithfulness - * to the original outline shapes. Not all of the outline hinting - * styles are supported by all font backends. - * - * New entries may be added in future versions. - **/ -typedef enum _cairo_hint_style { - CAIRO_HINT_STYLE_DEFAULT, - CAIRO_HINT_STYLE_NONE, - CAIRO_HINT_STYLE_SLIGHT, - CAIRO_HINT_STYLE_MEDIUM, - CAIRO_HINT_STYLE_FULL -} cairo_hint_style_t; - -/** - * cairo_hint_metrics_t: - * @CAIRO_HINT_METRICS_DEFAULT: Hint metrics in the default - * manner for the font backend and target device - * @CAIRO_HINT_METRICS_OFF: Do not hint font metrics - * @CAIRO_HINT_METRICS_ON: Hint font metrics - * - * Specifies whether to hint font metrics; hinting font metrics - * means quantizing them so that they are integer values in - * device space. Doing this improves the consistency of - * letter and line spacing, however it also means that text - * will be laid out differently at different zoom factors. - **/ -typedef enum _cairo_hint_metrics { - CAIRO_HINT_METRICS_DEFAULT, - CAIRO_HINT_METRICS_OFF, - CAIRO_HINT_METRICS_ON -} cairo_hint_metrics_t; - -/** - * cairo_font_options_t: - * - * An opaque structure holding all options that are used when - * rendering fonts. - * - * Individual features of a #cairo_font_options_t can be set or - * accessed using functions named - * cairo_font_options_set_feature_name and - * cairo_font_options_get_feature_name, like - * cairo_font_options_set_antialias() and - * cairo_font_options_get_antialias(). - * - * New features may be added to a #cairo_font_options_t in the - * future. For this reason, cairo_font_options_copy(), - * cairo_font_options_equal(), cairo_font_options_merge(), and - * cairo_font_options_hash() should be used to copy, check - * for equality, merge, or compute a hash value of - * #cairo_font_options_t objects. - **/ -typedef struct _cairo_font_options cairo_font_options_t; - -cairo_public cairo_font_options_t * -cairo_font_options_create (void); - -cairo_public cairo_font_options_t * -cairo_font_options_copy (const cairo_font_options_t *original); - -cairo_public void -cairo_font_options_destroy (cairo_font_options_t *options); - -cairo_public cairo_status_t -cairo_font_options_status (cairo_font_options_t *options); - -cairo_public void -cairo_font_options_merge (cairo_font_options_t *options, - const cairo_font_options_t *other); -cairo_public cairo_bool_t -cairo_font_options_equal (const cairo_font_options_t *options, - const cairo_font_options_t *other); - -cairo_public unsigned long -cairo_font_options_hash (const cairo_font_options_t *options); - -cairo_public void -cairo_font_options_set_antialias (cairo_font_options_t *options, - cairo_antialias_t antialias); -cairo_public cairo_antialias_t -cairo_font_options_get_antialias (const cairo_font_options_t *options); - -cairo_public void -cairo_font_options_set_subpixel_order (cairo_font_options_t *options, - cairo_subpixel_order_t subpixel_order); -cairo_public cairo_subpixel_order_t -cairo_font_options_get_subpixel_order (const cairo_font_options_t *options); - -cairo_public void -cairo_font_options_set_hint_style (cairo_font_options_t *options, - cairo_hint_style_t hint_style); -cairo_public cairo_hint_style_t -cairo_font_options_get_hint_style (const cairo_font_options_t *options); - -cairo_public void -cairo_font_options_set_hint_metrics (cairo_font_options_t *options, - cairo_hint_metrics_t hint_metrics); -cairo_public cairo_hint_metrics_t -cairo_font_options_get_hint_metrics (const cairo_font_options_t *options); - -/* This interface is for dealing with text as text, not caring about the - font object inside the the cairo_t. */ - -cairo_public void -cairo_select_font_face (cairo_t *cr, - const char *family, - cairo_font_slant_t slant, - cairo_font_weight_t weight); - -cairo_public void -cairo_set_font_size (cairo_t *cr, double size); - -cairo_public void -cairo_set_font_matrix (cairo_t *cr, - const cairo_matrix_t *matrix); - -cairo_public void -cairo_get_font_matrix (cairo_t *cr, - cairo_matrix_t *matrix); - -cairo_public void -cairo_set_font_options (cairo_t *cr, - const cairo_font_options_t *options); - -cairo_public void -cairo_get_font_options (cairo_t *cr, - cairo_font_options_t *options); - -cairo_public void -cairo_set_font_face (cairo_t *cr, cairo_font_face_t *font_face); - -cairo_public cairo_font_face_t * -cairo_get_font_face (cairo_t *cr); - -cairo_public void -cairo_set_scaled_font (cairo_t *cr, - const cairo_scaled_font_t *scaled_font); - -cairo_public cairo_scaled_font_t * -cairo_get_scaled_font (cairo_t *cr); - -cairo_public void -cairo_show_text (cairo_t *cr, const char *utf8); - -cairo_public void -cairo_show_glyphs (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs); - -cairo_public void -cairo_show_text_glyphs (cairo_t *cr, - const char *utf8, - int utf8_len, - const cairo_glyph_t *glyphs, - int num_glyphs, - const cairo_text_cluster_t *clusters, - int num_clusters, - cairo_text_cluster_flags_t cluster_flags); - -cairo_public void -cairo_text_path (cairo_t *cr, const char *utf8); - -cairo_public void -cairo_glyph_path (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs); - -cairo_public void -cairo_text_extents (cairo_t *cr, - const char *utf8, - cairo_text_extents_t *extents); - -cairo_public void -cairo_glyph_extents (cairo_t *cr, - const cairo_glyph_t *glyphs, - int num_glyphs, - cairo_text_extents_t *extents); - -cairo_public void -cairo_font_extents (cairo_t *cr, - cairo_font_extents_t *extents); - -/* Generic identifier for a font style */ - -cairo_public cairo_font_face_t * -cairo_font_face_reference (cairo_font_face_t *font_face); - -cairo_public void -cairo_font_face_destroy (cairo_font_face_t *font_face); - -cairo_public unsigned int -cairo_font_face_get_reference_count (cairo_font_face_t *font_face); - -cairo_public cairo_status_t -cairo_font_face_status (cairo_font_face_t *font_face); - - -/** - * cairo_font_type_t: - * @CAIRO_FONT_TYPE_TOY: The font was created using cairo's toy font api - * @CAIRO_FONT_TYPE_FT: The font is of type FreeType - * @CAIRO_FONT_TYPE_WIN32: The font is of type Win32 - * @CAIRO_FONT_TYPE_QUARTZ: The font is of type Quartz (Since: 1.6) - * @CAIRO_FONT_TYPE_USER: The font was create using cairo's user font api (Since: 1.8) - * - * #cairo_font_type_t is used to describe the type of a given font - * face or scaled font. The font types are also known as "font - * backends" within cairo. - * - * The type of a font face is determined by the function used to - * create it, which will generally be of the form - * cairo_type_font_face_create(). The font face type can be queried - * with cairo_font_face_get_type() - * - * The various #cairo_font_face_t functions can be used with a font face - * of any type. - * - * The type of a scaled font is determined by the type of the font - * face passed to cairo_scaled_font_create(). The scaled font type can - * be queried with cairo_scaled_font_get_type() - * - * The various #cairo_scaled_font_t functions can be used with scaled - * fonts of any type, but some font backends also provide - * type-specific functions that must only be called with a scaled font - * of the appropriate type. These functions have names that begin with - * cairo_type_scaled_font() such as cairo_ft_scaled_font_lock_face(). - * - * The behavior of calling a type-specific function with a scaled font - * of the wrong type is undefined. - * - * New entries may be added in future versions. - * - * Since: 1.2 - **/ -typedef enum _cairo_font_type { - CAIRO_FONT_TYPE_TOY, - CAIRO_FONT_TYPE_FT, - CAIRO_FONT_TYPE_WIN32, - CAIRO_FONT_TYPE_QUARTZ, - CAIRO_FONT_TYPE_USER -} cairo_font_type_t; - -cairo_public cairo_font_type_t -cairo_font_face_get_type (cairo_font_face_t *font_face); - -cairo_public void * -cairo_font_face_get_user_data (cairo_font_face_t *font_face, - const cairo_user_data_key_t *key); - -cairo_public cairo_status_t -cairo_font_face_set_user_data (cairo_font_face_t *font_face, - const cairo_user_data_key_t *key, - void *user_data, - cairo_destroy_func_t destroy); - -/* Portable interface to general font features. */ - -cairo_public cairo_scaled_font_t * -cairo_scaled_font_create (cairo_font_face_t *font_face, - const cairo_matrix_t *font_matrix, - const cairo_matrix_t *ctm, - const cairo_font_options_t *options); - -cairo_public cairo_scaled_font_t * -cairo_scaled_font_reference (cairo_scaled_font_t *scaled_font); - -cairo_public void -cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font); - -cairo_public unsigned int -cairo_scaled_font_get_reference_count (cairo_scaled_font_t *scaled_font); - -cairo_public cairo_status_t -cairo_scaled_font_status (cairo_scaled_font_t *scaled_font); - -cairo_public cairo_font_type_t -cairo_scaled_font_get_type (cairo_scaled_font_t *scaled_font); - -cairo_public void * -cairo_scaled_font_get_user_data (cairo_scaled_font_t *scaled_font, - const cairo_user_data_key_t *key); - -cairo_public cairo_status_t -cairo_scaled_font_set_user_data (cairo_scaled_font_t *scaled_font, - const cairo_user_data_key_t *key, - void *user_data, - cairo_destroy_func_t destroy); - -cairo_public void -cairo_scaled_font_extents (cairo_scaled_font_t *scaled_font, - cairo_font_extents_t *extents); - -cairo_public void -cairo_scaled_font_text_extents (cairo_scaled_font_t *scaled_font, - const char *utf8, - cairo_text_extents_t *extents); - -cairo_public void -cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font, - const cairo_glyph_t *glyphs, - int num_glyphs, - cairo_text_extents_t *extents); - -cairo_public cairo_status_t -cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font, - double x, - double y, - const char *utf8, - int utf8_len, - cairo_glyph_t **glyphs, - int *num_glyphs, - cairo_text_cluster_t **clusters, - int *num_clusters, - cairo_text_cluster_flags_t *cluster_flags); - -cairo_public cairo_font_face_t * -cairo_scaled_font_get_font_face (cairo_scaled_font_t *scaled_font); - -cairo_public void -cairo_scaled_font_get_font_matrix (cairo_scaled_font_t *scaled_font, - cairo_matrix_t *font_matrix); - -cairo_public void -cairo_scaled_font_get_ctm (cairo_scaled_font_t *scaled_font, - cairo_matrix_t *ctm); - -cairo_public void -cairo_scaled_font_get_scale_matrix (cairo_scaled_font_t *scaled_font, - cairo_matrix_t *scale_matrix); - -cairo_public void -cairo_scaled_font_get_font_options (cairo_scaled_font_t *scaled_font, - cairo_font_options_t *options); - - -/* Toy fonts */ - -cairo_public cairo_font_face_t * -cairo_toy_font_face_create (const char *family, - cairo_font_slant_t slant, - cairo_font_weight_t weight); - -cairo_public const char * -cairo_toy_font_face_get_family (cairo_font_face_t *font_face); - -cairo_public cairo_font_slant_t -cairo_toy_font_face_get_slant (cairo_font_face_t *font_face); - -cairo_public cairo_font_weight_t -cairo_toy_font_face_get_weight (cairo_font_face_t *font_face); - - -/* User fonts */ - -cairo_public cairo_font_face_t * -cairo_user_font_face_create (void); - -/* User-font method signatures */ - -/** - * cairo_user_scaled_font_init_func_t: - * @scaled_font: the scaled-font being created - * @cr: a cairo context, in font space - * @extents: font extents to fill in, in font space - * - * #cairo_user_scaled_font_init_func_t is the type of function which is - * called when a scaled-font needs to be created for a user font-face. - * - * The cairo context @cr is not used by the caller, but is prepared in font - * space, similar to what the cairo contexts passed to the render_glyph - * method will look like. The callback can use this context for extents - * computation for example. After the callback is called, @cr is checked - * for any error status. - * - * The @extents argument is where the user font sets the font extents for - * @scaled_font. It is in font space, which means that for most cases its - * ascent and descent members should add to 1.0. @extents is preset to - * hold a value of 1.0 for ascent, height, and max_x_advance, and 0.0 for - * descent and max_y_advance members. - * - * The callback is optional. If not set, default font extents as described - * in the previous paragraph will be used. - * - * Note that @scaled_font is not fully initialized at this - * point and trying to use it for text operations in the callback will result - * in deadlock. - * - * Returns: %CAIRO_STATUS_SUCCESS upon success, or - * %CAIRO_STATUS_USER_FONT_ERROR or any other error status on error. - * - * Since: 1.8 - **/ -typedef cairo_status_t (*cairo_user_scaled_font_init_func_t) (cairo_scaled_font_t *scaled_font, - cairo_t *cr, - cairo_font_extents_t *extents); - -/** - * cairo_user_scaled_font_render_glyph_func_t: - * @scaled_font: user scaled-font - * @glyph: glyph code to render - * @cr: cairo context to draw to, in font space - * @extents: glyph extents to fill in, in font space - * - * #cairo_user_scaled_font_render_glyph_func_t is the type of function which - * is called when a user scaled-font needs to render a glyph. - * - * The callback is mandatory, and expected to draw the glyph with code @glyph to - * the cairo context @cr. @cr is prepared such that the glyph drawing is done in - * font space. That is, the matrix set on @cr is the scale matrix of @scaled_font, - * The @extents argument is where the user font sets the font extents for - * @scaled_font. However, if user prefers to draw in user space, they can - * achieve that by changing the matrix on @cr. All cairo rendering operations - * to @cr are permitted, however, the result is undefined if any source other - * than the default source on @cr is used. That means, glyph bitmaps should - * be rendered using cairo_mask() instead of cairo_paint(). - * - * Other non-default settings on @cr include a font size of 1.0 (given that - * it is set up to be in font space), and font options corresponding to - * @scaled_font. - * - * The @extents argument is preset to have x_bearing, - * width, and y_advance of zero, - * y_bearing set to -font_extents.ascent, - * height to font_extents.ascent+font_extents.descent, - * and x_advance to font_extents.max_x_advance. - * The only field user needs to set in majority of cases is - * x_advance. - * If the width field is zero upon the callback returning - * (which is its preset value), the glyph extents are automatically computed - * based on the drawings done to @cr. This is in most cases exactly what the - * desired behavior is. However, if for any reason the callback sets the - * extents, it must be ink extents, and include the extents of all drawing - * done to @cr in the callback. - * - * Returns: %CAIRO_STATUS_SUCCESS upon success, or - * %CAIRO_STATUS_USER_FONT_ERROR or any other error status on error. - * - * Since: 1.8 - **/ -typedef cairo_status_t (*cairo_user_scaled_font_render_glyph_func_t) (cairo_scaled_font_t *scaled_font, - unsigned long glyph, - cairo_t *cr, - cairo_text_extents_t *extents); - -/** - * cairo_user_scaled_font_text_to_glyphs_func_t: - * @scaled_font: the scaled-font being created - * @utf8: a string of text encoded in UTF-8 - * @utf8_len: length of @utf8 in bytes - * @glyphs: pointer to array of glyphs to fill, in font space - * @num_glyphs: pointer to number of glyphs - * @clusters: pointer to array of cluster mapping information to fill, or %NULL - * @num_clusters: pointer to number of clusters - * @cluster_flags: pointer to location to store cluster flags corresponding to the - * output @clusters - * - * #cairo_user_scaled_font_text_to_glyphs_func_t is the type of function which - * is called to convert input text to an array of glyphs. This is used by the - * cairo_show_text() operation. - * - * Using this callback the user-font has full control on glyphs and their - * positions. That means, it allows for features like ligatures and kerning, - * as well as complex shaping required for scripts like - * Arabic and Indic. - * - * The @num_glyphs argument is preset to the number of glyph entries available - * in the @glyphs buffer. If the @glyphs buffer is %NULL, the value of - * @num_glyphs will be zero. If the provided glyph array is too short for - * the conversion (or for convenience), a new glyph array may be allocated - * using cairo_glyph_allocate() and placed in @glyphs. Upon return, - * @num_glyphs should contain the number of generated glyphs. If the value - * @glyphs points at has changed after the call, the caller will free the - * allocated glyph array using cairo_glyph_free(). - * The callback should populate the glyph indices and positions (in font space) - * assuming that the text is to be shown at the origin. - * - * If @clusters is not %NULL, @num_clusters and @cluster_flags are also - * non-%NULL, and cluster mapping should be computed. The semantics of how - * cluster array allocation works is similar to the glyph array. That is, - * if @clusters initially points to a non-%NULL value, that array may be used - * as a cluster buffer, and @num_clusters points to the number of cluster - * entries available there. If the provided cluster array is too short for - * the conversion (or for convenience), a new cluster array may be allocated - * using cairo_text_cluster_allocate() and placed in @clusters. Upon return, - * @num_clusters should contain the number of generated clusters. - * If the value @clusters points at has changed after the call, the caller - * will free the allocated cluster array using cairo_text_cluster_free(). - * - * The callback is optional. If @num_glyphs is negative upon - * the callback returning, the unicode_to_glyph callback - * is tried. See #cairo_user_scaled_font_unicode_to_glyph_func_t. - * - * Note: While cairo does not impose any limitation on glyph indices, - * some applications may assume that a glyph index fits in a 16-bit - * unsigned integer. As such, it is advised that user-fonts keep their - * glyphs in the 0 to 65535 range. Furthermore, some applications may - * assume that glyph 0 is a special glyph-not-found glyph. User-fonts - * are advised to use glyph 0 for such purposes and do not use that - * glyph value for other purposes. - * - * Returns: %CAIRO_STATUS_SUCCESS upon success, or - * %CAIRO_STATUS_USER_FONT_ERROR or any other error status on error. - * - * Since: 1.8 - **/ -typedef cairo_status_t (*cairo_user_scaled_font_text_to_glyphs_func_t) (cairo_scaled_font_t *scaled_font, - const char *utf8, - int utf8_len, - cairo_glyph_t **glyphs, - int *num_glyphs, - cairo_text_cluster_t **clusters, - int *num_clusters, - cairo_text_cluster_flags_t *cluster_flags); - -/** - * cairo_user_scaled_font_unicode_to_glyph_func_t: - * @scaled_font: the scaled-font being created - * @unicode: input unicode character code-point - * @glyph_index: output glyph index - * - * #cairo_user_scaled_font_unicode_to_glyph_func_t is the type of function which - * is called to convert an input Unicode character to a single glyph. - * This is used by the cairo_show_text() operation. - * - * This callback is used to provide the same functionality as the - * text_to_glyphs callback does (see #cairo_user_scaled_font_text_to_glyphs_func_t) - * but has much less control on the output, - * in exchange for increased ease of use. The inherent assumption to using - * this callback is that each character maps to one glyph, and that the - * mapping is context independent. It also assumes that glyphs are positioned - * according to their advance width. These mean no ligatures, kerning, or - * complex scripts can be implemented using this callback. - * - * The callback is optional, and only used if text_to_glyphs callback is not - * set or fails to return glyphs. If this callback is not set, an identity - * mapping from Unicode code-points to glyph indices is assumed. - * - * Note: While cairo does not impose any limitation on glyph indices, - * some applications may assume that a glyph index fits in a 16-bit - * unsigned integer. As such, it is advised that user-fonts keep their - * glyphs in the 0 to 65535 range. Furthermore, some applications may - * assume that glyph 0 is a special glyph-not-found glyph. User-fonts - * are advised to use glyph 0 for such purposes and do not use that - * glyph value for other purposes. - * - * Returns: %CAIRO_STATUS_SUCCESS upon success, or - * %CAIRO_STATUS_USER_FONT_ERROR or any other error status on error. - * - * Since: 1.8 - **/ -typedef cairo_status_t (*cairo_user_scaled_font_unicode_to_glyph_func_t) (cairo_scaled_font_t *scaled_font, - unsigned long unicode, - unsigned long *glyph_index); - -/* User-font method setters */ - -cairo_public void -cairo_user_font_face_set_init_func (cairo_font_face_t *font_face, - cairo_user_scaled_font_init_func_t init_func); - -cairo_public void -cairo_user_font_face_set_render_glyph_func (cairo_font_face_t *font_face, - cairo_user_scaled_font_render_glyph_func_t render_glyph_func); - -cairo_public void -cairo_user_font_face_set_text_to_glyphs_func (cairo_font_face_t *font_face, - cairo_user_scaled_font_text_to_glyphs_func_t text_to_glyphs_func); - -cairo_public void -cairo_user_font_face_set_unicode_to_glyph_func (cairo_font_face_t *font_face, - cairo_user_scaled_font_unicode_to_glyph_func_t unicode_to_glyph_func); - -/* User-font method getters */ - -cairo_public cairo_user_scaled_font_init_func_t -cairo_user_font_face_get_init_func (cairo_font_face_t *font_face); - -cairo_public cairo_user_scaled_font_render_glyph_func_t -cairo_user_font_face_get_render_glyph_func (cairo_font_face_t *font_face); - -cairo_public cairo_user_scaled_font_text_to_glyphs_func_t -cairo_user_font_face_get_text_to_glyphs_func (cairo_font_face_t *font_face); - -cairo_public cairo_user_scaled_font_unicode_to_glyph_func_t -cairo_user_font_face_get_unicode_to_glyph_func (cairo_font_face_t *font_face); - - -/* Query functions */ - -cairo_public cairo_operator_t -cairo_get_operator (cairo_t *cr); - -cairo_public cairo_pattern_t * -cairo_get_source (cairo_t *cr); - -cairo_public double -cairo_get_tolerance (cairo_t *cr); - -cairo_public cairo_antialias_t -cairo_get_antialias (cairo_t *cr); - -cairo_public cairo_bool_t -cairo_has_current_point (cairo_t *cr); - -cairo_public void -cairo_get_current_point (cairo_t *cr, double *x, double *y); - -cairo_public cairo_fill_rule_t -cairo_get_fill_rule (cairo_t *cr); - -cairo_public double -cairo_get_line_width (cairo_t *cr); - -cairo_public cairo_line_cap_t -cairo_get_line_cap (cairo_t *cr); - -cairo_public cairo_line_join_t -cairo_get_line_join (cairo_t *cr); - -cairo_public double -cairo_get_miter_limit (cairo_t *cr); - -cairo_public int -cairo_get_dash_count (cairo_t *cr); - -cairo_public void -cairo_get_dash (cairo_t *cr, double *dashes, double *offset); - -cairo_public void -cairo_get_matrix (cairo_t *cr, cairo_matrix_t *matrix); - -cairo_public cairo_surface_t * -cairo_get_target (cairo_t *cr); - -cairo_public cairo_surface_t * -cairo_get_group_target (cairo_t *cr); - -/** - * cairo_path_data_type_t: - * @CAIRO_PATH_MOVE_TO: A move-to operation - * @CAIRO_PATH_LINE_TO: A line-to operation - * @CAIRO_PATH_CURVE_TO: A curve-to operation - * @CAIRO_PATH_CLOSE_PATH: A close-path operation - * - * #cairo_path_data_t is used to describe the type of one portion - * of a path when represented as a #cairo_path_t. - * See #cairo_path_data_t for details. - **/ -typedef enum _cairo_path_data_type { - CAIRO_PATH_MOVE_TO, - CAIRO_PATH_LINE_TO, - CAIRO_PATH_CURVE_TO, - CAIRO_PATH_CLOSE_PATH -} cairo_path_data_type_t; - -/** - * cairo_path_data_t: - * - * #cairo_path_data_t is used to represent the path data inside a - * #cairo_path_t. - * - * The data structure is designed to try to balance the demands of - * efficiency and ease-of-use. A path is represented as an array of - * #cairo_path_data_t, which is a union of headers and points. - * - * Each portion of the path is represented by one or more elements in - * the array, (one header followed by 0 or more points). The length - * value of the header is the number of array elements for the current - * portion including the header, (ie. length == 1 + # of points), and - * where the number of points for each element type is as follows: - * - * - * %CAIRO_PATH_MOVE_TO: 1 point - * %CAIRO_PATH_LINE_TO: 1 point - * %CAIRO_PATH_CURVE_TO: 3 points - * %CAIRO_PATH_CLOSE_PATH: 0 points - * - * - * The semantics and ordering of the coordinate values are consistent - * with cairo_move_to(), cairo_line_to(), cairo_curve_to(), and - * cairo_close_path(). - * - * Here is sample code for iterating through a #cairo_path_t: - * - * - * int i; - * cairo_path_t *path; - * cairo_path_data_t *data; - *   - * path = cairo_copy_path (cr); - *   - * for (i=0; i < path->num_data; i += path->data[i].header.length) { - * data = &path->data[i]; - * switch (data->header.type) { - * case CAIRO_PATH_MOVE_TO: - * do_move_to_things (data[1].point.x, data[1].point.y); - * break; - * case CAIRO_PATH_LINE_TO: - * do_line_to_things (data[1].point.x, data[1].point.y); - * break; - * case CAIRO_PATH_CURVE_TO: - * do_curve_to_things (data[1].point.x, data[1].point.y, - * data[2].point.x, data[2].point.y, - * data[3].point.x, data[3].point.y); - * break; - * case CAIRO_PATH_CLOSE_PATH: - * do_close_path_things (); - * break; - * } - * } - * cairo_path_destroy (path); - * - * - * As of cairo 1.4, cairo does not mind if there are more elements in - * a portion of the path than needed. Such elements can be used by - * users of the cairo API to hold extra values in the path data - * structure. For this reason, it is recommended that applications - * always use data->header.length to - * iterate over the path data, instead of hardcoding the number of - * elements for each element type. - **/ -typedef union _cairo_path_data_t cairo_path_data_t; -union _cairo_path_data_t { - struct { - cairo_path_data_type_t type; - int length; - } header; - struct { - double x, y; - } point; -}; - -/** - * cairo_path_t: - * @status: the current error status - * @data: the elements in the path - * @num_data: the number of elements in the data array - * - * A data structure for holding a path. This data structure serves as - * the return value for cairo_copy_path() and - * cairo_copy_path_flat() as well the input value for - * cairo_append_path(). - * - * See #cairo_path_data_t for hints on how to iterate over the - * actual data within the path. - * - * The num_data member gives the number of elements in the data - * array. This number is larger than the number of independent path - * portions (defined in #cairo_path_data_type_t), since the data - * includes both headers and coordinates for each portion. - **/ -typedef struct cairo_path { - cairo_status_t status; - cairo_path_data_t *data; - int num_data; -} cairo_path_t; - -cairo_public cairo_path_t * -cairo_copy_path (cairo_t *cr); - -cairo_public cairo_path_t * -cairo_copy_path_flat (cairo_t *cr); - -cairo_public void -cairo_append_path (cairo_t *cr, - const cairo_path_t *path); - -cairo_public void -cairo_path_destroy (cairo_path_t *path); - -/* Error status queries */ - -cairo_public cairo_status_t -cairo_status (cairo_t *cr); - -cairo_public const char * -cairo_status_to_string (cairo_status_t status); - -/* Surface manipulation */ - -cairo_public cairo_surface_t * -cairo_surface_create_similar (cairo_surface_t *other, - cairo_content_t content, - int width, - int height); - -cairo_public cairo_surface_t * -cairo_surface_reference (cairo_surface_t *surface); - -cairo_public void -cairo_surface_finish (cairo_surface_t *surface); - -cairo_public void -cairo_surface_destroy (cairo_surface_t *surface); - -cairo_public unsigned int -cairo_surface_get_reference_count (cairo_surface_t *surface); - -cairo_public cairo_status_t -cairo_surface_status (cairo_surface_t *surface); - -/** - * cairo_surface_type_t: - * @CAIRO_SURFACE_TYPE_IMAGE: The surface is of type image - * @CAIRO_SURFACE_TYPE_PDF: The surface is of type pdf - * @CAIRO_SURFACE_TYPE_PS: The surface is of type ps - * @CAIRO_SURFACE_TYPE_XLIB: The surface is of type xlib - * @CAIRO_SURFACE_TYPE_XCB: The surface is of type xcb - * @CAIRO_SURFACE_TYPE_GLITZ: The surface is of type glitz - * @CAIRO_SURFACE_TYPE_QUARTZ: The surface is of type quartz - * @CAIRO_SURFACE_TYPE_WIN32: The surface is of type win32 - * @CAIRO_SURFACE_TYPE_BEOS: The surface is of type beos - * @CAIRO_SURFACE_TYPE_DIRECTFB: The surface is of type directfb - * @CAIRO_SURFACE_TYPE_SVG: The surface is of type svg - * @CAIRO_SURFACE_TYPE_OS2: The surface is of type os2 - * @CAIRO_SURFACE_TYPE_WIN32_PRINTING: The surface is a win32 printing surface - * @CAIRO_SURFACE_TYPE_QUARTZ_IMAGE: The surface is of type quartz_image - * - * #cairo_surface_type_t is used to describe the type of a given - * surface. The surface types are also known as "backends" or "surface - * backends" within cairo. - * - * The type of a surface is determined by the function used to create - * it, which will generally be of the form cairo_type_surface_create(), - * (though see cairo_surface_create_similar() as well). - * - * The surface type can be queried with cairo_surface_get_type() - * - * The various #cairo_surface_t functions can be used with surfaces of - * any type, but some backends also provide type-specific functions - * that must only be called with a surface of the appropriate - * type. These functions have names that begin with - * cairo_type_surface such as cairo_image_surface_get_width(). - * - * The behavior of calling a type-specific function with a surface of - * the wrong type is undefined. - * - * New entries may be added in future versions. - * - * Since: 1.2 - **/ -typedef enum _cairo_surface_type { - CAIRO_SURFACE_TYPE_IMAGE, - CAIRO_SURFACE_TYPE_PDF, - CAIRO_SURFACE_TYPE_PS, - CAIRO_SURFACE_TYPE_XLIB, - CAIRO_SURFACE_TYPE_XCB, - CAIRO_SURFACE_TYPE_GLITZ, - CAIRO_SURFACE_TYPE_QUARTZ, - CAIRO_SURFACE_TYPE_WIN32, - CAIRO_SURFACE_TYPE_BEOS, - CAIRO_SURFACE_TYPE_DIRECTFB, - CAIRO_SURFACE_TYPE_SVG, - CAIRO_SURFACE_TYPE_OS2, - CAIRO_SURFACE_TYPE_WIN32_PRINTING, - CAIRO_SURFACE_TYPE_QUARTZ_IMAGE -} cairo_surface_type_t; - -cairo_public cairo_surface_type_t -cairo_surface_get_type (cairo_surface_t *surface); - -cairo_public cairo_content_t -cairo_surface_get_content (cairo_surface_t *surface); - -#if CAIRO_HAS_PNG_FUNCTIONS - -cairo_public cairo_status_t -cairo_surface_write_to_png (cairo_surface_t *surface, - const char *filename); - -cairo_public cairo_status_t -cairo_surface_write_to_png_stream (cairo_surface_t *surface, - cairo_write_func_t write_func, - void *closure); - -#endif - -cairo_public void * -cairo_surface_get_user_data (cairo_surface_t *surface, - const cairo_user_data_key_t *key); - -cairo_public cairo_status_t -cairo_surface_set_user_data (cairo_surface_t *surface, - const cairo_user_data_key_t *key, - void *user_data, - cairo_destroy_func_t destroy); - -cairo_public void -cairo_surface_get_font_options (cairo_surface_t *surface, - cairo_font_options_t *options); - -cairo_public void -cairo_surface_flush (cairo_surface_t *surface); - -cairo_public void -cairo_surface_mark_dirty (cairo_surface_t *surface); - -cairo_public void -cairo_surface_mark_dirty_rectangle (cairo_surface_t *surface, - int x, - int y, - int width, - int height); - -cairo_public void -cairo_surface_set_device_offset (cairo_surface_t *surface, - double x_offset, - double y_offset); - -cairo_public void -cairo_surface_get_device_offset (cairo_surface_t *surface, - double *x_offset, - double *y_offset); - -cairo_public void -cairo_surface_set_fallback_resolution (cairo_surface_t *surface, - double x_pixels_per_inch, - double y_pixels_per_inch); - -cairo_public void -cairo_surface_get_fallback_resolution (cairo_surface_t *surface, - double *x_pixels_per_inch, - double *y_pixels_per_inch); - -cairo_public void -cairo_surface_copy_page (cairo_surface_t *surface); - -cairo_public void -cairo_surface_show_page (cairo_surface_t *surface); - -cairo_public cairo_bool_t -cairo_surface_has_show_text_glyphs (cairo_surface_t *surface); - -/* Image-surface functions */ - -/** - * cairo_format_t: - * @CAIRO_FORMAT_ARGB32: each pixel is a 32-bit quantity, with - * alpha in the upper 8 bits, then red, then green, then blue. - * The 32-bit quantities are stored native-endian. Pre-multiplied - * alpha is used. (That is, 50% transparent red is 0x80800000, - * not 0x80ff0000.) - * @CAIRO_FORMAT_RGB24: each pixel is a 32-bit quantity, with - * the upper 8 bits unused. Red, Green, and Blue are stored - * in the remaining 24 bits in that order. - * @CAIRO_FORMAT_A8: each pixel is a 8-bit quantity holding - * an alpha value. - * @CAIRO_FORMAT_A1: each pixel is a 1-bit quantity holding - * an alpha value. Pixels are packed together into 32-bit - * quantities. The ordering of the bits matches the - * endianess of the platform. On a big-endian machine, the - * first pixel is in the uppermost bit, on a little-endian - * machine the first pixel is in the least-significant bit. - * @CAIRO_FORMAT_RGB16_565: This format value is deprecated. It has - * never been properly implemented in cairo and should not be used - * by applications. (since 1.2) - * - * #cairo_format_t is used to identify the memory format of - * image data. - * - * New entries may be added in future versions. - **/ -typedef enum _cairo_format { - CAIRO_FORMAT_ARGB32, - CAIRO_FORMAT_RGB24, - CAIRO_FORMAT_A8, - CAIRO_FORMAT_A1 - /* The value of 4 is reserved by a deprecated enum value. - * The next format added must have an explicit value of 5. - CAIRO_FORMAT_RGB16_565 = 4, - */ -} cairo_format_t; - -cairo_public cairo_surface_t * -cairo_image_surface_create (cairo_format_t format, - int width, - int height); - -cairo_public int -cairo_format_stride_for_width (cairo_format_t format, - int width); - -cairo_public cairo_surface_t * -cairo_image_surface_create_for_data (unsigned char *data, - cairo_format_t format, - int width, - int height, - int stride); - -cairo_public unsigned char * -cairo_image_surface_get_data (cairo_surface_t *surface); - -cairo_public cairo_format_t -cairo_image_surface_get_format (cairo_surface_t *surface); - -cairo_public int -cairo_image_surface_get_width (cairo_surface_t *surface); - -cairo_public int -cairo_image_surface_get_height (cairo_surface_t *surface); - -cairo_public int -cairo_image_surface_get_stride (cairo_surface_t *surface); - -#if CAIRO_HAS_PNG_FUNCTIONS - -cairo_public cairo_surface_t * -cairo_image_surface_create_from_png (const char *filename); - -cairo_public cairo_surface_t * -cairo_image_surface_create_from_png_stream (cairo_read_func_t read_func, - void *closure); - -#endif - -/* Pattern creation functions */ - -cairo_public cairo_pattern_t * -cairo_pattern_create_rgb (double red, double green, double blue); - -cairo_public cairo_pattern_t * -cairo_pattern_create_rgba (double red, double green, double blue, - double alpha); - -cairo_public cairo_pattern_t * -cairo_pattern_create_for_surface (cairo_surface_t *surface); - -cairo_public cairo_pattern_t * -cairo_pattern_create_linear (double x0, double y0, - double x1, double y1); - -cairo_public cairo_pattern_t * -cairo_pattern_create_radial (double cx0, double cy0, double radius0, - double cx1, double cy1, double radius1); - -cairo_public cairo_pattern_t * -cairo_pattern_reference (cairo_pattern_t *pattern); - -cairo_public void -cairo_pattern_destroy (cairo_pattern_t *pattern); - -cairo_public unsigned int -cairo_pattern_get_reference_count (cairo_pattern_t *pattern); - -cairo_public cairo_status_t -cairo_pattern_status (cairo_pattern_t *pattern); - -cairo_public void * -cairo_pattern_get_user_data (cairo_pattern_t *pattern, - const cairo_user_data_key_t *key); - -cairo_public cairo_status_t -cairo_pattern_set_user_data (cairo_pattern_t *pattern, - const cairo_user_data_key_t *key, - void *user_data, - cairo_destroy_func_t destroy); - -/** - * cairo_pattern_type_t: - * @CAIRO_PATTERN_TYPE_SOLID: The pattern is a solid (uniform) - * color. It may be opaque or translucent. - * @CAIRO_PATTERN_TYPE_SURFACE: The pattern is a based on a surface (an image). - * @CAIRO_PATTERN_TYPE_LINEAR: The pattern is a linear gradient. - * @CAIRO_PATTERN_TYPE_RADIAL: The pattern is a radial gradient. - * - * #cairo_pattern_type_t is used to describe the type of a given pattern. - * - * The type of a pattern is determined by the function used to create - * it. The cairo_pattern_create_rgb() and cairo_pattern_create_rgba() - * functions create SOLID patterns. The remaining - * cairo_pattern_create functions map to pattern types in obvious - * ways. - * - * The pattern type can be queried with cairo_pattern_get_type() - * - * Most #cairo_pattern_t functions can be called with a pattern of any - * type, (though trying to change the extend or filter for a solid - * pattern will have no effect). A notable exception is - * cairo_pattern_add_color_stop_rgb() and - * cairo_pattern_add_color_stop_rgba() which must only be called with - * gradient patterns (either LINEAR or RADIAL). Otherwise the pattern - * will be shutdown and put into an error state. - * - * New entries may be added in future versions. - * - * Since: 1.2 - **/ -typedef enum _cairo_pattern_type { - CAIRO_PATTERN_TYPE_SOLID, - CAIRO_PATTERN_TYPE_SURFACE, - CAIRO_PATTERN_TYPE_LINEAR, - CAIRO_PATTERN_TYPE_RADIAL -} cairo_pattern_type_t; - -cairo_public cairo_pattern_type_t -cairo_pattern_get_type (cairo_pattern_t *pattern); - -cairo_public void -cairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern, - double offset, - double red, double green, double blue); - -cairo_public void -cairo_pattern_add_color_stop_rgba (cairo_pattern_t *pattern, - double offset, - double red, double green, double blue, - double alpha); - -cairo_public void -cairo_pattern_set_matrix (cairo_pattern_t *pattern, - const cairo_matrix_t *matrix); - -cairo_public void -cairo_pattern_get_matrix (cairo_pattern_t *pattern, - cairo_matrix_t *matrix); - -/** - * cairo_extend_t: - * @CAIRO_EXTEND_NONE: pixels outside of the source pattern - * are fully transparent - * @CAIRO_EXTEND_REPEAT: the pattern is tiled by repeating - * @CAIRO_EXTEND_REFLECT: the pattern is tiled by reflecting - * at the edges (Implemented for surface patterns since 1.6) - * @CAIRO_EXTEND_PAD: pixels outside of the pattern copy - * the closest pixel from the source (Since 1.2; but only - * implemented for surface patterns since 1.6) - * - * #cairo_extend_t is used to describe how pattern color/alpha will be - * determined for areas "outside" the pattern's natural area, (for - * example, outside the surface bounds or outside the gradient - * geometry). - * - * The default extend mode is %CAIRO_EXTEND_NONE for surface patterns - * and %CAIRO_EXTEND_PAD for gradient patterns. - * - * New entries may be added in future versions. - **/ -typedef enum _cairo_extend { - CAIRO_EXTEND_NONE, - CAIRO_EXTEND_REPEAT, - CAIRO_EXTEND_REFLECT, - CAIRO_EXTEND_PAD -} cairo_extend_t; - -cairo_public void -cairo_pattern_set_extend (cairo_pattern_t *pattern, cairo_extend_t extend); - -cairo_public cairo_extend_t -cairo_pattern_get_extend (cairo_pattern_t *pattern); - -/** - * cairo_filter_t: - * @CAIRO_FILTER_FAST: A high-performance filter, with quality similar - * to %CAIRO_FILTER_NEAREST - * @CAIRO_FILTER_GOOD: A reasonable-performance filter, with quality - * similar to %CAIRO_FILTER_BILINEAR - * @CAIRO_FILTER_BEST: The highest-quality available, performance may - * not be suitable for interactive use. - * @CAIRO_FILTER_NEAREST: Nearest-neighbor filtering - * @CAIRO_FILTER_BILINEAR: Linear interpolation in two dimensions - * @CAIRO_FILTER_GAUSSIAN: This filter value is currently - * unimplemented, and should not be used in current code. - * - * #cairo_filter_t is used to indicate what filtering should be - * applied when reading pixel values from patterns. See - * cairo_pattern_set_source() for indicating the desired filter to be - * used with a particular pattern. - */ -typedef enum _cairo_filter { - CAIRO_FILTER_FAST, - CAIRO_FILTER_GOOD, - CAIRO_FILTER_BEST, - CAIRO_FILTER_NEAREST, - CAIRO_FILTER_BILINEAR, - CAIRO_FILTER_GAUSSIAN -} cairo_filter_t; - -cairo_public void -cairo_pattern_set_filter (cairo_pattern_t *pattern, cairo_filter_t filter); - -cairo_public cairo_filter_t -cairo_pattern_get_filter (cairo_pattern_t *pattern); - -cairo_public cairo_status_t -cairo_pattern_get_rgba (cairo_pattern_t *pattern, - double *red, double *green, - double *blue, double *alpha); - -cairo_public cairo_status_t -cairo_pattern_get_surface (cairo_pattern_t *pattern, - cairo_surface_t **surface); - - -cairo_public cairo_status_t -cairo_pattern_get_color_stop_rgba (cairo_pattern_t *pattern, - int index, double *offset, - double *red, double *green, - double *blue, double *alpha); - -cairo_public cairo_status_t -cairo_pattern_get_color_stop_count (cairo_pattern_t *pattern, - int *count); - -cairo_public cairo_status_t -cairo_pattern_get_linear_points (cairo_pattern_t *pattern, - double *x0, double *y0, - double *x1, double *y1); - -cairo_public cairo_status_t -cairo_pattern_get_radial_circles (cairo_pattern_t *pattern, - double *x0, double *y0, double *r0, - double *x1, double *y1, double *r1); - -/* Matrix functions */ - -cairo_public void -cairo_matrix_init (cairo_matrix_t *matrix, - double xx, double yx, - double xy, double yy, - double x0, double y0); - -cairo_public void -cairo_matrix_init_identity (cairo_matrix_t *matrix); - -cairo_public void -cairo_matrix_init_translate (cairo_matrix_t *matrix, - double tx, double ty); - -cairo_public void -cairo_matrix_init_scale (cairo_matrix_t *matrix, - double sx, double sy); - -cairo_public void -cairo_matrix_init_rotate (cairo_matrix_t *matrix, - double radians); - -cairo_public void -cairo_matrix_translate (cairo_matrix_t *matrix, double tx, double ty); - -cairo_public void -cairo_matrix_scale (cairo_matrix_t *matrix, double sx, double sy); - -cairo_public void -cairo_matrix_rotate (cairo_matrix_t *matrix, double radians); - -cairo_public cairo_status_t -cairo_matrix_invert (cairo_matrix_t *matrix); - -cairo_public void -cairo_matrix_multiply (cairo_matrix_t *result, - const cairo_matrix_t *a, - const cairo_matrix_t *b); - -cairo_public void -cairo_matrix_transform_distance (const cairo_matrix_t *matrix, - double *dx, double *dy); - -cairo_public void -cairo_matrix_transform_point (const cairo_matrix_t *matrix, - double *x, double *y); - -/* Functions to be used while debugging (not intended for use in production code) */ -cairo_public void -cairo_debug_reset_static_data (void); - -CAIRO_END_DECLS - -#endif /* CAIRO_H */ diff --git a/uppdev/plugin/cairo/lib/cairoint.h b/uppdev/plugin/cairo/lib/cairoint.h deleted file mode 100644 index 43c5ae888..000000000 --- a/uppdev/plugin/cairo/lib/cairoint.h +++ /dev/null @@ -1,2539 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - */ - -/* - * These definitions are solely for use by the implementation of cairo - * and constitute no kind of standard. If you need any of these - * functions, please drop me a note. Either the library needs new - * functionality, or there's a way to do what you need using the - * existing published interfaces. cworth@cworth.org - */ - -#ifndef _CAIROINT_H_ -#define _CAIROINT_H_ - -#if HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef _MSC_VER -#define cairo_public __declspec(dllexport) -#endif - -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#define _USE_MATH_DEFINES -#endif -#include -#include -#include - -#include "cairo.h" -#include - -#include "cairo-compiler-private.h" - -#if CAIRO_HAS_PS_SURFACE || \ - CAIRO_HAS_PDF_SURFACE || \ - CAIRO_HAS_SVG_SURFACE || \ - CAIRO_HAS_WIN32_SURFACE -#define CAIRO_HAS_FONT_SUBSET 1 -#endif - -#if CAIRO_HAS_PS_SURFACE || CAIRO_HAS_PDF_SURFACE -#define CAIRO_HAS_PDF_OPERATORS 1 -#endif - -CAIRO_BEGIN_DECLS - -#ifdef _WIN32 -cairo_private FILE * -_cairo_win32_tmpfile (void); -#define tmpfile() _cairo_win32_tmpfile() -#endif - -#undef MIN -#define MIN(a, b) ((a) < (b) ? (a) : (b)) - -#undef MAX -#define MAX(a, b) ((a) > (b) ? (a) : (b)) - -#ifndef FALSE -#define FALSE 0 -#endif - -#ifndef TRUE -#define TRUE 1 -#endif - -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - -#ifndef M_SQRT2 -#define M_SQRT2 1.41421356237309504880 -#endif - -#ifndef M_SQRT1_2 -#define M_SQRT1_2 0.707106781186547524400844362104849039 -#endif - -#undef ARRAY_LENGTH -#define ARRAY_LENGTH(__array) ((int) (sizeof (__array) / sizeof (__array[0]))) - - -/* This has to be updated whenever #cairo_status_t is extended. That's - * a bit of a pain, but it should be easy to always catch as long as - * one adds a new test case to test a trigger of the new status value. - */ -#define CAIRO_STATUS_LAST_STATUS CAIRO_STATUS_INVALID_WEIGHT - -#ifdef __GNUC__ -#define cairo_container_of(ptr, type, member) ({ \ - const typeof(((type *) 0)->member) *mptr__ = (ptr); \ - (type *) ((char *) mptr__ - offsetof (type, member)); \ -}) -#else -#define cairo_container_of(ptr, type, member) \ - (type *)((char *) (ptr) - (char *) &((type *)0)->member) -#endif - - -/* Size in bytes of buffer to use off the stack per functions. - * Mostly used by text functions. For larger allocations, they'll - * malloc(). */ -#ifndef CAIRO_STACK_BUFFER_SIZE -#define CAIRO_STACK_BUFFER_SIZE (512 * sizeof (int)) -#endif - -#define CAIRO_STACK_ARRAY_LENGTH(T) (CAIRO_STACK_BUFFER_SIZE / sizeof(T)) - -#define ASSERT_NOT_REACHED \ -do { \ - static const int NOT_REACHED = 0; \ - assert (NOT_REACHED); \ -} while (0) -#define COMPILE_TIME_ASSERT1(condition, line) \ - typedef int compile_time_assertion_at_line_##line##_failed [(condition)?1:-1]; -#define COMPILE_TIME_ASSERT0(condition, line) COMPILE_TIME_ASSERT1(condition, line) -#define COMPILE_TIME_ASSERT(condition) COMPILE_TIME_ASSERT0(condition, __LINE__) - -#define CAIRO_ALPHA_IS_OPAQUE(alpha) ((alpha) >= ((double)0xff00 / (double)0xffff)) -#define CAIRO_ALPHA_SHORT_IS_OPAQUE(alpha) ((alpha) >= 0xff00) -#define CAIRO_ALPHA_IS_ZERO(alpha) ((alpha) <= 0.0) - -#define CAIRO_COLOR_IS_OPAQUE(color) CAIRO_ALPHA_SHORT_IS_OPAQUE ((color)->alpha_short) - -/* Reverse the bits in a byte with 7 operations (no 64-bit): - * Devised by Sean Anderson, July 13, 2001. - * Source: http://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith32Bits - */ -#define CAIRO_BITSWAP8(c) ((((c) * 0x0802LU & 0x22110LU) | ((c) * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16) - -/* Return the number of 1 bits in mask. - * - * GCC 3.4 supports a "population count" builtin, which on many targets is - * implemented with a single instruction. There is a fallback definition - * in libgcc in case a target does not have one, which should be just as - * good as the open-coded solution below, (which is "HACKMEM 169"). - */ -static inline int -_cairo_popcount (uint32_t mask) -{ -#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) - return __builtin_popcount (mask); -#else - register int y; - - y = (mask >> 1) &033333333333; - y = mask - y - ((y >>1) & 033333333333); - return (((y + (y >> 3)) & 030707070707) % 077); -#endif -} - -#ifdef WORDS_BIGENDIAN -#define CAIRO_BITSWAP8_IF_LITTLE_ENDIAN(c) (c) -#else -#define CAIRO_BITSWAP8_IF_LITTLE_ENDIAN(c) CAIRO_BITSWAP8(c) -#endif - -#ifdef WORDS_BIGENDIAN - -#define cpu_to_be16(v) (v) -#define be16_to_cpu(v) (v) -#define cpu_to_be32(v) (v) -#define be32_to_cpu(v) (v) - -#else - -static inline uint16_t -cpu_to_be16(uint16_t v) -{ - return (v << 8) | (v >> 8); -} - -static inline uint16_t -be16_to_cpu(uint16_t v) -{ - return cpu_to_be16 (v); -} - -static inline uint32_t -cpu_to_be32(uint32_t v) -{ - return (cpu_to_be16 (v) << 16) | cpu_to_be16 (v >> 16); -} - -static inline uint32_t -be32_to_cpu(uint32_t v) -{ - return cpu_to_be32 (v); -} - -#endif - -#include "cairo-types-private.h" -#include "cairo-cache-private.h" -#include "cairo-reference-count-private.h" - -cairo_private void -_cairo_box_from_doubles (cairo_box_t *box, - double *x1, double *y1, - double *x2, double *y2); - -cairo_private void -_cairo_box_to_doubles (const cairo_box_t *box, - double *x1, double *y1, - double *x2, double *y2); - -cairo_private void -_cairo_box_from_rectangle (cairo_box_t *box, - const cairo_rectangle_int_t *rectangle); - -cairo_private void -_cairo_box_round_to_rectangle (const cairo_box_t *box, - cairo_rectangle_int_t *rectangle); - -cairo_private cairo_bool_t -_cairo_rectangle_intersect (cairo_rectangle_int_t *dst, - const cairo_rectangle_int_t *src); - -cairo_private cairo_bool_t -_cairo_box_intersects_line_segment (cairo_box_t *box, cairo_line_t *line); - -cairo_private cairo_bool_t -_cairo_box_contains_point (cairo_box_t *box, cairo_point_t *point); - -/* cairo-array.c structures and functions */ - -cairo_private void -_cairo_array_init (cairo_array_t *array, int element_size); - -cairo_private void -_cairo_array_init_snapshot (cairo_array_t *array, - const cairo_array_t *other); - -cairo_private void -_cairo_array_fini (cairo_array_t *array); - -cairo_private cairo_status_t -_cairo_array_grow_by (cairo_array_t *array, unsigned int additional); - -cairo_private void -_cairo_array_truncate (cairo_array_t *array, unsigned int num_elements); - -cairo_private cairo_status_t -_cairo_array_append (cairo_array_t *array, const void *element); - -cairo_private cairo_status_t -_cairo_array_append_multiple (cairo_array_t *array, - const void *elements, - int num_elements); - -cairo_private cairo_status_t -_cairo_array_allocate (cairo_array_t *array, - unsigned int num_elements, - void **elements); - -cairo_private void * -_cairo_array_index (cairo_array_t *array, unsigned int index); - -cairo_private void -_cairo_array_copy_element (cairo_array_t *array, int index, void *dst); - -cairo_private int -_cairo_array_num_elements (cairo_array_t *array); - -cairo_private int -_cairo_array_size (cairo_array_t *array); - -cairo_private void -_cairo_user_data_array_init (cairo_user_data_array_t *array); - -cairo_private void -_cairo_user_data_array_fini (cairo_user_data_array_t *array); - -cairo_private void * -_cairo_user_data_array_get_data (cairo_user_data_array_t *array, - const cairo_user_data_key_t *key); - -cairo_private cairo_status_t -_cairo_user_data_array_set_data (cairo_user_data_array_t *array, - const cairo_user_data_key_t *key, - void *user_data, - cairo_destroy_func_t destroy); - -cairo_private unsigned long -_cairo_hash_string (const char *c); - -/* - * A #cairo_unscaled_font_t is just an opaque handle we use in the - * glyph cache. - */ -typedef struct _cairo_unscaled_font { - cairo_hash_entry_t hash_entry; - cairo_reference_count_t ref_count; - const cairo_unscaled_font_backend_t *backend; -} cairo_unscaled_font_t; - -typedef struct _cairo_scaled_glyph { - cairo_cache_entry_t cache_entry; /* hash is glyph index */ - cairo_scaled_font_t *scaled_font; /* font the glyph lives in */ - cairo_text_extents_t metrics; /* user-space metrics */ - cairo_box_t bbox; /* device-space bounds */ - int16_t x_advance; /* device-space rounded X advance */ - int16_t y_advance; /* device-space rounded Y advance */ - cairo_image_surface_t *surface; /* device-space image */ - cairo_path_fixed_t *path; /* device-space outline */ - cairo_surface_t *meta_surface; /* device-space meta-surface */ - void *surface_private; /* for the surface backend */ -} cairo_scaled_glyph_t; - -#define _cairo_scaled_glyph_index(g) ((g)->cache_entry.hash) -#define _cairo_scaled_glyph_set_index(g,i) ((g)->cache_entry.hash = (i)) - -#include "cairo-scaled-font-private.h" - -struct _cairo_font_face { - /* hash_entry must be first */ - cairo_hash_entry_t hash_entry; - cairo_status_t status; - cairo_reference_count_t ref_count; - cairo_user_data_array_t user_data; - const cairo_font_face_backend_t *backend; -}; - -cairo_private void -_cairo_font_face_reset_static_data (void); - -cairo_private void -_cairo_ft_font_reset_static_data (void); - -/* the font backend interface */ - -struct _cairo_unscaled_font_backend { - void (*destroy) (void *unscaled_font); -}; - -/* #cairo_toy_font_face_t - simple family/slant/weight font faces used for - * the built-in font API - */ - -typedef struct _cairo_toy_font_face { - cairo_font_face_t base; - const char *family; - cairo_bool_t owns_family; - cairo_font_slant_t slant; - cairo_font_weight_t weight; -} cairo_toy_font_face_t; - -typedef enum _cairo_scaled_glyph_info { - CAIRO_SCALED_GLYPH_INFO_METRICS = (1 << 0), - CAIRO_SCALED_GLYPH_INFO_SURFACE = (1 << 1), - CAIRO_SCALED_GLYPH_INFO_PATH = (1 << 2), - CAIRO_SCALED_GLYPH_INFO_META_SURFACE = (1 << 3) -} cairo_scaled_glyph_info_t; - -typedef struct _cairo_scaled_font_subset { - cairo_scaled_font_t *scaled_font; - unsigned int font_id; - unsigned int subset_id; - - /* Index of glyphs array is subset_glyph_index. - * Value of glyphs array is scaled_font_glyph_index. - */ - unsigned long *glyphs; - unsigned long *to_unicode; - char **utf8; - char **glyph_names; - unsigned int num_glyphs; - cairo_bool_t is_composite; -} cairo_scaled_font_subset_t; - -struct _cairo_scaled_font_backend { - cairo_font_type_t type; - - cairo_warn cairo_status_t - (*get_implementation) (cairo_toy_font_face_t *toy_face, - cairo_font_face_t **font_face); - - cairo_warn cairo_status_t - (*create_toy) (cairo_toy_font_face_t *toy_face, - const cairo_matrix_t *font_matrix, - const cairo_matrix_t *ctm, - const cairo_font_options_t *options, - cairo_scaled_font_t **scaled_font); - - void - (*fini) (void *scaled_font); - - cairo_warn cairo_int_status_t - (*scaled_glyph_init) (void *scaled_font, - cairo_scaled_glyph_t *scaled_glyph, - cairo_scaled_glyph_info_t info); - - /* A backend only needs to implement this or ucs4_to_index(), not - * both. This allows the backend to do something more sophisticated - * then just converting characters one by one. - */ - cairo_warn cairo_int_status_t - (*text_to_glyphs) (void *scaled_font, - double x, - double y, - const char *utf8, - int utf8_len, - cairo_glyph_t **glyphs, - int *num_glyphs, - cairo_text_cluster_t **clusters, - int *num_clusters, - cairo_text_cluster_flags_t *cluster_flags); - - unsigned long - (*ucs4_to_index) (void *scaled_font, - uint32_t ucs4); - cairo_warn cairo_int_status_t - (*show_glyphs) (void *scaled_font, - cairo_operator_t op, - cairo_pattern_t *pattern, - cairo_surface_t *surface, - int source_x, - int source_y, - int dest_x, - int dest_y, - unsigned int width, - unsigned int height, - cairo_glyph_t *glyphs, - int num_glyphs, - int *remaining_glyphs); - - cairo_warn cairo_int_status_t - (*load_truetype_table)(void *scaled_font, - unsigned long tag, - long offset, - unsigned char *buffer, - unsigned long *length); - - /* returns -1 if the unicode character could not be found for the glyph */ - cairo_warn cairo_int_status_t - (*index_to_ucs4)(void *scaled_font, - unsigned long index, - uint32_t *ucs4); -}; - -struct _cairo_font_face_backend { - cairo_font_type_t type; - - /* The destroy() function is allowed to resurrect the font face - * by re-referencing. This is needed for the FreeType backend. - */ - void - (*destroy) (void *font_face); - - cairo_warn cairo_status_t - (*get_implementation) (void *font_face, - cairo_font_face_t **font_face_out); - - cairo_warn cairo_status_t - (*scaled_font_create) (void *font_face, - const cairo_matrix_t *font_matrix, - const cairo_matrix_t *ctm, - const cairo_font_options_t *options, - cairo_scaled_font_t **scaled_font); -}; - -extern const cairo_private struct _cairo_scaled_font_backend _cairo_user_scaled_font_backend; - -/* concrete font backends */ -#if CAIRO_HAS_FT_FONT - -extern const cairo_private struct _cairo_scaled_font_backend _cairo_ft_scaled_font_backend; - -#endif - -#if CAIRO_HAS_WIN32_FONT - -extern const cairo_private struct _cairo_scaled_font_backend _cairo_win32_scaled_font_backend; - -#endif - -#if CAIRO_HAS_QUARTZ_FONT - -extern const cairo_private struct _cairo_scaled_font_backend _cairo_quartz_scaled_font_backend; - -#endif - -struct _cairo_surface_backend { - cairo_surface_type_t type; - - cairo_surface_t * - (*create_similar) (void *surface, - cairo_content_t content, - int width, - int height); - - cairo_warn cairo_status_t - (*finish) (void *surface); - - cairo_warn cairo_status_t - (*acquire_source_image) (void *abstract_surface, - cairo_image_surface_t **image_out, - void **image_extra); - - void - (*release_source_image) (void *abstract_surface, - cairo_image_surface_t *image, - void *image_extra); - - cairo_warn cairo_status_t - (*acquire_dest_image) (void *abstract_surface, - cairo_rectangle_int_t *interest_rect, - cairo_image_surface_t **image_out, - cairo_rectangle_int_t *image_rect, - void **image_extra); - - void - (*release_dest_image) (void *abstract_surface, - cairo_rectangle_int_t *interest_rect, - cairo_image_surface_t *image, - cairo_rectangle_int_t *image_rect, - void *image_extra); - - /* Create a new surface (@clone_out) with the following - * characteristics: - * - * 1. It is as compatible as possible with @surface (in terms of - * efficiency) - * - * 2. It has the same contents as @src within the given rectangle. - * - * 3. The offset of the similar surface with respect to the original - * surface is returned in the clone_offset vector. - * - if you clone the entire surface, this vector is zero. - * - if you clone (src_x, src_y)x(w, h) the vector is (src_x, src_y); - */ - cairo_warn cairo_status_t - (*clone_similar) (void *surface, - cairo_surface_t *src, - int src_x, - int src_y, - int width, - int height, - int *clone_offset_x, - int *clone_offset_y, - cairo_surface_t **clone_out); - - /* XXX: dst should be the first argument for consistency */ - cairo_warn cairo_int_status_t - (*composite) (cairo_operator_t op, - cairo_pattern_t *src, - cairo_pattern_t *mask, - void *dst, - 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_warn cairo_int_status_t - (*fill_rectangles) (void *surface, - cairo_operator_t op, - const cairo_color_t *color, - cairo_rectangle_int_t *rects, - int num_rects); - - /* XXX: dst should be the first argument for consistency */ - cairo_warn cairo_int_status_t - (*composite_trapezoids) (cairo_operator_t op, - cairo_pattern_t *pattern, - void *dst, - cairo_antialias_t antialias, - int src_x, - int src_y, - int dst_x, - int dst_y, - unsigned int width, - unsigned int height, - cairo_trapezoid_t *traps, - int num_traps); - - cairo_warn cairo_int_status_t - (*copy_page) (void *surface); - - cairo_warn cairo_int_status_t - (*show_page) (void *surface); - - /* Set given region as the clip region for the surface, replacing - * any previously set clip region. Passing in a NULL region will - * clear the surface clip region. - * - * The surface is expected to store the clip region and clip all - * following drawing operations against it until the clip region - * is cleared of replaced by another clip region. - * - * Cairo will call this function whenever a clip path can be - * represented as a device pixel aligned set of rectangles. When - * this is not possible, cairo will use mask surfaces for - * clipping. - */ - cairo_warn cairo_int_status_t - (*set_clip_region) (void *surface, - cairo_region_t *region); - - /* Intersect the given path against the clip path currently set in - * the surface, using the given fill_rule and tolerance, and set - * the result as the new clipping path for the surface. Passing - * in a NULL path will clear the surface clipping path. - * - * The surface is expected to store the resulting clip path and - * clip all following drawing operations against it until the clip - * path cleared or intersected with a new path. - * - * If a surface implements this function, set_clip_region() will - * never be called and should not be implemented. If this - * function is not implemented cairo will use set_clip_region() - * (if available) and mask surfaces for clipping. - */ - cairo_warn cairo_int_status_t - (*intersect_clip_path) (void *dst, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias); - - /* Get the extents of the current surface. For many surface types - * this will be as simple as { x=0, y=0, width=surface->width, - * height=surface->height}. - * - * This function need not take account of any clipping from - * set_clip_region since the generic version of set_clip_region - * saves those, and the generic get_clip_extents will only call - * into the specific surface->get_extents if there is no current - * clip. - * - * If this function is not implemented, or if it returns - * %CAIRO_INT_STATUS_UNSUPPORTED, the surface is considered to be - * boundless and inifnite bounds are used for it. - */ - cairo_warn cairo_int_status_t - (*get_extents) (void *surface, - cairo_rectangle_int_t *extents); - - /* - * This is an optional entry to let the surface manage its own glyph - * resources. If null, render against this surface, using image - * surfaces as glyphs. - */ - cairo_warn cairo_int_status_t - (*old_show_glyphs) (cairo_scaled_font_t *font, - cairo_operator_t op, - cairo_pattern_t *pattern, - void *surface, - int source_x, - int source_y, - int dest_x, - int dest_y, - unsigned int width, - unsigned int height, - cairo_glyph_t *glyphs, - int num_glyphs); - - void - (*get_font_options) (void *surface, - cairo_font_options_t *options); - - cairo_warn cairo_status_t - (*flush) (void *surface); - - cairo_warn cairo_status_t - (*mark_dirty_rectangle) (void *surface, - int x, - int y, - int width, - int height); - - void - (*scaled_font_fini) (cairo_scaled_font_t *scaled_font); - - void - (*scaled_glyph_fini) (cairo_scaled_glyph_t *scaled_glyph, - cairo_scaled_font_t *scaled_font); - - /* OK, I'm starting over somewhat by defining the 5 top-level - * drawing operators for the surface backend here with consistent - * naming and argument-order conventions. */ - cairo_warn cairo_int_status_t - (*paint) (void *surface, - cairo_operator_t op, - cairo_pattern_t *source); - - cairo_warn cairo_int_status_t - (*mask) (void *surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_pattern_t *mask); - - cairo_warn cairo_int_status_t - (*stroke) (void *surface, - cairo_operator_t op, - cairo_pattern_t *source, - 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_warn cairo_int_status_t - (*fill) (void *surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias); - - cairo_warn cairo_int_status_t - (*show_glyphs) (void *surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font, - int *remaining_glyphs); - - cairo_surface_t * - (*snapshot) (void *surface); - - cairo_bool_t - (*is_similar) (void *surface_a, - void *surface_b, - cairo_content_t content); - - cairo_warn cairo_status_t - (*reset) (void *surface); - - cairo_warn cairo_int_status_t - (*fill_stroke) (void *surface, - cairo_operator_t fill_op, - cairo_pattern_t *fill_source, - cairo_fill_rule_t fill_rule, - double fill_tolerance, - cairo_antialias_t fill_antialias, - cairo_path_fixed_t *path, - cairo_operator_t stroke_op, - cairo_pattern_t *stroke_source, - cairo_stroke_style_t *stroke_style, - cairo_matrix_t *stroke_ctm, - cairo_matrix_t *stroke_ctm_inverse, - double stroke_tolerance, - cairo_antialias_t stroke_antialias); - - cairo_surface_t * - (*create_solid_pattern_surface) - (void *surface, - cairo_solid_pattern_t *solid_pattern); - - cairo_bool_t - (*has_show_text_glyphs) (void *surface); - - cairo_warn cairo_int_status_t - (*show_text_glyphs) (void *surface, - cairo_operator_t op, - cairo_pattern_t *source, - const char *utf8, - int utf8_len, - cairo_glyph_t *glyphs, - int num_glyphs, - const cairo_text_cluster_t *clusters, - int num_clusters, - cairo_text_cluster_flags_t cluster_flags, - cairo_scaled_font_t *scaled_font); -}; - -#include "cairo-surface-private.h" - -struct _cairo_image_surface { - cairo_surface_t base; - - pixman_format_code_t pixman_format; - cairo_format_t format; - unsigned char *data; - cairo_bool_t owns_data; - cairo_bool_t has_clip; - cairo_image_transparency_t transparency; - - int width; - int height; - int stride; - int depth; - - pixman_image_t *pixman_image; -}; - -extern const cairo_private cairo_surface_backend_t _cairo_image_surface_backend; - -#define CAIRO_EXTEND_SURFACE_DEFAULT CAIRO_EXTEND_NONE -#define CAIRO_EXTEND_GRADIENT_DEFAULT CAIRO_EXTEND_PAD -#define CAIRO_FILTER_DEFAULT CAIRO_FILTER_GOOD - -struct _cairo_pattern { - cairo_pattern_type_t type; - cairo_reference_count_t ref_count; - cairo_status_t status; - cairo_user_data_array_t user_data; - - cairo_matrix_t matrix; - cairo_filter_t filter; - cairo_extend_t extend; -}; - -struct _cairo_solid_pattern { - cairo_pattern_t base; - cairo_color_t color; - cairo_content_t content; -}; - -extern const cairo_private cairo_solid_pattern_t _cairo_pattern_nil; -extern const cairo_private cairo_solid_pattern_t _cairo_pattern_none; - -typedef struct _cairo_surface_pattern { - cairo_pattern_t base; - - cairo_surface_t *surface; -} cairo_surface_pattern_t; - -typedef struct _cairo_gradient_stop { - double offset; - cairo_color_t color; -} cairo_gradient_stop_t; - -typedef struct _cairo_gradient_pattern { - cairo_pattern_t base; - - unsigned int n_stops; - unsigned int stops_size; - cairo_gradient_stop_t *stops; - cairo_gradient_stop_t stops_embedded[2]; -} cairo_gradient_pattern_t; - -typedef struct _cairo_linear_pattern { - cairo_gradient_pattern_t base; - - cairo_point_t p1; - cairo_point_t p2; -} cairo_linear_pattern_t; - -typedef struct _cairo_radial_pattern { - cairo_gradient_pattern_t base; - - cairo_point_t c1; - cairo_fixed_t r1; - cairo_point_t c2; - cairo_fixed_t r2; -} cairo_radial_pattern_t; - -typedef union { - cairo_gradient_pattern_t base; - - cairo_linear_pattern_t linear; - cairo_radial_pattern_t radial; -} cairo_gradient_pattern_union_t; - -typedef union { - cairo_pattern_t base; - - cairo_solid_pattern_t solid; - cairo_surface_pattern_t surface; - cairo_gradient_pattern_union_t gradient; -} cairo_pattern_union_t; - -typedef struct _cairo_surface_attributes { - cairo_matrix_t matrix; - cairo_extend_t extend; - cairo_filter_t filter; - int x_offset; - int y_offset; - cairo_bool_t acquired; - void *extra; -} cairo_surface_attributes_t; - -typedef struct _cairo_traps { - cairo_status_t status; - - cairo_box_t extents; - - int num_traps; - int traps_size; - cairo_trapezoid_t *traps; - cairo_trapezoid_t traps_embedded[1]; - - cairo_bool_t has_limits; - cairo_box_t limits; -} cairo_traps_t; - -#define CAIRO_FONT_SLANT_DEFAULT CAIRO_FONT_SLANT_NORMAL -#define CAIRO_FONT_WEIGHT_DEFAULT CAIRO_FONT_WEIGHT_NORMAL - -#define CAIRO_WIN32_FONT_FAMILY_DEFAULT "Arial" -#define CAIRO_QUARTZ_FONT_FAMILY_DEFAULT "Helvetica" -#define CAIRO_FT_FONT_FAMILY_DEFAULT "" - -#if CAIRO_HAS_WIN32_FONT - -#define CAIRO_FONT_FAMILY_DEFAULT CAIRO_WIN32_FONT_FAMILY_DEFAULT -#define CAIRO_SCALED_FONT_BACKEND_DEFAULT &_cairo_win32_scaled_font_backend - -#elif CAIRO_HAS_QUARTZ_FONT - -#define CAIRO_FONT_FAMILY_DEFAULT CAIRO_QUARTZ_FONT_FAMILY_DEFAULT -#define CAIRO_SCALED_FONT_BACKEND_DEFAULT &_cairo_quartz_scaled_font_backend - -#elif CAIRO_HAS_FT_FONT - -#define CAIRO_FONT_FAMILY_DEFAULT CAIRO_FT_FONT_FAMILY_DEFAULT -#define CAIRO_SCALED_FONT_BACKEND_DEFAULT &_cairo_ft_scaled_font_backend - -#else - -#define CAIRO_FONT_FAMILY_DEFAULT CAIRO_FT_FONT_FAMILY_DEFAULT -#define CAIRO_SCALED_FONT_BACKEND_DEFAULT &_cairo_user_scaled_font_backend - -#endif - -#define CAIRO_GSTATE_OPERATOR_DEFAULT CAIRO_OPERATOR_OVER -#define CAIRO_GSTATE_TOLERANCE_DEFAULT 0.1 -#define CAIRO_GSTATE_FILL_RULE_DEFAULT CAIRO_FILL_RULE_WINDING -#define CAIRO_GSTATE_LINE_WIDTH_DEFAULT 2.0 -#define CAIRO_GSTATE_LINE_CAP_DEFAULT CAIRO_LINE_CAP_BUTT -#define CAIRO_GSTATE_LINE_JOIN_DEFAULT CAIRO_LINE_JOIN_MITER -#define CAIRO_GSTATE_MITER_LIMIT_DEFAULT 10.0 -#define CAIRO_GSTATE_DEFAULT_FONT_SIZE 10.0 - -#define CAIRO_SURFACE_RESOLUTION_DEFAULT 72.0 -#define CAIRO_SURFACE_FALLBACK_RESOLUTION_DEFAULT 300.0 - -typedef struct _cairo_stroke_face { - cairo_point_t ccw; - cairo_point_t point; - cairo_point_t cw; - cairo_slope_t dev_vector; - cairo_point_double_t usr_vector; -} cairo_stroke_face_t; - -/* cairo.c */ -cairo_private void -_cairo_restrict_value (double *value, double min, double max); - -cairo_private int -_cairo_lround (double d); - -/* cairo-gstate.c */ -cairo_private cairo_status_t -_cairo_gstate_init (cairo_gstate_t *gstate, - cairo_surface_t *target); - -cairo_private void -_cairo_gstate_fini (cairo_gstate_t *gstate); - -cairo_private cairo_status_t -_cairo_gstate_save (cairo_gstate_t **gstate, cairo_gstate_t **freelist); - -cairo_private cairo_status_t -_cairo_gstate_restore (cairo_gstate_t **gstate, cairo_gstate_t **freelist); - -cairo_private cairo_bool_t -_cairo_gstate_is_redirected (cairo_gstate_t *gstate); - -cairo_private cairo_status_t -_cairo_gstate_redirect_target (cairo_gstate_t *gstate, cairo_surface_t *child); - -cairo_private cairo_surface_t * -_cairo_gstate_get_target (cairo_gstate_t *gstate); - -cairo_private cairo_surface_t * -_cairo_gstate_get_parent_target (cairo_gstate_t *gstate); - -cairo_private cairo_surface_t * -_cairo_gstate_get_original_target (cairo_gstate_t *gstate); - -cairo_private cairo_clip_t * -_cairo_gstate_get_clip (cairo_gstate_t *gstate); - -cairo_private cairo_status_t -_cairo_gstate_set_source (cairo_gstate_t *gstate, cairo_pattern_t *source); - -cairo_private cairo_pattern_t * -_cairo_gstate_get_source (cairo_gstate_t *gstate); - -cairo_private cairo_status_t -_cairo_gstate_set_operator (cairo_gstate_t *gstate, cairo_operator_t op); - -cairo_private cairo_operator_t -_cairo_gstate_get_operator (cairo_gstate_t *gstate); - -cairo_private cairo_status_t -_cairo_gstate_set_tolerance (cairo_gstate_t *gstate, double tolerance); - -cairo_private double -_cairo_gstate_get_tolerance (cairo_gstate_t *gstate); - -cairo_private cairo_status_t -_cairo_gstate_set_fill_rule (cairo_gstate_t *gstate, cairo_fill_rule_t fill_rule); - -cairo_private cairo_fill_rule_t -_cairo_gstate_get_fill_rule (cairo_gstate_t *gstate); - -cairo_private cairo_status_t -_cairo_gstate_set_line_width (cairo_gstate_t *gstate, double width); - -cairo_private double -_cairo_gstate_get_line_width (cairo_gstate_t *gstate); - -cairo_private cairo_status_t -_cairo_gstate_set_line_cap (cairo_gstate_t *gstate, cairo_line_cap_t line_cap); - -cairo_private cairo_line_cap_t -_cairo_gstate_get_line_cap (cairo_gstate_t *gstate); - -cairo_private cairo_status_t -_cairo_gstate_set_line_join (cairo_gstate_t *gstate, cairo_line_join_t line_join); - -cairo_private cairo_line_join_t -_cairo_gstate_get_line_join (cairo_gstate_t *gstate); - -cairo_private cairo_status_t -_cairo_gstate_set_dash (cairo_gstate_t *gstate, const double *dash, int num_dashes, double offset); - -cairo_private void -_cairo_gstate_get_dash (cairo_gstate_t *gstate, double *dash, int *num_dashes, double *offset); - -cairo_private cairo_status_t -_cairo_gstate_set_miter_limit (cairo_gstate_t *gstate, double limit); - -cairo_private double -_cairo_gstate_get_miter_limit (cairo_gstate_t *gstate); - -cairo_private void -_cairo_gstate_get_matrix (cairo_gstate_t *gstate, cairo_matrix_t *matrix); - -cairo_private cairo_status_t -_cairo_gstate_translate (cairo_gstate_t *gstate, double tx, double ty); - -cairo_private cairo_status_t -_cairo_gstate_scale (cairo_gstate_t *gstate, double sx, double sy); - -cairo_private cairo_status_t -_cairo_gstate_rotate (cairo_gstate_t *gstate, double angle); - -cairo_private cairo_status_t -_cairo_gstate_transform (cairo_gstate_t *gstate, - const cairo_matrix_t *matrix); - -cairo_private cairo_status_t -_cairo_gstate_set_matrix (cairo_gstate_t *gstate, - const cairo_matrix_t *matrix); - -cairo_private void -_cairo_gstate_identity_matrix (cairo_gstate_t *gstate); - -cairo_private void -_cairo_gstate_user_to_device (cairo_gstate_t *gstate, double *x, double *y); - -cairo_private void -_cairo_gstate_user_to_device_distance (cairo_gstate_t *gstate, double *dx, double *dy); - -cairo_private void -_cairo_gstate_device_to_user (cairo_gstate_t *gstate, double *x, double *y); - -cairo_private void -_cairo_gstate_device_to_user_distance (cairo_gstate_t *gstate, double *dx, double *dy); - -cairo_private void -_cairo_gstate_user_to_backend (cairo_gstate_t *gstate, double *x, double *y); - -cairo_private void -_cairo_gstate_backend_to_user (cairo_gstate_t *gstate, double *x, double *y); - -cairo_private void -_cairo_gstate_backend_to_user_rectangle (cairo_gstate_t *gstate, - double *x1, double *y1, - double *x2, double *y2, - cairo_bool_t *is_tight); - -cairo_private cairo_status_t -_cairo_gstate_path_extents (cairo_gstate_t *gstate, - cairo_path_fixed_t *path, - double *x1, double *y1, - double *x2, double *y2); - -cairo_private cairo_status_t -_cairo_gstate_paint (cairo_gstate_t *gstate); - -cairo_private cairo_status_t -_cairo_gstate_mask (cairo_gstate_t *gstate, - cairo_pattern_t *mask); - -cairo_private cairo_status_t -_cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path); - -cairo_private cairo_status_t -_cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path); - -cairo_private cairo_status_t -_cairo_gstate_copy_page (cairo_gstate_t *gstate); - -cairo_private cairo_status_t -_cairo_gstate_show_page (cairo_gstate_t *gstate); - -cairo_private cairo_status_t -_cairo_gstate_stroke_extents (cairo_gstate_t *gstate, - cairo_path_fixed_t *path, - double *x1, double *y1, - double *x2, double *y2); - -cairo_private cairo_status_t -_cairo_gstate_fill_extents (cairo_gstate_t *gstate, - cairo_path_fixed_t *path, - double *x1, double *y1, - double *x2, double *y2); - -cairo_private cairo_status_t -_cairo_gstate_in_stroke (cairo_gstate_t *gstate, - cairo_path_fixed_t *path, - double x, - double y, - cairo_bool_t *inside_ret); - -cairo_private cairo_status_t -_cairo_gstate_in_fill (cairo_gstate_t *gstate, - cairo_path_fixed_t *path, - double x, - double y, - cairo_bool_t *inside_ret); - -cairo_private cairo_status_t -_cairo_gstate_clip (cairo_gstate_t *gstate, cairo_path_fixed_t *path); - -cairo_private cairo_status_t -_cairo_gstate_reset_clip (cairo_gstate_t *gstate); - -cairo_private cairo_status_t -_cairo_gstate_clip_extents (cairo_gstate_t *gstate, - double *x1, - double *y1, - double *x2, - double *y2); - -cairo_private cairo_rectangle_list_t* -_cairo_gstate_copy_clip_rectangle_list (cairo_gstate_t *gstate); - -cairo_private cairo_status_t -_cairo_gstate_show_surface (cairo_gstate_t *gstate, - cairo_surface_t *surface, - double x, - double y, - double width, - double height); - -cairo_private cairo_status_t -_cairo_gstate_select_font_face (cairo_gstate_t *gstate, - const char *family, - cairo_font_slant_t slant, - cairo_font_weight_t weight); - -cairo_private cairo_status_t -_cairo_gstate_set_font_size (cairo_gstate_t *gstate, - double size); - -cairo_private void -_cairo_gstate_get_font_matrix (cairo_gstate_t *gstate, - cairo_matrix_t *matrix); - -cairo_private cairo_status_t -_cairo_gstate_set_font_matrix (cairo_gstate_t *gstate, - const cairo_matrix_t *matrix); - -cairo_private void -_cairo_gstate_get_font_options (cairo_gstate_t *gstate, - cairo_font_options_t *options); - -cairo_private void -_cairo_gstate_set_font_options (cairo_gstate_t *gstate, - const cairo_font_options_t *options); - -cairo_private cairo_status_t -_cairo_gstate_get_font_face (cairo_gstate_t *gstate, - cairo_font_face_t **font_face); - -cairo_private cairo_status_t -_cairo_gstate_get_scaled_font (cairo_gstate_t *gstate, - cairo_scaled_font_t **scaled_font); - -cairo_private cairo_status_t -_cairo_gstate_get_font_extents (cairo_gstate_t *gstate, - cairo_font_extents_t *extents); - -cairo_private cairo_status_t -_cairo_gstate_set_font_face (cairo_gstate_t *gstate, - cairo_font_face_t *font_face); - -cairo_private cairo_status_t -_cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate, - double x, - double y, - const char *utf8, - int utf8_len, - cairo_glyph_t **glyphs, - int *num_glyphs, - cairo_text_cluster_t **clusters, - int *num_clusters, - cairo_text_cluster_flags_t *cluster_flags); - -cairo_private cairo_status_t -_cairo_gstate_glyph_extents (cairo_gstate_t *gstate, - const cairo_glyph_t *glyphs, - int num_glyphs, - cairo_text_extents_t *extents); - -cairo_private cairo_status_t -_cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate, - const char *utf8, - int utf8_len, - const cairo_glyph_t *glyphs, - int num_glyphs, - const cairo_text_cluster_t *clusters, - int num_clusters, - cairo_text_cluster_flags_t cluster_flags); - -cairo_private cairo_status_t -_cairo_gstate_glyph_path (cairo_gstate_t *gstate, - const cairo_glyph_t *glyphs, - int num_glyphs, - cairo_path_fixed_t *path); - -cairo_private cairo_bool_t -_cairo_operator_bounded_by_mask (cairo_operator_t op); - -cairo_private cairo_bool_t -_cairo_operator_bounded_by_source (cairo_operator_t op); - -/* cairo-color.c */ -cairo_private const cairo_color_t * -_cairo_stock_color (cairo_stock_t stock); - -#define CAIRO_COLOR_WHITE _cairo_stock_color (CAIRO_STOCK_WHITE) -#define CAIRO_COLOR_BLACK _cairo_stock_color (CAIRO_STOCK_BLACK) -#define CAIRO_COLOR_TRANSPARENT _cairo_stock_color (CAIRO_STOCK_TRANSPARENT) - -cairo_private uint16_t -_cairo_color_double_to_short (double d); - -cairo_private void -_cairo_color_init (cairo_color_t *color); - -cairo_private void -_cairo_color_init_rgb (cairo_color_t *color, - double red, double green, double blue); - -cairo_private void -_cairo_color_init_rgba (cairo_color_t *color, - double red, double green, double blue, - double alpha); - -cairo_private void -_cairo_color_multiply_alpha (cairo_color_t *color, - double alpha); - -cairo_private void -_cairo_color_get_rgba (cairo_color_t *color, - double *red, - double *green, - double *blue, - double *alpha); - -cairo_private void -_cairo_color_get_rgba_premultiplied (cairo_color_t *color, - double *red, - double *green, - double *blue, - double *alpha); - -cairo_private cairo_bool_t -_cairo_color_equal (const cairo_color_t *color_a, - const cairo_color_t *color_b); - -/* cairo-font-face.c */ - -extern const cairo_private cairo_toy_font_face_t _cairo_font_face_nil; - -cairo_private void -_cairo_font_face_init (cairo_font_face_t *font_face, - const cairo_font_face_backend_t *backend); - -cairo_private cairo_status_t -_cairo_font_face_set_error (cairo_font_face_t *font_face, - cairo_status_t status); - -cairo_private void -_cairo_unscaled_font_init (cairo_unscaled_font_t *font, - const cairo_unscaled_font_backend_t *backend); - -cairo_private_no_warn cairo_unscaled_font_t * -_cairo_unscaled_font_reference (cairo_unscaled_font_t *font); - -cairo_private void -_cairo_unscaled_font_destroy (cairo_unscaled_font_t *font); - -/* cairo-font-face-twin.c */ - -cairo_private cairo_font_face_t * -_cairo_font_face_twin_create (cairo_font_slant_t slant, - cairo_font_weight_t weight); - -/* cairo-font-face-twin-data.c */ - -extern const cairo_private int8_t _cairo_twin_outlines[]; -extern const cairo_private uint16_t _cairo_twin_charmap[128]; - -/* cairo-font-options.c */ - -cairo_private void -_cairo_font_options_init_default (cairo_font_options_t *options); - -cairo_private void -_cairo_font_options_init_copy (cairo_font_options_t *options, - const cairo_font_options_t *other); - -/* cairo-hull.c */ -cairo_private cairo_status_t -_cairo_hull_compute (cairo_pen_vertex_t *vertices, int *num_vertices); - -/* cairo-lzw.c */ -cairo_private unsigned char * -_cairo_lzw_compress (unsigned char *data, unsigned long *size_in_out); - -/* cairo-misc.c */ -cairo_private cairo_status_t -_cairo_validate_text_clusters (const char *utf8, - int utf8_len, - const cairo_glyph_t *glyphs, - int num_glyphs, - const cairo_text_cluster_t *clusters, - int num_clusters, - cairo_text_cluster_flags_t cluster_flags); - -/* cairo-path-fixed.c */ -cairo_private void -_cairo_path_fixed_init (cairo_path_fixed_t *path); - -cairo_private cairo_status_t -_cairo_path_fixed_init_copy (cairo_path_fixed_t *path, - cairo_path_fixed_t *other); - -cairo_private cairo_bool_t -_cairo_path_fixed_is_equal (cairo_path_fixed_t *path, - cairo_path_fixed_t *other); - -cairo_private cairo_path_fixed_t * -_cairo_path_fixed_create (void); - -cairo_private void -_cairo_path_fixed_fini (cairo_path_fixed_t *path); - -cairo_private void -_cairo_path_fixed_destroy (cairo_path_fixed_t *path); - -cairo_private cairo_status_t -_cairo_path_fixed_move_to (cairo_path_fixed_t *path, - cairo_fixed_t x, - cairo_fixed_t y); - -cairo_private void -_cairo_path_fixed_new_sub_path (cairo_path_fixed_t *path); - -cairo_private cairo_status_t -_cairo_path_fixed_rel_move_to (cairo_path_fixed_t *path, - cairo_fixed_t dx, - cairo_fixed_t dy); - -cairo_private cairo_status_t -_cairo_path_fixed_line_to (cairo_path_fixed_t *path, - cairo_fixed_t x, - cairo_fixed_t y); - -cairo_private cairo_status_t -_cairo_path_fixed_rel_line_to (cairo_path_fixed_t *path, - cairo_fixed_t dx, - cairo_fixed_t dy); - -cairo_private cairo_status_t -_cairo_path_fixed_curve_to (cairo_path_fixed_t *path, - cairo_fixed_t x0, cairo_fixed_t y0, - cairo_fixed_t x1, cairo_fixed_t y1, - cairo_fixed_t x2, cairo_fixed_t y2); - -cairo_private cairo_status_t -_cairo_path_fixed_rel_curve_to (cairo_path_fixed_t *path, - cairo_fixed_t dx0, cairo_fixed_t dy0, - cairo_fixed_t dx1, cairo_fixed_t dy1, - cairo_fixed_t dx2, cairo_fixed_t dy2); - -cairo_private cairo_status_t -_cairo_path_fixed_close_path (cairo_path_fixed_t *path); - -cairo_private cairo_bool_t -_cairo_path_fixed_get_current_point (cairo_path_fixed_t *path, - cairo_fixed_t *x, - cairo_fixed_t *y); - -typedef cairo_status_t -(cairo_path_fixed_move_to_func_t) (void *closure, - cairo_point_t *point); - -typedef cairo_status_t -(cairo_path_fixed_line_to_func_t) (void *closure, - cairo_point_t *point); - -typedef cairo_status_t -(cairo_path_fixed_curve_to_func_t) (void *closure, - cairo_point_t *p0, - cairo_point_t *p1, - cairo_point_t *p2); - -typedef cairo_status_t -(cairo_path_fixed_close_path_func_t) (void *closure); - -cairo_private cairo_status_t -_cairo_path_fixed_interpret (const cairo_path_fixed_t *path, - cairo_direction_t dir, - 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_private cairo_status_t -_cairo_path_fixed_interpret_flat (const cairo_path_fixed_t *path, - cairo_direction_t dir, - cairo_path_fixed_move_to_func_t *move_to, - cairo_path_fixed_line_to_func_t *line_to, - cairo_path_fixed_close_path_func_t *close_path, - void *closure, - double tolerance); - -cairo_private cairo_status_t -_cairo_path_fixed_append (cairo_path_fixed_t *path, - const cairo_path_fixed_t *other, - cairo_direction_t dir); - -cairo_private cairo_status_t -_cairo_path_fixed_bounds (cairo_path_fixed_t *path, - double *x1, double *y1, - double *x2, double *y2, - double tolerance); - -cairo_private void -_cairo_path_fixed_transform (cairo_path_fixed_t *path, - cairo_matrix_t *matrix); - -cairo_private cairo_bool_t -_cairo_path_fixed_is_empty (cairo_path_fixed_t *path); - -cairo_private cairo_bool_t -_cairo_path_fixed_is_box (cairo_path_fixed_t *path, - cairo_box_t *box); - -cairo_private cairo_bool_t -_cairo_path_fixed_is_rectangle (cairo_path_fixed_t *path, - cairo_box_t *box); - -/* cairo-path-fill.c */ -cairo_private cairo_status_t -_cairo_path_fixed_fill_to_traps (cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_traps_t *traps); - -/* cairo-path-stroke.c */ -cairo_private cairo_status_t -_cairo_path_fixed_stroke_to_traps (cairo_path_fixed_t *path, - cairo_stroke_style_t *stroke_style, - cairo_matrix_t *ctm, - cairo_matrix_t *ctm_inverse, - double tolerance, - cairo_traps_t *traps); - -/* cairo-scaled-font.c */ - -cairo_private void -_cairo_scaled_font_freeze_cache (cairo_scaled_font_t *scaled_font); - -cairo_private void -_cairo_scaled_font_thaw_cache (cairo_scaled_font_t *scaled_font); - -cairo_private void -_cairo_scaled_font_reset_cache (cairo_scaled_font_t *scaled_font); - -cairo_private cairo_status_t -_cairo_scaled_font_set_error (cairo_scaled_font_t *scaled_font, - cairo_status_t status); - -cairo_private cairo_scaled_font_t * -_cairo_scaled_font_create_in_error (cairo_status_t status); - -cairo_private void -_cairo_scaled_font_reset_static_data (void); - -cairo_private cairo_status_t -_cairo_scaled_font_register_placeholder_and_unlock_font_map (cairo_scaled_font_t *scaled_font); - -cairo_private void -_cairo_scaled_font_unregister_placeholder_and_lock_font_map (cairo_scaled_font_t *scaled_font); - -cairo_private cairo_status_t -_cairo_scaled_font_init (cairo_scaled_font_t *scaled_font, - cairo_font_face_t *font_face, - const cairo_matrix_t *font_matrix, - const cairo_matrix_t *ctm, - const cairo_font_options_t *options, - const cairo_scaled_font_backend_t *backend); - -cairo_private cairo_status_t -_cairo_scaled_font_set_metrics (cairo_scaled_font_t *scaled_font, - cairo_font_extents_t *fs_metrics); - -/* This should only be called on an error path by a scaled_font constructor */ -cairo_private void -_cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font); - -cairo_private cairo_status_t -_cairo_scaled_font_font_extents (cairo_scaled_font_t *scaled_font, - cairo_font_extents_t *extents); - -cairo_private cairo_status_t -_cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font, - const cairo_glyph_t *glyphs, - int num_glyphs, - cairo_rectangle_int_t *extents); - -cairo_private cairo_status_t -_cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_surface_t *surface, - int source_x, - int source_y, - int dest_x, - int dest_y, - unsigned int width, - unsigned int height, - cairo_glyph_t *glyphs, - int num_glyphs); - -cairo_private cairo_status_t -_cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font, - const cairo_glyph_t *glyphs, - int num_glyphs, - cairo_path_fixed_t *path); - -cairo_private void -_cairo_scaled_glyph_set_metrics (cairo_scaled_glyph_t *scaled_glyph, - cairo_scaled_font_t *scaled_font, - cairo_text_extents_t *fs_metrics); - -cairo_private void -_cairo_scaled_glyph_set_surface (cairo_scaled_glyph_t *scaled_glyph, - cairo_scaled_font_t *scaled_font, - cairo_image_surface_t *surface); - -cairo_private void -_cairo_scaled_glyph_set_path (cairo_scaled_glyph_t *scaled_glyph, - cairo_scaled_font_t *scaled_font, - cairo_path_fixed_t *path); - -cairo_private void -_cairo_scaled_glyph_set_meta_surface (cairo_scaled_glyph_t *scaled_glyph, - cairo_scaled_font_t *scaled_font, - cairo_surface_t *meta_surface); - -cairo_private cairo_int_status_t -_cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font, - unsigned long index, - cairo_scaled_glyph_info_t info, - cairo_scaled_glyph_t **scaled_glyph_ret); - -cairo_private double -_cairo_scaled_font_get_max_scale (cairo_scaled_font_t *scaled_font); - -cairo_private void -_cairo_scaled_font_map_destroy (void); - -/* cairo-stroke-style.c */ - -cairo_private void -_cairo_stroke_style_init (cairo_stroke_style_t *style); - -cairo_private cairo_status_t -_cairo_stroke_style_init_copy (cairo_stroke_style_t *style, - cairo_stroke_style_t *other); - -cairo_private void -_cairo_stroke_style_fini (cairo_stroke_style_t *style); - -cairo_private void -_cairo_stroke_style_max_distance_from_path (const cairo_stroke_style_t *style, - const cairo_matrix_t *ctm, - double *dx, double *dy); - -/* cairo-surface.c */ - -cairo_private cairo_surface_t * -_cairo_surface_create_in_error (cairo_status_t status); - -cairo_private cairo_status_t -_cairo_surface_set_error (cairo_surface_t *surface, - cairo_status_t status); - -cairo_private void -_cairo_surface_set_resolution (cairo_surface_t *surface, - double x_res, - double y_res); - -cairo_private cairo_surface_t * -_cairo_surface_create_similar_scratch (cairo_surface_t *other, - cairo_content_t content, - int width, - int height); - -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_private cairo_surface_t * -_cairo_surface_create_solid_pattern_surface (cairo_surface_t *other, - cairo_solid_pattern_t *solid_pattern); - -cairo_private cairo_int_status_t -_cairo_surface_repaint_solid_pattern_surface (cairo_surface_t *other, - cairo_surface_t *solid_surface, - cairo_solid_pattern_t *solid_pattern); - -cairo_private void -_cairo_surface_init (cairo_surface_t *surface, - const cairo_surface_backend_t *backend, - cairo_content_t content); - -cairo_private void -_cairo_surface_set_font_options (cairo_surface_t *surface, - cairo_font_options_t *options); - -cairo_private cairo_clip_mode_t -_cairo_surface_get_clip_mode (cairo_surface_t *surface); - -cairo_private cairo_status_t -_cairo_surface_composite (cairo_operator_t op, - cairo_pattern_t *src, - cairo_pattern_t *mask, - cairo_surface_t *dst, - 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_private cairo_status_t -_cairo_surface_fill_rectangle (cairo_surface_t *surface, - cairo_operator_t op, - const cairo_color_t *color, - int x, - int y, - int width, - int height); - -cairo_private cairo_status_t -_cairo_surface_fill_region (cairo_surface_t *surface, - cairo_operator_t op, - const cairo_color_t *color, - cairo_region_t *region); - -cairo_private cairo_status_t -_cairo_surface_fill_rectangles (cairo_surface_t *surface, - cairo_operator_t op, - const cairo_color_t *color, - cairo_rectangle_int_t *rects, - int num_rects); - -cairo_private cairo_status_t -_cairo_surface_paint (cairo_surface_t *surface, - cairo_operator_t op, - cairo_pattern_t *source); - -cairo_private cairo_status_t -_cairo_surface_mask (cairo_surface_t *surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_pattern_t *mask); - -cairo_private cairo_status_t -_cairo_surface_fill_stroke (cairo_surface_t *surface, - cairo_operator_t fill_op, - cairo_pattern_t *fill_source, - cairo_fill_rule_t fill_rule, - double fill_tolerance, - cairo_antialias_t fill_antialias, - cairo_path_fixed_t *path, - cairo_operator_t stroke_op, - cairo_pattern_t *stroke_source, - cairo_stroke_style_t *stroke_style, - cairo_matrix_t *stroke_ctm, - cairo_matrix_t *stroke_ctm_inverse, - double stroke_tolerance, - cairo_antialias_t stroke_antialias); - -cairo_private cairo_status_t -_cairo_surface_stroke (cairo_surface_t *surface, - cairo_operator_t op, - cairo_pattern_t *source, - 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_private cairo_status_t -_cairo_surface_fill (cairo_surface_t *surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias); - -cairo_private cairo_status_t -_cairo_surface_show_text_glyphs (cairo_surface_t *surface, - cairo_operator_t op, - cairo_pattern_t *source, - const char *utf8, - int utf8_len, - cairo_glyph_t *glyphs, - int num_glyphs, - const cairo_text_cluster_t *clusters, - int num_clusters, - cairo_text_cluster_flags_t cluster_flags, - cairo_scaled_font_t *scaled_font); - -cairo_private cairo_status_t -_cairo_surface_composite_trapezoids (cairo_operator_t op, - cairo_pattern_t *pattern, - cairo_surface_t *dst, - cairo_antialias_t antialias, - int src_x, - int src_y, - int dst_x, - int dst_y, - unsigned int width, - unsigned int height, - cairo_trapezoid_t *traps, - int ntraps); - -cairo_private cairo_status_t -_cairo_surface_acquire_source_image (cairo_surface_t *surface, - cairo_image_surface_t **image_out, - void **image_extra); - -cairo_private void -_cairo_surface_release_source_image (cairo_surface_t *surface, - cairo_image_surface_t *image, - void *image_extra); - -cairo_private cairo_status_t -_cairo_surface_acquire_dest_image (cairo_surface_t *surface, - cairo_rectangle_int_t *interest_rect, - cairo_image_surface_t **image_out, - cairo_rectangle_int_t *image_rect, - void **image_extra); - -cairo_private void -_cairo_surface_release_dest_image (cairo_surface_t *surface, - cairo_rectangle_int_t *interest_rect, - cairo_image_surface_t *image, - cairo_rectangle_int_t *image_rect, - void *image_extra); - -cairo_private cairo_status_t -_cairo_surface_clone_similar (cairo_surface_t *surface, - cairo_surface_t *src, - int src_x, - int src_y, - int width, - int height, - int *clone_offset_x, - int *clone_offset_y, - cairo_surface_t **clone_out); - -cairo_private cairo_surface_t * -_cairo_surface_snapshot (cairo_surface_t *surface); - -cairo_private cairo_bool_t -_cairo_surface_is_similar (cairo_surface_t *surface_a, - cairo_surface_t *surface_b, - cairo_content_t content); - -cairo_private cairo_status_t -_cairo_surface_reset (cairo_surface_t *surface); - -cairo_private unsigned int -_cairo_surface_get_current_clip_serial (cairo_surface_t *surface); - -cairo_private unsigned int -_cairo_surface_allocate_clip_serial (cairo_surface_t *surface); - -cairo_private cairo_status_t -_cairo_surface_reset_clip (cairo_surface_t *surface); - -cairo_private cairo_status_t -_cairo_surface_set_clip_region (cairo_surface_t *surface, - cairo_region_t *region, - unsigned int serial); - -cairo_private cairo_int_status_t -_cairo_surface_intersect_clip_path (cairo_surface_t *surface, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias); - -cairo_private cairo_clip_t * -_cairo_surface_get_clip (cairo_surface_t *surface); - -cairo_private cairo_status_t -_cairo_surface_set_clip (cairo_surface_t *surface, cairo_clip_t *clip); - -cairo_private cairo_int_status_t -_cairo_surface_get_extents (cairo_surface_t *surface, - cairo_rectangle_int_t *extents); - -cairo_private cairo_status_t -_cairo_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font, - cairo_operator_t op, - cairo_pattern_t *pattern, - cairo_surface_t *surface, - int source_x, - int source_y, - int dest_x, - int dest_y, - unsigned int width, - unsigned int height, - cairo_glyph_t *glyphs, - int num_glyphs); - -cairo_private cairo_status_t -_cairo_surface_composite_fixup_unbounded (cairo_surface_t *dst, - cairo_surface_attributes_t *src_attr, - int src_width, - int src_height, - cairo_surface_attributes_t *mask_attr, - int mask_width, - int mask_height, - 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_private cairo_status_t -_cairo_surface_composite_shape_fixup_unbounded (cairo_surface_t *dst, - cairo_surface_attributes_t *src_attr, - int src_width, - int src_height, - int mask_width, - int mask_height, - 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_private cairo_bool_t -_cairo_surface_is_opaque (const cairo_surface_t *surface); - -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-image-surface.c */ - -/* XXX: In cairo 1.2.0 we added a new %CAIRO_FORMAT_RGB16_565 but - * neglected to adjust this macro. The net effect is that it's - * impossible to externally create an image surface with this - * format. This is perhaps a good thing since we also neglected to fix - * up things like cairo_surface_write_to_png() for the new format - * (-Wswitch-enum will tell you where). Is it obvious that format was - * added in haste? - * - * The reason for the new format was to allow the xlib backend to be - * used on X servers with a 565 visual. So the new format did its job - * for that, even without being considered "valid" for the sake of - * things like cairo_image_surface_create(). - * - * Since 1.2.0 we ran into the same situtation with X servers with BGR - * visuals. This time we invented #cairo_internal_format_t instead, - * (see it for more discussion). - * - * The punchline is that %CAIRO_FORMAT_VALID must not conside any - * internal format to be valid. Also we need to decide if the - * RGB16_565 should be moved to instead be an internal format. If so, - * this macro need not change for it. (We probably will need to leave - * an RGB16_565 value in the header files for the sake of code that - * might have that value in it.) - * - * If we do decide to start fully supporting RGB16_565 as an external - * format, then %CAIRO_FORMAT_VALID needs to be adjusted to include - * it. But that should not happen before all necessary code is fixed - * to support it (at least cairo_surface_write_to_png() and a few spots - * in cairo-xlib-surface.c--again see -Wswitch-enum). - */ -#define CAIRO_FORMAT_INVALID ((unsigned int) -1) -#define CAIRO_FORMAT_VALID(format) ((format) <= CAIRO_FORMAT_A1) - -/* pixman-required stride alignment in bytes. */ -#define CAIRO_STRIDE_ALIGNMENT (sizeof (uint32_t)) -#define CAIRO_STRIDE_FOR_WIDTH_BPP(w,bpp) \ - (((bpp)*(w)+7)/8 + CAIRO_STRIDE_ALIGNMENT-1) & ~(CAIRO_STRIDE_ALIGNMENT-1) - -#define CAIRO_CONTENT_VALID(content) ((content) && \ - (((content) & ~(CAIRO_CONTENT_COLOR | \ - CAIRO_CONTENT_ALPHA | \ - CAIRO_CONTENT_COLOR_ALPHA))\ - == 0)) - -cairo_private int -_cairo_format_bits_per_pixel (cairo_format_t format); - -cairo_private cairo_format_t -_cairo_format_from_content (cairo_content_t content); - -cairo_private cairo_content_t -_cairo_content_from_format (cairo_format_t format); - -cairo_private cairo_surface_t * -_cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image, - pixman_format_code_t pixman_format); - -cairo_private cairo_bool_t -_pixman_format_from_masks (cairo_format_masks_t *masks, - pixman_format_code_t *format_ret); - -cairo_private void -_pixman_format_to_masks (pixman_format_code_t pixman_format, - cairo_format_masks_t *masks); - -cairo_private cairo_surface_t * -_cairo_image_surface_create_with_pixman_format (unsigned char *data, - pixman_format_code_t pixman_format, - int width, - int height, - int stride); - -cairo_private cairo_surface_t * -_cairo_image_surface_create_with_masks (unsigned char *data, - cairo_format_masks_t *format, - int width, - int height, - int stride); - -cairo_private cairo_surface_t * -_cairo_image_surface_create_with_content (cairo_content_t content, - int width, - int height); - -cairo_private cairo_surface_t * -_cairo_image_surface_create_for_data_with_content (unsigned char *data, - cairo_content_t content, - int width, - int height, - int stride); - -cairo_private void -_cairo_image_surface_assume_ownership_of_data (cairo_image_surface_t *surface); - -/* XXX: It's a nasty kludge that this appears here. Backend functions - * like this should really be static. But we're doing this to work - * around some general defects in the backend clipping interfaces, - * (see some notes in test-paginated-surface.c). - * - * I want to fix the real defects, but it's "hard" as they touch many - * backends, so doing that will require synchronizing several backend - * maintainers. - */ -cairo_private cairo_int_status_t -_cairo_image_surface_set_clip_region (void *abstract_surface, - cairo_region_t *region); - -cairo_private cairo_image_surface_t * -_cairo_image_surface_clone (cairo_image_surface_t *surface, - cairo_format_t format); - -cairo_private cairo_image_transparency_t -_cairo_image_analyze_transparency (cairo_image_surface_t *image); - -cairo_private cairo_bool_t -_cairo_surface_is_image (const cairo_surface_t *surface); - -cairo_private cairo_bool_t -_cairo_surface_is_meta (const cairo_surface_t *surface); - -/* cairo-pen.c */ -cairo_private cairo_status_t -_cairo_pen_init (cairo_pen_t *pen, - double radius, - double tolerance, - cairo_matrix_t *ctm); - -cairo_private void -_cairo_pen_init_empty (cairo_pen_t *pen); - -cairo_private cairo_status_t -_cairo_pen_init_copy (cairo_pen_t *pen, cairo_pen_t *other); - -cairo_private void -_cairo_pen_fini (cairo_pen_t *pen); - -cairo_private cairo_status_t -_cairo_pen_add_points (cairo_pen_t *pen, cairo_point_t *point, int num_points); - -cairo_private cairo_status_t -_cairo_pen_add_points_for_slopes (cairo_pen_t *pen, - cairo_point_t *a, - cairo_point_t *b, - cairo_point_t *c, - cairo_point_t *d); - -cairo_private void -_cairo_pen_find_active_cw_vertex_index (cairo_pen_t *pen, - cairo_slope_t *slope, - int *active); - -cairo_private void -_cairo_pen_find_active_ccw_vertex_index (cairo_pen_t *pen, - cairo_slope_t *slope, - int *active); - -cairo_private cairo_status_t -_cairo_pen_stroke_spline (cairo_pen_t *pen, - cairo_spline_t *spline, - double tolerance, - cairo_traps_t *traps); - -/* cairo-polygon.c */ -cairo_private void -_cairo_polygon_init (cairo_polygon_t *polygon); - -cairo_private void -_cairo_polygon_fini (cairo_polygon_t *polygon); - -cairo_private void -_cairo_polygon_move_to (cairo_polygon_t *polygon, - const cairo_point_t *point); - -cairo_private void -_cairo_polygon_line_to (cairo_polygon_t *polygon, - const cairo_point_t *point); - -cairo_private void -_cairo_polygon_close (cairo_polygon_t *polygon); - -#define _cairo_polygon_status(P) (P)->status - -/* cairo-spline.c */ -cairo_private cairo_int_status_t -_cairo_spline_init (cairo_spline_t *spline, - const cairo_point_t *a, - const cairo_point_t *b, - const cairo_point_t *c, - const cairo_point_t *d); - -cairo_private cairo_status_t -_cairo_spline_decompose (cairo_spline_t *spline, double tolerance); - -cairo_private void -_cairo_spline_fini (cairo_spline_t *spline); - -/* cairo-matrix.c */ -cairo_private void -_cairo_matrix_get_affine (const cairo_matrix_t *matrix, - double *xx, double *yx, - double *xy, double *yy, - double *x0, double *y0); - -cairo_private void -_cairo_matrix_transform_bounding_box (const cairo_matrix_t *matrix, - double *x1, double *y1, - double *x2, double *y2, - cairo_bool_t *is_tight); - -cairo_private void -_cairo_matrix_transform_bounding_box_fixed (const cairo_matrix_t *matrix, - cairo_box_t *bbox, - cairo_bool_t *is_tight); - -cairo_private cairo_bool_t -_cairo_matrix_is_invertible (const cairo_matrix_t *matrix); - -cairo_private double -_cairo_matrix_compute_determinant (const cairo_matrix_t *matrix); - -cairo_private cairo_status_t -_cairo_matrix_compute_basis_scale_factors (const cairo_matrix_t *matrix, - double *sx, double *sy, int x_major); - -cairo_private cairo_bool_t -_cairo_matrix_is_identity (const cairo_matrix_t *matrix); - -cairo_private cairo_bool_t -_cairo_matrix_is_translation (const cairo_matrix_t *matrix); - -cairo_private cairo_bool_t -_cairo_matrix_is_integer_translation(const cairo_matrix_t *matrix, - int *itx, int *ity); - -cairo_private cairo_bool_t -_cairo_matrix_is_pixel_exact (const cairo_matrix_t *matrix); - -cairo_private double -_cairo_matrix_transformed_circle_major_axis(cairo_matrix_t *matrix, double radius); - -cairo_private void -_cairo_matrix_to_pixman_matrix (const cairo_matrix_t *matrix, - pixman_transform_t *pixman_transform); - -/* cairo-traps.c */ -cairo_private void -_cairo_traps_init (cairo_traps_t *traps); - -cairo_private void -_cairo_traps_limit (cairo_traps_t *traps, - cairo_box_t *limits); - -cairo_private cairo_bool_t -_cairo_traps_get_limit (cairo_traps_t *traps, - cairo_box_t *limits); - -cairo_private void -_cairo_traps_init_box (cairo_traps_t *traps, - const cairo_box_t *box); - -cairo_private void -_cairo_traps_clear (cairo_traps_t *traps); - -cairo_private void -_cairo_traps_fini (cairo_traps_t *traps); - -#define _cairo_traps_status(T) (T)->status - -cairo_private void -_cairo_traps_translate (cairo_traps_t *traps, int x, int y); - -cairo_private cairo_status_t -_cairo_traps_tessellate_triangle (cairo_traps_t *traps, - const cairo_point_t t[3]); - -cairo_private cairo_status_t -_cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, - const cairo_point_t q[4]); - -cairo_private cairo_status_t -_cairo_traps_tessellate_rectangle (cairo_traps_t *traps, - const cairo_point_t *top_left, - const cairo_point_t *bottom_right); - -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); - -cairo_private cairo_status_t -_cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps, - const cairo_polygon_t *polygon, - cairo_fill_rule_t fill_rule); - -cairo_private int -_cairo_traps_contain (const cairo_traps_t *traps, - double x, double y); - -cairo_private void -_cairo_traps_extents (const cairo_traps_t *traps, - cairo_box_t *extents); - -cairo_private cairo_int_status_t -_cairo_traps_extract_region (const cairo_traps_t *tr, - cairo_region_t *region); - -cairo_private cairo_status_t -_cairo_traps_path (const cairo_traps_t *traps, - cairo_path_fixed_t *path); - -cairo_private void -_cairo_trapezoid_array_translate_and_scale (cairo_trapezoid_t *offset_traps, - cairo_trapezoid_t *src_traps, - int num_traps, - double tx, double ty, - double sx, double sy); - -/* cairo-slope.c */ -cairo_private void -_cairo_slope_init (cairo_slope_t *slope, - const cairo_point_t *a, - const cairo_point_t *b); - -cairo_private int -_cairo_slope_compare (const cairo_slope_t *a, const cairo_slope_t *b); - -/* cairo-pattern.c */ - -cairo_private cairo_status_t -_cairo_pattern_create_copy (cairo_pattern_t **pattern, - const cairo_pattern_t *other); - -cairo_private cairo_status_t -_cairo_pattern_init_copy (cairo_pattern_t *pattern, - const cairo_pattern_t *other); - -cairo_private cairo_status_t -_cairo_pattern_init_snapshot (cairo_pattern_t *pattern, - const cairo_pattern_t *other); - -cairo_private void -_cairo_pattern_init_solid (cairo_solid_pattern_t *pattern, - const cairo_color_t *color, - cairo_content_t content); - -cairo_private void -_cairo_pattern_init_for_surface (cairo_surface_pattern_t *pattern, - cairo_surface_t *surface); - -cairo_private void -_cairo_pattern_init_linear (cairo_linear_pattern_t *pattern, - double x0, double y0, double x1, double y1); - -cairo_private void -_cairo_pattern_init_radial (cairo_radial_pattern_t *pattern, - double cx0, double cy0, double radius0, - double cx1, double cy1, double radius1); - -cairo_private void -_cairo_pattern_fini (cairo_pattern_t *pattern); - -cairo_private cairo_pattern_t * -_cairo_pattern_create_solid (const cairo_color_t *color, - cairo_content_t content); - -cairo_private void -_cairo_pattern_transform (cairo_pattern_t *pattern, - const cairo_matrix_t *ctm_inverse); - -cairo_private cairo_bool_t -_cairo_pattern_is_opaque_solid (const cairo_pattern_t *pattern); - -cairo_private cairo_bool_t -_cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern); - -cairo_private cairo_int_status_t -_cairo_pattern_acquire_surface (cairo_pattern_t *pattern, - cairo_surface_t *dst, - int x, - int y, - unsigned int width, - unsigned int height, - cairo_surface_t **surface_out, - cairo_surface_attributes_t *attributes); - -cairo_private void -_cairo_pattern_release_surface (cairo_pattern_t *pattern, - cairo_surface_t *surface, - cairo_surface_attributes_t *attributes); - -cairo_private cairo_int_status_t -_cairo_pattern_acquire_surfaces (cairo_pattern_t *src, - cairo_pattern_t *mask, - cairo_surface_t *dst, - int src_x, - int src_y, - int mask_x, - int mask_y, - unsigned int width, - unsigned int height, - cairo_surface_t **src_out, - cairo_surface_t **mask_out, - cairo_surface_attributes_t *src_attributes, - cairo_surface_attributes_t *mask_attributes); - -cairo_private cairo_status_t -_cairo_pattern_get_extents (cairo_pattern_t *pattern, - cairo_rectangle_int_t *extents); - -cairo_private void -_cairo_pattern_reset_static_data (void); - -cairo_private cairo_status_t -_cairo_gstate_set_antialias (cairo_gstate_t *gstate, - cairo_antialias_t antialias); - -cairo_private cairo_antialias_t -_cairo_gstate_get_antialias (cairo_gstate_t *gstate); - -/* cairo-region.c */ - -#include "cairo-region-private.h" - -/* cairo-unicode.c */ - -cairo_private int -_cairo_utf8_get_char_validated (const char *p, - uint32_t *unicode); - -cairo_private cairo_status_t -_cairo_utf8_to_ucs4 (const char *str, - int len, - uint32_t **result, - int *items_written); - -cairo_private int -_cairo_ucs4_to_utf8 (uint32_t unicode, - char *utf8); - -#if CAIRO_HAS_WIN32_FONT || CAIRO_HAS_QUARTZ_FONT || CAIRO_HAS_PDF_OPERATORS -# define CAIRO_HAS_UTF8_TO_UTF16 1 -#endif -#if CAIRO_HAS_UTF8_TO_UTF16 -cairo_private cairo_status_t -_cairo_utf8_to_utf16 (const char *str, - int len, - uint16_t **result, - int *items_written); -#endif - -#define _cairo_status_is_error(status) \ - (status != CAIRO_STATUS_SUCCESS && status <= CAIRO_STATUS_LAST_STATUS) - -cairo_private cairo_status_t -_cairo_error (cairo_status_t status); - -/* hide compiler warnings when discarding the return value */ -#define _cairo_error_throw(status) do { \ - cairo_status_t status__ = _cairo_error (status); \ - (void) status__; \ -} while (0) - -/* Avoid unnecessary PLT entries. */ -slim_hidden_proto (cairo_clip_preserve); -slim_hidden_proto (cairo_close_path); -slim_hidden_proto (cairo_create); -slim_hidden_proto (cairo_curve_to); -slim_hidden_proto (cairo_destroy); -slim_hidden_proto (cairo_fill_preserve); -slim_hidden_proto (cairo_font_face_destroy); -slim_hidden_proto (cairo_font_face_get_user_data); -slim_hidden_proto_no_warn (cairo_font_face_reference); -slim_hidden_proto (cairo_font_face_set_user_data); -slim_hidden_proto (cairo_font_options_equal); -slim_hidden_proto (cairo_font_options_hash); -slim_hidden_proto (cairo_font_options_merge); -slim_hidden_proto (cairo_font_options_set_antialias); -slim_hidden_proto (cairo_font_options_set_hint_metrics); -slim_hidden_proto (cairo_font_options_set_hint_style); -slim_hidden_proto (cairo_font_options_set_subpixel_order); -slim_hidden_proto (cairo_font_options_status); -slim_hidden_proto (cairo_get_current_point); -slim_hidden_proto (cairo_get_line_width); -slim_hidden_proto (cairo_get_matrix); -slim_hidden_proto (cairo_get_target); -slim_hidden_proto (cairo_get_tolerance); -slim_hidden_proto (cairo_glyph_allocate); -slim_hidden_proto (cairo_glyph_free); -slim_hidden_proto (cairo_image_surface_create); -slim_hidden_proto (cairo_image_surface_create_for_data); -slim_hidden_proto (cairo_image_surface_get_data); -slim_hidden_proto (cairo_image_surface_get_height); -slim_hidden_proto (cairo_image_surface_get_stride); -slim_hidden_proto (cairo_image_surface_get_width); -slim_hidden_proto (cairo_format_stride_for_width); -slim_hidden_proto (cairo_line_to); -slim_hidden_proto (cairo_mask); -slim_hidden_proto (cairo_matrix_init); -slim_hidden_proto (cairo_matrix_init_identity); -slim_hidden_proto (cairo_matrix_init_rotate); -slim_hidden_proto (cairo_matrix_init_scale); -slim_hidden_proto (cairo_matrix_init_translate); -slim_hidden_proto (cairo_matrix_invert); -slim_hidden_proto (cairo_matrix_multiply); -slim_hidden_proto (cairo_matrix_scale); -slim_hidden_proto (cairo_matrix_transform_distance); -slim_hidden_proto (cairo_matrix_transform_point); -slim_hidden_proto (cairo_matrix_translate); -slim_hidden_proto (cairo_move_to); -slim_hidden_proto (cairo_new_path); -slim_hidden_proto (cairo_paint); -slim_hidden_proto (cairo_path_extents); -slim_hidden_proto (cairo_pattern_create_for_surface); -slim_hidden_proto (cairo_pattern_create_rgb); -slim_hidden_proto (cairo_pattern_create_rgba); -slim_hidden_proto (cairo_pattern_destroy); -slim_hidden_proto (cairo_pattern_get_extend); -slim_hidden_proto (cairo_pattern_get_type); -slim_hidden_proto_no_warn (cairo_pattern_reference); -slim_hidden_proto (cairo_pattern_set_matrix); -slim_hidden_proto (cairo_pattern_status); -slim_hidden_proto (cairo_pop_group); -slim_hidden_proto (cairo_pop_group_to_source); -slim_hidden_proto (cairo_push_group); -slim_hidden_proto (cairo_push_group_with_content); -slim_hidden_proto (cairo_rel_line_to); -slim_hidden_proto (cairo_restore); -slim_hidden_proto (cairo_save); -slim_hidden_proto (cairo_scale); -slim_hidden_proto (cairo_scaled_font_create); -slim_hidden_proto (cairo_scaled_font_destroy); -slim_hidden_proto (cairo_scaled_font_extents); -slim_hidden_proto (cairo_scaled_font_get_ctm); -slim_hidden_proto (cairo_scaled_font_get_font_face); -slim_hidden_proto (cairo_scaled_font_get_font_matrix); -slim_hidden_proto (cairo_scaled_font_get_font_options); -slim_hidden_proto (cairo_scaled_font_text_to_glyphs); -slim_hidden_proto (cairo_scaled_font_glyph_extents); -slim_hidden_proto_no_warn (cairo_scaled_font_reference); -slim_hidden_proto (cairo_scaled_font_status); -slim_hidden_proto (cairo_set_font_size); -slim_hidden_proto (cairo_set_font_options); -slim_hidden_proto (cairo_set_line_cap); -slim_hidden_proto (cairo_set_line_join); -slim_hidden_proto (cairo_set_line_width); -slim_hidden_proto (cairo_set_matrix); -slim_hidden_proto (cairo_set_operator); -slim_hidden_proto (cairo_set_source); -slim_hidden_proto (cairo_set_source); -slim_hidden_proto (cairo_set_source_surface); -slim_hidden_proto (cairo_status); -slim_hidden_proto (cairo_stroke); -slim_hidden_proto (cairo_stroke_preserve); -slim_hidden_proto (cairo_surface_create_similar); -slim_hidden_proto (cairo_surface_destroy); -slim_hidden_proto (cairo_surface_finish); -slim_hidden_proto (cairo_surface_flush); -slim_hidden_proto (cairo_surface_get_content); -slim_hidden_proto (cairo_surface_get_device_offset); -slim_hidden_proto (cairo_surface_get_font_options); -slim_hidden_proto (cairo_surface_get_type); -slim_hidden_proto (cairo_surface_has_show_text_glyphs); -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_fallback_resolution); -slim_hidden_proto (cairo_surface_copy_page); -slim_hidden_proto (cairo_surface_show_page); -slim_hidden_proto (cairo_surface_status); -slim_hidden_proto (cairo_text_cluster_allocate); -slim_hidden_proto (cairo_text_cluster_free); -slim_hidden_proto (cairo_toy_font_face_create); -slim_hidden_proto (cairo_toy_font_face_get_slant); -slim_hidden_proto (cairo_toy_font_face_get_weight); -slim_hidden_proto (cairo_user_font_face_create); -slim_hidden_proto (cairo_user_font_face_set_init_func); -slim_hidden_proto (cairo_user_font_face_set_render_glyph_func); -slim_hidden_proto (cairo_user_font_face_set_unicode_to_glyph_func); -slim_hidden_proto (cairo_version_string); - -#if CAIRO_HAS_PNG_FUNCTIONS - -slim_hidden_proto (cairo_surface_write_to_png_stream); - -#endif - -CAIRO_END_DECLS - -#include "cairo-mutex-private.h" -#include "cairo-fixed-private.h" -#include "cairo-wideint-private.h" -#include "cairo-malloc-private.h" -#include "cairo-hash-private.h" - -#endif diff --git a/uppdev/plugin/cairo/lib/check-has-hidden-symbols.c b/uppdev/plugin/cairo/lib/check-has-hidden-symbols.c deleted file mode 100644 index 120412776..000000000 --- a/uppdev/plugin/cairo/lib/check-has-hidden-symbols.c +++ /dev/null @@ -1,3 +0,0 @@ -#include "cairoint.h" - -CAIRO_HAS_HIDDEN_SYMBOLS diff --git a/uppdev/plugin/cairo/lib/check-link.c b/uppdev/plugin/cairo/lib/check-link.c deleted file mode 100644 index 66ca1b241..000000000 --- a/uppdev/plugin/cairo/lib/check-link.c +++ /dev/null @@ -1,24 +0,0 @@ -#define CAIRO_VERSION_H 1 - -#include - -/* get the "real" version info instead of dummy cairo-version.h */ -#undef CAIRO_VERSION_H -#include "../cairo-version.h" - -#include - -int -main (void) -{ - printf ("Check linking to the just built cairo library\n"); - if (cairo_version () == CAIRO_VERSION) { - return 0; - } else { - fprintf (stderr, - "Error: linked to cairo version %s instead of %s\n", - cairo_version_string (), - CAIRO_VERSION_STRING); - return 1; - } -} diff --git a/uppdev/plugin/cairo/lib/test-fallback-surface.c b/uppdev/plugin/cairo/lib/test-fallback-surface.c deleted file mode 100644 index 883941df0..000000000 --- a/uppdev/plugin/cairo/lib/test-fallback-surface.c +++ /dev/null @@ -1,234 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Carl Worth - */ - -/* This isn't a "real" surface, but just something to be used by the - * test suite to test a mythical backend that uses nothing but - * fallbacks. - * - * The defining feature of this backend is that it has as many %NULL - * backend function entries as possible. The ones that aren't %NULL are - * simply those that must be implemented to have working fallbacks. - * (Except for create_similar---fallbacks would work fine without - * that---I implemented it here in order to create as many surfaces as - * possible of type test_fallback_surface_t during the test suite - * run). - * - * It's possible that this code might serve as a good starting point - * for someone working on bringing up a new backend, starting with the - * minimal all-fallbacks approach and working up gradually from - * there. - */ - -#include "cairoint.h" - -#include "test-fallback-surface.h" - -typedef struct _test_fallback_surface { - cairo_surface_t base; - - /* This is a cairo_image_surface to hold the actual contents. */ - cairo_surface_t *backing; -} test_fallback_surface_t; - -static const cairo_surface_backend_t test_fallback_surface_backend; - -slim_hidden_proto (_cairo_test_fallback_surface_create); - -cairo_surface_t * -_cairo_test_fallback_surface_create (cairo_content_t content, - int width, - int height) -{ - test_fallback_surface_t *surface; - cairo_surface_t *backing; - - backing = _cairo_image_surface_create_with_content (content, width, height); - if (cairo_surface_status (backing)) - return backing; - - surface = malloc (sizeof (test_fallback_surface_t)); - if (surface == NULL) { - cairo_surface_destroy (backing); - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - } - - _cairo_surface_init (&surface->base, &test_fallback_surface_backend, - content); - - surface->backing = backing; - - return &surface->base; -} -slim_hidden_def (_cairo_test_fallback_surface_create); - -static cairo_surface_t * -_test_fallback_surface_create_similar (void *abstract_surface, - cairo_content_t content, - int width, - int height) -{ - assert (CAIRO_CONTENT_VALID (content)); - - return _cairo_test_fallback_surface_create (content, - width, height); -} - -static cairo_status_t -_test_fallback_surface_finish (void *abstract_surface) -{ - test_fallback_surface_t *surface = abstract_surface; - - cairo_surface_destroy (surface->backing); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_test_fallback_surface_acquire_source_image (void *abstract_surface, - cairo_image_surface_t **image_out, - void **image_extra) -{ - test_fallback_surface_t *surface = abstract_surface; - - return _cairo_surface_acquire_source_image (surface->backing, - image_out, image_extra); -} - -static void -_test_fallback_surface_release_source_image (void *abstract_surface, - cairo_image_surface_t *image, - void *image_extra) -{ - test_fallback_surface_t *surface = abstract_surface; - - _cairo_surface_release_source_image (surface->backing, - image, image_extra); -} - -static cairo_status_t -_test_fallback_surface_acquire_dest_image (void *abstract_surface, - cairo_rectangle_int_t *interest_rect, - cairo_image_surface_t **image_out, - cairo_rectangle_int_t *image_rect_out, - void **image_extra) -{ - test_fallback_surface_t *surface = abstract_surface; - - return _cairo_surface_acquire_dest_image (surface->backing, - interest_rect, - image_out, - image_rect_out, - image_extra); -} - -static void -_test_fallback_surface_release_dest_image (void *abstract_surface, - cairo_rectangle_int_t *interest_rect, - cairo_image_surface_t *image, - cairo_rectangle_int_t *image_rect, - void *image_extra) -{ - test_fallback_surface_t *surface = abstract_surface; - - _cairo_surface_release_dest_image (surface->backing, - interest_rect, - image, - image_rect, - image_extra); -} - -static cairo_status_t -_test_fallback_surface_clone_similar (void *abstract_surface, - cairo_surface_t *src, - int src_x, - int src_y, - int width, - int height, - int *clone_offset_x, - int *clone_offset_y, - cairo_surface_t **clone_out) -{ - test_fallback_surface_t *surface = abstract_surface; - - if (src->backend == surface->base.backend) { - *clone_offset_x = 0; - *clone_offset_y = 0; - *clone_out = cairo_surface_reference (src); - - return CAIRO_STATUS_SUCCESS; - } - - return CAIRO_INT_STATUS_UNSUPPORTED; -} - -static cairo_int_status_t -_test_fallback_surface_get_extents (void *abstract_surface, - cairo_rectangle_int_t *rectangle) -{ - test_fallback_surface_t *surface = abstract_surface; - - return _cairo_surface_get_extents (surface->backing, rectangle); -} - -static const cairo_surface_backend_t test_fallback_surface_backend = { - CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK, - _test_fallback_surface_create_similar, - _test_fallback_surface_finish, - _test_fallback_surface_acquire_source_image, - _test_fallback_surface_release_source_image, - _test_fallback_surface_acquire_dest_image, - _test_fallback_surface_release_dest_image, - _test_fallback_surface_clone_similar, - NULL, /* composite */ - NULL, /* fill_rectangles */ - NULL, /* composite_trapezoids */ - NULL, /* copy_page */ - NULL, /* show_page */ - NULL, /* set_clip_region */ - NULL, /* intersect_clip_path */ - _test_fallback_surface_get_extents, - NULL, /* old_show_glyphs */ - NULL, /* get_font_options */ - NULL, /* flush */ - NULL, /* mark_dirty_rectangle */ - NULL, /* scaled_font_fini */ - NULL, /* scaled_glyph_fini */ - NULL, /* paint */ - NULL, /* mask */ - NULL, /* stroke */ - NULL, /* fill */ - NULL, /* show_glyphs */ - NULL /* snapshot */ -}; diff --git a/uppdev/plugin/cairo/lib/test-fallback-surface.h b/uppdev/plugin/cairo/lib/test-fallback-surface.h deleted file mode 100644 index 744b303a1..000000000 --- a/uppdev/plugin/cairo/lib/test-fallback-surface.h +++ /dev/null @@ -1,50 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Carl Worth - */ - -#ifndef TEST_FALLBACK_SURFACE_H -#define TEST_FALLBACK_SURFACE_H - -#include "cairo.h" - -CAIRO_BEGIN_DECLS - -cairo_surface_t * -_cairo_test_fallback_surface_create (cairo_content_t content, - int width, - int height); - -CAIRO_END_DECLS - -#endif /* TEST_FALLBACK_SURFACE_H */ diff --git a/uppdev/plugin/cairo/lib/test-meta-surface.c b/uppdev/plugin/cairo/lib/test-meta-surface.c deleted file mode 100644 index 6038430cf..000000000 --- a/uppdev/plugin/cairo/lib/test-meta-surface.c +++ /dev/null @@ -1,334 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Carl Worth - */ - -/* This isn't a "real" surface, but just something to be used by the - * test suite to help exercise the meta-surface paths in cairo. - * - * The defining feature of this backend is that it uses a meta surface - * to record all operations, and then replays everything to an image - * surface. - * - * It's possible that this code might serve as a good starting point - * for someone working on bringing up a new meta-surface-based - * backend. - */ - -#include "cairoint.h" - -#include "test-meta-surface.h" - -#include "cairo-meta-surface-private.h" - -typedef struct _test_meta_surface { - cairo_surface_t base; - - /* This is a cairo_meta_surface to record all operations. */ - cairo_surface_t *meta; - - /* And this is a cairo_image_surface to hold the final result. */ - cairo_surface_t *image; - - cairo_bool_t image_reflects_meta; -} test_meta_surface_t; - -static const cairo_surface_backend_t test_meta_surface_backend; - -static cairo_int_status_t -_test_meta_surface_show_page (void *abstract_surface); - -cairo_surface_t * -_cairo_test_meta_surface_create (cairo_content_t content, - int width, - int height) -{ - test_meta_surface_t *surface; - cairo_status_t status; - - surface = malloc (sizeof (test_meta_surface_t)); - if (surface == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto FAIL; - } - - _cairo_surface_init (&surface->base, &test_meta_surface_backend, - content); - - surface->meta = _cairo_meta_surface_create (content, width, height); - status = cairo_surface_status (surface->meta); - if (status) - goto FAIL_CLEANUP_SURFACE; - - surface->image = _cairo_image_surface_create_with_content (content, - width, height); - status = cairo_surface_status (surface->image); - if (status) - goto FAIL_CLEANUP_META; - - surface->image_reflects_meta = FALSE; - - return &surface->base; - - FAIL_CLEANUP_META: - cairo_surface_destroy (surface->meta); - FAIL_CLEANUP_SURFACE: - free (surface); - FAIL: - return _cairo_surface_create_in_error (status); -} - -static cairo_status_t -_test_meta_surface_finish (void *abstract_surface) -{ - test_meta_surface_t *surface = abstract_surface; - - cairo_surface_destroy (surface->meta); - cairo_surface_destroy (surface->image); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_test_meta_surface_acquire_source_image (void *abstract_surface, - cairo_image_surface_t **image_out, - void **image_extra) -{ - test_meta_surface_t *surface = abstract_surface; - cairo_status_t status; - - if (! surface->image_reflects_meta) { - status = _test_meta_surface_show_page (abstract_surface); - if (status) - return status; - } - - return _cairo_surface_acquire_source_image (surface->image, - image_out, image_extra); -} - -static void -_test_meta_surface_release_source_image (void *abstract_surface, - cairo_image_surface_t *image, - void *image_extra) -{ - test_meta_surface_t *surface = abstract_surface; - - _cairo_surface_release_source_image (surface->image, - image, image_extra); -} - -static cairo_int_status_t -_test_meta_surface_show_page (void *abstract_surface) -{ - test_meta_surface_t *surface = abstract_surface; - cairo_status_t status; - - if (surface->image_reflects_meta) - return CAIRO_STATUS_SUCCESS; - - status = _cairo_meta_surface_replay (surface->meta, surface->image); - if (status) - return status; - - surface->image_reflects_meta = TRUE; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_test_meta_surface_intersect_clip_path (void *abstract_surface, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias) -{ - test_meta_surface_t *surface = abstract_surface; - - return _cairo_surface_intersect_clip_path (surface->meta, - path, fill_rule, - tolerance, antialias); -} - -static cairo_int_status_t -_test_meta_surface_get_extents (void *abstract_surface, - cairo_rectangle_int_t *rectangle) -{ - test_meta_surface_t *surface = abstract_surface; - - surface->image_reflects_meta = FALSE; - - return _cairo_surface_get_extents (surface->image, rectangle); -} - -static cairo_int_status_t -_test_meta_surface_paint (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source) -{ - test_meta_surface_t *surface = abstract_surface; - - surface->image_reflects_meta = FALSE; - - return _cairo_surface_paint (surface->meta, op, source); -} - -static cairo_int_status_t -_test_meta_surface_mask (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_pattern_t *mask) -{ - test_meta_surface_t *surface = abstract_surface; - - surface->image_reflects_meta = FALSE; - - return _cairo_surface_mask (surface->meta, op, source, mask); -} - -static cairo_int_status_t -_test_meta_surface_stroke (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - 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) -{ - test_meta_surface_t *surface = abstract_surface; - - surface->image_reflects_meta = FALSE; - - return _cairo_surface_stroke (surface->meta, op, source, - path, style, - ctm, ctm_inverse, - tolerance, antialias); -} - -static cairo_int_status_t -_test_meta_surface_fill (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias) -{ - test_meta_surface_t *surface = abstract_surface; - - surface->image_reflects_meta = FALSE; - - return _cairo_surface_fill (surface->meta, op, source, - path, fill_rule, - tolerance, antialias); -} - -static cairo_bool_t -_test_meta_surface_has_show_text_glyphs (void *abstract_surface) -{ - test_meta_surface_t *surface = abstract_surface; - - return cairo_surface_has_show_text_glyphs (surface->meta); -} - -static cairo_int_status_t -_test_meta_surface_show_text_glyphs (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - const char *utf8, - int utf8_len, - cairo_glyph_t *glyphs, - int num_glyphs, - const cairo_text_cluster_t *clusters, - int num_clusters, - cairo_text_cluster_flags_t cluster_flags, - cairo_scaled_font_t *scaled_font) -{ - test_meta_surface_t *surface = abstract_surface; - - surface->image_reflects_meta = FALSE; - - return _cairo_surface_show_text_glyphs (surface->meta, op, source, - utf8, utf8_len, - glyphs, num_glyphs, - clusters, num_clusters, cluster_flags, - scaled_font); -} - - -static cairo_surface_t * -_test_meta_surface_snapshot (void *abstract_other) -{ - test_meta_surface_t *other = abstract_other; - - return _cairo_surface_snapshot (other->meta); -} - -static const cairo_surface_backend_t test_meta_surface_backend = { - CAIRO_INTERNAL_SURFACE_TYPE_TEST_META, - NULL, /* create_similar */ - _test_meta_surface_finish, - _test_meta_surface_acquire_source_image, - _test_meta_surface_release_source_image, - NULL, /* acquire_dest_image */ - NULL, /* release_dest_image */ - NULL, /* clone_similar */ - NULL, /* composite */ - NULL, /* fill_rectangles */ - NULL, /* composite_trapezoids */ - NULL, /* copy_page */ - _test_meta_surface_show_page, - NULL, /* set_clip_region */ - _test_meta_surface_intersect_clip_path, - _test_meta_surface_get_extents, - NULL, /* old_show_glyphs */ - NULL, /* get_font_options */ - NULL, /* flush */ - NULL, /* mark_dirty_rectangle */ - NULL, /* scaled_font_fini */ - NULL, /* scaled_glyph_fini */ - _test_meta_surface_paint, - _test_meta_surface_mask, - _test_meta_surface_stroke, - _test_meta_surface_fill, - NULL, /* show_glyphs */ - _test_meta_surface_snapshot, - NULL, /* is_similar */ - NULL, /* reset */ - NULL, /* fill_stroke */ - NULL, /* create_solid_pattern_surface */ - _test_meta_surface_has_show_text_glyphs, - _test_meta_surface_show_text_glyphs -}; diff --git a/uppdev/plugin/cairo/lib/test-meta-surface.h b/uppdev/plugin/cairo/lib/test-meta-surface.h deleted file mode 100644 index c036bb9c8..000000000 --- a/uppdev/plugin/cairo/lib/test-meta-surface.h +++ /dev/null @@ -1,50 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Carl Worth - */ - -#ifndef TEST_META_SURFACE_H -#define TEST_META_SURFACE_H - -#include "cairo.h" - -CAIRO_BEGIN_DECLS - -cairo_surface_t * -_cairo_test_meta_surface_create (cairo_content_t content, - int width, - int height); - -CAIRO_END_DECLS - -#endif /* TEST_META_SURFACE_H */ diff --git a/uppdev/plugin/cairo/lib/test-paginated-surface.c b/uppdev/plugin/cairo/lib/test-paginated-surface.c deleted file mode 100644 index 354f95d1a..000000000 --- a/uppdev/plugin/cairo/lib/test-paginated-surface.c +++ /dev/null @@ -1,330 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Carl Worth - */ - -/* This isn't a "real" surface, but just something to be used by the - * test suite to help exercise the paginated-surface paths in cairo. - * - * The defining feature of this backend is that it uses a paginated - * surface to record all operations, and then replays everything to an - * image surface. - * - * It's possible that this code might serve as a good starting point - * for someone working on bringing up a new paginated-surface-based - * backend. - */ - -#include "cairoint.h" - -#include "test-paginated-surface.h" - -#include "cairo-paginated-private.h" - -typedef struct _test_paginated_surface { - cairo_surface_t base; - cairo_surface_t *target; - cairo_paginated_mode_t paginated_mode; -} test_paginated_surface_t; - -static const cairo_surface_backend_t test_paginated_surface_backend; -static const cairo_paginated_surface_backend_t test_paginated_surface_paginated_backend; - -cairo_surface_t * -_cairo_test_paginated_surface_create_for_data (unsigned char *data, - cairo_content_t content, - int width, - int height, - int stride) -{ - cairo_status_t status; - cairo_surface_t *target; - cairo_surface_t *paginated; - test_paginated_surface_t *surface; - - target = _cairo_image_surface_create_for_data_with_content (data, content, - width, height, - stride); - status = cairo_surface_status (target); - if (status) - return target; - - surface = malloc (sizeof (test_paginated_surface_t)); - if (surface == NULL) { - cairo_surface_destroy (target); - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - } - - _cairo_surface_init (&surface->base, &test_paginated_surface_backend, - content); - - surface->target = target; - - paginated = _cairo_paginated_surface_create (&surface->base, - content, width, height, - &test_paginated_surface_paginated_backend); - status = paginated->status; - if (status == CAIRO_STATUS_SUCCESS) { - /* paginated keeps the only reference to surface now, drop ours */ - cairo_surface_destroy (&surface->base); - return paginated; - } - - cairo_surface_destroy (target); - free (surface); - return _cairo_surface_create_in_error (status); -} - -static cairo_status_t -_test_paginated_surface_finish (void *abstract_surface) -{ - test_paginated_surface_t *surface = abstract_surface; - - cairo_surface_destroy (surface->target); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_test_paginated_surface_set_clip_region (void *abstract_surface, - cairo_region_t *region) -{ - test_paginated_surface_t *surface = abstract_surface; - - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return CAIRO_STATUS_SUCCESS; - - /* XXX: The whole surface backend clipping interface is a giant - * disaster right now. In particular, its uncleanness shows up - * when trying to implement one surface that wraps another one (as - * we are doing here). - * - * Here are two of the problems that show up: - * - * 1. The most critical piece of information in all this stuff, - * the "clip" isn't getting passed to the backend - * functions. Instead the generic surface layer is caching that as - * surface->clip. This is a problem for surfaces like this one - * that do wrapping. Our base surface will have the clip set, but - * our target's surface will not. - * - * 2. We're here in our backend's set_clip_region function, and we - * want to call into our target surface's set_clip_region. - * Generally, we would do this by calling an equivalent - * _cairo_surface function, but _cairo_surface_set_clip_region - * does not have the same signature/semantics, (it has the - * clip_serial stuff as well). - * - * We kludge around each of these by manually copying the clip - * object from our base surface into the target's base surface - * (yuck!) and by reaching directly into the image surface's - * set_clip_region instead of calling into the generic - * _cairo_surface_set_clip_region (double yuck!). - */ - - surface->target->clip = surface->base.clip; - - return _cairo_image_surface_set_clip_region (surface->target, region); -} - -static cairo_int_status_t -_test_paginated_surface_get_extents (void *abstract_surface, - cairo_rectangle_int_t *rectangle) -{ - test_paginated_surface_t *surface = abstract_surface; - - return _cairo_surface_get_extents (surface->target, rectangle); -} - -static cairo_int_status_t -_test_paginated_surface_paint (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source) -{ - test_paginated_surface_t *surface = abstract_surface; - - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return CAIRO_STATUS_SUCCESS; - - return _cairo_surface_paint (surface->target, op, source); -} - -static cairo_int_status_t -_test_paginated_surface_mask (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_pattern_t *mask) -{ - test_paginated_surface_t *surface = abstract_surface; - - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return CAIRO_STATUS_SUCCESS; - - return _cairo_surface_mask (surface->target, op, source, mask); -} - -static cairo_int_status_t -_test_paginated_surface_stroke (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - 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) -{ - test_paginated_surface_t *surface = abstract_surface; - - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return CAIRO_STATUS_SUCCESS; - - return _cairo_surface_stroke (surface->target, op, source, - path, style, - ctm, ctm_inverse, - tolerance, antialias); -} - -static cairo_int_status_t -_test_paginated_surface_fill (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias) -{ - test_paginated_surface_t *surface = abstract_surface; - - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return CAIRO_STATUS_SUCCESS; - - return _cairo_surface_fill (surface->target, op, source, - path, fill_rule, - tolerance, antialias); -} - -static cairo_bool_t -_test_paginated_surface_has_show_text_glyphs (void *abstract_surface) -{ - test_paginated_surface_t *surface = abstract_surface; - - return cairo_surface_has_show_text_glyphs (surface->target); -} - -static cairo_int_status_t -_test_paginated_surface_show_text_glyphs (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - const char *utf8, - int utf8_len, - cairo_glyph_t *glyphs, - int num_glyphs, - const cairo_text_cluster_t *clusters, - int num_clusters, - cairo_text_cluster_flags_t cluster_flags, - cairo_scaled_font_t *scaled_font) -{ - test_paginated_surface_t *surface = abstract_surface; - - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return CAIRO_STATUS_SUCCESS; - - return _cairo_surface_show_text_glyphs (surface->target, op, source, - utf8, utf8_len, - glyphs, num_glyphs, - clusters, num_clusters, cluster_flags, - scaled_font); -} - - -static void -_test_paginated_surface_set_paginated_mode (void *abstract_surface, - cairo_paginated_mode_t mode) -{ - test_paginated_surface_t *surface = abstract_surface; - - surface->paginated_mode = mode; -} - -static const cairo_surface_backend_t test_paginated_surface_backend = { - CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED, - - /* Since we are a paginated user, we get to regard most of the - * surface backend interface as historical cruft and ignore it. */ - - NULL, /* create_similar */ - _test_paginated_surface_finish, - NULL, /* acquire_source_image */ - NULL, /* release_source_image */ - NULL, /* acquire_dest_image */ - NULL, /* release_dest_image */ - NULL, /* clone_similar */ - NULL, /* composite */ - NULL, /* fill_rectangles */ - NULL, /* composite_trapezoids */ - NULL, /* copy_page */ - NULL, /* show_page */ - _test_paginated_surface_set_clip_region, - NULL, /* intersect_clip_path */ - _test_paginated_surface_get_extents, - NULL, /* old_show_glyphs */ - NULL, /* get_font_options */ - NULL, /* flush */ - NULL, /* mark_dirty_rectangle */ - NULL, /* scaled_font_fini */ - NULL, /* scaled_glyph_fini */ - - /* Here is the more "modern" section of the surface backend - * interface which is mostly just drawing functions */ - - _test_paginated_surface_paint, - _test_paginated_surface_mask, - _test_paginated_surface_stroke, - _test_paginated_surface_fill, - NULL, /* show_glyphs */ - - NULL, /* snapshot */ - NULL, /* is_similar */ - NULL, /* reset */ - NULL, /* fill_stroke */ - NULL, /* create_solid_pattern_surface */ - - _test_paginated_surface_has_show_text_glyphs, - _test_paginated_surface_show_text_glyphs -}; - -static const cairo_paginated_surface_backend_t test_paginated_surface_paginated_backend = { - NULL, /* start_page */ - _test_paginated_surface_set_paginated_mode -}; diff --git a/uppdev/plugin/cairo/lib/test-paginated-surface.h b/uppdev/plugin/cairo/lib/test-paginated-surface.h deleted file mode 100644 index 4879cfcd1..000000000 --- a/uppdev/plugin/cairo/lib/test-paginated-surface.h +++ /dev/null @@ -1,52 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Carl Worth - */ - -#ifndef TEST_PAGINATED_SURFACE_H -#define TEST_PAGINATED_SURFACE_H - -#include "cairo.h" - -CAIRO_BEGIN_DECLS - -cairo_surface_t * -_cairo_test_paginated_surface_create_for_data (unsigned char *data, - cairo_content_t content, - int width, - int height, - int stride); - -CAIRO_END_DECLS - -#endif /* TEST_PAGINATED_SURFACE_H */ diff --git a/uppdev/plugin/libfetch/Makefile b/uppdev/plugin/libfetch/Makefile deleted file mode 100644 index 83ac3ea01..000000000 --- a/uppdev/plugin/libfetch/Makefile +++ /dev/null @@ -1,75 +0,0 @@ -# $FreeBSD: src/lib/libfetch/Makefile,v 1.42 2003/07/22 13:54:31 ru Exp $ - -LIB= fetch -CFLAGS+= -I. -CFLAGS+= -DINET6 -SRCS= fetch.c common.c ftp.c http.c file.c \ - ftperr.h httperr.h -INCS= fetch.h -MAN= fetch.3 -CLEANFILES= ftperr.h httperr.h - -.if !defined(NOCRYPT) && !defined(NO_OPENSSL) -DISTRIBUTION= crypto -CFLAGS+= -DWITH_SSL -DPADD= ${LIBSSL} ${LIBCRYPTO} -LDADD= -lssl -lcrypto -.endif - -CSTD?= c99 -WARNS?= 2 - -SHLIB_MAJOR= 3 - -ftperr.h: ftp.errors - @echo "static struct fetcherr _ftp_errlist[] = {" > ${.TARGET} - @cat ${.ALLSRC} \ - | grep -v ^# \ - | sort \ - | while read NUM CAT STRING; do \ - echo " { $${NUM}, FETCH_$${CAT}, \"$${STRING}\" },"; \ - done >> ${.TARGET} - @echo " { -1, FETCH_UNKNOWN, \"Unknown FTP error\" }" >> ${.TARGET} - @echo "};" >> ${.TARGET} - -httperr.h: http.errors - @echo "static struct fetcherr _http_errlist[] = {" > ${.TARGET} - @cat ${.ALLSRC} \ - | grep -v ^# \ - | sort \ - | while read NUM CAT STRING; do \ - echo " { $${NUM}, FETCH_$${CAT}, \"$${STRING}\" },"; \ - done >> ${.TARGET} - @echo " { -1, FETCH_UNKNOWN, \"Unknown HTTP error\" }" >> ${.TARGET} - @echo "};" >> ${.TARGET} - -MLINKS+= fetch.3 fetchFreeURL.3 -MLINKS+= fetch.3 fetchGet.3 -MLINKS+= fetch.3 fetchGetFTP.3 -MLINKS+= fetch.3 fetchGetFile.3 -MLINKS+= fetch.3 fetchGetHTTP.3 -MLINKS+= fetch.3 fetchGetURL.3 -MLINKS+= fetch.3 fetchList.3 -MLINKS+= fetch.3 fetchListFTP.3 -MLINKS+= fetch.3 fetchListFile.3 -MLINKS+= fetch.3 fetchListHTTP.3 -MLINKS+= fetch.3 fetchListURL.3 -MLINKS+= fetch.3 fetchMakeURL.3 -MLINKS+= fetch.3 fetchParseURL.3 -MLINKS+= fetch.3 fetchPut.3 -MLINKS+= fetch.3 fetchPutFTP.3 -MLINKS+= fetch.3 fetchPutFile.3 -MLINKS+= fetch.3 fetchPutHTTP.3 -MLINKS+= fetch.3 fetchPutURL.3 -MLINKS+= fetch.3 fetchStat.3 -MLINKS+= fetch.3 fetchStatFTP.3 -MLINKS+= fetch.3 fetchStatFile.3 -MLINKS+= fetch.3 fetchStatHTTP.3 -MLINKS+= fetch.3 fetchStatURL.3 -MLINKS+= fetch.3 fetchXGet.3 -MLINKS+= fetch.3 fetchXGetFTP.3 -MLINKS+= fetch.3 fetchXGetFile.3 -MLINKS+= fetch.3 fetchXGetHTTP.3 -MLINKS+= fetch.3 fetchXGetURL.3 - -.include diff --git a/uppdev/plugin/libfetch/fetch.3 b/uppdev/plugin/libfetch/fetch.3 deleted file mode 100644 index 7665f9eef..000000000 --- a/uppdev/plugin/libfetch/fetch.3 +++ /dev/null @@ -1,667 +0,0 @@ -.\" Copyright (c) 1998 Dag-Erling Coïdan Smørgrav -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" $FreeBSD: src/lib/libfetch/fetch.3,v 1.56 2004/01/25 11:39:41 des Exp $ -.\" -.Dd July 1, 1998 -.Dt FETCH 3 -.Os -.Sh NAME -.Nm fetchMakeURL , -.Nm fetchParseURL , -.Nm fetchFreeURL , -.Nm fetchXGetURL , -.Nm fetchGetURL , -.Nm fetchPutURL , -.Nm fetchStatURL , -.Nm fetchListURL , -.Nm fetchXGet , -.Nm fetchGet , -.Nm fetchPut , -.Nm fetchStat , -.Nm fetchList , -.Nm fetchXGetFile , -.Nm fetchGetFile , -.Nm fetchPutFile , -.Nm fetchStatFile , -.Nm fetchListFile , -.Nm fetchXGetHTTP , -.Nm fetchGetHTTP , -.Nm fetchPutHTTP , -.Nm fetchStatHTTP , -.Nm fetchListHTTP , -.Nm fetchXGetFTP , -.Nm fetchGetFTP , -.Nm fetchPutFTP , -.Nm fetchStatFTP , -.Nm fetchListFTP -.Nd file transfer functions -.Sh LIBRARY -.Lb libfetch -.Sh SYNOPSIS -.In sys/param.h -.In stdio.h -.In fetch.h -.Ft struct url * -.Fn fetchMakeURL "const char *scheme" "const char *host" "int port" "const char *doc" "const char *user" "const char *pwd" -.Ft struct url * -.Fn fetchParseURL "const char *URL" -.Ft void -.Fn fetchFreeURL "struct url *u" -.Ft FILE * -.Fn fetchXGetURL "const char *URL" "struct url_stat *us" "const char *flags" -.Ft FILE * -.Fn fetchGetURL "const char *URL" "const char *flags" -.Ft FILE * -.Fn fetchPutURL "const char *URL" "const char *flags" -.Ft int -.Fn fetchStatURL "const char *URL" "struct url_stat *us" "const char *flags" -.Ft struct url_ent * -.Fn fetchListURL "const char *URL" "const char *flags" -.Ft FILE * -.Fn fetchXGet "struct url *u" "struct url_stat *us" "const char *flags" -.Ft FILE * -.Fn fetchGet "struct url *u" "const char *flags" -.Ft FILE * -.Fn fetchPut "struct url *u" "const char *flags" -.Ft int -.Fn fetchStat "struct url *u" "struct url_stat *us" "const char *flags" -.Ft struct url_ent * -.Fn fetchList "struct url *u" "const char *flags" -.Ft FILE * -.Fn fetchXGetFile "struct url *u" "struct url_stat *us" "const char *flags" -.Ft FILE * -.Fn fetchGetFile "struct url *u" "const char *flags" -.Ft FILE * -.Fn fetchPutFile "struct url *u" "const char *flags" -.Ft int -.Fn fetchStatFile "struct url *u" "struct url_stat *us" "const char *flags" -.Ft struct url_ent * -.Fn fetchListFile "struct url *u" "const char *flags" -.Ft FILE * -.Fn fetchXGetHTTP "struct url *u" "struct url_stat *us" "const char *flags" -.Ft FILE * -.Fn fetchGetHTTP "struct url *u" "const char *flags" -.Ft FILE * -.Fn fetchPutHTTP "struct url *u" "const char *flags" -.Ft int -.Fn fetchStatHTTP "struct url *u" "struct url_stat *us" "const char *flags" -.Ft struct url_ent * -.Fn fetchListHTTP "struct url *u" "const char *flags" -.Ft FILE * -.Fn fetchXGetFTP "struct url *u" "struct url_stat *us" "const char *flags" -.Ft FILE * -.Fn fetchGetFTP "struct url *u" "const char *flags" -.Ft FILE * -.Fn fetchPutFTP "struct url *u" "const char *flags" -.Ft int -.Fn fetchStatFTP "struct url *u" "struct url_stat *us" "const char *flags" -.Ft struct url_ent * -.Fn fetchListFTP "struct url *u" "const char *flags" -.Sh DESCRIPTION -These functions implement a high-level library for retrieving and -uploading files using Uniform Resource Locators (URLs). -.Pp -.Fn fetchParseURL -takes a URL in the form of a null-terminated string and splits it into -its components function according to the Common Internet Scheme Syntax -detailed in RFC1738. -A regular expression which produces this syntax is: -.Bd -literal - :(//((:)?@)?(:)?)?/()? -.Ed -.Pp -If the URL does not seem to begin with a scheme name, the following -syntax is assumed: -.Bd -literal - (((:)?@)?(:)?)?/()? -.Ed -.Pp -Note that some components of the URL are not necessarily relevant to -all URL schemes. -For instance, the file scheme only needs the and -components. -.Pp -.Fn fetchMakeURL -and -.Fn fetchParseURL -return a pointer to a -.Vt url -structure, which is defined as follows in -.In fetch.h : -.Bd -literal -#define URL_SCHEMELEN 16 -#define URL_USERLEN 256 -#define URL_PWDLEN 256 - -struct url { - char scheme[URL_SCHEMELEN+1]; - char user[URL_USERLEN+1]; - char pwd[URL_PWDLEN+1]; - char host[MAXHOSTNAMELEN+1]; - int port; - char *doc; - off_t offset; - size_t length; -}; -.Ed -.Pp -The pointer returned by -.Fn fetchMakeURL -or -.Fn fetchParseURL -should be freed using -.Fn fetchFreeURL . -.Pp -.Fn fetchXGetURL , -.Fn fetchGetURL , -and -.Fn fetchPutURL -constitute the recommended interface to the -.Nm fetch -library. -They examine the URL passed to them to determine the transfer -method, and call the appropriate lower-level functions to perform the -actual transfer. -.Fn fetchXGetURL -also returns the remote document's metadata in the -.Vt url_stat -structure pointed to by the -.Fa us -argument. -.Pp -The -.Fa flags -argument is a string of characters which specify transfer options. -The -meaning of the individual flags is scheme-dependent, and is detailed -in the appropriate section below. -.Pp -.Fn fetchStatURL -attempts to obtain the requested document's metadata and fill in the -structure pointed to by its second argument. -The -.Vt url_stat -structure is defined as follows in -.In fetch.h : -.Bd -literal -struct url_stat { - off_t size; - time_t atime; - time_t mtime; -}; -.Ed -.Pp -If the size could not be obtained from the server, the -.Fa size -field is set to -1. -If the modification time could not be obtained from the server, the -.Fa mtime -field is set to the epoch. -If the access time could not be obtained from the server, the -.Fa atime -field is set to the modification time. -.Pp -.Fn fetchListURL -attempts to list the contents of the directory pointed to by the URL -provided. -If successful, it returns a malloced array of -.Vt url_ent -structures. -The -.Vt url_ent -structure is defined as follows in -.In fetch.h : -.Bd -literal -struct url_ent { - char name[MAXPATHLEN]; - struct url_stat stat; -}; -.Ed -.Pp -The list is terminated by an entry with an empty name. -.Pp -The pointer returned by -.Fn fetchListURL -should be freed using -.Fn free . -.Pp -.Fn fetchXGet , -.Fn fetchGet , -.Fn fetchPut -and -.Fn fetchStat -are similar to -.Fn fetchXGetURL , -.Fn fetchGetURL , -.Fn fetchPutURL -and -.Fn fetchStatURL , -except that they expect a pre-parsed URL in the form of a pointer to -a -.Vt struct url -rather than a string. -.Pp -All of the -.Fn fetchXGetXXX , -.Fn fetchGetXXX -and -.Fn fetchPutXXX -functions return a pointer to a stream which can be used to read or -write data from or to the requested document, respectively. -Note that -although the implementation details of the individual access methods -vary, it can generally be assumed that a stream returned by one of the -.Fn fetchXGetXXX -or -.Fn fetchGetXXX -functions is read-only, and that a stream returned by one of the -.Fn fetchPutXXX -functions is write-only. -.Sh FILE SCHEME -.Fn fetchXGetFile , -.Fn fetchGetFile -and -.Fn fetchPutFile -provide access to documents which are files in a locally mounted file -system. -Only the component of the URL is used. -.Pp -.Fn fetchXGetFile -and -.Fn fetchGetFile -do not accept any flags. -.Pp -.Fn fetchPutFile -accepts the -.Ql a -(append to file) flag. -If that flag is specified, the data written to -the stream returned by -.Fn fetchPutFile -will be appended to the previous contents of the file, instead of -replacing them. -.Sh FTP SCHEME -.Fn fetchXGetFTP , -.Fn fetchGetFTP -and -.Fn fetchPutFTP -implement the FTP protocol as described in RFC959. -.Pp -If the -.Ql p -(passive) flag is specified, a passive (rather than active) connection -will be attempted. -.Pp -If the -.Ql l -(low) flag is specified, data sockets will be allocated in the low (or -default) port range instead of the high port range (see -.Xr ip 4 ) . -.Pp -If the -.Ql d -(direct) flag is specified, -.Fn fetchXGetFTP , -.Fn fetchGetFTP -and -.Fn fetchPutFTP -will use a direct connection even if a proxy server is defined. -.Pp -If no user name or password is given, the -.Nm fetch -library will attempt an anonymous login, with user name "anonymous" -and password "anonymous@". -.Sh HTTP SCHEME -The -.Fn fetchXGetHTTP , -.Fn fetchGetHTTP -and -.Fn fetchPutHTTP -functions implement the HTTP/1.1 protocol. -With a little luck, there's -even a chance that they comply with RFC2616 and RFC2617. -.Pp -If the -.Ql d -(direct) flag is specified, -.Fn fetchXGetHTTP , -.Fn fetchGetHTTP -and -.Fn fetchPutHTTP -will use a direct connection even if a proxy server is defined. -.Pp -Since there seems to be no good way of implementing the HTTP PUT -method in a manner consistent with the rest of the -.Nm fetch -library, -.Fn fetchPutHTTP -is currently unimplemented. -.Sh AUTHENTICATION -Apart from setting the appropriate environment variables and -specifying the user name and password in the URL or the -.Vt struct url , -the calling program has the option of defining an authentication -function with the following prototype: -.Pp -.Ft int -.Fn myAuthMethod "struct url *u" -.Pp -The callback function should fill in the -.Fa user -and -.Fa pwd -fields in the provided -.Vt struct url -and return 0 on success, or any other value to indicate failure. -.Pp -To register the authentication callback, simply set -.Va fetchAuthMethod -to point at it. -The callback will be used whenever a site requires authentication and -the appropriate environment variables aren't set. -.Pp -This interface is experimental and may be subject to change. -.Sh RETURN VALUES -.Fn fetchParseURL -returns a pointer to a -.Vt struct url -containing the individual components of the URL. -If it is -unable to allocate memory, or the URL is syntactically incorrect, -.Fn fetchParseURL -returns a NULL pointer. -.Pp -The -.Fn fetchStat -functions return 0 on success and -1 on failure. -.Pp -All other functions return a stream pointer which may be used to -access the requested document, or NULL if an error occurred. -.Pp -The following error codes are defined in -.In fetch.h : -.Bl -tag -width 18n -.It Bq Er FETCH_ABORT -Operation aborted -.It Bq Er FETCH_AUTH -Authentication failed -.It Bq Er FETCH_DOWN -Service unavailable -.It Bq Er FETCH_EXISTS -File exists -.It Bq Er FETCH_FULL -File system full -.It Bq Er FETCH_INFO -Informational response -.It Bq Er FETCH_MEMORY -Insufficient memory -.It Bq Er FETCH_MOVED -File has moved -.It Bq Er FETCH_NETWORK -Network error -.It Bq Er FETCH_OK -No error -.It Bq Er FETCH_PROTO -Protocol error -.It Bq Er FETCH_RESOLV -Resolver error -.It Bq Er FETCH_SERVER -Server error -.It Bq Er FETCH_TEMP -Temporary error -.It Bq Er FETCH_TIMEOUT -Operation timed out -.It Bq Er FETCH_UNAVAIL -File is not available -.It Bq Er FETCH_UNKNOWN -Unknown error -.It Bq Er FETCH_URL -Invalid URL -.El -.Pp -The accompanying error message includes a protocol-specific error code -and message, e.g. "File is not available (404 Not Found)" -.Sh ENVIRONMENT -.Bl -tag -width ".Ev FETCH_BIND_ADDRESS" -.It Ev FETCH_BIND_ADDRESS -Specifies a hostname or IP address to which sockets used for outgoing -connections will be bound. -.It Ev FTP_LOGIN -Default FTP login if none was provided in the URL. -.It Ev FTP_PASSIVE_MODE -If set to anything but -.Ql no , -forces the FTP code to use passive mode. -.It Ev FTP_PASSWORD -Default FTP password if the remote server requests one and none was -provided in the URL. -.It Ev FTP_PROXY -URL of the proxy to use for FTP requests. -The document part is ignored. -FTP and HTTP proxies are supported; if no scheme is specified, FTP is -assumed. -If the proxy is an FTP proxy, -.Nm libfetch -will send -.Ql user@host -as user name to the proxy, where -.Ql user -is the real user name, and -.Ql host -is the name of the FTP server. -.Pp -If this variable is set to an empty string, no proxy will be used for -FTP requests, even if the -.Ev HTTP_PROXY -variable is set. -.It Ev ftp_proxy -Same as -.Ev FTP_PROXY , -for compatibility. -.It Ev HTTP_AUTH -Specifies HTTP authorization parameters as a colon-separated list of -items. -The first and second item are the authorization scheme and realm -respectively; further items are scheme-dependent. -Currently, only basic authorization is supported. -.Pp -Basic authorization requires two parameters: the user name and -password, in that order. -.Pp -This variable is only used if the server requires authorization and -no user name or password was specified in the URL. -.It Ev HTTP_PROXY -URL of the proxy to use for HTTP requests. -The document part is ignored. -Only HTTP proxies are supported for HTTP requests. -If no port number is specified, the default is 3128. -.Pp -Note that this proxy will also be used for FTP documents, unless the -.Ev FTP_PROXY -variable is set. -.It Ev http_proxy -Same as -.Ev HTTP_PROXY , -for compatibility. -.It Ev HTTP_PROXY_AUTH -Specifies authorization parameters for the HTTP proxy in the same -format as the -.Ev HTTP_AUTH -variable. -.Pp -This variable is used if and only if connected to an HTTP proxy, and -is ignored if a user and/or a password were specified in the proxy -URL. -.It Ev HTTP_REFERER -Specifies the referrer URL to use for HTTP requests. -If set to -.Dq auto , -the document URL will be used as referrer URL. -.It Ev HTTP_USER_AGENT -Specifies the User-Agent string to use for HTTP requests. -This can be useful when working with HTTP origin or proxy servers that -differentiate between user agents. -.It Ev NETRC -Specifies a file to use instead of -.Pa ~/.netrc -to look up login names and passwords for FTP sites. -See -.Xr ftp 1 -for a description of the file format. -This feature is experimental. -.El -.Sh EXAMPLES -To access a proxy server on -.Pa proxy.example.com -port 8080, set the -.Ev HTTP_PROXY -environment variable in a manner similar to this: -.Pp -.Dl HTTP_PROXY=http://proxy.example.com:8080 -.Pp -If the proxy server requires authentication, there are -two options available for passing the authentication data. -The first method is by using the proxy URL: -.Pp -.Dl HTTP_PROXY=http://:@proxy.example.com:8080 -.Pp -The second method is by using the -.Ev HTTP_PROXY_AUTH -environment variable: -.Bd -literal -offset indent -HTTP_PROXY=http://proxy.example.com:8080 -HTTP_PROXY_AUTH=basic:*:: -.Ed -.Sh SEE ALSO -.Xr fetch 1 , -.Xr ftpio 3 , -.Xr ip 4 -.Rs -.%A J. Postel -.%A J. K. Reynolds -.%D October 1985 -.%B File Transfer Protocol -.%O RFC959 -.Re -.Rs -.%A P. Deutsch -.%A A. Emtage -.%A A. Marine. -.%D May 1994 -.%T How to Use Anonymous FTP -.%O RFC1635 -.Re -.Rs -.%A T. Berners-Lee -.%A L. Masinter -.%A M. McCahill -.%D December 1994 -.%T Uniform Resource Locators (URL) -.%O RFC1738 -.Re -.Rs -.%A R. Fielding -.%A J. Gettys -.%A J. Mogul -.%A H. Frystyk -.%A L. Masinter -.%A P. Leach -.%A T. Berners-Lee -.%D January 1999 -.%B Hypertext Transfer Protocol -- HTTP/1.1 -.%O RFC2616 -.Re -.Rs -.%A J. Franks -.%A P. Hallam-Baker -.%A J. Hostetler -.%A S. Lawrence -.%A P. Leach -.%A A. Luotonen -.%A L. Stewart -.%D June 1999 -.%B HTTP Authentication: Basic and Digest Access Authentication -.%O RFC2617 -.Re -.Sh HISTORY -The -.Nm fetch -library first appeared in -.Fx 3.0 . -.Sh AUTHORS -.An -nosplit -The -.Nm fetch -library was mostly written by -.An Dag-Erling Sm\(/orgrav Aq des@FreeBSD.org -with numerous suggestions from -.An Jordan K. Hubbard Aq jkh@FreeBSD.org , -.An Eugene Skepner Aq eu@qub.com -and other -.Fx -developers. -It replaces the older -.Nm ftpio -library written by -.An Poul-Henning Kamp Aq pkh@FreeBSD.org -and -.An Jordan K. Hubbard Aq jkh@FreeBSD.org . -.Pp -This manual page was written by -.An Dag-Erling Sm\(/orgrav Aq des@FreeBSD.org . -.Sh BUGS -Some parts of the library are not yet implemented. -The most notable -examples of this are -.Fn fetchPutHTTP , -.Fn fetchListHTTP , -.Fn fetchListFTP -and FTP proxy support. -.Pp -There's no way to select a proxy at run-time other than setting the -.Ev HTTP_PROXY -or -.Ev FTP_PROXY -environment variables as appropriate. -.Pp -.Nm libfetch -does not understand or obey 305 (Use Proxy) replies. -.Pp -Error numbers are unique only within a certain context; the error -codes used for FTP and HTTP overlap, as do those used for resolver and -system errors. -For instance, error code 202 means "Command not -implemented, superfluous at this site" in an FTP context and -"Accepted" in an HTTP context. -.Pp -.Fn fetchStatFTP -does not check that the result of an MDTM command is a valid date. -.Pp -The man page is incomplete, poorly written and produces badly -formatted text. -.Pp -The error reporting mechanism is unsatisfactory. -.Pp -Some parts of the code are not fully reentrant. diff --git a/uppdev/plugin/libfetch/ftp.errors b/uppdev/plugin/libfetch/ftp.errors deleted file mode 100644 index c75a01241..000000000 --- a/uppdev/plugin/libfetch/ftp.errors +++ /dev/null @@ -1,47 +0,0 @@ -# $FreeBSD: src/lib/libfetch/ftp.errors,v 1.6 2002/10/30 06:06:16 des Exp $ -# -# This list is taken from RFC 959. -# It probably needs a going over. -# -110 OK Restart marker reply -120 TEMP Service ready in a few minutes -125 OK Data connection already open; transfer starting -150 OK File status okay; about to open data connection -200 OK Command okay -202 PROTO Command not implemented, superfluous at this site -211 INFO System status, or system help reply -212 INFO Directory status -213 INFO File status -214 INFO Help message -215 INFO Set system type -220 OK Service ready for new user -221 OK Service closing control connection -225 OK Data connection open; no transfer in progress -226 OK Requested file action successful -227 OK Entering Passive Mode -229 OK Entering Extended Passive Mode -230 OK User logged in, proceed -250 OK Requested file action okay, completed -257 OK File/directory created -331 AUTH User name okay, need password -332 AUTH Need account for login -350 OK Requested file action pending further information -421 DOWN Service not available, closing control connection -425 NETWORK Can't open data connection -426 ABORT Connection closed; transfer aborted -450 UNAVAIL File unavailable (e.g., file busy) -451 SERVER Requested action aborted: local error in processing -452 FULL Insufficient storage space in system -500 PROTO Syntax error, command unrecognized -501 PROTO Syntax error in parameters or arguments -502 PROTO Command not implemented -503 PROTO Bad sequence of commands -504 PROTO Command not implemented for that parameter -530 AUTH Not logged in -532 AUTH Need account for storing files -535 PROTO Bug in MediaHawk Video Kernel FTP server -550 UNAVAIL File unavailable (e.g., file not found, no access) -551 PROTO Requested action aborted. Page type unknown -552 FULL Exceeded storage allocation -553 EXISTS File name not allowed -999 PROTO Protocol error diff --git a/uppdev/plugin/libfetch/http.errors b/uppdev/plugin/libfetch/http.errors deleted file mode 100644 index bf2a9f7cd..000000000 --- a/uppdev/plugin/libfetch/http.errors +++ /dev/null @@ -1,45 +0,0 @@ -# $FreeBSD: src/lib/libfetch/http.errors,v 1.5 2001/05/23 18:52:02 des Exp $ -# -# This list is taken from RFC 2068. -# -100 OK Continue -101 OK Switching Protocols -200 OK OK -201 OK Created -202 OK Accepted -203 INFO Non-Authoritative Information -204 OK No Content -205 OK Reset Content -206 OK Partial Content -300 MOVED Multiple Choices -301 MOVED Moved Permanently -302 MOVED Moved Temporarily -303 MOVED See Other -304 OK Not Modified -305 INFO Use Proxy -307 MOVED Temporary Redirect -400 PROTO Bad Request -401 AUTH Unauthorized -402 AUTH Payment Required -403 AUTH Forbidden -404 UNAVAIL Not Found -405 PROTO Method Not Allowed -406 PROTO Not Acceptable -407 AUTH Proxy Authentication Required -408 TIMEOUT Request Time-out -409 EXISTS Conflict -410 UNAVAIL Gone -411 PROTO Length Required -412 SERVER Precondition Failed -413 PROTO Request Entity Too Large -414 PROTO Request-URI Too Large -415 PROTO Unsupported Media Type -416 UNAVAIL Requested Range Not Satisfiable -417 SERVER Expectation Failed -500 SERVER Internal Server Error -501 PROTO Not Implemented -502 SERVER Bad Gateway -503 TEMP Service Unavailable -504 TIMEOUT Gateway Time-out -505 PROTO HTTP Version not supported -999 PROTO Protocol error diff --git a/uppdev/plugin/libfetch/lib/common.c b/uppdev/plugin/libfetch/lib/common.c deleted file mode 100644 index 50e36022d..000000000 --- a/uppdev/plugin/libfetch/lib/common.c +++ /dev/null @@ -1,784 +0,0 @@ -/*- - * Copyright (c) 1998 Dag-Erling Coïdan Smørgrav - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#if defined(flagWIN32) -#include -#include -#include -#include -#include -#else -#include -__FBSDID("$FreeBSD: src/lib/libfetch/common.c,v 1.48 2003/10/23 13:50:01 ume Exp $"); - -#include -#include -#include -#include -#include -#endif - -#include -#if !defined(flagWIN32) -#include -#include -#endif -#include -#include -#include -#include -#if !defined(flagWIN32) -#include -#endif - -#include "fetch.h" -#include "common.h" - - -/*** Local data **************************************************************/ - -/* - * Error messages for resolver errors - */ -static struct fetcherr _netdb_errlist[] = { -#ifdef EAI_NODATA - { EAI_NODATA, FETCH_RESOLV, "Host not found" }, -#endif - { EAI_AGAIN, FETCH_TEMP, "Transient resolver failure" }, - { EAI_FAIL, FETCH_RESOLV, "Non-recoverable resolver failure" }, - { EAI_NONAME, FETCH_RESOLV, "No address record" }, - { -1, FETCH_UNKNOWN, "Unknown resolver error" } -}; - -/* End-of-Line */ -static const char ENDL[2] = "\r\n"; - - -/*** Error-reporting functions ***********************************************/ - -/* - * Map error code to string - */ -static struct fetcherr * -_fetch_finderr(struct fetcherr *p, int e) -{ - while (p->num != -1 && p->num != e) - p++; - return (p); -} - -/* - * Set error code - */ -void -_fetch_seterr(struct fetcherr *p, int e) -{ - p = _fetch_finderr(p, e); - fetchLastErrCode = p->cat; - snprintf(fetchLastErrString, MAXERRSTRING, "%s", p->string); -} - -/* - * Set error code according to errno - */ -void -_fetch_syserr(void) -{ - switch (errno) { - case 0: - fetchLastErrCode = FETCH_OK; - break; - case EPERM: - case WSA(EACCES): - case EROFS: -#ifndef flagWIN32 - case EAUTH: - case ENEEDAUTH: -#endif - fetchLastErrCode = FETCH_AUTH; - break; - case ENOENT: - case EISDIR: /* XXX */ - fetchLastErrCode = FETCH_UNAVAIL; - break; - case ENOMEM: - fetchLastErrCode = FETCH_MEMORY; - break; - case EBUSY: - case EAGAIN: - fetchLastErrCode = FETCH_TEMP; - break; - case EEXIST: - fetchLastErrCode = FETCH_EXISTS; - break; - case ENOSPC: - fetchLastErrCode = FETCH_FULL; - break; - case WSA(EADDRINUSE): - case WSA(EADDRNOTAVAIL): - case WSA(ENETDOWN): - case WSA(ENETUNREACH): - case WSA(ENETRESET): - case WSA(EHOSTUNREACH): - fetchLastErrCode = FETCH_NETWORK; - break; - case WSA(ECONNABORTED): - case WSA(ECONNRESET): - fetchLastErrCode = FETCH_ABORT; - break; - case WSA(ETIMEDOUT): - fetchLastErrCode = FETCH_TIMEOUT; - break; - case WSA(ECONNREFUSED): - case WSA(EHOSTDOWN): - fetchLastErrCode = FETCH_DOWN; - break; -default: - fetchLastErrCode = FETCH_UNKNOWN; - } - snprintf(fetchLastErrString, MAXERRSTRING, "%s", strerror(errno)); -} - - -/* - * Emit status message - */ -void -_fetch_info(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - fputc('\n', stderr); -} - - -/*** Network-related utility functions ***************************************/ - -/* - * Return the default port for a scheme - */ -int -_fetch_default_port(const char *scheme) -{ - struct servent *se; - - if ((se = getservbyname(scheme, "tcp")) != NULL) - return (ntohs(se->s_port)); - if (strcasecmp(scheme, SCHEME_FTP) == 0) - return (FTP_DEFAULT_PORT); - if (strcasecmp(scheme, SCHEME_HTTP) == 0) - return (HTTP_DEFAULT_PORT); - return (0); -} - -/* - * Return the default proxy port for a scheme - */ -int -_fetch_default_proxy_port(const char *scheme) -{ - if (strcasecmp(scheme, SCHEME_FTP) == 0) - return (FTP_DEFAULT_PROXY_PORT); - if (strcasecmp(scheme, SCHEME_HTTP) == 0) - return (HTTP_DEFAULT_PROXY_PORT); - return (0); -} - - -/* - * Create a connection for an existing descriptor. - */ -conn_t * -_fetch_reopen(int sd) -{ - conn_t *conn; - - /* allocate and fill connection structure */ - if ((conn = calloc(1, sizeof(*conn))) == NULL) - return (NULL); - conn->sd = sd; - ++conn->ref; - return (conn); -} - - -/* - * Bump a connection's reference count. - */ -conn_t * -_fetch_ref(conn_t *conn) -{ - - ++conn->ref; - return (conn); -} - - -/* - * Bind a socket to a specific local address - */ -int -_fetch_bind(int sd, int af, const char *addr) -{ - struct addrinfo hints, *res, *res0; - int err; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = af; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = 0; - if ((err = getaddrinfo(addr, NULL, &hints, &res0)) != 0) - return (-1); - for (res = res0; res; res = res->ai_next) - if (bind(sd, res->ai_addr, res->ai_addrlen) == 0) - return (0); - return (-1); -} - - -/* - * Establish a TCP connection to the specified port on the specified host. - */ -conn_t * -_fetch_connect(const char *host, int port, int af, int verbose) -{ - conn_t *conn; - char pbuf[10]; - const char *bindaddr; - struct addrinfo hints, *res, *res0; - int sd, err; - - DEBUG(fprintf(stderr, "---> %s:%d\n", host, port)); - - if (verbose) - _fetch_info("looking up %s", host); - - /* look up host name and set up socket address structure */ - snprintf(pbuf, sizeof(pbuf), "%d", port); - memset(&hints, 0, sizeof(hints)); - hints.ai_family = af; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = 0; - if ((err = getaddrinfo(host, pbuf, &hints, &res0)) != 0) { - _netdb_seterr(err); - return (NULL); - } - bindaddr = getenv("FETCH_BIND_ADDRESS"); - - if (verbose) - _fetch_info("connecting to %s:%d", host, port); - - /* try to connect */ - for (sd = -1, res = res0; res; sd = -1, res = res->ai_next) { - if ((sd = socket(res->ai_family, res->ai_socktype, - res->ai_protocol)) == -1) - continue; - if (bindaddr != NULL && *bindaddr != '\0' && - _fetch_bind(sd, res->ai_family, bindaddr) != 0) { - _fetch_info("failed to bind to '%s'", bindaddr); -#ifdef flagWIN32 - closesocket(sd); -#else - close(sd); -#endif - continue; - } - if (connect(sd, res->ai_addr, res->ai_addrlen) == 0) - break; -#ifdef flagWIN32 - closesocket(sd); -#else - close(sd); -#endif - } - freeaddrinfo(res0); - if (sd == -1) { - _fetch_syserr(); - return (NULL); - } - - if ((conn = _fetch_reopen(sd)) == NULL) { - _fetch_syserr(); -#ifdef flagWIN32 - closesocket(sd); -#else - close(sd); -#endif - } - return (conn); -} - - -/* - * Enable SSL on a connection. - */ -int -_fetch_ssl(conn_t *conn, int verbose) -{ - -#ifdef WITH_SSL - /* Init the SSL library and context */ - if (!SSL_library_init()){ - fprintf(stderr, "SSL library init failed\n"); - return (-1); - } - - SSL_load_error_strings(); - - conn->ssl_meth = SSLv23_client_method(); - conn->ssl_ctx = SSL_CTX_new(conn->ssl_meth); - SSL_CTX_set_mode(conn->ssl_ctx, SSL_MODE_AUTO_RETRY); - - conn->ssl = SSL_new(conn->ssl_ctx); - if (conn->ssl == NULL){ - fprintf(stderr, "SSL context creation failed\n"); - return (-1); - } - SSL_set_fd(conn->ssl, conn->sd); - if (SSL_connect(conn->ssl) == -1){ - ERR_print_errors_fp(stderr); - return (-1); - } - - if (verbose) { - X509_NAME *name; - char *str; - - fprintf(stderr, "SSL connection established using %s\n", - SSL_get_cipher(conn->ssl)); - conn->ssl_cert = SSL_get_peer_certificate(conn->ssl); - name = X509_get_subject_name(conn->ssl_cert); - str = X509_NAME_oneline(name, 0, 0); - printf("Certificate subject: %s\n", str); - free(str); - name = X509_get_issuer_name(conn->ssl_cert); - str = X509_NAME_oneline(name, 0, 0); - printf("Certificate issuer: %s\n", str); - free(str); - } - - return (0); -#else - (void)conn; - (void)verbose; - fprintf(stderr, "SSL support disabled\n"); - return (-1); -#endif -} - - -#ifdef flagWIN32 -void gettimeofday(struct timeval *tv, void *dummy) -{ - unsigned ticks = GetTickCount(); - tv->tv_usec = (ticks % 1000) * 1000; - tv->tv_sec = ticks / 1000; -} -#endif - -/* - * Read a character from a connection w/ timeout - */ -ssize_t -_fetch_read(conn_t *conn, char *buf, size_t len) -{ - struct timeval now, timeout, wait; - fd_set readfds; - ssize_t rlen, total; - int r; - - if (fetchTimeout) { - FD_ZERO(&readfds); - gettimeofday(&timeout, NULL); - timeout.tv_sec += fetchTimeout; - } - - total = 0; - while (len > 0) { - while (fetchTimeout && !FD_ISSET(conn->sd, &readfds)) { - FD_SET(conn->sd, &readfds); - gettimeofday(&now, NULL); - wait.tv_sec = timeout.tv_sec - now.tv_sec; - wait.tv_usec = timeout.tv_usec - now.tv_usec; - if (wait.tv_usec < 0) { - wait.tv_usec += 1000000; - wait.tv_sec--; - } - if (wait.tv_sec < 0) { - errno = WSA(ETIMEDOUT); - _fetch_syserr(); - return (-1); - } - errno = 0; - r = select(conn->sd + 1, &readfds, NULL, NULL, &wait); - if (r == -1) { - if (errno == EINTR && fetchRestartCalls) - continue; - _fetch_syserr(); - return (-1); - } - } -#ifdef WITH_SSL - if (conn->ssl != NULL) - rlen = SSL_read(conn->ssl, buf, len); - else -#endif -#ifdef flagWIN32 - rlen = recv(conn->sd, buf, len, 0); -#else - rlen = read(conn->sd, buf, len); -#endif - if (rlen == 0) - break; - if (rlen < 0) { - if (errno == EINTR && fetchRestartCalls) - continue; - return (-1); - } - len -= rlen; - buf += rlen; - total += rlen; - } - return (total); -} - - -/* - * Read a line of text from a connection w/ timeout - */ -#define MIN_BUF_SIZE 1024 - -int -_fetch_getln(conn_t *conn) -{ - char *tmp; - size_t tmpsize; - ssize_t len; - char c; - - if (conn->buf == NULL) { - if ((conn->buf = malloc(MIN_BUF_SIZE)) == NULL) { - errno = ENOMEM; - return (-1); - } - conn->bufsize = MIN_BUF_SIZE; - } - - conn->buf[0] = '\0'; - conn->buflen = 0; - - do { - len = _fetch_read(conn, &c, 1); - if (len == -1) - return (-1); - if (len == 0) - break; - conn->buf[conn->buflen++] = c; - if (conn->buflen == conn->bufsize) { - tmp = conn->buf; - tmpsize = conn->bufsize * 2 + 1; - if ((tmp = realloc(tmp, tmpsize)) == NULL) { - errno = ENOMEM; - return (-1); - } - conn->buf = tmp; - conn->bufsize = tmpsize; - } - } while (c != '\n'); - - conn->buf[conn->buflen] = '\0'; - DEBUG(fprintf(stderr, "<<< %s", conn->buf)); - return (0); -} - - -/* - * Write to a connection w/ timeout - */ -ssize_t -_fetch_write(conn_t *conn, const char *buf, size_t len) -{ - struct iovec iov; - - iov.iov_base = __DECONST(char *, buf); - iov.iov_len = len; - return _fetch_writev(conn, &iov, 1); -} - -/* - * Write a vector to a connection w/ timeout - * Note: can modify the iovec. - */ -ssize_t -_fetch_writev(conn_t *conn, struct iovec *iov, int iovcnt) -{ - struct timeval now, timeout, wait; - fd_set writefds; - ssize_t wlen, total; - int r; - - if (fetchTimeout) { - FD_ZERO(&writefds); - gettimeofday(&timeout, NULL); - timeout.tv_sec += fetchTimeout; - } - - total = 0; - while (iovcnt > 0) { - while (fetchTimeout && !FD_ISSET(conn->sd, &writefds)) { - FD_SET(conn->sd, &writefds); - gettimeofday(&now, NULL); - wait.tv_sec = timeout.tv_sec - now.tv_sec; - wait.tv_usec = timeout.tv_usec - now.tv_usec; - if (wait.tv_usec < 0) { - wait.tv_usec += 1000000; - wait.tv_sec--; - } - if (wait.tv_sec < 0) { - errno = WSA(ETIMEDOUT); - _fetch_syserr(); - return (-1); - } - errno = 0; - r = select(conn->sd + 1, NULL, &writefds, NULL, &wait); - if (r == -1) { - if (errno == WSA(EINTR) && fetchRestartCalls) - continue; - return (-1); - } - } - errno = 0; -#ifdef WITH_SSL - if (conn->ssl != NULL) - wlen = SSL_write(conn->ssl, - iov->iov_base, iov->iov_len); - else -#endif -#ifdef flagWIN32 - wlen = send(conn->sd, iov->iov_base, iov->iov_len, 0); -#else - wlen = writev(conn->sd, iov, iovcnt); -#endif - if (wlen == 0) { - /* we consider a short write a failure */ - errno = EPIPE; - _fetch_syserr(); - return (-1); - } - if (wlen < 0) { - if (errno == EINTR && fetchRestartCalls) - continue; - return (-1); - } - total += wlen; - while (iovcnt > 0 && wlen >= (ssize_t)iov->iov_len) { - wlen -= iov->iov_len; - iov++; - iovcnt--; - } - if (iovcnt > 0) { - iov->iov_len -= wlen; - iov->iov_base = __DECONST(char *, iov->iov_base) + wlen; - } - } - return (total); -} - - -/* - * Write a line of text to a connection w/ timeout - */ -int -_fetch_putln(conn_t *conn, const char *str, size_t len) -{ - struct iovec iov[2]; - int ret; - - DEBUG(fprintf(stderr, ">>> %s\n", str)); - iov[0].iov_base = __DECONST(char *, str); - iov[0].iov_len = len; - iov[1].iov_base = __DECONST(char *, ENDL); - iov[1].iov_len = sizeof(ENDL); - if (len == 0) - ret = _fetch_writev(conn, &iov[1], 1); - else - ret = _fetch_writev(conn, iov, 2); - if (ret == -1) - return (-1); - return (0); -} - - -/* - * Close connection - */ -int -_fetch_close(conn_t *conn) -{ - int ret; - - if (--conn->ref > 0) - return (0); -#ifdef flagWIN32 - ret = closesocket(conn->sd); -#else - ret = close(conn->sd); -#endif - free(conn); - return (ret); -} - - -/*** Directory-related utility functions *************************************/ - -int -_fetch_add_entry(struct url_ent **p, int *size, int *len, - const char *name, struct url_stat *us) -{ - struct url_ent *tmp; - - if (*p == NULL) { - *size = 0; - *len = 0; - } - - if (*len >= *size - 1) { - tmp = realloc(*p, (*size * 2 + 1) * sizeof(**p)); - if (tmp == NULL) { - errno = ENOMEM; - _fetch_syserr(); - return (-1); - } - *size = (*size * 2 + 1); - *p = tmp; - } - - tmp = *p + *len; - snprintf(tmp->name, PATH_MAX, "%s", name); - bcopy(us, &tmp->stat, sizeof(*us)); - - (*len)++; - (++tmp)->name[0] = 0; - - return (0); -} - - -/*** Authentication-related utility functions ********************************/ - -static const char * -_fetch_read_word(FILE *f) -{ - static char word[1024]; - - if (fscanf(f, " %1024s ", word) != 1) - return (NULL); - return (word); -} - -/* - * Get authentication data for a URL from .netrc - */ -int -_fetch_netrc_auth(struct url *url) -{ - char fn[PATH_MAX]; - const char *word; - char *p; - FILE *f; - - if ((p = getenv("NETRC")) != NULL) { - if (snprintf(fn, sizeof(fn), "%s", p) >= (int)sizeof(fn)) { - _fetch_info("$NETRC specifies a file name " - "longer than PATH_MAX"); - return (-1); - } - } else { -#ifndef flagWIN32 - if ((p = getenv("HOME")) != NULL) { - struct passwd *pwd; - - if ((pwd = getpwuid(getuid())) == NULL || - (p = pwd->pw_dir) == NULL) - return (-1); - } -#endif - if (snprintf(fn, sizeof(fn), "%s/.netrc", p) >= (int)sizeof(fn)) - return (-1); - } - - if ((f = fopen(fn, "r")) == NULL) - return (-1); - while ((word = _fetch_read_word(f)) != NULL) { - if (strcmp(word, "default") == 0) { - DEBUG(_fetch_info("Using default .netrc settings")); - break; - } - if (strcmp(word, "machine") == 0 && - (word = _fetch_read_word(f)) != NULL && - strcasecmp(word, url->host) == 0) { - DEBUG(_fetch_info("Using .netrc settings for %s", word)); - break; - } - } - if (word == NULL) - goto ferr; - while ((word = _fetch_read_word(f)) != NULL) { - if (strcmp(word, "login") == 0) { - if ((word = _fetch_read_word(f)) == NULL) - goto ferr; - if (snprintf(url->user, sizeof(url->user), - "%s", word) > (int)sizeof(url->user)) { - _fetch_info("login name in .netrc is too long"); - url->user[0] = '\0'; - } - } else if (strcmp(word, "password") == 0) { - if ((word = _fetch_read_word(f)) == NULL) - goto ferr; - if (snprintf(url->pwd, sizeof(url->pwd), - "%s", word) > (int)sizeof(url->pwd)) { - _fetch_info("password in .netrc is too long"); - url->pwd[0] = '\0'; - } - } else if (strcmp(word, "account") == 0) { - if ((word = _fetch_read_word(f)) == NULL) - goto ferr; - /* XXX not supported! */ - } else { - break; - } - } - fclose(f); - return (0); - ferr: - fclose(f); - return (-1); -} diff --git a/uppdev/plugin/libfetch/lib/common.h b/uppdev/plugin/libfetch/lib/common.h deleted file mode 100644 index 5a16bba23..000000000 --- a/uppdev/plugin/libfetch/lib/common.h +++ /dev/null @@ -1,146 +0,0 @@ -/*- - * Copyright (c) 1998 Dag-Erling Coïdan Smørgrav - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/lib/libfetch/common.h,v 1.27 2003/03/03 12:35:03 des Exp $ - */ - -#ifndef _COMMON_H_INCLUDED -#define _COMMON_H_INCLUDED - -#define FTP_DEFAULT_PORT 21 -#define HTTP_DEFAULT_PORT 80 -#define FTP_DEFAULT_PROXY_PORT 21 -#define HTTP_DEFAULT_PROXY_PORT 3128 - -#ifdef WITH_SSL -#include -#include -#include -#include -#include -#endif - -/* Connection */ -typedef struct fetchconn conn_t; -struct fetchconn { - int sd; /* socket descriptor */ - char *buf; /* buffer */ - size_t bufsize; /* buffer size */ - size_t buflen; /* length of buffer contents */ - int err; /* last protocol reply code */ -#ifdef WITH_SSL - SSL *ssl; /* SSL handle */ - SSL_CTX *ssl_ctx; /* SSL context */ - X509 *ssl_cert; /* server certificate */ - SSL_METHOD *ssl_meth; /* SSL method */ -#endif - int ref; /* reference count */ -}; - -/* Structure used for error message lists */ -struct fetcherr { - const int num; - const int cat; - const char *string; -}; - -#if defined(flagWIN32) -typedef int ssize_t; - -#define snprintf _snprintf -#define strcasecmp _stricmp -#define WSA(e) WSA##e -#define __DECONST(t, v) ((t)(v)) -#define bcopy(dest, src, size) memcpy((dest), (src), (size)) -#define fseeko fseek -#define __unused -#else -#define WSA(e) e -#endif - -/* for _fetch_writev */ -#if defined(flagWIN32) -struct iovec { - void *iov_base; - size_t iov_len; -}; -void gettimeofday(struct timeval *tv, void *); -#else -struct iovec; -#endif - -void _fetch_seterr(struct fetcherr *, int); -void _fetch_syserr(void); -void _fetch_info(const char *, ...); -int _fetch_default_port(const char *); -int _fetch_default_proxy_port(const char *); -int _fetch_bind(int, int, const char *); -conn_t *_fetch_connect(const char *, int, int, int); -conn_t *_fetch_reopen(int); -conn_t *_fetch_ref(conn_t *); -int _fetch_ssl(conn_t *, int); -ssize_t _fetch_read(conn_t *, char *, size_t); -int _fetch_getln(conn_t *); -ssize_t _fetch_write(conn_t *, const char *, size_t); -ssize_t _fetch_writev(conn_t *, struct iovec *, int); -int _fetch_putln(conn_t *, const char *, size_t); -int _fetch_close(conn_t *); -int _fetch_add_entry(struct url_ent **, int *, int *, - const char *, struct url_stat *); -int _fetch_netrc_auth(struct url *url); - -#define _ftp_seterr(n) _fetch_seterr(_ftp_errlist, n) -#define _http_seterr(n) _fetch_seterr(_http_errlist, n) -#define _netdb_seterr(n) _fetch_seterr(_netdb_errlist, n) -#define _url_seterr(n) _fetch_seterr(_url_errlist, n) - -#ifndef NDEBUG -#define DEBUG(x) do { if (fetchDebug) { x; } } while (0) -#else -#define DEBUG(x) do { } while (0) -#endif - -/* - * I don't really like exporting _http_request() and _ftp_request(), - * but the HTTP and FTP code occasionally needs to cross-call - * eachother, and this saves me from adding a lot of special-case code - * to handle those cases. - * - * Note that _*_request() free purl, which is way ugly but saves us a - * whole lot of trouble. - */ -FILE *_http_request(struct url *, const char *, - struct url_stat *, struct url *, const char *); -FILE *_ftp_request(struct url *, const char *, - struct url_stat *, struct url *, const char *); - -/* - * Check whether a particular flag is set - */ -#define CHECK_FLAG(x) (flags && strchr(flags, (x))) - -#endif diff --git a/uppdev/plugin/libfetch/lib/fetch.c b/uppdev/plugin/libfetch/lib/fetch.c deleted file mode 100644 index e3fafdc94..000000000 --- a/uppdev/plugin/libfetch/lib/fetch.c +++ /dev/null @@ -1,446 +0,0 @@ -/*- - * Copyright (c) 1998 Dag-Erling Coïdan Smørgrav - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifdef flagWIN32 -#include -#include -#include -#include -#include -#else -#include -__FBSDID("$FreeBSD: src/lib/libfetch/fetch.c,v 1.37 2003/01/28 08:04:40 des Exp $"); - -#include -#include -#endif - -#include -#include -#include -#include - -#include "fetch.h" -#include "common.h" - -auth_t fetchAuthMethod; -int fetchLastErrCode; -char fetchLastErrString[MAXERRSTRING]; -int fetchTimeout; -int fetchRestartCalls = 1; -int fetchDebug; - - -/*** Local data **************************************************************/ - -/* - * Error messages for parser errors - */ -#define URL_MALFORMED 1 -#define URL_BAD_SCHEME 2 -#define URL_BAD_PORT 3 -static struct fetcherr _url_errlist[] = { - { URL_MALFORMED, FETCH_URL, "Malformed URL" }, - { URL_BAD_SCHEME, FETCH_URL, "Invalid URL scheme" }, - { URL_BAD_PORT, FETCH_URL, "Invalid server port" }, - { -1, FETCH_UNKNOWN, "Unknown parser error" } -}; - - -/*** Public API **************************************************************/ - -/* - * Select the appropriate protocol for the URL scheme, and return a - * read-only stream connected to the document referenced by the URL. - * Also fill out the struct url_stat. - */ -FILE * -fetchXGet(struct url *URL, struct url_stat *us, const char *flags) -{ - int direct; - - direct = CHECK_FLAG('d'); - if (us != NULL) { - us->size = -1; - us->atime = us->mtime = 0; - } - if (strcasecmp(URL->scheme, SCHEME_FILE) == 0) - return (fetchXGetFile(URL, us, flags)); - else if (strcasecmp(URL->scheme, SCHEME_FTP) == 0) - return (fetchXGetFTP(URL, us, flags)); - else if (strcasecmp(URL->scheme, SCHEME_HTTP) == 0) - return (fetchXGetHTTP(URL, us, flags)); - else if (strcasecmp(URL->scheme, SCHEME_HTTPS) == 0) - return (fetchXGetHTTP(URL, us, flags)); - _url_seterr(URL_BAD_SCHEME); - return (NULL); -} - -/* - * Select the appropriate protocol for the URL scheme, and return a - * read-only stream connected to the document referenced by the URL. - */ -FILE * -fetchGet(struct url *URL, const char *flags) -{ - return (fetchXGet(URL, NULL, flags)); -} - -/* - * Select the appropriate protocol for the URL scheme, and return a - * write-only stream connected to the document referenced by the URL. - */ -FILE * -fetchPut(struct url *URL, const char *flags) -{ - int direct; - - direct = CHECK_FLAG('d'); - if (strcasecmp(URL->scheme, SCHEME_FILE) == 0) - return (fetchPutFile(URL, flags)); - else if (strcasecmp(URL->scheme, SCHEME_FTP) == 0) - return (fetchPutFTP(URL, flags)); - else if (strcasecmp(URL->scheme, SCHEME_HTTP) == 0) - return (fetchPutHTTP(URL, flags)); - else if (strcasecmp(URL->scheme, SCHEME_HTTPS) == 0) - return (fetchPutHTTP(URL, flags)); - _url_seterr(URL_BAD_SCHEME); - return (NULL); -} - -/* - * Select the appropriate protocol for the URL scheme, and return the - * size of the document referenced by the URL if it exists. - */ -int -fetchStat(struct url *URL, struct url_stat *us, const char *flags) -{ - int direct; - - direct = CHECK_FLAG('d'); - if (us != NULL) { - us->size = -1; - us->atime = us->mtime = 0; - } - if (strcasecmp(URL->scheme, SCHEME_FILE) == 0) - return (fetchStatFile(URL, us, flags)); - else if (strcasecmp(URL->scheme, SCHEME_FTP) == 0) - return (fetchStatFTP(URL, us, flags)); - else if (strcasecmp(URL->scheme, SCHEME_HTTP) == 0) - return (fetchStatHTTP(URL, us, flags)); - else if (strcasecmp(URL->scheme, SCHEME_HTTPS) == 0) - return (fetchStatHTTP(URL, us, flags)); - _url_seterr(URL_BAD_SCHEME); - return (-1); -} - -/* - * Select the appropriate protocol for the URL scheme, and return a - * list of files in the directory pointed to by the URL. - */ -struct url_ent * -fetchList(struct url *URL, const char *flags) -{ - int direct; - - direct = CHECK_FLAG('d'); - if (strcasecmp(URL->scheme, SCHEME_FILE) == 0) - return (fetchListFile(URL, flags)); - else if (strcasecmp(URL->scheme, SCHEME_FTP) == 0) - return (fetchListFTP(URL, flags)); - else if (strcasecmp(URL->scheme, SCHEME_HTTP) == 0) - return (fetchListHTTP(URL, flags)); - else if (strcasecmp(URL->scheme, SCHEME_HTTPS) == 0) - return (fetchListHTTP(URL, flags)); - _url_seterr(URL_BAD_SCHEME); - return (NULL); -} - -/* - * Attempt to parse the given URL; if successful, call fetchXGet(). - */ -FILE * -fetchXGetURL(const char *URL, struct url_stat *us, const char *flags) -{ - struct url *u; - FILE *f; - - if ((u = fetchParseURL(URL)) == NULL) - return (NULL); - - f = fetchXGet(u, us, flags); - - fetchFreeURL(u); - return (f); -} - -/* - * Attempt to parse the given URL; if successful, call fetchGet(). - */ -FILE * -fetchGetURL(const char *URL, const char *flags) -{ - return (fetchXGetURL(URL, NULL, flags)); -} - -/* - * Attempt to parse the given URL; if successful, call fetchPut(). - */ -FILE * -fetchPutURL(const char *URL, const char *flags) -{ - struct url *u; - FILE *f; - - if ((u = fetchParseURL(URL)) == NULL) - return (NULL); - - f = fetchPut(u, flags); - - fetchFreeURL(u); - return (f); -} - -/* - * Attempt to parse the given URL; if successful, call fetchStat(). - */ -int -fetchStatURL(const char *URL, struct url_stat *us, const char *flags) -{ - struct url *u; - int s; - - if ((u = fetchParseURL(URL)) == NULL) - return (-1); - - s = fetchStat(u, us, flags); - - fetchFreeURL(u); - return (s); -} - -/* - * Attempt to parse the given URL; if successful, call fetchList(). - */ -struct url_ent * -fetchListURL(const char *URL, const char *flags) -{ - struct url *u; - struct url_ent *ue; - - if ((u = fetchParseURL(URL)) == NULL) - return (NULL); - - ue = fetchList(u, flags); - - fetchFreeURL(u); - return (ue); -} - -/* - * Make a URL - */ -struct url * -fetchMakeURL(const char *scheme, const char *host, int port, const char *doc, - const char *user, const char *pwd) -{ - struct url *u; - - if (!scheme || (!host && !doc)) { - _url_seterr(URL_MALFORMED); - return (NULL); - } - - if (port < 0 || port > 65535) { - _url_seterr(URL_BAD_PORT); - return (NULL); - } - - /* allocate struct url */ - if ((u = calloc(1, sizeof(*u))) == NULL) { - _fetch_syserr(); - return (NULL); - } - - if ((u->doc = strdup(doc ? doc : "/")) == NULL) { - _fetch_syserr(); - free(u); - return (NULL); - } - -#define seturl(x) snprintf(u->x, sizeof(u->x), "%s", x) - seturl(scheme); - seturl(host); - seturl(user); - seturl(pwd); -#undef seturl - u->port = port; - - return (u); -} - -/* - * Split an URL into components. URL syntax is: - * [method:/][/[user[:pwd]@]host[:port]/][document] - * This almost, but not quite, RFC1738 URL syntax. - */ -struct url * -fetchParseURL(const char *URL) -{ - char *doc; - const char *p, *q; - struct url *u; - int i; - - /* allocate struct url */ - if ((u = calloc(1, sizeof(*u))) == NULL) { - _fetch_syserr(); - return (NULL); - } - - /* scheme name */ - if ((p = strstr(URL, ":/"))) { - snprintf(u->scheme, URL_SCHEMELEN+1, - "%.*s", (int)(p - URL), URL); - URL = ++p; - /* - * Only one slash: no host, leave slash as part of document - * Two slashes: host follows, strip slashes - */ - if (URL[1] == '/') - URL = (p += 2); - } else { - p = URL; - } - if (!*URL || *URL == '/' || *URL == '.' || - (u->scheme[0] == '\0' && - strchr(URL, '/') == NULL && strchr(URL, ':') == NULL)) - goto nohost; - - p = strpbrk(URL, "/@"); - if (p && *p == '@') { - /* username */ - for (q = URL, i = 0; (*q != ':') && (*q != '@'); q++) - if (i < URL_USERLEN) - u->user[i++] = *q; - - /* password */ - if (*q == ':') - for (q++, i = 0; (*q != ':') && (*q != '@'); q++) - if (i < URL_PWDLEN) - u->pwd[i++] = *q; - - p++; - } else { - p = URL; - } - - /* hostname */ -#ifdef INET6 - if (*p == '[' && (q = strchr(p + 1, ']')) != NULL && - (*++q == '\0' || *q == '/' || *q == ':')) { - if ((i = q - p - 2) > MAXHOSTNAMELEN) - i = MAXHOSTNAMELEN; - strncpy(u->host, ++p, i); - p = q; - } else -#endif - for (i = 0; *p && (*p != '/') && (*p != ':'); p++) - if (i < MAXHOSTNAMELEN) - u->host[i++] = *p; - - /* port */ - if (*p == ':') { - for (q = ++p; *q && (*q != '/'); q++) - if (isdigit(*q)) - u->port = u->port * 10 + (*q - '0'); - else { - /* invalid port */ - _url_seterr(URL_BAD_PORT); - goto ouch; - } - p = q; - } - -nohost: - /* document */ - if (!*p) - p = "/"; - - if (strcasecmp(u->scheme, SCHEME_HTTP) == 0 || - strcasecmp(u->scheme, SCHEME_HTTPS) == 0) { - const char hexnums[] = "0123456789abcdef"; - - /* percent-escape whitespace. */ - if ((doc = malloc(strlen(p) * 3 + 1)) == NULL) { - _fetch_syserr(); - goto ouch; - } - u->doc = doc; - while (*p != '\0') { - if (!isspace(*p)) { - *doc++ = *p++; - } else { - *doc++ = '%'; - *doc++ = hexnums[((unsigned int)*p) >> 4]; - *doc++ = hexnums[((unsigned int)*p) & 0xf]; - p++; - } - } - *doc = '\0'; - } else if ((u->doc = strdup(p)) == NULL) { - _fetch_syserr(); - goto ouch; - } - - DEBUG(fprintf(stderr, - "scheme: [%s]\n" - "user: [%s]\n" - "password: [%s]\n" - "host: [%s]\n" - "port: [%d]\n" - "document: [%s]\n", - u->scheme, u->user, u->pwd, - u->host, u->port, u->doc)); - - return (u); - -ouch: - free(u); - return (NULL); -} - -/* - * Free a URL - */ -void -fetchFreeURL(struct url *u) -{ - free(u->doc); - free(u); -} diff --git a/uppdev/plugin/libfetch/lib/fetch.h b/uppdev/plugin/libfetch/lib/fetch.h deleted file mode 100644 index be77f98c4..000000000 --- a/uppdev/plugin/libfetch/lib/fetch.h +++ /dev/null @@ -1,162 +0,0 @@ -/*- - * Copyright (c) 1998 Dag-Erling Coïdan Smørgrav - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/lib/libfetch/fetch.h,v 1.25 2002/07/22 16:11:39 des Exp $ - */ - -#ifndef _FETCH_H_INCLUDED -#define _FETCH_H_INCLUDED - -#define _LIBFETCH_VER "libfetch/2.0" - -#define URL_SCHEMELEN 16 -#define URL_USERLEN 256 -#define URL_PWDLEN 256 - -#ifndef MAXHOSTNAMELEN -#define MAXHOSTNAMELEN 1024 -#endif - -struct url { - char scheme[URL_SCHEMELEN+1]; - char user[URL_USERLEN+1]; - char pwd[URL_PWDLEN+1]; - char host[MAXHOSTNAMELEN+1]; - int port; - char *doc; - off_t offset; - size_t length; -}; - -struct url_stat { - off_t size; - time_t atime; - time_t mtime; -}; - -#ifndef PATH_MAX -#define PATH_MAX _MAX_PATH -#endif - -struct url_ent { - char name[PATH_MAX]; - struct url_stat stat; -}; - -/* Recognized schemes */ -#define SCHEME_FTP "ftp" -#define SCHEME_HTTP "http" -#define SCHEME_HTTPS "https" -#define SCHEME_FILE "file" - -/* Error codes */ -#define FETCH_ABORT 1 -#define FETCH_AUTH 2 -#define FETCH_DOWN 3 -#define FETCH_EXISTS 4 -#define FETCH_FULL 5 -#define FETCH_INFO 6 -#define FETCH_MEMORY 7 -#define FETCH_MOVED 8 -#define FETCH_NETWORK 9 -#define FETCH_OK 10 -#define FETCH_PROTO 11 -#define FETCH_RESOLV 12 -#define FETCH_SERVER 13 -#define FETCH_TEMP 14 -#define FETCH_TIMEOUT 15 -#define FETCH_UNAVAIL 16 -#define FETCH_UNKNOWN 17 -#define FETCH_URL 18 -#define FETCH_VERBOSE 19 - -#if !defined(flagWIN32) -__BEGIN_DECLS -#endif - -/* FILE-specific functions */ -FILE *fetchXGetFile(struct url *, struct url_stat *, const char *); -FILE *fetchGetFile(struct url *, const char *); -FILE *fetchPutFile(struct url *, const char *); -int fetchStatFile(struct url *, struct url_stat *, const char *); -struct url_ent *fetchListFile(struct url *, const char *); - -/* HTTP-specific functions */ -FILE *fetchXGetHTTP(struct url *, struct url_stat *, const char *); -FILE *fetchGetHTTP(struct url *, const char *); -FILE *fetchPutHTTP(struct url *, const char *); -int fetchStatHTTP(struct url *, struct url_stat *, const char *); -struct url_ent *fetchListHTTP(struct url *, const char *); - -/* FTP-specific functions */ -FILE *fetchXGetFTP(struct url *, struct url_stat *, const char *); -FILE *fetchGetFTP(struct url *, const char *); -FILE *fetchPutFTP(struct url *, const char *); -int fetchStatFTP(struct url *, struct url_stat *, const char *); -struct url_ent *fetchListFTP(struct url *, const char *); - -/* Generic functions */ -FILE *fetchXGetURL(const char *, struct url_stat *, const char *); -FILE *fetchGetURL(const char *, const char *); -FILE *fetchPutURL(const char *, const char *); -int fetchStatURL(const char *, struct url_stat *, const char *); -struct url_ent *fetchListURL(const char *, const char *); -FILE *fetchXGet(struct url *, struct url_stat *, const char *); -FILE *fetchGet(struct url *, const char *); -FILE *fetchPut(struct url *, const char *); -int fetchStat(struct url *, struct url_stat *, const char *); -struct url_ent *fetchList(struct url *, const char *); - -/* URL parsing */ -struct url *fetchMakeURL(const char *, const char *, int, - const char *, const char *, const char *); -struct url *fetchParseURL(const char *); -void fetchFreeURL(struct url *); - -#if !defined(flagWIN32) -__END_DECLS -#endif - -/* Authentication */ -typedef int (*auth_t)(struct url *); -extern auth_t fetchAuthMethod; - -/* Last error code */ -extern int fetchLastErrCode; -#define MAXERRSTRING 256 -extern char fetchLastErrString[MAXERRSTRING]; - -/* I/O timeout */ -extern int fetchTimeout; - -/* Restart interrupted syscalls */ -extern int fetchRestartCalls; - -/* Extra verbosity */ -extern int fetchDebug; - -#endif diff --git a/uppdev/plugin/libfetch/lib/file.c b/uppdev/plugin/libfetch/lib/file.c deleted file mode 100644 index 00aca9dfc..000000000 --- a/uppdev/plugin/libfetch/lib/file.c +++ /dev/null @@ -1,156 +0,0 @@ -/*- - * Copyright (c) 1998 Dag-Erling Coïdan Smørgrav - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifdef flagWIN32 -#include -#include -#include -#include -#include -#else -#include -__FBSDID("$FreeBSD: src/lib/libfetch/file.c,v 1.16 2003/01/28 08:04:40 des Exp $"); - -#include - -#include -#endif - -#include - -#include -#include - -#include "fetch.h" -#include "common.h" - -FILE * -fetchXGetFile(struct url *u, struct url_stat *us, const char *flags) -{ - FILE *f; - - if (us && fetchStatFile(u, us, flags) == -1) - return (NULL); - - f = fopen(u->doc, "r"); - - if (f == NULL) - _fetch_syserr(); - - if (u->offset && fseeko(f, u->offset, SEEK_SET) == -1) { - fclose(f); - _fetch_syserr(); - } - - return (f); -} - -FILE * -fetchGetFile(struct url *u, const char *flags) -{ - return (fetchXGetFile(u, NULL, flags)); -} - -FILE * -fetchPutFile(struct url *u, const char *flags) -{ - FILE *f; - - if (CHECK_FLAG('a')) - f = fopen(u->doc, "a"); - else - f = fopen(u->doc, "w+"); - - if (f == NULL) - _fetch_syserr(); - - if (u->offset && fseeko(f, u->offset, SEEK_SET) == -1) { - fclose(f); - _fetch_syserr(); - } - - return (f); -} - -static int -_fetch_stat_file(const char *fn, struct url_stat *us) -{ - struct stat sb; - - us->size = -1; - us->atime = us->mtime = 0; - if (stat(fn, &sb) == -1) { - _fetch_syserr(); - return (-1); - } - us->size = sb.st_size; - us->atime = sb.st_atime; - us->mtime = sb.st_mtime; - return (0); -} - -int -fetchStatFile(struct url *u, struct url_stat *us, const char *flags __unused) -{ - return (_fetch_stat_file(u->doc, us)); -} - -struct url_ent * -fetchListFile(struct url *u, const char *flags __unused) -{ - struct dirent *de; - struct url_stat us; - struct url_ent *ue; - int size, len; - char fn[PATH_MAX], *p; - DIR *dir; - int l; - - if ((dir = opendir(u->doc)) == NULL) { - _fetch_syserr(); - return (NULL); - } - - ue = NULL; - strncpy(fn, u->doc, sizeof(fn) - 2); - fn[sizeof(fn) - 2] = 0; - strcat(fn, "/"); - p = strchr(fn, 0); - l = sizeof(fn) - strlen(fn) - 1; - - while ((de = readdir(dir)) != NULL) { - strncpy(p, de->d_name, l - 1); - p[l - 1] = 0; - if (_fetch_stat_file(fn, &us) == -1) - /* should I return a partial result, or abort? */ - break; - _fetch_add_entry(&ue, &size, &len, de->d_name, &us); - } - - return (ue); -} diff --git a/uppdev/plugin/libfetch/lib/ftp.c b/uppdev/plugin/libfetch/lib/ftp.c deleted file mode 100644 index ce29a1839..000000000 --- a/uppdev/plugin/libfetch/lib/ftp.c +++ /dev/null @@ -1,1020 +0,0 @@ -/*- - * Copyright (c) 1998 Dag-Erling Coïdan Smørgrav - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD: src/lib/libfetch/ftp.c,v 1.90 2003/08/29 15:56:52 des Exp $"); - -/* - * Portions of this code were taken from or based on ftpio.c: - * - * ---------------------------------------------------------------------------- - * "THE BEER-WARE LICENSE" (Revision 42): - * wrote this file. As long as you retain this notice you - * can do whatever you want with this stuff. If we meet some day, and you think - * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp - * ---------------------------------------------------------------------------- - * - * Major Changelog: - * - * Dag-Erling Coïdan Smørgrav - * 9 Jun 1998 - * - * Incorporated into libfetch - * - * Jordan K. Hubbard - * 17 Jan 1996 - * - * Turned inside out. Now returns xfers as new file ids, not as a special - * `state' of FTP_t - * - * $ftpioId: ftpio.c,v 1.30 1998/04/11 07:28:53 phk Exp $ - * - */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "fetch.h" -#include "common.h" -#include "ftperr.h" - -#define FTP_ANONYMOUS_USER "anonymous" - -#define FTP_CONNECTION_ALREADY_OPEN 125 -#define FTP_OPEN_DATA_CONNECTION 150 -#define FTP_OK 200 -#define FTP_FILE_STATUS 213 -#define FTP_SERVICE_READY 220 -#define FTP_TRANSFER_COMPLETE 226 -#define FTP_PASSIVE_MODE 227 -#define FTP_LPASSIVE_MODE 228 -#define FTP_EPASSIVE_MODE 229 -#define FTP_LOGGED_IN 230 -#define FTP_FILE_ACTION_OK 250 -#define FTP_NEED_PASSWORD 331 -#define FTP_NEED_ACCOUNT 332 -#define FTP_FILE_OK 350 -#define FTP_SYNTAX_ERROR 500 -#define FTP_PROTOCOL_ERROR 999 - -static struct url cached_host; -static conn_t *cached_connection; - -#define isftpreply(foo) (isdigit(foo[0]) && isdigit(foo[1]) \ - && isdigit(foo[2]) \ - && (foo[3] == ' ' || foo[3] == '\0')) -#define isftpinfo(foo) (isdigit(foo[0]) && isdigit(foo[1]) \ - && isdigit(foo[2]) && foo[3] == '-') - -/* - * Translate IPv4 mapped IPv6 address to IPv4 address - */ -static void -unmappedaddr(struct sockaddr_in6 *sin6) -{ - struct sockaddr_in *sin4; - u_int32_t addr; - int port; - - if (sin6->sin6_family != AF_INET6 || - !IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) - return; - sin4 = (struct sockaddr_in *)sin6; - addr = *(u_int32_t *)&sin6->sin6_addr.s6_addr[12]; - port = sin6->sin6_port; - memset(sin4, 0, sizeof(struct sockaddr_in)); - sin4->sin_addr.s_addr = addr; - sin4->sin_port = port; - sin4->sin_family = AF_INET; - sin4->sin_len = sizeof(struct sockaddr_in); -} - -/* - * Get server response - */ -static int -_ftp_chkerr(conn_t *conn) -{ - if (_fetch_getln(conn) == -1) { - _fetch_syserr(); - return (-1); - } - if (isftpinfo(conn->buf)) { - while (conn->buflen && !isftpreply(conn->buf)) { - if (_fetch_getln(conn) == -1) { - _fetch_syserr(); - return (-1); - } - } - } - - while (conn->buflen && isspace(conn->buf[conn->buflen - 1])) - conn->buflen--; - conn->buf[conn->buflen] = '\0'; - - if (!isftpreply(conn->buf)) { - _ftp_seterr(FTP_PROTOCOL_ERROR); - return (-1); - } - - conn->err = (conn->buf[0] - '0') * 100 - + (conn->buf[1] - '0') * 10 - + (conn->buf[2] - '0'); - - return (conn->err); -} - -/* - * Send a command and check reply - */ -static int -_ftp_cmd(conn_t *conn, const char *fmt, ...) -{ - va_list ap; - size_t len; - char *msg; - int r; - - va_start(ap, fmt); - len = vasprintf(&msg, fmt, ap); - va_end(ap); - - if (msg == NULL) { - errno = ENOMEM; - _fetch_syserr(); - return (-1); - } - - r = _fetch_putln(conn, msg, len); - free(msg); - - if (r == -1) { - _fetch_syserr(); - return (-1); - } - - return (_ftp_chkerr(conn)); -} - -/* - * Return a pointer to the filename part of a path - */ -static const char * -_ftp_filename(const char *file) -{ - char *s; - - if ((s = strrchr(file, '/')) == NULL) - return (file); - else - return (s + 1); -} - -/* - * Change working directory to the directory that contains the specified - * file. - */ -static int -_ftp_cwd(conn_t *conn, const char *file) -{ - char *s; - int e; - - if ((s = strrchr(file, '/')) == NULL || s == file) { - e = _ftp_cmd(conn, "CWD /"); - } else { - e = _ftp_cmd(conn, "CWD %.*s", s - file, file); - } - if (e != FTP_FILE_ACTION_OK) { - _ftp_seterr(e); - return (-1); - } - return (0); -} - -/* - * Request and parse file stats - */ -static int -_ftp_stat(conn_t *conn, const char *file, struct url_stat *us) -{ - char *ln; - const char *s; - struct tm tm; - time_t t; - int e; - - us->size = -1; - us->atime = us->mtime = 0; - - if ((s = strrchr(file, '/')) == NULL) - s = file; - else - ++s; - - if ((e = _ftp_cmd(conn, "SIZE %s", s)) != FTP_FILE_STATUS) { - _ftp_seterr(e); - return (-1); - } - for (ln = conn->buf + 4; *ln && isspace(*ln); ln++) - /* nothing */ ; - for (us->size = 0; *ln && isdigit(*ln); ln++) - us->size = us->size * 10 + *ln - '0'; - if (*ln && !isspace(*ln)) { - _ftp_seterr(FTP_PROTOCOL_ERROR); - us->size = -1; - return (-1); - } - if (us->size == 0) - us->size = -1; - DEBUG(fprintf(stderr, "size: [%lld]\n", (long long)us->size)); - - if ((e = _ftp_cmd(conn, "MDTM %s", s)) != FTP_FILE_STATUS) { - _ftp_seterr(e); - return (-1); - } - for (ln = conn->buf + 4; *ln && isspace(*ln); ln++) - /* nothing */ ; - switch (strspn(ln, "0123456789")) { - case 14: - break; - case 15: - ln++; - ln[0] = '2'; - ln[1] = '0'; - break; - default: - _ftp_seterr(FTP_PROTOCOL_ERROR); - return (-1); - } - if (sscanf(ln, "%04d%02d%02d%02d%02d%02d", - &tm.tm_year, &tm.tm_mon, &tm.tm_mday, - &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) { - _ftp_seterr(FTP_PROTOCOL_ERROR); - return (-1); - } - tm.tm_mon--; - tm.tm_year -= 1900; - tm.tm_isdst = -1; - t = timegm(&tm); - if (t == (time_t)-1) - t = time(NULL); - us->mtime = t; - us->atime = t; - DEBUG(fprintf(stderr, - "last modified: [%04d-%02d-%02d %02d:%02d:%02d]\n", - tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec)); - return (0); -} - -/* - * I/O functions for FTP - */ -struct ftpio { - conn_t *cconn; /* Control connection */ - conn_t *dconn; /* Data connection */ - int dir; /* Direction */ - int eof; /* EOF reached */ - int err; /* Error code */ -}; - -static int _ftp_readfn(void *, char *, int); -static int _ftp_writefn(void *, const char *, int); -static fpos_t _ftp_seekfn(void *, fpos_t, int); -static int _ftp_closefn(void *); - -static int -_ftp_readfn(void *v, char *buf, int len) -{ - struct ftpio *io; - int r; - - io = (struct ftpio *)v; - if (io == NULL) { - errno = EBADF; - return (-1); - } - if (io->cconn == NULL || io->dconn == NULL || io->dir == O_WRONLY) { - errno = EBADF; - return (-1); - } - if (io->err) { - errno = io->err; - return (-1); - } - if (io->eof) - return (0); - r = _fetch_read(io->dconn, buf, len); - if (r > 0) - return (r); - if (r == 0) { - io->eof = 1; - return (0); - } - if (errno != EINTR) - io->err = errno; - return (-1); -} - -static int -_ftp_writefn(void *v, const char *buf, int len) -{ - struct ftpio *io; - int w; - - io = (struct ftpio *)v; - if (io == NULL) { - errno = EBADF; - return (-1); - } - if (io->cconn == NULL || io->dconn == NULL || io->dir == O_RDONLY) { - errno = EBADF; - return (-1); - } - if (io->err) { - errno = io->err; - return (-1); - } - w = _fetch_write(io->dconn, buf, len); - if (w >= 0) - return (w); - if (errno != EINTR) - io->err = errno; - return (-1); -} - -static fpos_t -_ftp_seekfn(void *v, fpos_t pos __unused, int whence __unused) -{ - struct ftpio *io; - - io = (struct ftpio *)v; - if (io == NULL) { - errno = EBADF; - return (-1); - } - errno = ESPIPE; - return (-1); -} - -static int -_ftp_closefn(void *v) -{ - struct ftpio *io; - int r; - - io = (struct ftpio *)v; - if (io == NULL) { - errno = EBADF; - return (-1); - } - if (io->dir == -1) - return (0); - if (io->cconn == NULL || io->dconn == NULL) { - errno = EBADF; - return (-1); - } - _fetch_close(io->dconn); - io->dir = -1; - io->dconn = NULL; - DEBUG(fprintf(stderr, "Waiting for final status\n")); - r = _ftp_chkerr(io->cconn); - if (io->cconn == cached_connection && io->cconn->ref == 1) - cached_connection = NULL; - _fetch_close(io->cconn); - free(io); - return (r == FTP_TRANSFER_COMPLETE) ? 0 : -1; -} - -static FILE * -_ftp_setup(conn_t *cconn, conn_t *dconn, int mode) -{ - struct ftpio *io; - FILE *f; - - if (cconn == NULL || dconn == NULL) - return (NULL); - if ((io = malloc(sizeof(*io))) == NULL) - return (NULL); - io->cconn = cconn; - io->dconn = dconn; - io->dir = mode; - io->eof = io->err = 0; - f = funopen(io, _ftp_readfn, _ftp_writefn, _ftp_seekfn, _ftp_closefn); - if (f == NULL) - free(io); - return (f); -} - -/* - * Transfer file - */ -static FILE * -_ftp_transfer(conn_t *conn, const char *oper, const char *file, - int mode, off_t offset, const char *flags) -{ - struct sockaddr_storage sa; - struct sockaddr_in6 *sin6; - struct sockaddr_in *sin4; - int low, pasv, verbose; - int e, sd = -1; - socklen_t l; - char *s; - FILE *df; - - /* check flags */ - low = CHECK_FLAG('l'); - pasv = CHECK_FLAG('p'); - verbose = CHECK_FLAG('v'); - - /* passive mode */ - if (!pasv) - pasv = ((s = getenv("FTP_PASSIVE_MODE")) != NULL && - strncasecmp(s, "no", 2) != 0); - - /* find our own address, bind, and listen */ - l = sizeof(sa); - if (getsockname(conn->sd, (struct sockaddr *)&sa, &l) == -1) - goto sysouch; - if (sa.ss_family == AF_INET6) - unmappedaddr((struct sockaddr_in6 *)&sa); - - /* open data socket */ - if ((sd = socket(sa.ss_family, SOCK_STREAM, IPPROTO_TCP)) == -1) { - _fetch_syserr(); - return (NULL); - } - - if (pasv) { - u_char addr[64]; - char *ln, *p; - unsigned int i; - int port; - - /* send PASV command */ - if (verbose) - _fetch_info("setting passive mode"); - switch (sa.ss_family) { - case AF_INET: - if ((e = _ftp_cmd(conn, "PASV")) != FTP_PASSIVE_MODE) - goto ouch; - break; - case AF_INET6: - if ((e = _ftp_cmd(conn, "EPSV")) != FTP_EPASSIVE_MODE) { - if (e == -1) - goto ouch; - if ((e = _ftp_cmd(conn, "LPSV")) != - FTP_LPASSIVE_MODE) - goto ouch; - } - break; - default: - e = FTP_PROTOCOL_ERROR; /* XXX: error code should be prepared */ - goto ouch; - } - - /* - * Find address and port number. The reply to the PASV command - * is IMHO the one and only weak point in the FTP protocol. - */ - ln = conn->buf; - switch (e) { - case FTP_PASSIVE_MODE: - case FTP_LPASSIVE_MODE: - for (p = ln + 3; *p && !isdigit(*p); p++) - /* nothing */ ; - if (!*p) { - e = FTP_PROTOCOL_ERROR; - goto ouch; - } - l = (e == FTP_PASSIVE_MODE ? 6 : 21); - for (i = 0; *p && i < l; i++, p++) - addr[i] = strtol(p, &p, 10); - if (i < l) { - e = FTP_PROTOCOL_ERROR; - goto ouch; - } - break; - case FTP_EPASSIVE_MODE: - for (p = ln + 3; *p && *p != '('; p++) - /* nothing */ ; - if (!*p) { - e = FTP_PROTOCOL_ERROR; - goto ouch; - } - ++p; - if (sscanf(p, "%c%c%c%d%c", &addr[0], &addr[1], &addr[2], - &port, &addr[3]) != 5 || - addr[0] != addr[1] || - addr[0] != addr[2] || addr[0] != addr[3]) { - e = FTP_PROTOCOL_ERROR; - goto ouch; - } - break; - } - - /* seek to required offset */ - if (offset) - if (_ftp_cmd(conn, "REST %lu", (u_long)offset) != FTP_FILE_OK) - goto sysouch; - - /* construct sockaddr for data socket */ - l = sizeof(sa); - if (getpeername(conn->sd, (struct sockaddr *)&sa, &l) == -1) - goto sysouch; - if (sa.ss_family == AF_INET6) - unmappedaddr((struct sockaddr_in6 *)&sa); - switch (sa.ss_family) { - case AF_INET6: - sin6 = (struct sockaddr_in6 *)&sa; - if (e == FTP_EPASSIVE_MODE) - sin6->sin6_port = htons(port); - else { - bcopy(addr + 2, (char *)&sin6->sin6_addr, 16); - bcopy(addr + 19, (char *)&sin6->sin6_port, 2); - } - break; - case AF_INET: - sin4 = (struct sockaddr_in *)&sa; - if (e == FTP_EPASSIVE_MODE) - sin4->sin_port = htons(port); - else { - bcopy(addr, (char *)&sin4->sin_addr, 4); - bcopy(addr + 4, (char *)&sin4->sin_port, 2); - } - break; - default: - e = FTP_PROTOCOL_ERROR; /* XXX: error code should be prepared */ - break; - } - - /* connect to data port */ - if (verbose) - _fetch_info("opening data connection"); - if (connect(sd, (struct sockaddr *)&sa, sa.ss_len) == -1) - goto sysouch; - - /* make the server initiate the transfer */ - if (verbose) - _fetch_info("initiating transfer"); - e = _ftp_cmd(conn, "%s %s", oper, _ftp_filename(file)); - if (e != FTP_CONNECTION_ALREADY_OPEN && e != FTP_OPEN_DATA_CONNECTION) - goto ouch; - - } else { - u_int32_t a; - u_short p; - int arg, d; - char *ap; - char hname[INET6_ADDRSTRLEN]; - - switch (sa.ss_family) { - case AF_INET6: - ((struct sockaddr_in6 *)&sa)->sin6_port = 0; -#ifdef IPV6_PORTRANGE - arg = low ? IPV6_PORTRANGE_DEFAULT : IPV6_PORTRANGE_HIGH; - if (setsockopt(sd, IPPROTO_IPV6, IPV6_PORTRANGE, - (char *)&arg, sizeof(arg)) == -1) - goto sysouch; -#endif - break; - case AF_INET: - ((struct sockaddr_in *)&sa)->sin_port = 0; - arg = low ? IP_PORTRANGE_DEFAULT : IP_PORTRANGE_HIGH; - if (setsockopt(sd, IPPROTO_IP, IP_PORTRANGE, - (char *)&arg, sizeof(arg)) == -1) - goto sysouch; - break; - } - if (verbose) - _fetch_info("binding data socket"); - if (bind(sd, (struct sockaddr *)&sa, sa.ss_len) == -1) - goto sysouch; - if (listen(sd, 1) == -1) - goto sysouch; - - /* find what port we're on and tell the server */ - if (getsockname(sd, (struct sockaddr *)&sa, &l) == -1) - goto sysouch; - switch (sa.ss_family) { - case AF_INET: - sin4 = (struct sockaddr_in *)&sa; - a = ntohl(sin4->sin_addr.s_addr); - p = ntohs(sin4->sin_port); - e = _ftp_cmd(conn, "PORT %d,%d,%d,%d,%d,%d", - (a >> 24) & 0xff, (a >> 16) & 0xff, - (a >> 8) & 0xff, a & 0xff, - (p >> 8) & 0xff, p & 0xff); - break; - case AF_INET6: -#define UC(b) (((int)b)&0xff) - e = -1; - sin6 = (struct sockaddr_in6 *)&sa; - sin6->sin6_scope_id = 0; - if (getnameinfo((struct sockaddr *)&sa, sa.ss_len, - hname, sizeof(hname), - NULL, 0, NI_NUMERICHOST) == 0) { - e = _ftp_cmd(conn, "EPRT |%d|%s|%d|", 2, hname, - htons(sin6->sin6_port)); - if (e == -1) - goto ouch; - } - if (e != FTP_OK) { - ap = (char *)&sin6->sin6_addr; - e = _ftp_cmd(conn, - "LPRT %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", - 6, 16, - UC(ap[0]), UC(ap[1]), UC(ap[2]), UC(ap[3]), - UC(ap[4]), UC(ap[5]), UC(ap[6]), UC(ap[7]), - UC(ap[8]), UC(ap[9]), UC(ap[10]), UC(ap[11]), - UC(ap[12]), UC(ap[13]), UC(ap[14]), UC(ap[15]), - 2, - (ntohs(sin6->sin6_port) >> 8) & 0xff, - ntohs(sin6->sin6_port) & 0xff); - } - break; - default: - e = FTP_PROTOCOL_ERROR; /* XXX: error code should be prepared */ - goto ouch; - } - if (e != FTP_OK) - goto ouch; - - /* seek to required offset */ - if (offset) - if (_ftp_cmd(conn, "REST %ju", (uintmax_t)offset) != FTP_FILE_OK) - goto sysouch; - - /* make the server initiate the transfer */ - if (verbose) - _fetch_info("initiating transfer"); - e = _ftp_cmd(conn, "%s %s", oper, _ftp_filename(file)); - if (e != FTP_CONNECTION_ALREADY_OPEN && e != FTP_OPEN_DATA_CONNECTION) - goto ouch; - - /* accept the incoming connection and go to town */ - if ((d = accept(sd, NULL, NULL)) == -1) - goto sysouch; - close(sd); - sd = d; - } - - if ((df = _ftp_setup(conn, _fetch_reopen(sd), mode)) == NULL) - goto sysouch; - return (df); - -sysouch: - _fetch_syserr(); - if (sd >= 0) - close(sd); - return (NULL); - -ouch: - if (e != -1) - _ftp_seterr(e); - if (sd >= 0) - close(sd); - return (NULL); -} - -/* - * Authenticate - */ -static int -_ftp_authenticate(conn_t *conn, struct url *url, struct url *purl) -{ - const char *user, *pwd, *logname; - char pbuf[MAXHOSTNAMELEN + MAXLOGNAME + 1]; - int e, len; - - /* XXX FTP_AUTH, and maybe .netrc */ - - /* send user name and password */ - if (url->user[0] == '\0') - _fetch_netrc_auth(url); - user = url->user; - if (*user == '\0') - user = getenv("FTP_LOGIN"); - if (user == NULL || *user == '\0') - user = FTP_ANONYMOUS_USER; - if (purl && url->port == _fetch_default_port(url->scheme)) - e = _ftp_cmd(conn, "USER %s@%s", user, url->host); - else if (purl) - e = _ftp_cmd(conn, "USER %s@%s@%d", user, url->host, url->port); - else - e = _ftp_cmd(conn, "USER %s", user); - - /* did the server request a password? */ - if (e == FTP_NEED_PASSWORD) { - pwd = url->pwd; - if (*pwd == '\0') - pwd = getenv("FTP_PASSWORD"); - if (pwd == NULL || *pwd == '\0') { - if ((logname = getlogin()) == 0) - logname = FTP_ANONYMOUS_USER; - if ((len = snprintf(pbuf, MAXLOGNAME + 1, "%s@", logname)) < 0) - len = 0; - else if (len > MAXLOGNAME) - len = MAXLOGNAME; - gethostname(pbuf + len, sizeof(pbuf) - len); - pwd = pbuf; - } - e = _ftp_cmd(conn, "PASS %s", pwd); - } - - return (e); -} - -/* - * Log on to FTP server - */ -static conn_t * -_ftp_connect(struct url *url, struct url *purl, const char *flags) -{ - conn_t *conn; - int e, direct, verbose; -#ifdef INET6 - int af = AF_UNSPEC; -#else - int af = AF_INET; -#endif - - direct = CHECK_FLAG('d'); - verbose = CHECK_FLAG('v'); - if (CHECK_FLAG('4')) - af = AF_INET; - else if (CHECK_FLAG('6')) - af = AF_INET6; - - if (direct) - purl = NULL; - - /* check for proxy */ - if (purl) { - /* XXX proxy authentication! */ - conn = _fetch_connect(purl->host, purl->port, af, verbose); - } else { - /* no proxy, go straight to target */ - conn = _fetch_connect(url->host, url->port, af, verbose); - purl = NULL; - } - - /* check connection */ - if (conn == NULL) - /* _fetch_connect() has already set an error code */ - return (NULL); - - /* expect welcome message */ - if ((e = _ftp_chkerr(conn)) != FTP_SERVICE_READY) - goto fouch; - - /* authenticate */ - if ((e = _ftp_authenticate(conn, url, purl)) != FTP_LOGGED_IN) - goto fouch; - - /* might as well select mode and type at once */ -#ifdef FTP_FORCE_STREAM_MODE - if ((e = _ftp_cmd(conn, "MODE S")) != FTP_OK) /* default is S */ - goto fouch; -#endif - if ((e = _ftp_cmd(conn, "TYPE I")) != FTP_OK) /* default is A */ - goto fouch; - - /* done */ - return (conn); - -fouch: - if (e != -1) - _ftp_seterr(e); - _fetch_close(conn); - return (NULL); -} - -/* - * Disconnect from server - */ -static void -_ftp_disconnect(conn_t *conn) -{ - (void)_ftp_cmd(conn, "QUIT"); - if (conn == cached_connection && conn->ref == 1) - cached_connection = NULL; - _fetch_close(conn); -} - -/* - * Check if we're already connected - */ -static int -_ftp_isconnected(struct url *url) -{ - return (cached_connection - && (strcmp(url->host, cached_host.host) == 0) - && (strcmp(url->user, cached_host.user) == 0) - && (strcmp(url->pwd, cached_host.pwd) == 0) - && (url->port == cached_host.port)); -} - -/* - * Check the cache, reconnect if no luck - */ -static conn_t * -_ftp_cached_connect(struct url *url, struct url *purl, const char *flags) -{ - conn_t *conn; - int e; - - /* set default port */ - if (!url->port) - url->port = _fetch_default_port(url->scheme); - - /* try to use previously cached connection */ - if (_ftp_isconnected(url)) { - e = _ftp_cmd(cached_connection, "NOOP"); - if (e == FTP_OK || e == FTP_SYNTAX_ERROR) - return (_fetch_ref(cached_connection)); - } - - /* connect to server */ - if ((conn = _ftp_connect(url, purl, flags)) == NULL) - return (NULL); - if (cached_connection) - _ftp_disconnect(cached_connection); - cached_connection = _fetch_ref(conn); - memcpy(&cached_host, url, sizeof(*url)); - return (conn); -} - -/* - * Check the proxy settings - */ -static struct url * -_ftp_get_proxy(const char *flags) -{ - struct url *purl; - char *p; - - if (flags != NULL && strchr(flags, 'd') != NULL) - return (NULL); - if (((p = getenv("FTP_PROXY")) || (p = getenv("ftp_proxy")) || - (p = getenv("HTTP_PROXY")) || (p = getenv("http_proxy"))) && - *p && (purl = fetchParseURL(p)) != NULL) { - if (!*purl->scheme) { - if (getenv("FTP_PROXY") || getenv("ftp_proxy")) - strcpy(purl->scheme, SCHEME_FTP); - else - strcpy(purl->scheme, SCHEME_HTTP); - } - if (!purl->port) - purl->port = _fetch_default_proxy_port(purl->scheme); - if (strcasecmp(purl->scheme, SCHEME_FTP) == 0 || - strcasecmp(purl->scheme, SCHEME_HTTP) == 0) - return (purl); - fetchFreeURL(purl); - } - return (NULL); -} - -/* - * Process an FTP request - */ -FILE * -_ftp_request(struct url *url, const char *op, struct url_stat *us, - struct url *purl, const char *flags) -{ - conn_t *conn; - int oflag; - - /* check if we should use HTTP instead */ - if (purl && strcasecmp(purl->scheme, SCHEME_HTTP) == 0) { - if (strcmp(op, "STAT") == 0) - return (_http_request(url, "HEAD", us, purl, flags)); - else if (strcmp(op, "RETR") == 0) - return (_http_request(url, "GET", us, purl, flags)); - /* - * Our HTTP code doesn't support PUT requests yet, so try - * a direct connection. - */ - } - - /* connect to server */ - conn = _ftp_cached_connect(url, purl, flags); - if (purl) - fetchFreeURL(purl); - if (conn == NULL) - return (NULL); - - /* change directory */ - if (_ftp_cwd(conn, url->doc) == -1) - return (NULL); - - /* stat file */ - if (us && _ftp_stat(conn, url->doc, us) == -1 - && fetchLastErrCode != FETCH_PROTO - && fetchLastErrCode != FETCH_UNAVAIL) - return (NULL); - - /* just a stat */ - if (strcmp(op, "STAT") == 0) - return (FILE *)1; /* bogus return value */ - if (strcmp(op, "STOR") == 0 || strcmp(op, "APPE") == 0) - oflag = O_WRONLY; - else - oflag = O_RDONLY; - - /* initiate the transfer */ - return (_ftp_transfer(conn, op, url->doc, oflag, url->offset, flags)); -} - -/* - * Get and stat file - */ -FILE * -fetchXGetFTP(struct url *url, struct url_stat *us, const char *flags) -{ - return (_ftp_request(url, "RETR", us, _ftp_get_proxy(flags), flags)); -} - -/* - * Get file - */ -FILE * -fetchGetFTP(struct url *url, const char *flags) -{ - return (fetchXGetFTP(url, NULL, flags)); -} - -/* - * Put file - */ -FILE * -fetchPutFTP(struct url *url, const char *flags) -{ - - return (_ftp_request(url, CHECK_FLAG('a') ? "APPE" : "STOR", NULL, - _ftp_get_proxy(flags), flags)); -} - -/* - * Get file stats - */ -int -fetchStatFTP(struct url *url, struct url_stat *us, const char *flags) -{ - FILE *f; - - f = _ftp_request(url, "STAT", us, _ftp_get_proxy(flags), flags); - if (f == NULL) - return (-1); - return (0); -} - -/* - * List a directory - */ -struct url_ent * -fetchListFTP(struct url *url __unused, const char *flags __unused) -{ - warnx("fetchListFTP(): not implemented"); - return (NULL); -} diff --git a/uppdev/plugin/libfetch/lib/http.c b/uppdev/plugin/libfetch/lib/http.c deleted file mode 100644 index 9226981bf..000000000 --- a/uppdev/plugin/libfetch/lib/http.c +++ /dev/null @@ -1,1192 +0,0 @@ -/*- - * Copyright (c) 2000 Dag-Erling Coïdan Smørgrav - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD: src/lib/libfetch/http.c,v 1.72 2004/02/11 09:35:27 des Exp $"); - -/* - * The following copyright applies to the base64 code: - * - *- - * Copyright 1997 Massachusetts Institute of Technology - * - * Permission to use, copy, modify, and distribute this software and - * its documentation for any purpose and without fee is hereby - * granted, provided that both the above copyright notice and this - * permission notice appear in all copies, that both the above - * copyright notice and this permission notice appear in all - * supporting documentation, and that the name of M.I.T. not be used - * in advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. M.I.T. makes - * no representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied - * warranty. - * - * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS - * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT - * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "fetch.h" -#include "common.h" -#include "httperr.h" - -/* Maximum number of redirects to follow */ -#define MAX_REDIRECT 5 - -/* Symbolic names for reply codes we care about */ -#define HTTP_OK 200 -#define HTTP_PARTIAL 206 -#define HTTP_MOVED_PERM 301 -#define HTTP_MOVED_TEMP 302 -#define HTTP_SEE_OTHER 303 -#define HTTP_NEED_AUTH 401 -#define HTTP_NEED_PROXY_AUTH 407 -#define HTTP_BAD_RANGE 416 -#define HTTP_PROTOCOL_ERROR 999 - -#define HTTP_REDIRECT(xyz) ((xyz) == HTTP_MOVED_PERM \ - || (xyz) == HTTP_MOVED_TEMP \ - || (xyz) == HTTP_SEE_OTHER) - -#define HTTP_ERROR(xyz) ((xyz) > 400 && (xyz) < 599) - - -/***************************************************************************** - * I/O functions for decoding chunked streams - */ - -struct httpio -{ - conn_t *conn; /* connection */ - int chunked; /* chunked mode */ - char *buf; /* chunk buffer */ - size_t bufsize; /* size of chunk buffer */ - ssize_t buflen; /* amount of data currently in buffer */ - int bufpos; /* current read offset in buffer */ - int eof; /* end-of-file flag */ - int error; /* error flag */ - size_t chunksize; /* remaining size of current chunk */ -#ifndef NDEBUG - size_t total; -#endif -}; - -/* - * Get next chunk header - */ -static int -_http_new_chunk(struct httpio *io) -{ - char *p; - - if (_fetch_getln(io->conn) == -1) - return (-1); - - if (io->conn->buflen < 2 || !ishexnumber(*io->conn->buf)) - return (-1); - - for (p = io->conn->buf; *p && !isspace(*p); ++p) { - if (*p == ';') - break; - if (!ishexnumber(*p)) - return (-1); - if (isdigit(*p)) { - io->chunksize = io->chunksize * 16 + - *p - '0'; - } else { - io->chunksize = io->chunksize * 16 + - 10 + tolower(*p) - 'a'; - } - } - -#ifndef NDEBUG - if (fetchDebug) { - io->total += io->chunksize; - if (io->chunksize == 0) - fprintf(stderr, "%s(): end of last chunk\n", __func__); - else - fprintf(stderr, "%s(): new chunk: %lu (%lu)\n", - __func__, (unsigned long)io->chunksize, - (unsigned long)io->total); - } -#endif - - return (io->chunksize); -} - -/* - * Grow the input buffer to at least len bytes - */ -static inline int -_http_growbuf(struct httpio *io, size_t len) -{ - char *tmp; - - if (io->bufsize >= len) - return (0); - - if ((tmp = realloc(io->buf, len)) == NULL) - return (-1); - io->buf = tmp; - io->bufsize = len; - return (0); -} - -/* - * Fill the input buffer, do chunk decoding on the fly - */ -static int -_http_fillbuf(struct httpio *io, size_t len) -{ - if (io->error) - return (-1); - if (io->eof) - return (0); - - if (io->chunked == 0) { - if (_http_growbuf(io, len) == -1) - return (-1); - if ((io->buflen = _fetch_read(io->conn, io->buf, len)) == -1) { - io->error = 1; - return (-1); - } - io->bufpos = 0; - return (io->buflen); - } - - if (io->chunksize == 0) { - switch (_http_new_chunk(io)) { - case -1: - io->error = 1; - return (-1); - case 0: - io->eof = 1; - return (0); - } - } - - if (len > io->chunksize) - len = io->chunksize; - if (_http_growbuf(io, len) == -1) - return (-1); - if ((io->buflen = _fetch_read(io->conn, io->buf, len)) == -1) { - io->error = 1; - return (-1); - } - io->chunksize -= io->buflen; - - if (io->chunksize == 0) { - char endl[2]; - - if (_fetch_read(io->conn, endl, 2) != 2 || - endl[0] != '\r' || endl[1] != '\n') - return (-1); - } - - io->bufpos = 0; - - return (io->buflen); -} - -/* - * Read function - */ -static int -_http_readfn(void *v, char *buf, int len) -{ - struct httpio *io = (struct httpio *)v; - int l, pos; - - if (io->error) - return (-1); - if (io->eof) - return (0); - - for (pos = 0; len > 0; pos += l, len -= l) { - /* empty buffer */ - if (!io->buf || io->bufpos == io->buflen) - if (_http_fillbuf(io, len) < 1) - break; - l = io->buflen - io->bufpos; - if (len < l) - l = len; - bcopy(io->buf + io->bufpos, buf + pos, l); - io->bufpos += l; - } - - if (!pos && io->error) - return (-1); - return (pos); -} - -/* - * Write function - */ -static int -_http_writefn(void *v, const char *buf, int len) -{ - struct httpio *io = (struct httpio *)v; - - return (_fetch_write(io->conn, buf, len)); -} - -/* - * Close function - */ -static int -_http_closefn(void *v) -{ - struct httpio *io = (struct httpio *)v; - int r; - - r = _fetch_close(io->conn); - if (io->buf) - free(io->buf); - free(io); - return (r); -} - -/* - * Wrap a file descriptor up - */ -static FILE * -_http_funopen(conn_t *conn, int chunked) -{ - struct httpio *io; - FILE *f; - - if ((io = calloc(1, sizeof(*io))) == NULL) { - _fetch_syserr(); - return (NULL); - } - io->conn = conn; - io->chunked = chunked; - f = funopen(io, _http_readfn, _http_writefn, NULL, _http_closefn); - if (f == NULL) { - _fetch_syserr(); - free(io); - return (NULL); - } - return (f); -} - - -/***************************************************************************** - * Helper functions for talking to the server and parsing its replies - */ - -/* Header types */ -typedef enum { - hdr_syserror = -2, - hdr_error = -1, - hdr_end = 0, - hdr_unknown = 1, - hdr_content_length, - hdr_content_range, - hdr_last_modified, - hdr_location, - hdr_transfer_encoding, - hdr_www_authenticate -} hdr_t; - -/* Names of interesting headers */ -static struct { - hdr_t num; - const char *name; -} hdr_names[] = { - { hdr_content_length, "Content-Length" }, - { hdr_content_range, "Content-Range" }, - { hdr_last_modified, "Last-Modified" }, - { hdr_location, "Location" }, - { hdr_transfer_encoding, "Transfer-Encoding" }, - { hdr_www_authenticate, "WWW-Authenticate" }, - { hdr_unknown, NULL }, -}; - -/* - * Send a formatted line; optionally echo to terminal - */ -static int -_http_cmd(conn_t *conn, const char *fmt, ...) -{ - va_list ap; - size_t len; - char *msg; - int r; - - va_start(ap, fmt); - len = vasprintf(&msg, fmt, ap); - va_end(ap); - - if (msg == NULL) { - errno = ENOMEM; - _fetch_syserr(); - return (-1); - } - - r = _fetch_putln(conn, msg, len); - free(msg); - - if (r == -1) { - _fetch_syserr(); - return (-1); - } - - return (0); -} - -/* - * Get and parse status line - */ -static int -_http_get_reply(conn_t *conn) -{ - char *p; - - if (_fetch_getln(conn) == -1) - return (-1); - /* - * A valid status line looks like "HTTP/m.n xyz reason" where m - * and n are the major and minor protocol version numbers and xyz - * is the reply code. - * Unfortunately, there are servers out there (NCSA 1.5.1, to name - * just one) that do not send a version number, so we can't rely - * on finding one, but if we do, insist on it being 1.0 or 1.1. - * We don't care about the reason phrase. - */ - if (strncmp(conn->buf, "HTTP", 4) != 0) - return (HTTP_PROTOCOL_ERROR); - p = conn->buf + 4; - if (*p == '/') { - if (p[1] != '1' || p[2] != '.' || (p[3] != '0' && p[3] != '1')) - return (HTTP_PROTOCOL_ERROR); - p += 4; - } - if (*p != ' ' || !isdigit(p[1]) || !isdigit(p[2]) || !isdigit(p[3])) - return (HTTP_PROTOCOL_ERROR); - - conn->err = (p[1] - '0') * 100 + (p[2] - '0') * 10 + (p[3] - '0'); - return (conn->err); -} - -/* - * Check a header; if the type matches the given string, return a pointer - * to the beginning of the value. - */ -static const char * -_http_match(const char *str, const char *hdr) -{ - while (*str && *hdr && tolower(*str++) == tolower(*hdr++)) - /* nothing */; - if (*str || *hdr != ':') - return (NULL); - while (*hdr && isspace(*++hdr)) - /* nothing */; - return (hdr); -} - -/* - * Get the next header and return the appropriate symbolic code. - */ -static hdr_t -_http_next_header(conn_t *conn, const char **p) -{ - int i; - - if (_fetch_getln(conn) == -1) - return (hdr_syserror); - while (conn->buflen && isspace(conn->buf[conn->buflen - 1])) - conn->buflen--; - conn->buf[conn->buflen] = '\0'; - if (conn->buflen == 0) - return (hdr_end); - /* - * We could check for malformed headers but we don't really care. - * A valid header starts with a token immediately followed by a - * colon; a token is any sequence of non-control, non-whitespace - * characters except "()<>@,;:\\\"{}". - */ - for (i = 0; hdr_names[i].num != hdr_unknown; i++) - if ((*p = _http_match(hdr_names[i].name, conn->buf)) != NULL) - return (hdr_names[i].num); - return (hdr_unknown); -} - -/* - * Parse a last-modified header - */ -static int -_http_parse_mtime(const char *p, time_t *mtime) -{ - char locale[64], *r; - struct tm tm; - - strncpy(locale, setlocale(LC_TIME, NULL), sizeof(locale)); - setlocale(LC_TIME, "C"); - r = strptime(p, "%a, %d %b %Y %H:%M:%S GMT", &tm); - /* XXX should add support for date-2 and date-3 */ - setlocale(LC_TIME, locale); - if (r == NULL) - return (-1); - DEBUG(fprintf(stderr, "last modified: [%04d-%02d-%02d " - "%02d:%02d:%02d]\n", - tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec)); - *mtime = timegm(&tm); - return (0); -} - -/* - * Parse a content-length header - */ -static int -_http_parse_length(const char *p, off_t *length) -{ - off_t len; - - for (len = 0; *p && isdigit(*p); ++p) - len = len * 10 + (*p - '0'); - if (*p) - return (-1); - DEBUG(fprintf(stderr, "content length: [%lld]\n", - (long long)len)); - *length = len; - return (0); -} - -/* - * Parse a content-range header - */ -static int -_http_parse_range(const char *p, off_t *offset, off_t *length, off_t *size) -{ - off_t first, last, len; - - if (strncasecmp(p, "bytes ", 6) != 0) - return (-1); - p += 6; - if (*p == '*') { - first = last = -1; - ++p; - } else { - for (first = 0; *p && isdigit(*p); ++p) - first = first * 10 + *p - '0'; - if (*p != '-') - return (-1); - for (last = 0, ++p; *p && isdigit(*p); ++p) - last = last * 10 + *p - '0'; - } - if (first > last || *p != '/') - return (-1); - for (len = 0, ++p; *p && isdigit(*p); ++p) - len = len * 10 + *p - '0'; - if (*p || len < last - first + 1) - return (-1); - if (first == -1) { - DEBUG(fprintf(stderr, "content range: [*/%lld]\n", - (long long)len)); - *length = 0; - } else { - DEBUG(fprintf(stderr, "content range: [%lld-%lld/%lld]\n", - (long long)first, (long long)last, (long long)len)); - *length = last - first + 1; - } - *offset = first; - *size = len; - return (0); -} - - -/***************************************************************************** - * Helper functions for authorization - */ - -/* - * Base64 encoding - */ -static char * -_http_base64(const char *src) -{ - static const char base64[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789+/"; - char *str, *dst; - size_t l; - int t, r; - - l = strlen(src); - if ((str = malloc(((l + 2) / 3) * 4)) == NULL) - return (NULL); - dst = str; - r = 0; - - while (l >= 3) { - t = (src[0] << 16) | (src[1] << 8) | src[2]; - dst[0] = base64[(t >> 18) & 0x3f]; - dst[1] = base64[(t >> 12) & 0x3f]; - dst[2] = base64[(t >> 6) & 0x3f]; - dst[3] = base64[(t >> 0) & 0x3f]; - src += 3; l -= 3; - dst += 4; r += 4; - } - - switch (l) { - case 2: - t = (src[0] << 16) | (src[1] << 8); - dst[0] = base64[(t >> 18) & 0x3f]; - dst[1] = base64[(t >> 12) & 0x3f]; - dst[2] = base64[(t >> 6) & 0x3f]; - dst[3] = '='; - dst += 4; - r += 4; - break; - case 1: - t = src[0] << 16; - dst[0] = base64[(t >> 18) & 0x3f]; - dst[1] = base64[(t >> 12) & 0x3f]; - dst[2] = dst[3] = '='; - dst += 4; - r += 4; - break; - case 0: - break; - } - - *dst = 0; - return (str); -} - -/* - * Encode username and password - */ -static int -_http_basic_auth(conn_t *conn, const char *hdr, const char *usr, const char *pwd) -{ - char *upw, *auth; - int r; - - DEBUG(fprintf(stderr, "usr: [%s]\n", usr)); - DEBUG(fprintf(stderr, "pwd: [%s]\n", pwd)); - if (asprintf(&upw, "%s:%s", usr, pwd) == -1) - return (-1); - auth = _http_base64(upw); - free(upw); - if (auth == NULL) - return (-1); - r = _http_cmd(conn, "%s: Basic %s", hdr, auth); - free(auth); - return (r); -} - -/* - * Send an authorization header - */ -static int -_http_authorize(conn_t *conn, const char *hdr, const char *p) -{ - /* basic authorization */ - if (strncasecmp(p, "basic:", 6) == 0) { - char *user, *pwd, *str; - int r; - - /* skip realm */ - for (p += 6; *p && *p != ':'; ++p) - /* nothing */ ; - if (!*p || strchr(++p, ':') == NULL) - return (-1); - if ((str = strdup(p)) == NULL) - return (-1); /* XXX */ - user = str; - pwd = strchr(str, ':'); - *pwd++ = '\0'; - r = _http_basic_auth(conn, hdr, user, pwd); - free(str); - return (r); - } - return (-1); -} - - -/***************************************************************************** - * Helper functions for connecting to a server or proxy - */ - -/* - * Connect to the correct HTTP server or proxy. - */ -static conn_t * -_http_connect(struct url *URL, struct url *purl, const char *flags) -{ - conn_t *conn; - int verbose; - int af; - -#ifdef INET6 - af = AF_UNSPEC; -#else - af = AF_INET; -#endif - - verbose = CHECK_FLAG('v'); - if (CHECK_FLAG('4')) - af = AF_INET; -#ifdef INET6 - else if (CHECK_FLAG('6')) - af = AF_INET6; -#endif - - if (purl && strcasecmp(URL->scheme, SCHEME_HTTPS) != 0) { - URL = purl; - } else if (strcasecmp(URL->scheme, SCHEME_FTP) == 0) { - /* can't talk http to an ftp server */ - /* XXX should set an error code */ - return (NULL); - } - - if ((conn = _fetch_connect(URL->host, URL->port, af, verbose)) == NULL) - /* _fetch_connect() has already set an error code */ - return (NULL); - if (strcasecmp(URL->scheme, SCHEME_HTTPS) == 0 && - _fetch_ssl(conn, verbose) == -1) { - _fetch_close(conn); - /* grrr */ - errno = EAUTH; - _fetch_syserr(); - return (NULL); - } - return (conn); -} - -static struct url * -_http_get_proxy(const char *flags) -{ - struct url *purl; - char *p; - - if (flags != NULL && strchr(flags, 'd') != NULL) - return (NULL); - if (((p = getenv("HTTP_PROXY")) || (p = getenv("http_proxy"))) && - (purl = fetchParseURL(p))) { - if (!*purl->scheme) - strcpy(purl->scheme, SCHEME_HTTP); - if (!purl->port) - purl->port = _fetch_default_proxy_port(purl->scheme); - if (strcasecmp(purl->scheme, SCHEME_HTTP) == 0) - return (purl); - fetchFreeURL(purl); - } - return (NULL); -} - -static void -_http_print_html(FILE *out, FILE *in) -{ - size_t len; - char *line, *p, *q; - int comment, tag; - - comment = tag = 0; - while ((line = fgetln(in, &len)) != NULL) { - while (len && isspace(line[len - 1])) - --len; - for (p = q = line; q < line + len; ++q) { - if (comment && *q == '-') { - if (q + 2 < line + len && - strcmp(q, "-->") == 0) { - tag = comment = 0; - q += 2; - } - } else if (tag && !comment && *q == '>') { - p = q + 1; - tag = 0; - } else if (!tag && *q == '<') { - if (q > p) - fwrite(p, q - p, 1, out); - tag = 1; - if (q + 3 < line + len && - strcmp(q, " BGR. */ \ - if (PIXMAN_FORMAT_TYPE (format__) != PIXMAN_FORMAT_TYPE(fmt)) \ - { \ - (res) = ((((res) & 0xff000000) >> 0) | \ - (((res) & 0x00ff0000) >> 16) | \ - (((res) & 0x0000ff00) >> 0) | \ - (((res) & 0x000000ff) << 16)); \ - } \ - } \ - while (0) - -#define fbComposeGetStart(pict,x,y,type,out_stride,line,mul) do { \ - uint32_t *__bits__; \ - int __stride__; \ - int __bpp__; \ - \ - __bits__ = pict->bits.bits; \ - __stride__ = pict->bits.rowstride; \ - __bpp__ = PIXMAN_FORMAT_BPP(pict->bits.format); \ - (out_stride) = __stride__ * (int) sizeof (uint32_t) / (int) sizeof (type); \ - (line) = ((type *) __bits__) + \ - (out_stride) * (y) + (mul) * (x); \ - } while (0) - - -#define PIXMAN_FORMAT_16BPC(f) (PIXMAN_FORMAT_A(f) > 8 || \ - PIXMAN_FORMAT_R(f) > 8 || \ - PIXMAN_FORMAT_G(f) > 8 || \ - PIXMAN_FORMAT_B(f) > 8) -/* - * Edges - */ - -#define MAX_ALPHA(n) ((1 << (n)) - 1) -#define N_Y_FRAC(n) ((n) == 1 ? 1 : (1 << ((n)/2)) - 1) -#define N_X_FRAC(n) ((n) == 1 ? 1 : (1 << ((n)/2)) + 1) - -#define STEP_Y_SMALL(n) (pixman_fixed_1 / N_Y_FRAC(n)) -#define STEP_Y_BIG(n) (pixman_fixed_1 - (N_Y_FRAC(n) - 1) * STEP_Y_SMALL(n)) - -#define Y_FRAC_FIRST(n) (STEP_Y_SMALL(n) / 2) -#define Y_FRAC_LAST(n) (Y_FRAC_FIRST(n) + (N_Y_FRAC(n) - 1) * STEP_Y_SMALL(n)) - -#define STEP_X_SMALL(n) (pixman_fixed_1 / N_X_FRAC(n)) -#define STEP_X_BIG(n) (pixman_fixed_1 - (N_X_FRAC(n) - 1) * STEP_X_SMALL(n)) - -#define X_FRAC_FIRST(n) (STEP_X_SMALL(n) / 2) -#define X_FRAC_LAST(n) (X_FRAC_FIRST(n) + (N_X_FRAC(n) - 1) * STEP_X_SMALL(n)) - -#define RenderSamplesX(x,n) ((n) == 1 ? 0 : (pixman_fixed_frac (x) + X_FRAC_FIRST(n)) / STEP_X_SMALL(n)) - -/* - * Step across a small sample grid gap - */ -#define RenderEdgeStepSmall(edge) { \ - edge->x += edge->stepx_small; \ - edge->e += edge->dx_small; \ - if (edge->e > 0) \ - { \ - edge->e -= edge->dy; \ - edge->x += edge->signdx; \ - } \ -} - -/* - * Step across a large sample grid gap - */ -#define RenderEdgeStepBig(edge) { \ - edge->x += edge->stepx_big; \ - edge->e += edge->dx_big; \ - if (edge->e > 0) \ - { \ - edge->e -= edge->dy; \ - edge->x += edge->signdx; \ - } \ -} - -void -pixman_rasterize_edges_accessors (pixman_image_t *image, - pixman_edge_t *l, - pixman_edge_t *r, - pixman_fixed_t t, - pixman_fixed_t b); - -pixman_bool_t -pixman_image_is_opaque(pixman_image_t *image); - -pixman_bool_t -pixman_image_can_get_solid (pixman_image_t *image); - -pixman_bool_t -pixman_compute_composite_region32 (pixman_region32_t * pRegion, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height); - -/* GCC visibility */ -#if defined(__GNUC__) && __GNUC__ >= 4 -#define PIXMAN_EXPORT __attribute__ ((visibility("default"))) -/* Sun Studio 8 visibility */ -#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550) -#define PIXMAN_EXPORT __global -#else -#define PIXMAN_EXPORT -#endif - -/* Region Helpers */ -pixman_bool_t pixman_region32_copy_from_region16 (pixman_region32_t *dst, - pixman_region16_t *src); -pixman_bool_t pixman_region16_copy_from_region32 (pixman_region16_t *dst, - pixman_region32_t *src); -void pixman_region_internal_set_static_pointers (pixman_box16_t *empty_box, - pixman_region16_data_t *empty_data, - pixman_region16_data_t *broken_data); - -#ifdef PIXMAN_TIMING - -/* Timing */ -static inline uint64_t -oil_profile_stamp_rdtsc (void) -{ - uint64_t ts; - __asm__ __volatile__("rdtsc\n" : "=A" (ts)); - return ts; -} -#define OIL_STAMP oil_profile_stamp_rdtsc - -typedef struct PixmanTimer PixmanTimer; - -struct PixmanTimer -{ - int initialized; - const char *name; - uint64_t n_times; - uint64_t total; - PixmanTimer *next; -}; - -extern int timer_defined; -void pixman_timer_register (PixmanTimer *timer); - -#define TIMER_BEGIN(tname) \ - { \ - static PixmanTimer timer##tname; \ - uint64_t begin##tname; \ - \ - if (!timer##tname.initialized) \ - { \ - timer##tname.initialized = 1; \ - timer##tname.name = #tname; \ - pixman_timer_register (&timer##tname); \ - } \ - \ - timer##tname.n_times++; \ - begin##tname = OIL_STAMP(); - -#define TIMER_END(tname) \ - timer##tname.total += OIL_STAMP() - begin##tname; \ - } - -#endif /* PIXMAN_TIMING */ - -#endif /* PIXMAN_PRIVATE_H */ diff --git a/uppdev/plugin/pixman/lib/pixman-region.c b/uppdev/plugin/pixman/lib/pixman-region.c deleted file mode 100644 index d6bea465b..000000000 --- a/uppdev/plugin/pixman/lib/pixman-region.c +++ /dev/null @@ -1,2129 +0,0 @@ -/*********************************************************** - -Copyright 1987, 1988, 1989, 1998 The Open Group - -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. - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall not be -used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization from The Open Group. - -Copyright 1987, 1988, 1989 by -Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -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 Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL 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 -#include -#include -#include - -#define PIXREGION_NIL(reg) ((reg)->data && !(reg)->data->numRects) -/* not a region */ -#define PIXREGION_NAR(reg) ((reg)->data == pixman_brokendata) -#define PIXREGION_NUM_RECTS(reg) ((reg)->data ? (reg)->data->numRects : 1) -#define PIXREGION_SIZE(reg) ((reg)->data ? (reg)->data->size : 0) -#define PIXREGION_RECTS(reg) ((reg)->data ? (box_type_t *)((reg)->data + 1) \ - : &(reg)->extents) -#define PIXREGION_BOXPTR(reg) ((box_type_t *)((reg)->data + 1)) -#define PIXREGION_BOX(reg,i) (&PIXREGION_BOXPTR(reg)[i]) -#define PIXREGION_TOP(reg) PIXREGION_BOX(reg, (reg)->data->numRects) -#define PIXREGION_END(reg) PIXREGION_BOX(reg, (reg)->data->numRects - 1) - - -#undef assert -#ifdef DEBUG_PIXREGION -#define assert(expr) {if (!(expr)) \ - FatalError("Assertion failed file %s, line %d: expr\n", \ - __FILE__, __LINE__); } -#else -#define assert(expr) -#endif - -#define good(reg) assert(PREFIX(_selfcheck) (reg)) - -#undef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#undef MAX -#define MAX(a,b) ((a) > (b) ? (a) : (b)) - -static const box_type_t PREFIX(_emptyBox_) = {0, 0, 0, 0}; -static const region_data_type_t PREFIX(_emptyData_) = {0, 0}; -static const region_data_type_t PREFIX(_brokendata_) = {0, 0}; - -static box_type_t *pixman_region_emptyBox = (box_type_t *)&PREFIX(_emptyBox_); -static region_data_type_t *pixman_region_emptyData = (region_data_type_t *)&PREFIX(_emptyData_); -static region_data_type_t *pixman_brokendata = (region_data_type_t *)&PREFIX(_brokendata_); - -/* This function exists only to make it possible to preserve the X ABI - it should - * go away at first opportunity. - * - * The problem is that the X ABI exports the three structs and has used - * them through macros. So the X server calls this function with - * the addresses of those structs which makes the existing code continue to - * work. - */ -void -PREFIX(_internal_set_static_pointers) (box_type_t *empty_box, - region_data_type_t *empty_data, - region_data_type_t *broken_data) -{ - pixman_region_emptyBox = empty_box; - pixman_region_emptyData = empty_data; - pixman_brokendata = broken_data; -} - -static pixman_bool_t -pixman_break (region_type_t *pReg); - -/* - * The functions in this file implement the Region abstraction used extensively - * throughout the X11 sample server. A Region is simply a set of disjoint - * (non-overlapping) rectangles, plus an "extent" rectangle which is the - * smallest single rectangle that contains all the non-overlapping rectangles. - * - * A Region is implemented as a "y-x-banded" array of rectangles. This array - * imposes two degrees of order. First, all rectangles are sorted by top side - * y coordinate first (y1), and then by left side x coordinate (x1). - * - * Furthermore, the rectangles are grouped into "bands". Each rectangle in a - * band has the same top y coordinate (y1), and each has the same bottom y - * coordinate (y2). Thus all rectangles in a band differ only in their left - * and right side (x1 and x2). Bands are implicit in the array of rectangles: - * there is no separate list of band start pointers. - * - * The y-x band representation does not minimize rectangles. In particular, - * if a rectangle vertically crosses a band (the rectangle has scanlines in - * the y1 to y2 area spanned by the band), then the rectangle may be broken - * down into two or more smaller rectangles stacked one atop the other. - * - * ----------- ----------- - * | | | | band 0 - * | | -------- ----------- -------- - * | | | | in y-x banded | | | | band 1 - * | | | | form is | | | | - * ----------- | | ----------- -------- - * | | | | band 2 - * -------- -------- - * - * An added constraint on the rectangles is that they must cover as much - * horizontal area as possible: no two rectangles within a band are allowed - * to touch. - * - * Whenever possible, bands will be merged together to cover a greater vertical - * distance (and thus reduce the number of rectangles). Two bands can be merged - * only if the bottom of one touches the top of the other and they have - * rectangles in the same places (of the same width, of course). - * - * Adam de Boor wrote most of the original region code. Joel McCormack - * substantially modified or rewrote most of the core arithmetic routines, and - * added pixman_region_validate in order to support several speed improvements to - * pixman_region_validateTree. Bob Scheifler changed the representation to be more - * compact when empty or a single rectangle, and did a bunch of gratuitous - * reformatting. Carl Worth did further gratuitous reformatting while re-merging - * the server and client region code into libpixregion. - */ - -/* true iff two Boxes overlap */ -#define EXTENTCHECK(r1,r2) \ - (!( ((r1)->x2 <= (r2)->x1) || \ - ((r1)->x1 >= (r2)->x2) || \ - ((r1)->y2 <= (r2)->y1) || \ - ((r1)->y1 >= (r2)->y2) ) ) - -/* true iff (x,y) is in Box */ -#define INBOX(r,x,y) \ - ( ((r)->x2 > x) && \ - ((r)->x1 <= x) && \ - ((r)->y2 > y) && \ - ((r)->y1 <= y) ) - -/* true iff Box r1 contains Box r2 */ -#define SUBSUMES(r1,r2) \ - ( ((r1)->x1 <= (r2)->x1) && \ - ((r1)->x2 >= (r2)->x2) && \ - ((r1)->y1 <= (r2)->y1) && \ - ((r1)->y2 >= (r2)->y2) ) - -static size_t -PIXREGION_SZOF(size_t n) -{ - size_t size = n * sizeof(box_type_t); - if (n > UINT32_MAX / sizeof(box_type_t)) - return 0; - - if (sizeof(region_data_type_t) > UINT32_MAX - size) - return 0; - - return size + sizeof(region_data_type_t); -} - -static void * -allocData(size_t n) -{ - size_t sz = PIXREGION_SZOF(n); - if (!sz) - return NULL; - - return malloc(sz); -} - -#define freeData(reg) if ((reg)->data && (reg)->data->size) free((reg)->data) - -#define RECTALLOC_BAIL(pReg,n,bail) \ -if (!(pReg)->data || (((pReg)->data->numRects + (n)) > (pReg)->data->size)) \ - if (!pixman_rect_alloc(pReg, n)) { goto bail; } - -#define RECTALLOC(pReg,n) \ -if (!(pReg)->data || (((pReg)->data->numRects + (n)) > (pReg)->data->size)) \ - if (!pixman_rect_alloc(pReg, n)) { return FALSE; } - -#define ADDRECT(pNextRect,nx1,ny1,nx2,ny2) \ -{ \ - pNextRect->x1 = nx1; \ - pNextRect->y1 = ny1; \ - pNextRect->x2 = nx2; \ - pNextRect->y2 = ny2; \ - pNextRect++; \ -} - -#define NEWRECT(pReg,pNextRect,nx1,ny1,nx2,ny2) \ -{ \ - if (!(pReg)->data || ((pReg)->data->numRects == (pReg)->data->size))\ - { \ - if (!pixman_rect_alloc(pReg, 1)) \ - return FALSE; \ - pNextRect = PIXREGION_TOP(pReg); \ - } \ - ADDRECT(pNextRect,nx1,ny1,nx2,ny2); \ - pReg->data->numRects++; \ - assert(pReg->data->numRects<=pReg->data->size); \ -} - -#define DOWNSIZE(reg,numRects) \ - if (((numRects) < ((reg)->data->size >> 1)) && ((reg)->data->size > 50)) \ - { \ - region_data_type_t * NewData; \ - size_t data_size = PIXREGION_SZOF(numRects); \ - if (!data_size) \ - NewData = NULL; \ - else \ - NewData = (region_data_type_t *)realloc((reg)->data, data_size); \ - if (NewData) \ - { \ - NewData->size = (numRects); \ - (reg)->data = NewData; \ - } \ - } - -PIXMAN_EXPORT pixman_bool_t -PREFIX(_equal) (reg1, reg2) - region_type_t * reg1; - region_type_t * reg2; -{ - int i; - box_type_t *rects1; - box_type_t *rects2; - - if (reg1->extents.x1 != reg2->extents.x1) return FALSE; - if (reg1->extents.x2 != reg2->extents.x2) return FALSE; - if (reg1->extents.y1 != reg2->extents.y1) return FALSE; - if (reg1->extents.y2 != reg2->extents.y2) return FALSE; - if (PIXREGION_NUM_RECTS(reg1) != PIXREGION_NUM_RECTS(reg2)) return FALSE; - - rects1 = PIXREGION_RECTS(reg1); - rects2 = PIXREGION_RECTS(reg2); - for (i = 0; i != PIXREGION_NUM_RECTS(reg1); i++) { - if (rects1[i].x1 != rects2[i].x1) return FALSE; - if (rects1[i].x2 != rects2[i].x2) return FALSE; - if (rects1[i].y1 != rects2[i].y1) return FALSE; - if (rects1[i].y2 != rects2[i].y2) return FALSE; - } - return TRUE; -} - -int -PREFIX(_print) (rgn) - region_type_t * rgn; -{ - int num, size; - int i; - box_type_t * rects; - - num = PIXREGION_NUM_RECTS(rgn); - size = PIXREGION_SIZE(rgn); - rects = PIXREGION_RECTS(rgn); - fprintf(stderr, "num: %d size: %d\n", num, size); - fprintf(stderr, "extents: %d %d %d %d\n", - rgn->extents.x1, rgn->extents.y1, rgn->extents.x2, rgn->extents.y2); - for (i = 0; i < num; i++) - fprintf(stderr, "%d %d %d %d \n", - rects[i].x1, rects[i].y1, rects[i].x2, rects[i].y2); - fprintf(stderr, "\n"); - return(num); -} - - -PIXMAN_EXPORT void -PREFIX(_init) (region_type_t *region) -{ - region->extents = *pixman_region_emptyBox; - region->data = pixman_region_emptyData; -} - -PIXMAN_EXPORT void -PREFIX(_init_rect) (region_type_t *region, - int x, int y, unsigned int width, unsigned int height) -{ - region->extents.x1 = x; - region->extents.y1 = y; - region->extents.x2 = x + width; - region->extents.y2 = y + height; - region->data = NULL; -} - -PIXMAN_EXPORT void -PREFIX(_init_with_extents) (region_type_t *region, box_type_t *extents) -{ - region->extents = *extents; - region->data = NULL; -} - -PIXMAN_EXPORT void -PREFIX(_fini) (region_type_t *region) -{ - good (region); - freeData (region); -} - -PIXMAN_EXPORT int -PREFIX(_n_rects) (region_type_t *region) -{ - return PIXREGION_NUM_RECTS (region); -} - -PIXMAN_EXPORT box_type_t * -PREFIX(_rectangles) (region_type_t *region, - int *n_rects) -{ - if (n_rects) - *n_rects = PIXREGION_NUM_RECTS (region); - - return PIXREGION_RECTS (region); -} - -static pixman_bool_t -pixman_break (region_type_t *region) -{ - freeData (region); - region->extents = *pixman_region_emptyBox; - region->data = pixman_brokendata; - return FALSE; -} - -static pixman_bool_t -pixman_rect_alloc (region_type_t * region, int n) -{ - region_data_type_t *data; - - if (!region->data) - { - n++; - region->data = allocData(n); - if (!region->data) - return pixman_break (region); - region->data->numRects = 1; - *PIXREGION_BOXPTR(region) = region->extents; - } - else if (!region->data->size) - { - region->data = allocData(n); - if (!region->data) - return pixman_break (region); - region->data->numRects = 0; - } - else - { - size_t data_size; - if (n == 1) - { - n = region->data->numRects; - if (n > 500) /* XXX pick numbers out of a hat */ - n = 250; - } - n += region->data->numRects; - data_size = PIXREGION_SZOF(n); - if (!data_size) - data = NULL; - else - data = (region_data_type_t *)realloc(region->data, PIXREGION_SZOF(n)); - if (!data) - return pixman_break (region); - region->data = data; - } - region->data->size = n; - return TRUE; -} - -PIXMAN_EXPORT pixman_bool_t -PREFIX(_copy) (region_type_t *dst, region_type_t *src) -{ - good(dst); - good(src); - if (dst == src) - return TRUE; - dst->extents = src->extents; - if (!src->data || !src->data->size) - { - freeData(dst); - dst->data = src->data; - return TRUE; - } - if (!dst->data || (dst->data->size < src->data->numRects)) - { - freeData(dst); - dst->data = allocData(src->data->numRects); - if (!dst->data) - return pixman_break (dst); - dst->data->size = src->data->numRects; - } - dst->data->numRects = src->data->numRects; - memmove((char *)PIXREGION_BOXPTR(dst),(char *)PIXREGION_BOXPTR(src), - dst->data->numRects * sizeof(box_type_t)); - return TRUE; -} - -/*====================================================================== - * Generic Region Operator - *====================================================================*/ - -/*- - *----------------------------------------------------------------------- - * pixman_coalesce -- - * Attempt to merge the boxes in the current band with those in the - * previous one. We are guaranteed that the current band extends to - * the end of the rects array. Used only by pixman_op. - * - * Results: - * The new index for the previous band. - * - * Side Effects: - * If coalescing takes place: - * - rectangles in the previous band will have their y2 fields - * altered. - * - region->data->numRects will be decreased. - * - *----------------------------------------------------------------------- - */ -static inline int -pixman_coalesce ( - region_type_t * region, /* Region to coalesce */ - int prevStart, /* Index of start of previous band */ - int curStart) /* Index of start of current band */ -{ - box_type_t * pPrevBox; /* Current box in previous band */ - box_type_t * pCurBox; /* Current box in current band */ - int numRects; /* Number rectangles in both bands */ - int y2; /* Bottom of current band */ - /* - * Figure out how many rectangles are in the band. - */ - numRects = curStart - prevStart; - assert(numRects == region->data->numRects - curStart); - - if (!numRects) return curStart; - - /* - * The bands may only be coalesced if the bottom of the previous - * matches the top scanline of the current. - */ - pPrevBox = PIXREGION_BOX(region, prevStart); - pCurBox = PIXREGION_BOX(region, curStart); - if (pPrevBox->y2 != pCurBox->y1) return curStart; - - /* - * Make sure the bands have boxes in the same places. This - * assumes that boxes have been added in such a way that they - * cover the most area possible. I.e. two boxes in a band must - * have some horizontal space between them. - */ - y2 = pCurBox->y2; - - do { - if ((pPrevBox->x1 != pCurBox->x1) || (pPrevBox->x2 != pCurBox->x2)) { - return (curStart); - } - pPrevBox++; - pCurBox++; - numRects--; - } while (numRects); - - /* - * The bands may be merged, so set the bottom y of each box - * in the previous band to the bottom y of the current band. - */ - numRects = curStart - prevStart; - region->data->numRects -= numRects; - do { - pPrevBox--; - pPrevBox->y2 = y2; - numRects--; - } while (numRects); - return prevStart; -} - -/* Quicky macro to avoid trivial reject procedure calls to pixman_coalesce */ - -#define Coalesce(newReg, prevBand, curBand) \ - if (curBand - prevBand == newReg->data->numRects - curBand) { \ - prevBand = pixman_coalesce(newReg, prevBand, curBand); \ - } else { \ - prevBand = curBand; \ - } - -/*- - *----------------------------------------------------------------------- - * pixman_region_appendNonO -- - * Handle a non-overlapping band for the union and subtract operations. - * Just adds the (top/bottom-clipped) rectangles into the region. - * Doesn't have to check for subsumption or anything. - * - * Results: - * None. - * - * Side Effects: - * region->data->numRects is incremented and the rectangles overwritten - * with the rectangles we're passed. - * - *----------------------------------------------------------------------- - */ - -static inline pixman_bool_t -pixman_region_appendNonO ( - region_type_t * region, - box_type_t * r, - box_type_t * rEnd, - int y1, - int y2) -{ - box_type_t * pNextRect; - int newRects; - - newRects = rEnd - r; - - assert(y1 < y2); - assert(newRects != 0); - - /* Make sure we have enough space for all rectangles to be added */ - RECTALLOC(region, newRects); - pNextRect = PIXREGION_TOP(region); - region->data->numRects += newRects; - do { - assert(r->x1 < r->x2); - ADDRECT(pNextRect, r->x1, y1, r->x2, y2); - r++; - } while (r != rEnd); - - return TRUE; -} - -#define FindBand(r, rBandEnd, rEnd, ry1) \ -{ \ - ry1 = r->y1; \ - rBandEnd = r+1; \ - while ((rBandEnd != rEnd) && (rBandEnd->y1 == ry1)) { \ - rBandEnd++; \ - } \ -} - -#define AppendRegions(newReg, r, rEnd) \ -{ \ - int newRects; \ - if ((newRects = rEnd - r)) { \ - RECTALLOC(newReg, newRects); \ - memmove((char *)PIXREGION_TOP(newReg),(char *)r, \ - newRects * sizeof(box_type_t)); \ - newReg->data->numRects += newRects; \ - } \ -} - -/*- - *----------------------------------------------------------------------- - * pixman_op -- - * Apply an operation to two regions. Called by pixman_region_union, pixman_region_inverse, - * pixman_region_subtract, pixman_region_intersect.... Both regions MUST have at least one - * rectangle, and cannot be the same object. - * - * Results: - * TRUE if successful. - * - * Side Effects: - * The new region is overwritten. - * pOverlap set to TRUE if overlapFunc ever returns TRUE. - * - * Notes: - * The idea behind this function is to view the two regions as sets. - * Together they cover a rectangle of area that this function divides - * into horizontal bands where points are covered only by one region - * or by both. For the first case, the nonOverlapFunc is called with - * each the band and the band's upper and lower extents. For the - * second, the overlapFunc is called to process the entire band. It - * is responsible for clipping the rectangles in the band, though - * this function provides the boundaries. - * At the end of each band, the new region is coalesced, if possible, - * to reduce the number of rectangles in the region. - * - *----------------------------------------------------------------------- - */ - -typedef pixman_bool_t (*OverlapProcPtr)( - region_type_t *region, - box_type_t *r1, - box_type_t *r1End, - box_type_t *r2, - box_type_t *r2End, - int y1, - int y2, - int *pOverlap); - -static pixman_bool_t -pixman_op( - region_type_t *newReg, /* Place to store result */ - region_type_t * reg1, /* First region in operation */ - region_type_t * reg2, /* 2d region in operation */ - OverlapProcPtr overlapFunc, /* Function to call for over- - * lapping bands */ - int appendNon1, /* Append non-overlapping bands */ - /* in region 1 ? */ - int appendNon2, /* Append non-overlapping bands */ - /* in region 2 ? */ - int *pOverlap) -{ - box_type_t * r1; /* Pointer into first region */ - box_type_t * r2; /* Pointer into 2d region */ - box_type_t * r1End; /* End of 1st region */ - box_type_t * r2End; /* End of 2d region */ - int ybot; /* Bottom of intersection */ - int ytop; /* Top of intersection */ - region_data_type_t * oldData; /* Old data for newReg */ - int prevBand; /* Index of start of - * previous band in newReg */ - int curBand; /* Index of start of current - * band in newReg */ - box_type_t * r1BandEnd; /* End of current band in r1 */ - box_type_t * r2BandEnd; /* End of current band in r2 */ - int top; /* Top of non-overlapping band */ - int bot; /* Bottom of non-overlapping band*/ - int r1y1; /* Temps for r1->y1 and r2->y1 */ - int r2y1; - int newSize; - int numRects; - - /* - * Break any region computed from a broken region - */ - if (PIXREGION_NAR (reg1) || PIXREGION_NAR(reg2)) - return pixman_break (newReg); - - /* - * Initialization: - * set r1, r2, r1End and r2End appropriately, save the rectangles - * of the destination region until the end in case it's one of - * the two source regions, then mark the "new" region empty, allocating - * another array of rectangles for it to use. - */ - - r1 = PIXREGION_RECTS(reg1); - newSize = PIXREGION_NUM_RECTS(reg1); - r1End = r1 + newSize; - numRects = PIXREGION_NUM_RECTS(reg2); - r2 = PIXREGION_RECTS(reg2); - r2End = r2 + numRects; - assert(r1 != r1End); - assert(r2 != r2End); - - oldData = (region_data_type_t *)NULL; - if (((newReg == reg1) && (newSize > 1)) || - ((newReg == reg2) && (numRects > 1))) - { - oldData = newReg->data; - newReg->data = pixman_region_emptyData; - } - /* guess at new size */ - if (numRects > newSize) - newSize = numRects; - newSize <<= 1; - if (!newReg->data) - newReg->data = pixman_region_emptyData; - else if (newReg->data->size) - newReg->data->numRects = 0; - if (newSize > newReg->data->size) { - if (!pixman_rect_alloc(newReg, newSize)) { - if (oldData) - free (oldData); - return FALSE; - } - } - - /* - * Initialize ybot. - * In the upcoming loop, ybot and ytop serve different functions depending - * on whether the band being handled is an overlapping or non-overlapping - * band. - * In the case of a non-overlapping band (only one of the regions - * has points in the band), ybot is the bottom of the most recent - * intersection and thus clips the top of the rectangles in that band. - * ytop is the top of the next intersection between the two regions and - * serves to clip the bottom of the rectangles in the current band. - * For an overlapping band (where the two regions intersect), ytop clips - * the top of the rectangles of both regions and ybot clips the bottoms. - */ - - ybot = MIN(r1->y1, r2->y1); - - /* - * prevBand serves to mark the start of the previous band so rectangles - * can be coalesced into larger rectangles. qv. pixman_coalesce, above. - * In the beginning, there is no previous band, so prevBand == curBand - * (curBand is set later on, of course, but the first band will always - * start at index 0). prevBand and curBand must be indices because of - * the possible expansion, and resultant moving, of the new region's - * array of rectangles. - */ - prevBand = 0; - - do { - /* - * This algorithm proceeds one source-band (as opposed to a - * destination band, which is determined by where the two regions - * intersect) at a time. r1BandEnd and r2BandEnd serve to mark the - * rectangle after the last one in the current band for their - * respective regions. - */ - assert(r1 != r1End); - assert(r2 != r2End); - - FindBand(r1, r1BandEnd, r1End, r1y1); - FindBand(r2, r2BandEnd, r2End, r2y1); - - /* - * First handle the band that doesn't intersect, if any. - * - * Note that attention is restricted to one band in the - * non-intersecting region at once, so if a region has n - * bands between the current position and the next place it overlaps - * the other, this entire loop will be passed through n times. - */ - if (r1y1 < r2y1) { - if (appendNon1) { - top = MAX(r1y1, ybot); - bot = MIN(r1->y2, r2y1); - if (top != bot) { - curBand = newReg->data->numRects; - pixman_region_appendNonO(newReg, r1, r1BandEnd, top, bot); - Coalesce(newReg, prevBand, curBand); - } - } - ytop = r2y1; - } else if (r2y1 < r1y1) { - if (appendNon2) { - top = MAX(r2y1, ybot); - bot = MIN(r2->y2, r1y1); - if (top != bot) { - curBand = newReg->data->numRects; - pixman_region_appendNonO(newReg, r2, r2BandEnd, top, bot); - Coalesce(newReg, prevBand, curBand); - } - } - ytop = r1y1; - } else { - ytop = r1y1; - } - - /* - * Now see if we've hit an intersecting band. The two bands only - * intersect if ybot > ytop - */ - ybot = MIN(r1->y2, r2->y2); - if (ybot > ytop) { - curBand = newReg->data->numRects; - (* overlapFunc)(newReg, r1, r1BandEnd, r2, r2BandEnd, ytop, ybot, - pOverlap); - Coalesce(newReg, prevBand, curBand); - } - - /* - * If we've finished with a band (y2 == ybot) we skip forward - * in the region to the next band. - */ - if (r1->y2 == ybot) r1 = r1BandEnd; - if (r2->y2 == ybot) r2 = r2BandEnd; - - } while (r1 != r1End && r2 != r2End); - - /* - * Deal with whichever region (if any) still has rectangles left. - * - * We only need to worry about banding and coalescing for the very first - * band left. After that, we can just group all remaining boxes, - * regardless of how many bands, into one final append to the list. - */ - - if ((r1 != r1End) && appendNon1) { - /* Do first nonOverlap1Func call, which may be able to coalesce */ - FindBand(r1, r1BandEnd, r1End, r1y1); - curBand = newReg->data->numRects; - pixman_region_appendNonO(newReg, r1, r1BandEnd, MAX(r1y1, ybot), r1->y2); - Coalesce(newReg, prevBand, curBand); - /* Just append the rest of the boxes */ - AppendRegions(newReg, r1BandEnd, r1End); - - } else if ((r2 != r2End) && appendNon2) { - /* Do first nonOverlap2Func call, which may be able to coalesce */ - FindBand(r2, r2BandEnd, r2End, r2y1); - curBand = newReg->data->numRects; - pixman_region_appendNonO(newReg, r2, r2BandEnd, MAX(r2y1, ybot), r2->y2); - Coalesce(newReg, prevBand, curBand); - /* Append rest of boxes */ - AppendRegions(newReg, r2BandEnd, r2End); - } - - if (oldData) - free(oldData); - - if (!(numRects = newReg->data->numRects)) - { - freeData(newReg); - newReg->data = pixman_region_emptyData; - } - else if (numRects == 1) - { - newReg->extents = *PIXREGION_BOXPTR(newReg); - freeData(newReg); - newReg->data = (region_data_type_t *)NULL; - } - else - { - DOWNSIZE(newReg, numRects); - } - - return TRUE; -} - -/*- - *----------------------------------------------------------------------- - * pixman_set_extents -- - * Reset the extents of a region to what they should be. Called by - * pixman_region_subtract and pixman_region_intersect as they can't figure it out along the - * way or do so easily, as pixman_region_union can. - * - * Results: - * None. - * - * Side Effects: - * The region's 'extents' structure is overwritten. - * - *----------------------------------------------------------------------- - */ -static void -pixman_set_extents (region_type_t *region) -{ - box_type_t *box, *boxEnd; - - if (!region->data) - return; - if (!region->data->size) - { - region->extents.x2 = region->extents.x1; - region->extents.y2 = region->extents.y1; - return; - } - - box = PIXREGION_BOXPTR(region); - boxEnd = PIXREGION_END(region); - - /* - * Since box is the first rectangle in the region, it must have the - * smallest y1 and since boxEnd is the last rectangle in the region, - * it must have the largest y2, because of banding. Initialize x1 and - * x2 from box and boxEnd, resp., as good things to initialize them - * to... - */ - region->extents.x1 = box->x1; - region->extents.y1 = box->y1; - region->extents.x2 = boxEnd->x2; - region->extents.y2 = boxEnd->y2; - - assert(region->extents.y1 < region->extents.y2); - while (box <= boxEnd) { - if (box->x1 < region->extents.x1) - region->extents.x1 = box->x1; - if (box->x2 > region->extents.x2) - region->extents.x2 = box->x2; - box++; - }; - - assert(region->extents.x1 < region->extents.x2); -} - -/*====================================================================== - * Region Intersection - *====================================================================*/ -/*- - *----------------------------------------------------------------------- - * pixman_region_intersectO -- - * Handle an overlapping band for pixman_region_intersect. - * - * Results: - * TRUE if successful. - * - * Side Effects: - * Rectangles may be added to the region. - * - *----------------------------------------------------------------------- - */ -/*ARGSUSED*/ -static pixman_bool_t -pixman_region_intersectO (region_type_t *region, - box_type_t *r1, - box_type_t *r1End, - box_type_t *r2, - box_type_t *r2End, - int y1, - int y2, - int *pOverlap) -{ - int x1; - int x2; - box_type_t * pNextRect; - - pNextRect = PIXREGION_TOP(region); - - assert(y1 < y2); - assert(r1 != r1End && r2 != r2End); - - do { - x1 = MAX(r1->x1, r2->x1); - x2 = MIN(r1->x2, r2->x2); - - /* - * If there's any overlap between the two rectangles, add that - * overlap to the new region. - */ - if (x1 < x2) - NEWRECT(region, pNextRect, x1, y1, x2, y2); - - /* - * Advance the pointer(s) with the leftmost right side, since the next - * rectangle on that list may still overlap the other region's - * current rectangle. - */ - if (r1->x2 == x2) { - r1++; - } - if (r2->x2 == x2) { - r2++; - } - } while ((r1 != r1End) && (r2 != r2End)); - - return TRUE; -} - -PIXMAN_EXPORT pixman_bool_t -PREFIX(_intersect) (region_type_t * newReg, - region_type_t * reg1, - region_type_t * reg2) -{ - good(reg1); - good(reg2); - good(newReg); - /* check for trivial reject */ - if (PIXREGION_NIL(reg1) || PIXREGION_NIL(reg2) || - !EXTENTCHECK(®1->extents, ®2->extents)) - { - /* Covers about 20% of all cases */ - freeData(newReg); - newReg->extents.x2 = newReg->extents.x1; - newReg->extents.y2 = newReg->extents.y1; - if (PIXREGION_NAR(reg1) || PIXREGION_NAR(reg2)) - { - newReg->data = pixman_brokendata; - return FALSE; - } - else - newReg->data = pixman_region_emptyData; - } - else if (!reg1->data && !reg2->data) - { - /* Covers about 80% of cases that aren't trivially rejected */ - newReg->extents.x1 = MAX(reg1->extents.x1, reg2->extents.x1); - newReg->extents.y1 = MAX(reg1->extents.y1, reg2->extents.y1); - newReg->extents.x2 = MIN(reg1->extents.x2, reg2->extents.x2); - newReg->extents.y2 = MIN(reg1->extents.y2, reg2->extents.y2); - freeData(newReg); - newReg->data = (region_data_type_t *)NULL; - } - else if (!reg2->data && SUBSUMES(®2->extents, ®1->extents)) - { - return PREFIX(_copy) (newReg, reg1); - } - else if (!reg1->data && SUBSUMES(®1->extents, ®2->extents)) - { - return PREFIX(_copy) (newReg, reg2); - } - else if (reg1 == reg2) - { - return PREFIX(_copy) (newReg, reg1); - } - else - { - /* General purpose intersection */ - int overlap; /* result ignored */ - if (!pixman_op(newReg, reg1, reg2, pixman_region_intersectO, FALSE, FALSE, - &overlap)) - return FALSE; - pixman_set_extents(newReg); - } - - good(newReg); - return(TRUE); -} - -#define MERGERECT(r) \ -{ \ - if (r->x1 <= x2) { \ - /* Merge with current rectangle */ \ - if (r->x1 < x2) *pOverlap = TRUE; \ - if (x2 < r->x2) x2 = r->x2; \ - } else { \ - /* Add current rectangle, start new one */ \ - NEWRECT(region, pNextRect, x1, y1, x2, y2); \ - x1 = r->x1; \ - x2 = r->x2; \ - } \ - r++; \ -} - -/*====================================================================== - * Region Union - *====================================================================*/ - -/*- - *----------------------------------------------------------------------- - * pixman_region_unionO -- - * Handle an overlapping band for the union operation. Picks the - * left-most rectangle each time and merges it into the region. - * - * Results: - * TRUE if successful. - * - * Side Effects: - * region is overwritten. - * pOverlap is set to TRUE if any boxes overlap. - * - *----------------------------------------------------------------------- - */ -static pixman_bool_t -pixman_region_unionO ( - region_type_t *region, - box_type_t *r1, - box_type_t *r1End, - box_type_t *r2, - box_type_t *r2End, - int y1, - int y2, - int *pOverlap) -{ - box_type_t * pNextRect; - int x1; /* left and right side of current union */ - int x2; - - assert (y1 < y2); - assert(r1 != r1End && r2 != r2End); - - pNextRect = PIXREGION_TOP(region); - - /* Start off current rectangle */ - if (r1->x1 < r2->x1) - { - x1 = r1->x1; - x2 = r1->x2; - r1++; - } - else - { - x1 = r2->x1; - x2 = r2->x2; - r2++; - } - while (r1 != r1End && r2 != r2End) - { - if (r1->x1 < r2->x1) MERGERECT(r1) else MERGERECT(r2); - } - - /* Finish off whoever (if any) is left */ - if (r1 != r1End) - { - do - { - MERGERECT(r1); - } while (r1 != r1End); - } - else if (r2 != r2End) - { - do - { - MERGERECT(r2); - } while (r2 != r2End); - } - - /* Add current rectangle */ - NEWRECT(region, pNextRect, x1, y1, x2, y2); - - return TRUE; -} - -/* Convenience function for performing union of region with a - * single rectangle - */ -PIXMAN_EXPORT pixman_bool_t -PREFIX(_union_rect) (region_type_t *dest, - region_type_t *source, - int x, int y, - unsigned int width, unsigned int height) -{ - region_type_t region; - - if (!width || !height) - return PREFIX(_copy) (dest, source); - region.data = NULL; - region.extents.x1 = x; - region.extents.y1 = y; - region.extents.x2 = x + width; - region.extents.y2 = y + height; - - return PREFIX(_union) (dest, source, ®ion); -} - -PIXMAN_EXPORT pixman_bool_t -PREFIX(_union) (region_type_t *newReg, - region_type_t *reg1, - region_type_t *reg2) -{ - int overlap; /* result ignored */ - - /* Return TRUE if some overlap - * between reg1, reg2 - */ - good(reg1); - good(reg2); - good(newReg); - /* checks all the simple cases */ - - /* - * Region 1 and 2 are the same - */ - if (reg1 == reg2) - { - return PREFIX(_copy) (newReg, reg1); - } - - /* - * Region 1 is empty - */ - if (PIXREGION_NIL(reg1)) - { - if (PIXREGION_NAR(reg1)) - return pixman_break (newReg); - if (newReg != reg2) - return PREFIX(_copy) (newReg, reg2); - return TRUE; - } - - /* - * Region 2 is empty - */ - if (PIXREGION_NIL(reg2)) - { - if (PIXREGION_NAR(reg2)) - return pixman_break (newReg); - if (newReg != reg1) - return PREFIX(_copy) (newReg, reg1); - return TRUE; - } - - /* - * Region 1 completely subsumes region 2 - */ - if (!reg1->data && SUBSUMES(®1->extents, ®2->extents)) - { - if (newReg != reg1) - return PREFIX(_copy) (newReg, reg1); - return TRUE; - } - - /* - * Region 2 completely subsumes region 1 - */ - if (!reg2->data && SUBSUMES(®2->extents, ®1->extents)) - { - if (newReg != reg2) - return PREFIX(_copy) (newReg, reg2); - return TRUE; - } - - if (!pixman_op(newReg, reg1, reg2, pixman_region_unionO, TRUE, TRUE, &overlap)) - return FALSE; - - newReg->extents.x1 = MIN(reg1->extents.x1, reg2->extents.x1); - newReg->extents.y1 = MIN(reg1->extents.y1, reg2->extents.y1); - newReg->extents.x2 = MAX(reg1->extents.x2, reg2->extents.x2); - newReg->extents.y2 = MAX(reg1->extents.y2, reg2->extents.y2); - good(newReg); - return TRUE; -} - -/*====================================================================== - * Batch Rectangle Union - *====================================================================*/ - -#define ExchangeRects(a, b) \ -{ \ - box_type_t t; \ - t = rects[a]; \ - rects[a] = rects[b]; \ - rects[b] = t; \ -} - -static void -QuickSortRects( - box_type_t rects[], - int numRects) -{ - int y1; - int x1; - int i, j; - box_type_t *r; - - /* Always called with numRects > 1 */ - - do - { - if (numRects == 2) - { - if (rects[0].y1 > rects[1].y1 || - (rects[0].y1 == rects[1].y1 && rects[0].x1 > rects[1].x1)) - ExchangeRects(0, 1); - return; - } - - /* Choose partition element, stick in location 0 */ - ExchangeRects(0, numRects >> 1); - y1 = rects[0].y1; - x1 = rects[0].x1; - - /* Partition array */ - i = 0; - j = numRects; - do - { - r = &(rects[i]); - do - { - r++; - i++; - } while (i != numRects && - (r->y1 < y1 || (r->y1 == y1 && r->x1 < x1))); - r = &(rects[j]); - do - { - r--; - j--; - } while (y1 < r->y1 || (y1 == r->y1 && x1 < r->x1)); - if (i < j) - ExchangeRects(i, j); - } while (i < j); - - /* Move partition element back to middle */ - ExchangeRects(0, j); - - /* Recurse */ - if (numRects-j-1 > 1) - QuickSortRects(&rects[j+1], numRects-j-1); - numRects = j; - } while (numRects > 1); -} - -/*- - *----------------------------------------------------------------------- - * pixman_region_validate -- - * - * Take a ``region'' which is a non-y-x-banded random collection of - * rectangles, and compute a nice region which is the union of all the - * rectangles. - * - * Results: - * TRUE if successful. - * - * Side Effects: - * The passed-in ``region'' may be modified. - * pOverlap set to TRUE if any retangles overlapped, - * else FALSE; - * - * Strategy: - * Step 1. Sort the rectangles into ascending order with primary key y1 - * and secondary key x1. - * - * Step 2. Split the rectangles into the minimum number of proper y-x - * banded regions. This may require horizontally merging - * rectangles, and vertically coalescing bands. With any luck, - * this step in an identity transformation (ala the Box widget), - * or a coalescing into 1 box (ala Menus). - * - * Step 3. Merge the separate regions down to a single region by calling - * pixman_region_union. Maximize the work each pixman_region_union call does by using - * a binary merge. - * - *----------------------------------------------------------------------- - */ - -static pixman_bool_t -validate (region_type_t * badreg, - int *pOverlap) -{ - /* Descriptor for regions under construction in Step 2. */ - typedef struct { - region_type_t reg; - int prevBand; - int curBand; - } RegionInfo; - - int numRects; /* Original numRects for badreg */ - RegionInfo *ri; /* Array of current regions */ - int numRI; /* Number of entries used in ri */ - int sizeRI; /* Number of entries available in ri */ - int i; /* Index into rects */ - int j; /* Index into ri */ - RegionInfo *rit; /* &ri[j] */ - region_type_t * reg; /* ri[j].reg */ - box_type_t * box; /* Current box in rects */ - box_type_t * riBox; /* Last box in ri[j].reg */ - region_type_t * hreg; /* ri[j_half].reg */ - pixman_bool_t ret = TRUE; - - *pOverlap = FALSE; - if (!badreg->data) - { - good(badreg); - return TRUE; - } - numRects = badreg->data->numRects; - if (!numRects) - { - if (PIXREGION_NAR(badreg)) - return FALSE; - good(badreg); - return TRUE; - } - if (badreg->extents.x1 < badreg->extents.x2) - { - if ((numRects) == 1) - { - freeData(badreg); - badreg->data = (region_data_type_t *) NULL; - } - else - { - DOWNSIZE(badreg, numRects); - } - good(badreg); - return TRUE; - } - - /* Step 1: Sort the rects array into ascending (y1, x1) order */ - QuickSortRects(PIXREGION_BOXPTR(badreg), numRects); - - /* Step 2: Scatter the sorted array into the minimum number of regions */ - - /* Set up the first region to be the first rectangle in badreg */ - /* Note that step 2 code will never overflow the ri[0].reg rects array */ - ri = (RegionInfo *) pixman_malloc_ab (4, sizeof(RegionInfo)); - if (!ri) - return pixman_break (badreg); - sizeRI = 4; - numRI = 1; - ri[0].prevBand = 0; - ri[0].curBand = 0; - ri[0].reg = *badreg; - box = PIXREGION_BOXPTR(&ri[0].reg); - ri[0].reg.extents = *box; - ri[0].reg.data->numRects = 1; - badreg->extents = *pixman_region_emptyBox; - badreg->data = pixman_region_emptyData; - - /* Now scatter rectangles into the minimum set of valid regions. If the - next rectangle to be added to a region would force an existing rectangle - in the region to be split up in order to maintain y-x banding, just - forget it. Try the next region. If it doesn't fit cleanly into any - region, make a new one. */ - - for (i = numRects; --i > 0;) - { - box++; - /* Look for a region to append box to */ - for (j = numRI, rit = ri; --j >= 0; rit++) - { - reg = &rit->reg; - riBox = PIXREGION_END(reg); - - if (box->y1 == riBox->y1 && box->y2 == riBox->y2) - { - /* box is in same band as riBox. Merge or append it */ - if (box->x1 <= riBox->x2) - { - /* Merge it with riBox */ - if (box->x1 < riBox->x2) *pOverlap = TRUE; - if (box->x2 > riBox->x2) riBox->x2 = box->x2; - } - else - { - RECTALLOC_BAIL(reg, 1, bail); - *PIXREGION_TOP(reg) = *box; - reg->data->numRects++; - } - goto NextRect; /* So sue me */ - } - else if (box->y1 >= riBox->y2) - { - /* Put box into new band */ - if (reg->extents.x2 < riBox->x2) reg->extents.x2 = riBox->x2; - if (reg->extents.x1 > box->x1) reg->extents.x1 = box->x1; - Coalesce(reg, rit->prevBand, rit->curBand); - rit->curBand = reg->data->numRects; - RECTALLOC_BAIL(reg, 1, bail); - *PIXREGION_TOP(reg) = *box; - reg->data->numRects++; - goto NextRect; - } - /* Well, this region was inappropriate. Try the next one. */ - } /* for j */ - - /* Uh-oh. No regions were appropriate. Create a new one. */ - if (sizeRI == numRI) - { - size_t data_size; - - /* Oops, allocate space for new region information */ - sizeRI <<= 1; - - data_size = sizeRI * sizeof(RegionInfo); - if (data_size / sizeRI != sizeof(RegionInfo)) - goto bail; - rit = (RegionInfo *) realloc(ri, data_size); - if (!rit) - goto bail; - ri = rit; - rit = &ri[numRI]; - } - numRI++; - rit->prevBand = 0; - rit->curBand = 0; - rit->reg.extents = *box; - rit->reg.data = (region_data_type_t *)NULL; - if (!pixman_rect_alloc(&rit->reg, (i+numRI) / numRI)) /* MUST force allocation */ - goto bail; -NextRect: ; - } /* for i */ - - /* Make a final pass over each region in order to Coalesce and set - extents.x2 and extents.y2 */ - - for (j = numRI, rit = ri; --j >= 0; rit++) - { - reg = &rit->reg; - riBox = PIXREGION_END(reg); - reg->extents.y2 = riBox->y2; - if (reg->extents.x2 < riBox->x2) reg->extents.x2 = riBox->x2; - Coalesce(reg, rit->prevBand, rit->curBand); - if (reg->data->numRects == 1) /* keep unions happy below */ - { - freeData(reg); - reg->data = (region_data_type_t *)NULL; - } - } - - /* Step 3: Union all regions into a single region */ - while (numRI > 1) - { - int half = numRI/2; - for (j = numRI & 1; j < (half + (numRI & 1)); j++) - { - reg = &ri[j].reg; - hreg = &ri[j+half].reg; - if (!pixman_op(reg, reg, hreg, pixman_region_unionO, TRUE, TRUE, pOverlap)) - ret = FALSE; - if (hreg->extents.x1 < reg->extents.x1) - reg->extents.x1 = hreg->extents.x1; - if (hreg->extents.y1 < reg->extents.y1) - reg->extents.y1 = hreg->extents.y1; - if (hreg->extents.x2 > reg->extents.x2) - reg->extents.x2 = hreg->extents.x2; - if (hreg->extents.y2 > reg->extents.y2) - reg->extents.y2 = hreg->extents.y2; - freeData(hreg); - } - numRI -= half; - if (!ret) - goto bail; - } - *badreg = ri[0].reg; - free(ri); - good(badreg); - return ret; -bail: - for (i = 0; i < numRI; i++) - freeData(&ri[i].reg); - free (ri); - - return pixman_break (badreg); -} - -/*====================================================================== - * Region Subtraction - *====================================================================*/ - -/*- - *----------------------------------------------------------------------- - * pixman_region_subtractO -- - * Overlapping band subtraction. x1 is the left-most point not yet - * checked. - * - * Results: - * TRUE if successful. - * - * Side Effects: - * region may have rectangles added to it. - * - *----------------------------------------------------------------------- - */ -/*ARGSUSED*/ -static pixman_bool_t -pixman_region_subtractO ( - region_type_t * region, - box_type_t * r1, - box_type_t * r1End, - box_type_t * r2, - box_type_t * r2End, - int y1, - int y2, - int *pOverlap) -{ - box_type_t * pNextRect; - int x1; - - x1 = r1->x1; - - assert(y1x2 <= x1) - { - /* - * Subtrahend entirely to left of minuend: go to next subtrahend. - */ - r2++; - } - else if (r2->x1 <= x1) - { - /* - * Subtrahend preceeds minuend: nuke left edge of minuend. - */ - x1 = r2->x2; - if (x1 >= r1->x2) - { - /* - * Minuend completely covered: advance to next minuend and - * reset left fence to edge of new minuend. - */ - r1++; - if (r1 != r1End) - x1 = r1->x1; - } - else - { - /* - * Subtrahend now used up since it doesn't extend beyond - * minuend - */ - r2++; - } - } - else if (r2->x1 < r1->x2) - { - /* - * Left part of subtrahend covers part of minuend: add uncovered - * part of minuend to region and skip to next subtrahend. - */ - assert(x1x1); - NEWRECT(region, pNextRect, x1, y1, r2->x1, y2); - - x1 = r2->x2; - if (x1 >= r1->x2) - { - /* - * Minuend used up: advance to new... - */ - r1++; - if (r1 != r1End) - x1 = r1->x1; - } - else - { - /* - * Subtrahend used up - */ - r2++; - } - } - else - { - /* - * Minuend used up: add any remaining piece before advancing. - */ - if (r1->x2 > x1) - NEWRECT(region, pNextRect, x1, y1, r1->x2, y2); - r1++; - if (r1 != r1End) - x1 = r1->x1; - } - } while ((r1 != r1End) && (r2 != r2End)); - - /* - * Add remaining minuend rectangles to region. - */ - while (r1 != r1End) - { - assert(x1x2); - NEWRECT(region, pNextRect, x1, y1, r1->x2, y2); - r1++; - if (r1 != r1End) - x1 = r1->x1; - } - return TRUE; -} - -/*- - *----------------------------------------------------------------------- - * pixman_region_subtract -- - * Subtract regS from regM and leave the result in regD. - * S stands for subtrahend, M for minuend and D for difference. - * - * Results: - * TRUE if successful. - * - * Side Effects: - * regD is overwritten. - * - *----------------------------------------------------------------------- - */ -PIXMAN_EXPORT pixman_bool_t -PREFIX(_subtract) (region_type_t * regD, - region_type_t * regM, - region_type_t * regS) -{ - int overlap; /* result ignored */ - - good(regM); - good(regS); - good(regD); - /* check for trivial rejects */ - if (PIXREGION_NIL(regM) || PIXREGION_NIL(regS) || - !EXTENTCHECK(®M->extents, ®S->extents)) - { - if (PIXREGION_NAR (regS)) - return pixman_break (regD); - return PREFIX(_copy) (regD, regM); - } - else if (regM == regS) - { - freeData(regD); - regD->extents.x2 = regD->extents.x1; - regD->extents.y2 = regD->extents.y1; - regD->data = pixman_region_emptyData; - return TRUE; - } - - /* Add those rectangles in region 1 that aren't in region 2, - do yucky substraction for overlaps, and - just throw away rectangles in region 2 that aren't in region 1 */ - if (!pixman_op(regD, regM, regS, pixman_region_subtractO, TRUE, FALSE, &overlap)) - return FALSE; - - /* - * Can't alter RegD's extents before we call pixman_op because - * it might be one of the source regions and pixman_op depends - * on the extents of those regions being unaltered. Besides, this - * way there's no checking against rectangles that will be nuked - * due to coalescing, so we have to examine fewer rectangles. - */ - pixman_set_extents(regD); - good(regD); - return TRUE; -} - -/*====================================================================== - * Region Inversion - *====================================================================*/ - -/*- - *----------------------------------------------------------------------- - * pixman_region_inverse -- - * Take a region and a box and return a region that is everything - * in the box but not in the region. The careful reader will note - * that this is the same as subtracting the region from the box... - * - * Results: - * TRUE. - * - * Side Effects: - * newReg is overwritten. - * - *----------------------------------------------------------------------- - */ -pixman_bool_t -PIXMAN_EXPORT PREFIX(_inverse) (region_type_t * newReg, /* Destination region */ - region_type_t * reg1, /* Region to invert */ - box_type_t * invRect) /* Bounding box for inversion */ -{ - region_type_t invReg; /* Quick and dirty region made from the - * bounding box */ - int overlap; /* result ignored */ - - good(reg1); - good(newReg); - /* check for trivial rejects */ - if (PIXREGION_NIL(reg1) || !EXTENTCHECK(invRect, ®1->extents)) - { - if (PIXREGION_NAR(reg1)) - return pixman_break (newReg); - newReg->extents = *invRect; - freeData(newReg); - newReg->data = (region_data_type_t *)NULL; - return TRUE; - } - - /* Add those rectangles in region 1 that aren't in region 2, - do yucky substraction for overlaps, and - just throw away rectangles in region 2 that aren't in region 1 */ - invReg.extents = *invRect; - invReg.data = (region_data_type_t *)NULL; - if (!pixman_op(newReg, &invReg, reg1, pixman_region_subtractO, TRUE, FALSE, &overlap)) - return FALSE; - - /* - * Can't alter newReg's extents before we call pixman_op because - * it might be one of the source regions and pixman_op depends - * on the extents of those regions being unaltered. Besides, this - * way there's no checking against rectangles that will be nuked - * due to coalescing, so we have to examine fewer rectangles. - */ - pixman_set_extents(newReg); - good(newReg); - return TRUE; -} - -/* - * RectIn(region, rect) - * This routine takes a pointer to a region and a pointer to a box - * and determines if the box is outside/inside/partly inside the region. - * - * The idea is to travel through the list of rectangles trying to cover the - * passed box with them. Anytime a piece of the rectangle isn't covered - * by a band of rectangles, partOut is set TRUE. Any time a rectangle in - * the region covers part of the box, partIn is set TRUE. The process ends - * when either the box has been completely covered (we reached a band that - * doesn't overlap the box, partIn is TRUE and partOut is false), the - * box has been partially covered (partIn == partOut == TRUE -- because of - * the banding, the first time this is true we know the box is only - * partially in the region) or is outside the region (we reached a band - * that doesn't overlap the box at all and partIn is false) - */ - -pixman_region_overlap_t -PIXMAN_EXPORT PREFIX(_contains_rectangle) (region_type_t * region, - box_type_t * prect) -{ - int x; - int y; - box_type_t * pbox; - box_type_t * pboxEnd; - int partIn, partOut; - int numRects; - - good(region); - numRects = PIXREGION_NUM_RECTS(region); - /* useful optimization */ - if (!numRects || !EXTENTCHECK(®ion->extents, prect)) - return(PIXMAN_REGION_OUT); - - if (numRects == 1) - { - /* We know that it must be PIXMAN_REGION_IN or PIXMAN_REGION_PART */ - if (SUBSUMES(®ion->extents, prect)) - return(PIXMAN_REGION_IN); - else - return(PIXMAN_REGION_PART); - } - - partOut = FALSE; - partIn = FALSE; - - /* (x,y) starts at upper left of rect, moving to the right and down */ - x = prect->x1; - y = prect->y1; - - /* can stop when both partOut and partIn are TRUE, or we reach prect->y2 */ - for (pbox = PIXREGION_BOXPTR(region), pboxEnd = pbox + numRects; - pbox != pboxEnd; - pbox++) - { - - if (pbox->y2 <= y) - continue; /* getting up to speed or skipping remainder of band */ - - if (pbox->y1 > y) - { - partOut = TRUE; /* missed part of rectangle above */ - if (partIn || (pbox->y1 >= prect->y2)) - break; - y = pbox->y1; /* x guaranteed to be == prect->x1 */ - } - - if (pbox->x2 <= x) - continue; /* not far enough over yet */ - - if (pbox->x1 > x) - { - partOut = TRUE; /* missed part of rectangle to left */ - if (partIn) - break; - } - - if (pbox->x1 < prect->x2) - { - partIn = TRUE; /* definitely overlap */ - if (partOut) - break; - } - - if (pbox->x2 >= prect->x2) - { - y = pbox->y2; /* finished with this band */ - if (y >= prect->y2) - break; - x = prect->x1; /* reset x out to left again */ - } - else - { - /* - * Because boxes in a band are maximal width, if the first box - * to overlap the rectangle doesn't completely cover it in that - * band, the rectangle must be partially out, since some of it - * will be uncovered in that band. partIn will have been set true - * by now... - */ - partOut = TRUE; - break; - } - } - - if (partIn) - { - if (y < prect->y2) - return PIXMAN_REGION_PART; - else - return PIXMAN_REGION_IN; - } - else - { - return PIXMAN_REGION_OUT; - } -} - -/* PREFIX(_translate) (region, x, y) - translates in place -*/ - -PIXMAN_EXPORT void -PREFIX(_translate) (region_type_t * region, int x, int y) -{ - int x1, x2, y1, y2; - int nbox; - box_type_t * pbox; - - good(region); - region->extents.x1 = x1 = region->extents.x1 + x; - region->extents.y1 = y1 = region->extents.y1 + y; - region->extents.x2 = x2 = region->extents.x2 + x; - region->extents.y2 = y2 = region->extents.y2 + y; - if (((x1 - SHRT_MIN)|(y1 - SHRT_MIN)|(SHRT_MAX - x2)|(SHRT_MAX - y2)) >= 0) - { - if (region->data && (nbox = region->data->numRects)) - { - for (pbox = PIXREGION_BOXPTR(region); nbox--; pbox++) - { - pbox->x1 += x; - pbox->y1 += y; - pbox->x2 += x; - pbox->y2 += y; - } - } - return; - } - if (((x2 - SHRT_MIN)|(y2 - SHRT_MIN)|(SHRT_MAX - x1)|(SHRT_MAX - y1)) <= 0) - { - region->extents.x2 = region->extents.x1; - region->extents.y2 = region->extents.y1; - freeData(region); - region->data = pixman_region_emptyData; - return; - } - if (x1 < SHRT_MIN) - region->extents.x1 = SHRT_MIN; - else if (x2 > SHRT_MAX) - region->extents.x2 = SHRT_MAX; - if (y1 < SHRT_MIN) - region->extents.y1 = SHRT_MIN; - else if (y2 > SHRT_MAX) - region->extents.y2 = SHRT_MAX; - if (region->data && (nbox = region->data->numRects)) - { - box_type_t * pboxout; - - for (pboxout = pbox = PIXREGION_BOXPTR(region); nbox--; pbox++) - { - pboxout->x1 = x1 = pbox->x1 + x; - pboxout->y1 = y1 = pbox->y1 + y; - pboxout->x2 = x2 = pbox->x2 + x; - pboxout->y2 = y2 = pbox->y2 + y; - if (((x2 - SHRT_MIN)|(y2 - SHRT_MIN)| - (SHRT_MAX - x1)|(SHRT_MAX - y1)) <= 0) - { - region->data->numRects--; - continue; - } - if (x1 < SHRT_MIN) - pboxout->x1 = SHRT_MIN; - else if (x2 > SHRT_MAX) - pboxout->x2 = SHRT_MAX; - if (y1 < SHRT_MIN) - pboxout->y1 = SHRT_MIN; - else if (y2 > SHRT_MAX) - pboxout->y2 = SHRT_MAX; - pboxout++; - } - if (pboxout != pbox) - { - if (region->data->numRects == 1) - { - region->extents = *PIXREGION_BOXPTR(region); - freeData(region); - region->data = (region_data_type_t *)NULL; - } - else - pixman_set_extents(region); - } - } -} - -PIXMAN_EXPORT void -PREFIX(_reset) (region_type_t *region, box_type_t *box) -{ - good(region); - assert(box->x1<=box->x2); - assert(box->y1<=box->y2); - region->extents = *box; - freeData(region); - region->data = (region_data_type_t *)NULL; -} - -/* box is "return" value */ -PIXMAN_EXPORT int -PREFIX(_contains_point) (region_type_t * region, - int x, int y, - box_type_t * box) -{ - box_type_t *pbox, *pboxEnd; - int numRects; - - good(region); - numRects = PIXREGION_NUM_RECTS(region); - if (!numRects || !INBOX(®ion->extents, x, y)) - return(FALSE); - if (numRects == 1) - { - if (box) - *box = region->extents; - - return(TRUE); - } - for (pbox = PIXREGION_BOXPTR(region), pboxEnd = pbox + numRects; - pbox != pboxEnd; - pbox++) - { - if (y >= pbox->y2) - continue; /* not there yet */ - if ((y < pbox->y1) || (x < pbox->x1)) - break; /* missed it */ - if (x >= pbox->x2) - continue; /* not there yet */ - - if (box) - *box = *pbox; - - return(TRUE); - } - return(FALSE); -} - -PIXMAN_EXPORT int -PREFIX(_not_empty) (region_type_t * region) -{ - good(region); - return(!PIXREGION_NIL(region)); -} - -PIXMAN_EXPORT box_type_t * -PREFIX(_extents) (region_type_t * region) -{ - good(region); - return(®ion->extents); -} - -/* - Clip a list of scanlines to a region. The caller has allocated the - space. FSorted is non-zero if the scanline origins are in ascending - order. - returns the number of new, clipped scanlines. -*/ - -PIXMAN_EXPORT pixman_bool_t -PREFIX(_selfcheck) (reg) - region_type_t * reg; -{ - int i, numRects; - - if ((reg->extents.x1 > reg->extents.x2) || - (reg->extents.y1 > reg->extents.y2)) - return FALSE; - numRects = PIXREGION_NUM_RECTS(reg); - if (!numRects) - return ((reg->extents.x1 == reg->extents.x2) && - (reg->extents.y1 == reg->extents.y2) && - (reg->data->size || (reg->data == pixman_region_emptyData))); - else if (numRects == 1) - return (!reg->data); - else - { - box_type_t * pboxP, * pboxN; - box_type_t box; - - pboxP = PIXREGION_RECTS(reg); - box = *pboxP; - box.y2 = pboxP[numRects-1].y2; - pboxN = pboxP + 1; - for (i = numRects; --i > 0; pboxP++, pboxN++) - { - if ((pboxN->x1 >= pboxN->x2) || - (pboxN->y1 >= pboxN->y2)) - return FALSE; - if (pboxN->x1 < box.x1) - box.x1 = pboxN->x1; - if (pboxN->x2 > box.x2) - box.x2 = pboxN->x2; - if ((pboxN->y1 < pboxP->y1) || - ((pboxN->y1 == pboxP->y1) && - ((pboxN->x1 < pboxP->x2) || (pboxN->y2 != pboxP->y2)))) - return FALSE; - } - return ((box.x1 == reg->extents.x1) && - (box.x2 == reg->extents.x2) && - (box.y1 == reg->extents.y1) && - (box.y2 == reg->extents.y2)); - } -} - -PIXMAN_EXPORT pixman_bool_t -PREFIX(_init_rects) (region_type_t *region, - box_type_t *boxes, int count) -{ - int overlap; - - /* if it's 1, then we just want to set the extents, so call - * the existing method. */ - if (count == 1) { - PREFIX(_init_rect) (region, - boxes[0].x1, - boxes[0].y1, - boxes[0].x2 - boxes[0].x1, - boxes[0].y2 - boxes[0].y1); - return TRUE; - } - - PREFIX(_init) (region); - - /* if it's 0, don't call pixman_rect_alloc -- 0 rectangles is - * a special case, and causing pixman_rect_alloc would cause - * us to leak memory (because the 0-rect case should be the - * static pixman_region_emptyData data). - */ - if (count == 0) - return TRUE; - - if (!pixman_rect_alloc(region, count)) - return FALSE; - - /* Copy in the rects */ - memcpy (PIXREGION_RECTS(region), boxes, sizeof(box_type_t) * count); - region->data->numRects = count; - - /* Validate */ - region->extents.x1 = region->extents.x2 = 0; - return validate (region, &overlap); -} diff --git a/uppdev/plugin/pixman/lib/pixman-region16.c b/uppdev/plugin/pixman/lib/pixman-region16.c deleted file mode 100644 index e770ffe47..000000000 --- a/uppdev/plugin/pixman/lib/pixman-region16.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright © 2008 Red Hat, Inc. - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without - * fee, provided that the above copyright notice appear in all copies - * and that both that copyright notice and this permission notice - * appear in supporting documentation, and that the name of - * Red Hat, Inc. not be used in advertising or publicity pertaining to - * distribution of the software without specific, written prior - * permission. Red Hat, Inc. makes no representations about the - * suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL, - * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER - * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR - * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Author: Soren Sandmann - */ -#ifdef HAVE_CONFIG_H -#include -#endif - -#undef PIXMAN_DISABLE_DEPRECATED - -#include "pixman-private.h" - -#include - -typedef pixman_box16_t box_type_t; -typedef pixman_region16_data_t region_data_type_t; -typedef pixman_region16_t region_type_t; - -typedef struct { - int x, y; -} point_type_t; - -#define PREFIX(x) pixman_region##x - -PIXMAN_EXPORT void -pixman_region_set_static_pointers (pixman_box16_t *empty_box, - pixman_region16_data_t *empty_data, - pixman_region16_data_t *broken_data) -{ - pixman_region_internal_set_static_pointers (empty_box, empty_data, broken_data); -} - -pixman_bool_t -pixman_region16_copy_from_region32 (pixman_region16_t *dst, - pixman_region32_t *src) -{ - int n_boxes, i; - pixman_box32_t *boxes32; - pixman_box16_t *boxes16; - pixman_bool_t retval; - - boxes32 = pixman_region32_rectangles (src, &n_boxes); - - boxes16 = pixman_malloc_ab (n_boxes, sizeof (pixman_box16_t)); - - if (!boxes16) - return FALSE; - - for (i = 0; i < n_boxes; ++i) - { - boxes16[i].x1 = boxes32[i].x1; - boxes16[i].y1 = boxes32[i].y1; - boxes16[i].x2 = boxes32[i].x2; - boxes16[i].y2 = boxes32[i].y2; - } - - pixman_region_fini (dst); - retval = pixman_region_init_rects (dst, boxes16, n_boxes); - free (boxes16); - return retval; -} - -#include "pixman-region.c" diff --git a/uppdev/plugin/pixman/lib/pixman-region32.c b/uppdev/plugin/pixman/lib/pixman-region32.c deleted file mode 100644 index 80039c8a0..000000000 --- a/uppdev/plugin/pixman/lib/pixman-region32.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright © 2008 Red Hat, Inc. - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without - * fee, provided that the above copyright notice appear in all copies - * and that both that copyright notice and this permission notice - * appear in supporting documentation, and that the name of - * Red Hat, Inc. not be used in advertising or publicity pertaining to - * distribution of the software without specific, written prior - * permission. Red Hat, Inc. makes no representations about the - * suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL, - * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER - * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR - * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Author: Soren Sandmann - */ -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "pixman-private.h" - -#include - -typedef pixman_box32_t box_type_t; -typedef pixman_region32_data_t region_data_type_t; -typedef pixman_region32_t region_type_t; - -typedef struct { - int x, y; -} point_type_t; - -#define PREFIX(x) pixman_region32##x - -pixman_bool_t -pixman_region32_copy_from_region16 (pixman_region32_t *dst, - pixman_region16_t *src) -{ - int n_boxes, i; - pixman_box16_t *boxes16; - pixman_box32_t *boxes32; - pixman_bool_t retval; - - boxes16 = pixman_region_rectangles (src, &n_boxes); - - boxes32 = pixman_malloc_ab (n_boxes, sizeof (pixman_box32_t)); - - if (!boxes32) - return FALSE; - - for (i = 0; i < n_boxes; ++i) - { - boxes32[i].x1 = boxes16[i].x1; - boxes32[i].y1 = boxes16[i].y1; - boxes32[i].x2 = boxes16[i].x2; - boxes32[i].y2 = boxes16[i].y2; - } - - pixman_region32_fini (dst); - retval = pixman_region32_init_rects (dst, boxes32, n_boxes); - free (boxes32); - return retval; -} - -#include "pixman-region.c" diff --git a/uppdev/plugin/pixman/lib/pixman-source.c b/uppdev/plugin/pixman/lib/pixman-source.c deleted file mode 100644 index 2f0448aa8..000000000 --- a/uppdev/plugin/pixman/lib/pixman-source.c +++ /dev/null @@ -1,709 +0,0 @@ -/* - * - * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc. - * 2005 Lars Knoll & Zack Rusin, Trolltech - * - * 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. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS 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. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include - -#include "pixman-private.h" - -typedef struct -{ - uint32_t left_ag; - uint32_t left_rb; - uint32_t right_ag; - uint32_t right_rb; - int32_t left_x; - int32_t right_x; - int32_t stepper; - - pixman_gradient_stop_t *stops; - int num_stops; - unsigned int spread; - - int need_reset; -} GradientWalker; - -static void -_gradient_walker_init (GradientWalker *walker, - gradient_t *gradient, - unsigned int spread) -{ - walker->num_stops = gradient->n_stops; - walker->stops = gradient->stops; - walker->left_x = 0; - walker->right_x = 0x10000; - walker->stepper = 0; - walker->left_ag = 0; - walker->left_rb = 0; - walker->right_ag = 0; - walker->right_rb = 0; - walker->spread = spread; - - walker->need_reset = TRUE; -} - -static void -_gradient_walker_reset (GradientWalker *walker, - pixman_fixed_32_32_t pos) -{ - int32_t x, left_x, right_x; - pixman_color_t *left_c, *right_c; - int n, count = walker->num_stops; - pixman_gradient_stop_t * stops = walker->stops; - - static const pixman_color_t transparent_black = { 0, 0, 0, 0 }; - - switch (walker->spread) - { - case PIXMAN_REPEAT_NORMAL: - x = (int32_t)pos & 0xFFFF; - for (n = 0; n < count; n++) - if (x < stops[n].x) - break; - if (n == 0) { - left_x = stops[count-1].x - 0x10000; - left_c = &stops[count-1].color; - } else { - left_x = stops[n-1].x; - left_c = &stops[n-1].color; - } - - if (n == count) { - right_x = stops[0].x + 0x10000; - right_c = &stops[0].color; - } else { - right_x = stops[n].x; - right_c = &stops[n].color; - } - left_x += (pos - x); - right_x += (pos - x); - break; - - case PIXMAN_REPEAT_PAD: - for (n = 0; n < count; n++) - if (pos < stops[n].x) - break; - - if (n == 0) { - left_x = INT32_MIN; - left_c = &stops[0].color; - } else { - left_x = stops[n-1].x; - left_c = &stops[n-1].color; - } - - if (n == count) { - right_x = INT32_MAX; - right_c = &stops[n-1].color; - } else { - right_x = stops[n].x; - right_c = &stops[n].color; - } - break; - - case PIXMAN_REPEAT_REFLECT: - x = (int32_t)pos & 0xFFFF; - if ((int32_t)pos & 0x10000) - x = 0x10000 - x; - for (n = 0; n < count; n++) - if (x < stops[n].x) - break; - - if (n == 0) { - left_x = -stops[0].x; - left_c = &stops[0].color; - } else { - left_x = stops[n-1].x; - left_c = &stops[n-1].color; - } - - if (n == count) { - right_x = 0x20000 - stops[n-1].x; - right_c = &stops[n-1].color; - } else { - right_x = stops[n].x; - right_c = &stops[n].color; - } - - if ((int32_t)pos & 0x10000) { - pixman_color_t *tmp_c; - int32_t tmp_x; - - tmp_x = 0x10000 - right_x; - right_x = 0x10000 - left_x; - left_x = tmp_x; - - tmp_c = right_c; - right_c = left_c; - left_c = tmp_c; - - x = 0x10000 - x; - } - left_x += (pos - x); - right_x += (pos - x); - break; - - default: /* RepeatNone */ - for (n = 0; n < count; n++) - if (pos < stops[n].x) - break; - - if (n == 0) - { - left_x = INT32_MIN; - right_x = stops[0].x; - left_c = right_c = (pixman_color_t*) &transparent_black; - } - else if (n == count) - { - left_x = stops[n-1].x; - right_x = INT32_MAX; - left_c = right_c = (pixman_color_t*) &transparent_black; - } - else - { - left_x = stops[n-1].x; - right_x = stops[n].x; - left_c = &stops[n-1].color; - right_c = &stops[n].color; - } - } - - walker->left_x = left_x; - walker->right_x = right_x; - walker->left_ag = ((left_c->alpha >> 8) << 16) | (left_c->green >> 8); - walker->left_rb = ((left_c->red & 0xff00) << 8) | (left_c->blue >> 8); - walker->right_ag = ((right_c->alpha >> 8) << 16) | (right_c->green >> 8); - walker->right_rb = ((right_c->red & 0xff00) << 8) | (right_c->blue >> 8); - - if ( walker->left_x == walker->right_x || - ( walker->left_ag == walker->right_ag && - walker->left_rb == walker->right_rb ) ) - { - walker->stepper = 0; - } - else - { - int32_t width = right_x - left_x; - walker->stepper = ((1 << 24) + width/2)/width; - } - - walker->need_reset = FALSE; -} - -#define GRADIENT_WALKER_NEED_RESET(w,x) \ - ( (w)->need_reset || (x) < (w)->left_x || (x) >= (w)->right_x) - - -/* the following assumes that GRADIENT_WALKER_NEED_RESET(w,x) is FALSE */ -static uint32_t -_gradient_walker_pixel (GradientWalker *walker, - pixman_fixed_32_32_t x) -{ - int dist, idist; - uint32_t t1, t2, a, color; - - if (GRADIENT_WALKER_NEED_RESET (walker, x)) - _gradient_walker_reset (walker, x); - - dist = ((int)(x - walker->left_x)*walker->stepper) >> 16; - idist = 256 - dist; - - /* combined INTERPOLATE and premultiply */ - t1 = walker->left_rb*idist + walker->right_rb*dist; - t1 = (t1 >> 8) & 0xff00ff; - - t2 = walker->left_ag*idist + walker->right_ag*dist; - t2 &= 0xff00ff00; - - color = t2 & 0xff000000; - a = t2 >> 24; - - t1 = t1*a + 0x800080; - t1 = (t1 + ((t1 >> 8) & 0xff00ff)) >> 8; - - t2 = (t2 >> 8)*a + 0x800080; - t2 = (t2 + ((t2 >> 8) & 0xff00ff)); - - return (color | (t1 & 0xff00ff) | (t2 & 0xff00)); -} - -void pixmanFetchSourcePict(source_image_t * pict, int x, int y, int width, - uint32_t *buffer, uint32_t *mask, uint32_t maskBits) -{ -#if 0 - SourcePictPtr pGradient = pict->pSourcePict; -#endif - GradientWalker walker; - uint32_t *end = buffer + width; - gradient_t *gradient; - - if (pict->common.type == SOLID) - { - register uint32_t color = ((solid_fill_t *)pict)->color; - - while (buffer < end) - *(buffer++) = color; - - return; - } - - gradient = (gradient_t *)pict; - - _gradient_walker_init (&walker, gradient, pict->common.repeat); - - if (pict->common.type == LINEAR) { - pixman_vector_t v, unit; - pixman_fixed_32_32_t l; - pixman_fixed_48_16_t dx, dy, a, b, off; - linear_gradient_t *linear = (linear_gradient_t *)pict; - - /* reference point is the center of the pixel */ - v.vector[0] = pixman_int_to_fixed(x) + pixman_fixed_1/2; - v.vector[1] = pixman_int_to_fixed(y) + pixman_fixed_1/2; - v.vector[2] = pixman_fixed_1; - if (pict->common.transform) { - if (!pixman_transform_point_3d (pict->common.transform, &v)) - return; - unit.vector[0] = pict->common.transform->matrix[0][0]; - unit.vector[1] = pict->common.transform->matrix[1][0]; - unit.vector[2] = pict->common.transform->matrix[2][0]; - } else { - unit.vector[0] = pixman_fixed_1; - unit.vector[1] = 0; - unit.vector[2] = 0; - } - - dx = linear->p2.x - linear->p1.x; - dy = linear->p2.y - linear->p1.y; - l = dx*dx + dy*dy; - if (l != 0) { - a = (dx << 32) / l; - b = (dy << 32) / l; - off = (-a*linear->p1.x - b*linear->p1.y)>>16; - } - if (l == 0 || (unit.vector[2] == 0 && v.vector[2] == pixman_fixed_1)) { - pixman_fixed_48_16_t inc, t; - /* affine transformation only */ - if (l == 0) { - t = 0; - inc = 0; - } else { - t = ((a*v.vector[0] + b*v.vector[1]) >> 16) + off; - inc = (a * unit.vector[0] + b * unit.vector[1]) >> 16; - } - - if (pict->class == SOURCE_IMAGE_CLASS_VERTICAL) - { - register uint32_t color; - - color = _gradient_walker_pixel( &walker, t ); - while (buffer < end) - *(buffer++) = color; - } - else - { - if (!mask) { - while (buffer < end) - { - *(buffer) = _gradient_walker_pixel (&walker, t); - buffer += 1; - t += inc; - } - } else { - while (buffer < end) { - if (*mask++ & maskBits) - { - *(buffer) = _gradient_walker_pixel (&walker, t); - } - buffer += 1; - t += inc; - } - } - } - } - else /* projective transformation */ - { - pixman_fixed_48_16_t t; - - if (pict->class == SOURCE_IMAGE_CLASS_VERTICAL) - { - register uint32_t color; - - if (v.vector[2] == 0) - { - t = 0; - } - else - { - pixman_fixed_48_16_t x, y; - - x = ((pixman_fixed_48_16_t) v.vector[0] << 16) / v.vector[2]; - y = ((pixman_fixed_48_16_t) v.vector[1] << 16) / v.vector[2]; - t = ((a * x + b * y) >> 16) + off; - } - - color = _gradient_walker_pixel( &walker, t ); - while (buffer < end) - *(buffer++) = color; - } - else - { - while (buffer < end) - { - if (!mask || *mask++ & maskBits) - { - if (v.vector[2] == 0) { - t = 0; - } else { - pixman_fixed_48_16_t x, y; - x = ((pixman_fixed_48_16_t)v.vector[0] << 16) / v.vector[2]; - y = ((pixman_fixed_48_16_t)v.vector[1] << 16) / v.vector[2]; - t = ((a*x + b*y) >> 16) + off; - } - *(buffer) = _gradient_walker_pixel (&walker, t); - } - ++buffer; - v.vector[0] += unit.vector[0]; - v.vector[1] += unit.vector[1]; - v.vector[2] += unit.vector[2]; - } - } - } - } else { - -/* - * In the radial gradient problem we are given two circles (câ‚,râ‚) and - * (câ‚‚,râ‚‚) that define the gradient itself. Then, for any point p, we - * must compute the value(s) of t within [0.0, 1.0] representing the - * circle(s) that would color the point. - * - * There are potentially two values of t since the point p can be - * colored by both sides of the circle, (which happens whenever one - * circle is not entirely contained within the other). - * - * If we solve for a value of t that is outside of [0.0, 1.0] then we - * use the extend mode (NONE, REPEAT, REFLECT, or PAD) to map to a - * value within [0.0, 1.0]. - * - * Here is an illustration of the problem: - * - * pâ‚‚ - * p • - * • ╲ - * · ╲râ‚‚ - * p₠· ╲ - * • θ╲ - * ╲ ╌╌• - * ╲r₠· câ‚‚ - * θ╲ · - * ╌╌• - * câ‚ - * - * Given (câ‚,râ‚), (câ‚‚,râ‚‚) and p, we must find an angle θ such that two - * points pâ‚ and pâ‚‚ on the two circles are collinear with p. Then, the - * desired value of t is the ratio of the length of pâ‚p to the length - * of pâ‚pâ‚‚. - * - * So, we have six unknown values: (pâ‚x, pâ‚y), (pâ‚‚x, pâ‚‚y), θ and t. - * We can also write six equations that constrain the problem: - * - * Point pâ‚ is a distance râ‚ from câ‚ at an angle of θ: - * - * 1. pâ‚x = câ‚x + râ‚·cos θ - * 2. pâ‚y = câ‚y + râ‚·sin θ - * - * Point pâ‚‚ is a distance râ‚‚ from câ‚‚ at an angle of θ: - * - * 3. pâ‚‚x = câ‚‚x + r2·cos θ - * 4. pâ‚‚y = câ‚‚y + r2·sin θ - * - * Point p lies at a fraction t along the line segment pâ‚pâ‚‚: - * - * 5. px = t·pâ‚‚x + (1-t)·pâ‚x - * 6. py = t·pâ‚‚y + (1-t)·pâ‚y - * - * To solve, first subtitute 1-4 into 5 and 6: - * - * px = t·(câ‚‚x + r₂·cos θ) + (1-t)·(câ‚x + râ‚·cos θ) - * py = t·(câ‚‚y + r₂·sin θ) + (1-t)·(câ‚y + râ‚·sin θ) - * - * Then solve each for cos θ and sin θ expressed as a function of t: - * - * cos θ = (-(câ‚‚x - câ‚x)·t + (px - câ‚x)) / ((râ‚‚-râ‚)·t + râ‚) - * sin θ = (-(câ‚‚y - câ‚y)·t + (py - câ‚y)) / ((râ‚‚-râ‚)·t + râ‚) - * - * To simplify this a bit, we define new variables for several of the - * common terms as shown below: - * - * pâ‚‚ - * p • - * • ╲ - * · ┆ ╲râ‚‚ - * p₠· ┆ ╲ - * • pdy┆ ╲ - * ╲ ┆ •câ‚‚ - * ╲r₠┆ · ┆ - * ╲ ·┆ ┆cdy - * •╌╌╌╌┴╌╌╌╌╌╌╌┘ - * câ‚ pdx cdx - * - * cdx = (câ‚‚x - câ‚x) - * cdy = (câ‚‚y - câ‚y) - * dr = râ‚‚-râ‚ - * pdx = px - câ‚x - * pdy = py - câ‚y - * - * Note that cdx, cdy, and dr do not depend on point p at all, so can - * be pre-computed for the entire gradient. The simplifed equations - * are now: - * - * cos θ = (-cdx·t + pdx) / (dr·t + râ‚) - * sin θ = (-cdy·t + pdy) / (dr·t + râ‚) - * - * Finally, to get a single function of t and eliminate the last - * unknown θ, we use the identity sin²θ + cos²θ = 1. First, square - * each equation, (we knew a quadratic was coming since it must be - * possible to obtain two solutions in some cases): - * - * cos²θ = (cdx²t² - 2·cdx·pdx·t + pdx²) / (dr²·t² + 2·râ‚·dr·t + r₲) - * sin²θ = (cdy²t² - 2·cdy·pdy·t + pdy²) / (dr²·t² + 2·râ‚·dr·t + r₲) - * - * Then add both together, set the result equal to 1, and express as a - * standard quadratic equation in t of the form At² + Bt + C = 0 - * - * (cdx² + cdy² - dr²)·t² - 2·(cdx·pdx + cdy·pdy + râ‚·dr)·t + (pdx² + pdy² - r₲) = 0 - * - * In other words: - * - * A = cdx² + cdy² - dr² - * B = -2·(pdx·cdx + pdy·cdy + râ‚·dr) - * C = pdx² + pdy² - r₲ - * - * And again, notice that A does not depend on p, so can be - * precomputed. From here we just use the quadratic formula to solve - * for t: - * - * t = (-2·B ± ⎷(B² - 4·A·C)) / 2·A - */ - /* radial or conical */ - pixman_bool_t affine = TRUE; - double cx = 1.; - double cy = 0.; - double cz = 0.; - double rx = x + 0.5; - double ry = y + 0.5; - double rz = 1.; - - if (pict->common.transform) { - pixman_vector_t v; - /* reference point is the center of the pixel */ - v.vector[0] = pixman_int_to_fixed(x) + pixman_fixed_1/2; - v.vector[1] = pixman_int_to_fixed(y) + pixman_fixed_1/2; - v.vector[2] = pixman_fixed_1; - if (!pixman_transform_point_3d (pict->common.transform, &v)) - return; - - cx = pict->common.transform->matrix[0][0]/65536.; - cy = pict->common.transform->matrix[1][0]/65536.; - cz = pict->common.transform->matrix[2][0]/65536.; - rx = v.vector[0]/65536.; - ry = v.vector[1]/65536.; - rz = v.vector[2]/65536.; - affine = pict->common.transform->matrix[2][0] == 0 && v.vector[2] == pixman_fixed_1; - } - - if (pict->common.type == RADIAL) { - radial_gradient_t *radial = (radial_gradient_t *)pict; - if (affine) { - while (buffer < end) { - if (!mask || *mask++ & maskBits) - { - double pdx, pdy; - double B, C; - double det; - double c1x = radial->c1.x / 65536.0; - double c1y = radial->c1.y / 65536.0; - double r1 = radial->c1.radius / 65536.0; - pixman_fixed_48_16_t t; - - pdx = rx - c1x; - pdy = ry - c1y; - - B = -2 * ( pdx * radial->cdx - + pdy * radial->cdy - + r1 * radial->dr); - C = (pdx * pdx + pdy * pdy - r1 * r1); - - det = (B * B) - (4 * radial->A * C); - if (det < 0.0) - det = 0.0; - - if (radial->A < 0) - t = (pixman_fixed_48_16_t) ((- B - sqrt(det)) / (2.0 * radial->A) * 65536); - else - t = (pixman_fixed_48_16_t) ((- B + sqrt(det)) / (2.0 * radial->A) * 65536); - - *(buffer) = _gradient_walker_pixel (&walker, t); - } - ++buffer; - - rx += cx; - ry += cy; - } - } else { - /* projective */ - while (buffer < end) { - if (!mask || *mask++ & maskBits) - { - double pdx, pdy; - double B, C; - double det; - double c1x = radial->c1.x / 65536.0; - double c1y = radial->c1.y / 65536.0; - double r1 = radial->c1.radius / 65536.0; - pixman_fixed_48_16_t t; - double x, y; - - if (rz != 0) { - x = rx/rz; - y = ry/rz; - } else { - x = y = 0.; - } - - pdx = x - c1x; - pdy = y - c1y; - - B = -2 * ( pdx * radial->cdx - + pdy * radial->cdy - + r1 * radial->dr); - C = (pdx * pdx + pdy * pdy - r1 * r1); - - det = (B * B) - (4 * radial->A * C); - if (det < 0.0) - det = 0.0; - - if (radial->A < 0) - t = (pixman_fixed_48_16_t) ((- B - sqrt(det)) / (2.0 * radial->A) * 65536); - else - t = (pixman_fixed_48_16_t) ((- B + sqrt(det)) / (2.0 * radial->A) * 65536); - - *(buffer) = _gradient_walker_pixel (&walker, t); - } - ++buffer; - - rx += cx; - ry += cy; - rz += cz; - } - } - } else /* SourcePictTypeConical */ { - conical_gradient_t *conical = (conical_gradient_t *)pict; - double a = conical->angle/(180.*65536); - if (affine) { - rx -= conical->center.x/65536.; - ry -= conical->center.y/65536.; - - while (buffer < end) { - double angle; - - if (!mask || *mask++ & maskBits) - { - pixman_fixed_48_16_t t; - - angle = atan2(ry, rx) + a; - t = (pixman_fixed_48_16_t) (angle * (65536. / (2*M_PI))); - - *(buffer) = _gradient_walker_pixel (&walker, t); - } - - ++buffer; - rx += cx; - ry += cy; - } - } else { - while (buffer < end) { - double x, y; - double angle; - - if (!mask || *mask++ & maskBits) - { - pixman_fixed_48_16_t t; - - if (rz != 0) { - x = rx/rz; - y = ry/rz; - } else { - x = y = 0.; - } - x -= conical->center.x/65536.; - y -= conical->center.y/65536.; - angle = atan2(y, x) + a; - t = (pixman_fixed_48_16_t) (angle * (65536. / (2*M_PI))); - - *(buffer) = _gradient_walker_pixel (&walker, t); - } - - ++buffer; - rx += cx; - ry += cy; - rz += cz; - } - } - } - } -} - -/* - * For now, just evaluate the source picture at 32bpp and expand. We could - * produce smoother gradients by evaluating them at higher color depth, but - * that's a project for the future. - */ -void pixmanFetchSourcePict64(source_image_t * pict, int x, int y, int width, - uint64_t *buffer, uint64_t *mask, uint32_t maskBits) -{ - uint32_t *mask8 = NULL; - - // Contract the mask image, if one exists, so that the 32-bit fetch function - // can use it. - if (mask) { - mask8 = pixman_malloc_ab(width, sizeof(uint32_t)); - pixman_contract(mask8, mask, width); - } - - // Fetch the source image into the first half of buffer. - pixmanFetchSourcePict(pict, x, y, width, (uint32_t*)buffer, mask8, - maskBits); - - // Expand from 32bpp to 64bpp in place. - pixman_expand(buffer, (uint32_t*)buffer, PIXMAN_a8r8g8b8, width); - - free(mask8); -} diff --git a/uppdev/plugin/pixman/lib/pixman-sse2.c b/uppdev/plugin/pixman/lib/pixman-sse2.c deleted file mode 100644 index 309ac6890..000000000 --- a/uppdev/plugin/pixman/lib/pixman-sse2.c +++ /dev/null @@ -1,4717 +0,0 @@ -/* - * Copyright © 2008 Rodrigo Kumpera - * Copyright © 2008 André Tupinambá - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Red Hat not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. Red Hat makes no representations about the - * suitability of this software for any purpose. It is provided "as is" - * without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - * - * Author: Rodrigo Kumpera (kumpera@gmail.com) - * André Tupinambá (andrelrt@gmail.com) - * - * Based on work by Owen Taylor and Søren Sandmann - */ -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include /* for _mm_shuffle_pi16 and _MM_SHUFFLE */ -#include /* for SSE2 intrinsics */ - -#include "pixman-sse2.h" - -#ifdef USE_SSE2 - -/* ------------------------------------------------------------------------------------------------- - * Locals - */ - -static __m64 xMask0080; -static __m64 xMask00ff; -static __m64 xMask0101; -static __m64 xMaskAlpha; - -static __m64 xMask565rgb; -static __m64 xMask565Unpack; - -static __m128i Mask0080; -static __m128i Mask00ff; -static __m128i Mask0101; -static __m128i Maskffff; -static __m128i Maskff000000; -static __m128i MaskAlpha; - -static __m128i Mask565r; -static __m128i Mask565g1, Mask565g2; -static __m128i Mask565b; -static __m128i MaskRed; -static __m128i MaskGreen; -static __m128i MaskBlue; - -static __m128i Mask565FixRB; -static __m128i Mask565FixG; - -/* ------------------------------------------------------------------------------------------------- - * SSE2 Inlines - */ -static force_inline __m128i -unpack_32_1x128 (uint32_t data) -{ - return _mm_unpacklo_epi8 (_mm_cvtsi32_si128 (data), _mm_setzero_si128()); -} - -static force_inline void -unpack_128_2x128 (__m128i data, __m128i* dataLo, __m128i* dataHi) -{ - *dataLo = _mm_unpacklo_epi8 (data, _mm_setzero_si128 ()); - *dataHi = _mm_unpackhi_epi8 (data, _mm_setzero_si128 ()); -} - -static force_inline __m128i -unpack565to8888 (__m128i lo) -{ - __m128i r, g, b, rb, t; - - r = _mm_and_si128 (_mm_slli_epi32 (lo, 8), MaskRed); - g = _mm_and_si128 (_mm_slli_epi32 (lo, 5), MaskGreen); - b = _mm_and_si128 (_mm_slli_epi32 (lo, 3), MaskBlue); - - rb = _mm_or_si128 (r, b); - t = _mm_and_si128 (rb, Mask565FixRB); - t = _mm_srli_epi32 (t, 5); - rb = _mm_or_si128 (rb, t); - - t = _mm_and_si128 (g, Mask565FixG); - t = _mm_srli_epi32 (t, 6); - g = _mm_or_si128 (g, t); - - return _mm_or_si128 (rb, g); -} - -static force_inline void -unpack565_128_4x128 (__m128i data, __m128i* data0, __m128i* data1, __m128i* data2, __m128i* data3) -{ - __m128i lo, hi; - - lo = _mm_unpacklo_epi16 (data, _mm_setzero_si128 ()); - hi = _mm_unpackhi_epi16 (data, _mm_setzero_si128 ()); - - lo = unpack565to8888 (lo); - hi = unpack565to8888 (hi); - - unpack_128_2x128 (lo, data0, data1); - unpack_128_2x128 (hi, data2, data3); -} - -static force_inline uint16_t -pack565_32_16 (uint32_t pixel) -{ - return (uint16_t) (((pixel>>8) & 0xf800) | ((pixel>>5) & 0x07e0) | ((pixel>>3) & 0x001f)); -} - -static force_inline __m128i -pack_2x128_128 (__m128i lo, __m128i hi) -{ - return _mm_packus_epi16 (lo, hi); -} - -static force_inline __m128i -pack565_2x128_128 (__m128i lo, __m128i hi) -{ - __m128i data; - __m128i r, g1, g2, b; - - data = pack_2x128_128 ( lo, hi ); - - r = _mm_and_si128 (data , Mask565r); - g1 = _mm_and_si128 (_mm_slli_epi32 (data , 3), Mask565g1); - g2 = _mm_and_si128 (_mm_srli_epi32 (data , 5), Mask565g2); - b = _mm_and_si128 (_mm_srli_epi32 (data , 3), Mask565b); - - return _mm_or_si128 (_mm_or_si128 (_mm_or_si128 (r, g1), g2), b); -} - -static force_inline __m128i -pack565_4x128_128 (__m128i* xmm0, __m128i* xmm1, __m128i* xmm2, __m128i* xmm3) -{ - return _mm_packus_epi16 (pack565_2x128_128 (*xmm0, *xmm1), pack565_2x128_128 (*xmm2, *xmm3)); -} - -static force_inline uint32_t -packAlpha (__m128i x) -{ - return _mm_cvtsi128_si32 (_mm_packus_epi16 (_mm_packus_epi16 (_mm_srli_epi32 (x, 24), - _mm_setzero_si128 ()), - _mm_setzero_si128 ())); -} - -static force_inline __m128i -expandPixel_32_1x128 (uint32_t data) -{ - return _mm_shuffle_epi32 (unpack_32_1x128 (data), _MM_SHUFFLE(1, 0, 1, 0)); -} - -static force_inline __m128i -expandAlpha_1x128 (__m128i data) -{ - return _mm_shufflehi_epi16 (_mm_shufflelo_epi16 (data, _MM_SHUFFLE(3, 3, 3, 3)), _MM_SHUFFLE(3, 3, 3, 3)); -} - -static force_inline void -expandAlpha_2x128 (__m128i dataLo, __m128i dataHi, __m128i* alphaLo, __m128i* alphaHi) -{ - __m128i lo, hi; - - lo = _mm_shufflelo_epi16 (dataLo, _MM_SHUFFLE(3, 3, 3, 3)); - hi = _mm_shufflelo_epi16 (dataHi, _MM_SHUFFLE(3, 3, 3, 3)); - *alphaLo = _mm_shufflehi_epi16 (lo, _MM_SHUFFLE(3, 3, 3, 3)); - *alphaHi = _mm_shufflehi_epi16 (hi, _MM_SHUFFLE(3, 3, 3, 3)); -} - -static force_inline void -expandAlphaRev_2x128 (__m128i dataLo, __m128i dataHi, __m128i* alphaLo, __m128i* alphaHi) -{ - __m128i lo, hi; - - lo = _mm_shufflelo_epi16 (dataLo, _MM_SHUFFLE(0, 0, 0, 0)); - hi = _mm_shufflelo_epi16 (dataHi, _MM_SHUFFLE(0, 0, 0, 0)); - *alphaLo = _mm_shufflehi_epi16 (lo, _MM_SHUFFLE(0, 0, 0, 0)); - *alphaHi = _mm_shufflehi_epi16 (hi, _MM_SHUFFLE(0, 0, 0, 0)); -} - -static force_inline void -pixMultiply_2x128 (__m128i* dataLo, __m128i* dataHi, __m128i* alphaLo, __m128i* alphaHi, __m128i* retLo, __m128i* retHi) -{ - __m128i lo, hi; - - lo = _mm_mullo_epi16 (*dataLo, *alphaLo); - hi = _mm_mullo_epi16 (*dataHi, *alphaHi); - lo = _mm_adds_epu16 (lo, Mask0080); - hi = _mm_adds_epu16 (hi, Mask0080); - *retLo = _mm_mulhi_epu16 (lo, Mask0101); - *retHi = _mm_mulhi_epu16 (hi, Mask0101); -} - -static force_inline void -pixAddMultiply_2x128 (__m128i* srcLo, __m128i* srcHi, __m128i* alphaDstLo, __m128i* alphaDstHi, - __m128i* dstLo, __m128i* dstHi, __m128i* alphaSrcLo, __m128i* alphaSrcHi, - __m128i* retLo, __m128i* retHi) -{ - __m128i lo, hi; - __m128i mulLo, mulHi; - - lo = _mm_mullo_epi16 (*srcLo, *alphaDstLo); - hi = _mm_mullo_epi16 (*srcHi, *alphaDstHi); - mulLo = _mm_mullo_epi16 (*dstLo, *alphaSrcLo); - mulHi = _mm_mullo_epi16 (*dstHi, *alphaSrcHi); - lo = _mm_adds_epu16 (lo, Mask0080); - hi = _mm_adds_epu16 (hi, Mask0080); - lo = _mm_adds_epu16 (lo, mulLo); - hi = _mm_adds_epu16 (hi, mulHi); - *retLo = _mm_mulhi_epu16 (lo, Mask0101); - *retHi = _mm_mulhi_epu16 (hi, Mask0101); -} - -static force_inline void -negate_2x128 (__m128i dataLo, __m128i dataHi, __m128i* negLo, __m128i* negHi) -{ - *negLo = _mm_xor_si128 (dataLo, Mask00ff); - *negHi = _mm_xor_si128 (dataHi, Mask00ff); -} - -static force_inline void -invertColors_2x128 (__m128i dataLo, __m128i dataHi, __m128i* invLo, __m128i* invHi) -{ - __m128i lo, hi; - - lo = _mm_shufflelo_epi16 (dataLo, _MM_SHUFFLE(3, 0, 1, 2)); - hi = _mm_shufflelo_epi16 (dataHi, _MM_SHUFFLE(3, 0, 1, 2)); - *invLo = _mm_shufflehi_epi16 (lo, _MM_SHUFFLE(3, 0, 1, 2)); - *invHi = _mm_shufflehi_epi16 (hi, _MM_SHUFFLE(3, 0, 1, 2)); -} - -static force_inline void -over_2x128 (__m128i* srcLo, __m128i* srcHi, __m128i* alphaLo, __m128i* alphaHi, __m128i* dstLo, __m128i* dstHi) -{ - __m128i t1, t2; - - negate_2x128 (*alphaLo, *alphaHi, &t1, &t2); - - pixMultiply_2x128 (dstLo, dstHi, &t1, &t2, dstLo, dstHi); - - *dstLo = _mm_adds_epu8 (*srcLo, *dstLo); - *dstHi = _mm_adds_epu8 (*srcHi, *dstHi); -} - -static force_inline void -overRevNonPre_2x128 (__m128i srcLo, __m128i srcHi, __m128i* dstLo, __m128i* dstHi) -{ - __m128i lo, hi; - __m128i alphaLo, alphaHi; - - expandAlpha_2x128 (srcLo, srcHi, &alphaLo, &alphaHi); - - lo = _mm_or_si128 (alphaLo, MaskAlpha); - hi = _mm_or_si128 (alphaHi, MaskAlpha); - - invertColors_2x128 (srcLo, srcHi, &srcLo, &srcHi); - - pixMultiply_2x128 (&srcLo, &srcHi, &lo, &hi, &lo, &hi); - - over_2x128 (&lo, &hi, &alphaLo, &alphaHi, dstLo, dstHi); -} - -static force_inline void -inOver_2x128 (__m128i* srcLo, __m128i* srcHi, __m128i* alphaLo, __m128i* alphaHi, - __m128i* maskLo, __m128i* maskHi, __m128i* dstLo, __m128i* dstHi) -{ - __m128i sLo, sHi; - __m128i aLo, aHi; - - pixMultiply_2x128 ( srcLo, srcHi, maskLo, maskHi, &sLo, &sHi); - pixMultiply_2x128 (alphaLo, alphaHi, maskLo, maskHi, &aLo, &aHi); - - over_2x128 (&sLo, &sHi, &aLo, &aHi, dstLo, dstHi); -} - -static force_inline void -cachePrefetch (__m128i* addr) -{ - _mm_prefetch (addr, _MM_HINT_T0); -} - -static force_inline void -cachePrefetchNext (__m128i* addr) -{ - _mm_prefetch (addr + 4, _MM_HINT_T0); // 64 bytes ahead -} - -/* load 4 pixels from a 16-byte boundary aligned address */ -static force_inline __m128i -load128Aligned (__m128i* src) -{ - return _mm_load_si128 (src); -} - -/* load 4 pixels from a unaligned address */ -static force_inline __m128i -load128Unaligned (__m128i* src) -{ - return _mm_loadu_si128 (src); -} - -/* save 4 pixels using Write Combining memory on a 16-byte boundary aligned address */ -static force_inline void -save128WriteCombining (__m128i* dst, __m128i data) -{ - _mm_stream_si128 (dst, data); -} - -/* save 4 pixels on a 16-byte boundary aligned address */ -static force_inline void -save128Aligned (__m128i* dst, __m128i data) -{ - _mm_store_si128 (dst, data); -} - -/* save 4 pixels on a unaligned address */ -static force_inline void -save128Unaligned (__m128i* dst, __m128i data) -{ - _mm_storeu_si128 (dst, data); -} - -/* ------------------------------------------------------------------------------------------------- - * MMX inlines - */ - -static force_inline __m64 -unpack_32_1x64 (uint32_t data) -{ - return _mm_unpacklo_pi8 (_mm_cvtsi32_si64 (data), _mm_setzero_si64()); -} - -static force_inline __m64 -expandAlpha_1x64 (__m64 data) -{ - return _mm_shuffle_pi16 (data, _MM_SHUFFLE(3, 3, 3, 3)); -} - -static force_inline __m64 -expandAlphaRev_1x64 (__m64 data) -{ - return _mm_shuffle_pi16 (data, _MM_SHUFFLE(0, 0, 0, 0)); -} - -static force_inline __m64 -expandPixel_8_1x64 (uint8_t data) -{ - return _mm_shuffle_pi16 (unpack_32_1x64 ((uint32_t)data), _MM_SHUFFLE(0, 0, 0, 0)); -} - -static force_inline __m64 -pixMultiply_1x64 (__m64 data, __m64 alpha) -{ - return _mm_mulhi_pu16 (_mm_adds_pu16 (_mm_mullo_pi16 (data, alpha), - xMask0080), - xMask0101); -} - -static force_inline __m64 -pixAddMultiply_1x64 (__m64* src, __m64* alphaDst, __m64* dst, __m64* alphaSrc) -{ - return _mm_mulhi_pu16 (_mm_adds_pu16 (_mm_adds_pu16 (_mm_mullo_pi16 (*src, *alphaDst), - xMask0080), - _mm_mullo_pi16 (*dst, *alphaSrc)), - xMask0101); -} - -static force_inline __m64 -negate_1x64 (__m64 data) -{ - return _mm_xor_si64 (data, xMask00ff); -} - -static force_inline __m64 -invertColors_1x64 (__m64 data) -{ - return _mm_shuffle_pi16 (data, _MM_SHUFFLE(3, 0, 1, 2)); -} - -static force_inline __m64 -over_1x64 (__m64 src, __m64 alpha, __m64 dst) -{ - return _mm_adds_pu8 (src, pixMultiply_1x64 (dst, negate_1x64 (alpha))); -} - -static force_inline __m64 -inOver_1x64 (__m64* src, __m64* alpha, __m64* mask, __m64* dst) -{ - return over_1x64 (pixMultiply_1x64 (*src, *mask), - pixMultiply_1x64 (*alpha, *mask), - *dst); -} - -static force_inline __m64 -overRevNonPre_1x64 (__m64 src, __m64 dst) -{ - __m64 alpha = expandAlpha_1x64 (src); - - return over_1x64 (pixMultiply_1x64 (invertColors_1x64 (src), - _mm_or_si64 (alpha, xMaskAlpha)), - alpha, - dst); -} - -static force_inline uint32_t -pack_1x64_32( __m64 data ) -{ - return _mm_cvtsi64_si32 (_mm_packs_pu16 (data, _mm_setzero_si64())); -} - -/* Expand 16 bits positioned at @pos (0-3) of a mmx register into - * - * 00RR00GG00BB - * - * --- Expanding 565 in the low word --- - * - * m = (m << (32 - 3)) | (m << (16 - 5)) | m; - * m = m & (01f0003f001f); - * m = m * (008404100840); - * m = m >> 8; - * - * Note the trick here - the top word is shifted by another nibble to - * avoid it bumping into the middle word - */ -static force_inline __m64 -expand565_16_1x64 (uint16_t pixel) -{ - __m64 p; - __m64 t1, t2; - - p = _mm_cvtsi32_si64 ((uint32_t) pixel); - - t1 = _mm_slli_si64 (p, 36 - 11); - t2 = _mm_slli_si64 (p, 16 - 5); - - p = _mm_or_si64 (t1, p); - p = _mm_or_si64 (t2, p); - p = _mm_and_si64 (p, xMask565rgb); - p = _mm_mullo_pi16 (p, xMask565Unpack); - - return _mm_srli_pi16 (p, 8); -} - -/* ------------------------------------------------------------------------------------------------- - * Compose Core transformations - */ -static force_inline uint32_t -coreCombineOverUPixelsse2 (uint32_t src, uint32_t dst) -{ - uint8_t a; - __m64 ms; - - a = src >> 24; - - if (a == 0xff) - { - return src; - } - else if (a) - { - ms = unpack_32_1x64 (src); - return pack_1x64_32 (over_1x64 (ms, expandAlpha_1x64 (ms), unpack_32_1x64 (dst))); - } - - return dst; -} - -static force_inline void -coreCombineOverUsse2 (uint32_t* pd, const uint32_t* ps, int w) -{ - uint32_t pa; - uint32_t s, d; - - __m128i xmmDstLo, xmmDstHi; - __m128i xmmSrcLo, xmmSrcHi; - __m128i xmmAlphaLo, xmmAlphaHi; - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - - /* Align dst on a 16-byte boundary */ - while (w && - ((unsigned long)pd & 15)) - { - d = *pd; - s = *ps++; - - *pd++ = coreCombineOverUPixelsse2 (s, d); - w--; - } - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - - while (w >= 4) - { - /* fill cache line with next memory */ - cachePrefetchNext ((__m128i*)ps); - cachePrefetchNext ((__m128i*)pd); - - /* I'm loading unaligned because I'm not sure about the address alignment. */ - xmmSrcHi = load128Unaligned ((__m128i*) ps); - - /* Check the alpha channel */ - pa = packAlpha (xmmSrcHi); - - if (pa == 0xffffffff) - { - save128Aligned ((__m128i*)pd, xmmSrcHi); - } - else if (pa) - { - xmmDstHi = load128Aligned ((__m128i*) pd); - - unpack_128_2x128 (xmmSrcHi, &xmmSrcLo, &xmmSrcHi); - unpack_128_2x128 (xmmDstHi, &xmmDstLo, &xmmDstHi); - - expandAlpha_2x128 (xmmSrcLo, xmmSrcHi, &xmmAlphaLo, &xmmAlphaHi); - - over_2x128 (&xmmSrcLo, &xmmSrcHi, &xmmAlphaLo, &xmmAlphaHi, &xmmDstLo, &xmmDstHi); - - /* rebuid the 4 pixel data and save*/ - save128Aligned ((__m128i*)pd, pack_2x128_128 (xmmDstLo, xmmDstHi)); - } - - w -= 4; - ps += 4; - pd += 4; - } - - while (w) - { - d = *pd; - s = *ps++; - - *pd++ = coreCombineOverUPixelsse2 (s, d); - w--; - } -} - -static force_inline void -coreCombineOverReverseUsse2 (uint32_t* pd, const uint32_t* ps, int w) -{ - uint32_t s, d; - - __m128i xmmDstLo, xmmDstHi; - __m128i xmmSrcLo, xmmSrcHi; - __m128i xmmAlphaLo, xmmAlphaHi; - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - - /* Align dst on a 16-byte boundary */ - while (w && - ((unsigned long)pd & 15)) - { - d = *pd; - s = *ps++; - - *pd++ = coreCombineOverUPixelsse2 (d, s); - w--; - } - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - - while (w >= 4) - { - /* fill cache line with next memory */ - cachePrefetchNext ((__m128i*)ps); - cachePrefetchNext ((__m128i*)pd); - - /* I'm loading unaligned because I'm not sure about the address alignment. */ - xmmSrcHi = load128Unaligned ((__m128i*) ps); - xmmDstHi = load128Aligned ((__m128i*) pd); - - unpack_128_2x128 (xmmSrcHi, &xmmSrcLo, &xmmSrcHi); - unpack_128_2x128 (xmmDstHi, &xmmDstLo, &xmmDstHi); - - expandAlpha_2x128 (xmmDstLo, xmmDstHi, &xmmAlphaLo, &xmmAlphaHi); - - over_2x128 (&xmmDstLo, &xmmDstHi, &xmmAlphaLo, &xmmAlphaHi, &xmmSrcLo, &xmmSrcHi); - - /* rebuid the 4 pixel data and save*/ - save128Aligned ((__m128i*)pd, pack_2x128_128 (xmmSrcLo, xmmSrcHi)); - - w -= 4; - ps += 4; - pd += 4; - } - - while (w) - { - d = *pd; - s = *ps++; - - *pd++ = coreCombineOverUPixelsse2 (d, s); - w--; - } -} - -static force_inline uint32_t -coreCombineInUPixelsse2 (uint32_t src, uint32_t dst) -{ - uint32_t maska = src >> 24; - - if (maska == 0) - { - return 0; - } - else if (maska != 0xff) - { - return pack_1x64_32(pixMultiply_1x64 (unpack_32_1x64 (dst), expandAlpha_1x64 (unpack_32_1x64 (src)))); - } - - return dst; -} - -static force_inline void -coreCombineInUsse2 (uint32_t* pd, const uint32_t* ps, int w) -{ - uint32_t s, d; - - __m128i xmmSrcLo, xmmSrcHi; - __m128i xmmDstLo, xmmDstHi; - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - - while (w && ((unsigned long) pd & 15)) - { - s = *ps++; - d = *pd; - - *pd++ = coreCombineInUPixelsse2 (d, s); - w--; - } - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - - while (w >= 4) - { - /* fill cache line with next memory */ - cachePrefetchNext ((__m128i*)ps); - cachePrefetchNext ((__m128i*)pd); - - xmmDstHi = load128Aligned ((__m128i*) pd); - xmmSrcHi = load128Unaligned ((__m128i*) ps); - - unpack_128_2x128 (xmmDstHi, &xmmDstLo, &xmmDstHi); - expandAlpha_2x128 (xmmDstLo, xmmDstHi, &xmmDstLo, &xmmDstHi); - - unpack_128_2x128 (xmmSrcHi, &xmmSrcLo, &xmmSrcHi); - pixMultiply_2x128 (&xmmSrcLo, &xmmSrcHi, &xmmDstLo, &xmmDstHi, &xmmDstLo, &xmmDstHi); - - save128Aligned ((__m128i*)pd, pack_2x128_128 (xmmDstLo, xmmDstHi)); - - ps += 4; - pd += 4; - w -= 4; - } - - while (w) - { - s = *ps++; - d = *pd; - - *pd++ = coreCombineInUPixelsse2 (d, s); - w--; - } -} - -static force_inline void -coreCombineReverseInUsse2 (uint32_t* pd, const uint32_t* ps, int w) -{ - uint32_t s, d; - - __m128i xmmSrcLo, xmmSrcHi; - __m128i xmmDstLo, xmmDstHi; - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - - while (w && ((unsigned long) pd & 15)) - { - s = *ps++; - d = *pd; - - *pd++ = coreCombineInUPixelsse2 (s, d); - w--; - } - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - - while (w >= 4) - { - /* fill cache line with next memory */ - cachePrefetchNext ((__m128i*)ps); - cachePrefetchNext ((__m128i*)pd); - - xmmDstHi = load128Aligned ((__m128i*) pd); - xmmSrcHi = load128Unaligned ((__m128i*) ps); - - unpack_128_2x128 (xmmSrcHi, &xmmSrcLo, &xmmSrcHi); - expandAlpha_2x128 (xmmSrcLo, xmmSrcHi, &xmmSrcLo, &xmmSrcHi); - - unpack_128_2x128 (xmmDstHi, &xmmDstLo, &xmmDstHi); - pixMultiply_2x128 (&xmmDstLo, &xmmDstHi, &xmmSrcLo, &xmmSrcHi, &xmmDstLo, &xmmDstHi); - - save128Aligned ((__m128i*)pd, pack_2x128_128 (xmmDstLo, xmmDstHi)); - - ps += 4; - pd += 4; - w -= 4; - } - - while (w) - { - s = *ps++; - d = *pd; - - *pd++ = coreCombineInUPixelsse2 (s, d); - w--; - } -} - -static force_inline void -coreCombineReverseOutUsse2 (uint32_t* pd, const uint32_t* ps, int w) -{ - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - - while (w && ((unsigned long) pd & 15)) - { - uint32_t s = *ps++; - uint32_t d = *pd; - - *pd++ = pack_1x64_32 (pixMultiply_1x64 (unpack_32_1x64 (d), negate_1x64 (expandAlpha_1x64 (unpack_32_1x64 (s))))); - w--; - } - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - - while (w >= 4) - { - __m128i xmmSrcLo, xmmSrcHi; - __m128i xmmDstLo, xmmDstHi; - - /* fill cache line with next memory */ - cachePrefetchNext ((__m128i*)ps); - cachePrefetchNext ((__m128i*)pd); - - xmmSrcHi = load128Unaligned ((__m128i*) ps); - xmmDstHi = load128Aligned ((__m128i*) pd); - - unpack_128_2x128 (xmmSrcHi, &xmmSrcLo, &xmmSrcHi); - unpack_128_2x128 (xmmDstHi, &xmmDstLo, &xmmDstHi); - - expandAlpha_2x128 (xmmSrcLo, xmmSrcHi, &xmmSrcLo, &xmmSrcHi); - negate_2x128 (xmmSrcLo, xmmSrcHi, &xmmSrcLo, &xmmSrcHi); - - pixMultiply_2x128 (&xmmDstLo, &xmmDstHi, &xmmSrcLo, &xmmSrcHi, &xmmDstLo, &xmmDstHi); - - save128Aligned ((__m128i*)pd, pack_2x128_128 (xmmDstLo, xmmDstHi)); - - ps += 4; - pd += 4; - w -= 4; - } - - while (w) - { - uint32_t s = *ps++; - uint32_t d = *pd; - - *pd++ = pack_1x64_32 (pixMultiply_1x64 (unpack_32_1x64 (d), negate_1x64 (expandAlpha_1x64 (unpack_32_1x64 (s))))); - w--; - } -} - -static force_inline void -coreCombineOutUsse2 (uint32_t* pd, const uint32_t* ps, int w) -{ - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - - while (w && ((unsigned long) pd & 15)) - { - uint32_t s = *ps++; - uint32_t d = *pd; - - *pd++ = pack_1x64_32 (pixMultiply_1x64 (unpack_32_1x64 (s), negate_1x64 (expandAlpha_1x64 (unpack_32_1x64 (d))))); - w--; - } - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - - while (w >= 4) - { - __m128i xmmSrcLo, xmmSrcHi; - __m128i xmmDstLo, xmmDstHi; - - /* fill cache line with next memory */ - cachePrefetchNext ((__m128i*)ps); - cachePrefetchNext ((__m128i*)pd); - - xmmSrcHi = load128Unaligned ((__m128i*) ps); - xmmDstHi = load128Aligned ((__m128i*) pd); - - unpack_128_2x128 (xmmSrcHi, &xmmSrcLo, &xmmSrcHi); - unpack_128_2x128 (xmmDstHi, &xmmDstLo, &xmmDstHi); - - expandAlpha_2x128 (xmmDstLo, xmmDstHi, &xmmDstLo, &xmmDstHi); - negate_2x128 (xmmDstLo, xmmDstHi, &xmmDstLo, &xmmDstHi); - - pixMultiply_2x128 (&xmmSrcLo, &xmmSrcHi, &xmmDstLo, &xmmDstHi, &xmmDstLo, &xmmDstHi); - - save128Aligned ((__m128i*)pd, pack_2x128_128 (xmmDstLo, xmmDstHi)); - - ps += 4; - pd += 4; - w -= 4; - } - - while (w) - { - uint32_t s = *ps++; - uint32_t d = *pd; - - *pd++ = pack_1x64_32 (pixMultiply_1x64 (unpack_32_1x64 (s), negate_1x64 (expandAlpha_1x64 (unpack_32_1x64 (d))))); - w--; - } -} - -static force_inline uint32_t -coreCombineAtopUPixelsse2 (uint32_t src, uint32_t dst) -{ - __m64 s = unpack_32_1x64 (src); - __m64 d = unpack_32_1x64 (dst); - - __m64 sa = negate_1x64 (expandAlpha_1x64 (s)); - __m64 da = expandAlpha_1x64 (d); - - return pack_1x64_32 (pixAddMultiply_1x64 (&s, &da, &d, &sa)); -} - -static force_inline void -coreCombineAtopUsse2 (uint32_t* pd, const uint32_t* ps, int w) -{ - uint32_t s, d; - - __m128i xmmSrcLo, xmmSrcHi; - __m128i xmmDstLo, xmmDstHi; - __m128i xmmAlphaSrcLo, xmmAlphaSrcHi; - __m128i xmmAlphaDstLo, xmmAlphaDstHi; - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - - while (w && ((unsigned long) pd & 15)) - { - s = *ps++; - d = *pd; - - *pd++ = coreCombineAtopUPixelsse2 (s, d); - w--; - } - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - - while (w >= 4) - { - /* fill cache line with next memory */ - cachePrefetchNext ((__m128i*)ps); - cachePrefetchNext ((__m128i*)pd); - - xmmSrcHi = load128Unaligned ((__m128i*) ps); - xmmDstHi = load128Aligned ((__m128i*) pd); - - unpack_128_2x128 (xmmSrcHi, &xmmSrcLo, &xmmSrcHi); - unpack_128_2x128 (xmmDstHi, &xmmDstLo, &xmmDstHi); - - expandAlpha_2x128 (xmmSrcLo, xmmSrcHi, &xmmAlphaSrcLo, &xmmAlphaSrcHi); - expandAlpha_2x128 (xmmDstLo, xmmDstHi, &xmmAlphaDstLo, &xmmAlphaDstHi); - - negate_2x128 (xmmAlphaSrcLo, xmmAlphaSrcHi, &xmmAlphaSrcLo, &xmmAlphaSrcHi); - - pixAddMultiply_2x128 ( &xmmSrcLo, &xmmSrcHi, &xmmAlphaDstLo, &xmmAlphaDstHi, - &xmmDstLo, &xmmDstHi, &xmmAlphaSrcLo, &xmmAlphaSrcHi, - &xmmDstLo, &xmmDstHi ); - - save128Aligned ((__m128i*)pd, pack_2x128_128 (xmmDstLo, xmmDstHi)); - - ps += 4; - pd += 4; - w -= 4; - } - - while (w) - { - s = *ps++; - d = *pd; - - *pd++ = coreCombineAtopUPixelsse2 (s, d); - w--; - } -} - -static force_inline uint32_t -coreCombineReverseAtopUPixelsse2 (uint32_t src, uint32_t dst) -{ - __m64 s = unpack_32_1x64 (src); - __m64 d = unpack_32_1x64 (dst); - - __m64 sa = expandAlpha_1x64 (s); - __m64 da = negate_1x64 (expandAlpha_1x64 (d)); - - return pack_1x64_32 (pixAddMultiply_1x64 (&s, &da, &d, &sa)); -} - -static force_inline void -coreCombineReverseAtopUsse2 (uint32_t* pd, const uint32_t* ps, int w) -{ - uint32_t s, d; - - __m128i xmmSrcLo, xmmSrcHi; - __m128i xmmDstLo, xmmDstHi; - __m128i xmmAlphaSrcLo, xmmAlphaSrcHi; - __m128i xmmAlphaDstLo, xmmAlphaDstHi; - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - - while (w && ((unsigned long) pd & 15)) - { - s = *ps++; - d = *pd; - - *pd++ = coreCombineReverseAtopUPixelsse2 (s, d); - w--; - } - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - - while (w >= 4) - { - /* fill cache line with next memory */ - cachePrefetchNext ((__m128i*)ps); - cachePrefetchNext ((__m128i*)pd); - - xmmSrcHi = load128Unaligned ((__m128i*) ps); - xmmDstHi = load128Aligned ((__m128i*) pd); - - unpack_128_2x128 (xmmSrcHi, &xmmSrcLo, &xmmSrcHi); - unpack_128_2x128 (xmmDstHi, &xmmDstLo, &xmmDstHi); - - expandAlpha_2x128 (xmmSrcLo, xmmSrcHi, &xmmAlphaSrcLo, &xmmAlphaSrcHi); - expandAlpha_2x128 (xmmDstLo, xmmDstHi, &xmmAlphaDstLo, &xmmAlphaDstHi); - - negate_2x128 (xmmAlphaDstLo, xmmAlphaDstHi, &xmmAlphaDstLo, &xmmAlphaDstHi); - - pixAddMultiply_2x128 ( &xmmSrcLo, &xmmSrcHi, &xmmAlphaDstLo, &xmmAlphaDstHi, - &xmmDstLo, &xmmDstHi, &xmmAlphaSrcLo, &xmmAlphaSrcHi, - &xmmDstLo, &xmmDstHi ); - - save128Aligned ((__m128i*)pd, pack_2x128_128 (xmmDstLo, xmmDstHi)); - - ps += 4; - pd += 4; - w -= 4; - } - - while (w) - { - s = *ps++; - d = *pd; - - *pd++ = coreCombineReverseAtopUPixelsse2 (s, d); - w--; - } -} - -static force_inline uint32_t -coreCombineXorUPixelsse2 (uint32_t src, uint32_t dst) -{ - __m64 s = unpack_32_1x64 (src); - __m64 d = unpack_32_1x64 (dst); - - __m64 negD = negate_1x64 (expandAlpha_1x64 (d)); - __m64 negS = negate_1x64 (expandAlpha_1x64 (s)); - - return pack_1x64_32 (pixAddMultiply_1x64 (&s, &negD, &d, &negS)); -} - -static force_inline void -coreCombineXorUsse2 (uint32_t* dst, const uint32_t* src, int width) -{ - int w = width; - uint32_t s, d; - uint32_t* pd = dst; - const uint32_t* ps = src; - - __m128i xmmSrc, xmmSrcLo, xmmSrcHi; - __m128i xmmDst, xmmDstLo, xmmDstHi; - __m128i xmmAlphaSrcLo, xmmAlphaSrcHi; - __m128i xmmAlphaDstLo, xmmAlphaDstHi; - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - - while (w && ((unsigned long) pd & 15)) - { - s = *ps++; - d = *pd; - - *pd++ = coreCombineXorUPixelsse2 (s, d); - w--; - } - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - - while (w >= 4) - { - /* fill cache line with next memory */ - cachePrefetchNext ((__m128i*)ps); - cachePrefetchNext ((__m128i*)pd); - - xmmSrc = load128Unaligned ((__m128i*) ps); - xmmDst = load128Aligned ((__m128i*) pd); - - unpack_128_2x128 (xmmSrc, &xmmSrcLo, &xmmSrcHi); - unpack_128_2x128 (xmmDst, &xmmDstLo, &xmmDstHi); - - expandAlpha_2x128 (xmmSrcLo, xmmSrcHi, &xmmAlphaSrcLo, &xmmAlphaSrcHi); - expandAlpha_2x128 (xmmDstLo, xmmDstHi, &xmmAlphaDstLo, &xmmAlphaDstHi); - - negate_2x128 (xmmAlphaSrcLo, xmmAlphaSrcHi, &xmmAlphaSrcLo, &xmmAlphaSrcHi); - negate_2x128 (xmmAlphaDstLo, xmmAlphaDstHi, &xmmAlphaDstLo, &xmmAlphaDstHi); - - pixAddMultiply_2x128 ( &xmmSrcLo, &xmmSrcHi, &xmmAlphaDstLo, &xmmAlphaDstHi, - &xmmDstLo, &xmmDstHi, &xmmAlphaSrcLo, &xmmAlphaSrcHi, - &xmmDstLo, &xmmDstHi ); - - save128Aligned ((__m128i*)pd, pack_2x128_128 (xmmDstLo, xmmDstHi)); - - ps += 4; - pd += 4; - w -= 4; - } - - while (w) - { - s = *ps++; - d = *pd; - - *pd++ = coreCombineXorUPixelsse2 (s, d); - w--; - } -} - -static force_inline void -coreCombineAddUsse2 (uint32_t* dst, const uint32_t* src, int width) -{ - int w = width; - uint32_t s,d; - uint32_t* pd = dst; - const uint32_t* ps = src; - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - - while (w && (unsigned long)pd & 15) - { - s = *ps++; - d = *pd; - *pd++ = _mm_cvtsi64_si32 (_mm_adds_pu8 (_mm_cvtsi32_si64 (s), _mm_cvtsi32_si64 (d))); - w--; - } - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - - while (w >= 4) - { - /* fill cache line with next memory */ - cachePrefetchNext ((__m128i*)ps); - cachePrefetchNext ((__m128i*)pd); - - save128Aligned( (__m128i*)pd, - _mm_adds_epu8( load128Unaligned((__m128i*)ps), - load128Aligned ((__m128i*)pd)) ); - pd += 4; - ps += 4; - w -= 4; - } - - while (w--) - { - s = *ps++; - d = *pd; - *pd++ = _mm_cvtsi64_si32 (_mm_adds_pu8 (_mm_cvtsi32_si64 (s), _mm_cvtsi32_si64 (d))); - } -} - -static force_inline uint32_t -coreCombineSaturateUPixelsse2 (uint32_t src, uint32_t dst) -{ - __m64 ms = unpack_32_1x64 (src); - __m64 md = unpack_32_1x64 (dst); - uint32_t sa = src >> 24; - uint32_t da = ~dst >> 24; - - if (sa > da) - { - ms = pixMultiply_1x64 (ms, expandAlpha_1x64 (unpack_32_1x64 (FbIntDiv(da, sa) << 24))); - } - - return pack_1x64_32 (_mm_adds_pu16 (md, ms)); -} - -static force_inline void -coreCombineSaturateUsse2 (uint32_t *pd, const uint32_t *ps, int w) -{ - uint32_t s,d; - - uint32_t packCmp; - __m128i xmmSrc, xmmDst; - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - - while (w && (unsigned long)pd & 15) - { - s = *ps++; - d = *pd; - *pd++ = coreCombineSaturateUPixelsse2 (s, d); - w--; - } - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - - while (w >= 4) - { - /* fill cache line with next memory */ - cachePrefetchNext ((__m128i*)ps); - cachePrefetchNext ((__m128i*)pd); - - xmmDst = load128Aligned ((__m128i*)pd); - xmmSrc = load128Unaligned((__m128i*)ps); - - packCmp = _mm_movemask_epi8 (_mm_cmpgt_epi32 (_mm_srli_epi32 (xmmSrc, 24), - _mm_srli_epi32 (_mm_xor_si128 (xmmDst, Maskff000000), 24))); - - /* if some alpha src is grater than respective ~alpha dst */ - if (packCmp) - { - s = *ps++; - d = *pd; - *pd++ = coreCombineSaturateUPixelsse2 (s, d); - - s = *ps++; - d = *pd; - *pd++ = coreCombineSaturateUPixelsse2 (s, d); - - s = *ps++; - d = *pd; - *pd++ = coreCombineSaturateUPixelsse2 (s, d); - - s = *ps++; - d = *pd; - *pd++ = coreCombineSaturateUPixelsse2 (s, d); - } - else - { - save128Aligned ((__m128i*)pd, _mm_adds_epu8 (xmmDst, xmmSrc)); - - pd += 4; - ps += 4; - } - - w -= 4; - } - - while (w--) - { - s = *ps++; - d = *pd; - *pd++ = coreCombineSaturateUPixelsse2 (s, d); - } -} - -static force_inline void -coreCombineSrcCsse2 (uint32_t* pd, const uint32_t* ps, const uint32_t *pm, int w) -{ - uint32_t s, m; - - __m128i xmmSrcLo, xmmSrcHi; - __m128i xmmMaskLo, xmmMaskHi; - __m128i xmmDstLo, xmmDstHi; - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - cachePrefetch ((__m128i*)pm); - - while (w && (unsigned long)pd & 15) - { - s = *ps++; - m = *pm++; - *pd++ = pack_1x64_32 (pixMultiply_1x64 (unpack_32_1x64 (s), unpack_32_1x64 (m))); - w--; - } - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - cachePrefetch ((__m128i*)pm); - - while (w >= 4) - { - /* fill cache line with next memory */ - cachePrefetchNext ((__m128i*)ps); - cachePrefetchNext ((__m128i*)pd); - cachePrefetchNext ((__m128i*)pm); - - xmmSrcHi = load128Unaligned ((__m128i*)ps); - xmmMaskHi = load128Unaligned ((__m128i*)pm); - - unpack_128_2x128 (xmmSrcHi, &xmmSrcLo, &xmmSrcHi); - unpack_128_2x128 (xmmMaskHi, &xmmMaskLo, &xmmMaskHi); - - pixMultiply_2x128 (&xmmSrcLo, &xmmSrcHi, &xmmMaskLo, &xmmMaskHi, &xmmDstLo, &xmmDstHi); - - save128Aligned( (__m128i*)pd, pack_2x128_128 (xmmDstLo, xmmDstHi)); - - ps += 4; - pd += 4; - pm += 4; - w -= 4; - } - - while (w) - { - s = *ps++; - m = *pm++; - *pd++ = pack_1x64_32 (pixMultiply_1x64 (unpack_32_1x64 (s), unpack_32_1x64 (m))); - w--; - } -} - -static force_inline uint32_t -coreCombineOverCPixelsse2 (uint32_t src, uint32_t mask, uint32_t dst) -{ - __m64 s = unpack_32_1x64 (src); - __m64 expAlpha = expandAlpha_1x64 (s); - __m64 unpkMask = unpack_32_1x64 (mask); - __m64 unpkDst = unpack_32_1x64 (dst); - - return pack_1x64_32 (inOver_1x64 (&s, &expAlpha, &unpkMask, &unpkDst)); -} - -static force_inline void -coreCombineOverCsse2 (uint32_t* pd, const uint32_t* ps, const uint32_t *pm, int w) -{ - uint32_t s, m, d; - - __m128i xmmAlphaLo, xmmAlphaHi; - __m128i xmmSrcLo, xmmSrcHi; - __m128i xmmDstLo, xmmDstHi; - __m128i xmmMaskLo, xmmMaskHi; - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - cachePrefetch ((__m128i*)pm); - - while (w && (unsigned long)pd & 15) - { - s = *ps++; - m = *pm++; - d = *pd; - - *pd++ = coreCombineOverCPixelsse2 (s, m, d); - w--; - } - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - cachePrefetch ((__m128i*)pm); - - while (w >= 4) - { - /* fill cache line with next memory */ - cachePrefetchNext ((__m128i*)ps); - cachePrefetchNext ((__m128i*)pd); - cachePrefetchNext ((__m128i*)pm); - - xmmDstHi = load128Aligned ((__m128i*)pd); - xmmSrcHi = load128Unaligned ((__m128i*)ps); - xmmMaskHi = load128Unaligned ((__m128i*)pm); - - unpack_128_2x128 (xmmDstHi, &xmmDstLo, &xmmDstHi); - unpack_128_2x128 (xmmSrcHi, &xmmSrcLo, &xmmSrcHi); - unpack_128_2x128 (xmmMaskHi, &xmmMaskLo, &xmmMaskHi); - - expandAlpha_2x128 (xmmSrcLo, xmmSrcHi, &xmmAlphaLo, &xmmAlphaHi); - - inOver_2x128 (&xmmSrcLo, &xmmSrcHi, &xmmAlphaLo, &xmmAlphaHi, &xmmMaskLo, &xmmMaskHi, &xmmDstLo, &xmmDstHi); - - save128Aligned( (__m128i*)pd, pack_2x128_128 (xmmDstLo, xmmDstHi)); - - ps += 4; - pd += 4; - pm += 4; - w -= 4; - } - - while (w) - { - s = *ps++; - m = *pm++; - d = *pd; - - *pd++ = coreCombineOverCPixelsse2 (s, m, d); - w--; - } -} - -static force_inline uint32_t -coreCombineOverReverseCPixelsse2 (uint32_t src, uint32_t mask, uint32_t dst) -{ - __m64 d = unpack_32_1x64 (dst); - - return pack_1x64_32(over_1x64 (d, expandAlpha_1x64 (d), pixMultiply_1x64 (unpack_32_1x64 (src), unpack_32_1x64 (mask)))); -} - -static force_inline void -coreCombineOverReverseCsse2 (uint32_t* pd, const uint32_t* ps, const uint32_t *pm, int w) -{ - uint32_t s, m, d; - - __m128i xmmAlphaLo, xmmAlphaHi; - __m128i xmmSrcLo, xmmSrcHi; - __m128i xmmDstLo, xmmDstHi; - __m128i xmmMaskLo, xmmMaskHi; - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - cachePrefetch ((__m128i*)pm); - - while (w && (unsigned long)pd & 15) - { - s = *ps++; - m = *pm++; - d = *pd; - - *pd++ = coreCombineOverReverseCPixelsse2 (s, m, d); - w--; - } - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - cachePrefetch ((__m128i*)pm); - - while (w >= 4) - { - /* fill cache line with next memory */ - cachePrefetchNext ((__m128i*)ps); - cachePrefetchNext ((__m128i*)pd); - cachePrefetchNext ((__m128i*)pm); - - xmmDstHi = load128Aligned ((__m128i*)pd); - xmmSrcHi = load128Unaligned ((__m128i*)ps); - xmmMaskHi = load128Unaligned ((__m128i*)pm); - - unpack_128_2x128 (xmmDstHi, &xmmDstLo, &xmmDstHi); - unpack_128_2x128 (xmmSrcHi, &xmmSrcLo, &xmmSrcHi); - unpack_128_2x128 (xmmMaskHi, &xmmMaskLo, &xmmMaskHi); - - expandAlpha_2x128 (xmmDstLo, xmmDstHi, &xmmAlphaLo, &xmmAlphaHi); - pixMultiply_2x128 (&xmmSrcLo, &xmmSrcHi, &xmmMaskLo, &xmmMaskHi, &xmmMaskLo, &xmmMaskHi); - - over_2x128 (&xmmDstLo, &xmmDstHi, &xmmAlphaLo, &xmmAlphaHi, &xmmMaskLo, &xmmMaskHi); - - save128Aligned( (__m128i*)pd, pack_2x128_128 (xmmMaskLo, xmmMaskHi)); - - ps += 4; - pd += 4; - pm += 4; - w -= 4; - } - - while (w) - { - s = *ps++; - m = *pm++; - d = *pd; - - *pd++ = coreCombineOverReverseCPixelsse2 (s, m, d); - w--; - } -} - -static force_inline void -coreCombineInCsse2 (uint32_t *pd, uint32_t *ps, uint32_t *pm, int w) -{ - uint32_t s, m, d; - - __m128i xmmAlphaLo, xmmAlphaHi; - __m128i xmmSrcLo, xmmSrcHi; - __m128i xmmDstLo, xmmDstHi; - __m128i xmmMaskLo, xmmMaskHi; - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - cachePrefetch ((__m128i*)pm); - - while (w && (unsigned long)pd & 15) - { - s = *ps++; - m = *pm++; - d = *pd; - - *pd++ = pack_1x64_32 (pixMultiply_1x64 (pixMultiply_1x64 (unpack_32_1x64 (s), unpack_32_1x64 (m)), - expandAlpha_1x64 (unpack_32_1x64 (d)))); - w--; - } - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - cachePrefetch ((__m128i*)pm); - - while (w >= 4) - { - /* fill cache line with next memory */ - cachePrefetchNext ((__m128i*)ps); - cachePrefetchNext ((__m128i*)pd); - cachePrefetchNext ((__m128i*)pm); - - xmmDstHi = load128Aligned ((__m128i*)pd); - xmmSrcHi = load128Unaligned ((__m128i*)ps); - xmmMaskHi = load128Unaligned ((__m128i*)pm); - - unpack_128_2x128 (xmmDstHi, &xmmDstLo, &xmmDstHi); - unpack_128_2x128 (xmmSrcHi, &xmmSrcLo, &xmmSrcHi); - unpack_128_2x128 (xmmMaskHi, &xmmMaskLo, &xmmMaskHi); - - expandAlpha_2x128 (xmmDstLo, xmmDstHi, &xmmAlphaLo, &xmmAlphaHi); - pixMultiply_2x128 (&xmmSrcLo, &xmmSrcHi, &xmmMaskLo, &xmmMaskHi, &xmmDstLo, &xmmDstHi); - - pixMultiply_2x128 (&xmmDstLo, &xmmDstHi, &xmmAlphaLo, &xmmAlphaHi, &xmmDstLo, &xmmDstHi); - - save128Aligned( (__m128i*)pd, pack_2x128_128 (xmmDstLo, xmmDstHi)); - - ps += 4; - pd += 4; - pm += 4; - w -= 4; - } - - while (w) - { - s = *ps++; - m = *pm++; - d = *pd; - - *pd++ = pack_1x64_32 (pixMultiply_1x64 (pixMultiply_1x64 (unpack_32_1x64 (s), unpack_32_1x64 (m)), - expandAlpha_1x64 (unpack_32_1x64 (d)))); - w--; - } -} - -static force_inline void -coreCombineInReverseCsse2 (uint32_t *pd, uint32_t *ps, uint32_t *pm, int w) -{ - uint32_t s, m, d; - - __m128i xmmAlphaLo, xmmAlphaHi; - __m128i xmmSrcLo, xmmSrcHi; - __m128i xmmDstLo, xmmDstHi; - __m128i xmmMaskLo, xmmMaskHi; - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - cachePrefetch ((__m128i*)pm); - - while (w && (unsigned long)pd & 15) - { - s = *ps++; - m = *pm++; - d = *pd; - - *pd++ = pack_1x64_32 (pixMultiply_1x64 (unpack_32_1x64 (d), - pixMultiply_1x64 (unpack_32_1x64 (m), - expandAlpha_1x64 (unpack_32_1x64 (s))))); - w--; - } - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - cachePrefetch ((__m128i*)pm); - - while (w >= 4) - { - /* fill cache line with next memory */ - cachePrefetchNext ((__m128i*)ps); - cachePrefetchNext ((__m128i*)pd); - cachePrefetchNext ((__m128i*)pm); - - xmmDstHi = load128Aligned ((__m128i*)pd); - xmmSrcHi = load128Unaligned ((__m128i*)ps); - xmmMaskHi = load128Unaligned ((__m128i*)pm); - - unpack_128_2x128 (xmmDstHi, &xmmDstLo, &xmmDstHi); - unpack_128_2x128 (xmmSrcHi, &xmmSrcLo, &xmmSrcHi); - unpack_128_2x128 (xmmMaskHi, &xmmMaskLo, &xmmMaskHi); - - expandAlpha_2x128 (xmmSrcLo, xmmSrcHi, &xmmAlphaLo, &xmmAlphaHi); - pixMultiply_2x128 (&xmmMaskLo, &xmmMaskHi, &xmmAlphaLo, &xmmAlphaHi, &xmmAlphaLo, &xmmAlphaHi); - - pixMultiply_2x128 (&xmmDstLo, &xmmDstHi, &xmmAlphaLo, &xmmAlphaHi, &xmmDstLo, &xmmDstHi); - - save128Aligned( (__m128i*)pd, pack_2x128_128 (xmmDstLo, xmmDstHi)); - - ps += 4; - pd += 4; - pm += 4; - w -= 4; - } - - while (w) - { - s = *ps++; - m = *pm++; - d = *pd; - - *pd++ = pack_1x64_32 (pixMultiply_1x64 (unpack_32_1x64 (d), - pixMultiply_1x64 (unpack_32_1x64 (m), - expandAlpha_1x64 (unpack_32_1x64 (s))))); - w--; - } -} - -static force_inline void -coreCombineOutCsse2 (uint32_t *pd, uint32_t *ps, uint32_t *pm, int w) -{ - uint32_t s, m, d; - - __m128i xmmAlphaLo, xmmAlphaHi; - __m128i xmmSrcLo, xmmSrcHi; - __m128i xmmDstLo, xmmDstHi; - __m128i xmmMaskLo, xmmMaskHi; - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - cachePrefetch ((__m128i*)pm); - - while (w && (unsigned long)pd & 15) - { - s = *ps++; - m = *pm++; - d = *pd; - - *pd++ = pack_1x64_32 (pixMultiply_1x64 (pixMultiply_1x64 (unpack_32_1x64 (s), unpack_32_1x64 (m)), - negate_1x64 (expandAlpha_1x64 (unpack_32_1x64 (d))))); - w--; - } - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - cachePrefetch ((__m128i*)pm); - - while (w >= 4) - { - /* fill cache line with next memory */ - cachePrefetchNext ((__m128i*)ps); - cachePrefetchNext ((__m128i*)pd); - cachePrefetchNext ((__m128i*)pm); - - xmmDstHi = load128Aligned ((__m128i*)pd); - xmmSrcHi = load128Unaligned ((__m128i*)ps); - xmmMaskHi = load128Unaligned ((__m128i*)pm); - - unpack_128_2x128 (xmmDstHi, &xmmDstLo, &xmmDstHi); - unpack_128_2x128 (xmmSrcHi, &xmmSrcLo, &xmmSrcHi); - unpack_128_2x128 (xmmMaskHi, &xmmMaskLo, &xmmMaskHi); - - expandAlpha_2x128 (xmmDstLo, xmmDstHi, &xmmAlphaLo, &xmmAlphaHi); - negate_2x128 (xmmAlphaLo, xmmAlphaHi, &xmmAlphaLo, &xmmAlphaHi); - - pixMultiply_2x128 (&xmmSrcLo, &xmmSrcHi, &xmmMaskLo, &xmmMaskHi, &xmmDstLo, &xmmDstHi); - pixMultiply_2x128 (&xmmDstLo, &xmmDstHi, &xmmAlphaLo, &xmmAlphaHi, &xmmDstLo, &xmmDstHi); - - save128Aligned( (__m128i*)pd, pack_2x128_128 (xmmDstLo, xmmDstHi)); - - ps += 4; - pd += 4; - pm += 4; - w -= 4; - } - - while (w) - { - s = *ps++; - m = *pm++; - d = *pd; - - *pd++ = pack_1x64_32 (pixMultiply_1x64 (pixMultiply_1x64 (unpack_32_1x64 (s), unpack_32_1x64 (m)), - negate_1x64 (expandAlpha_1x64 (unpack_32_1x64 (d))))); - w--; - } -} - -static force_inline void -coreCombineOutReverseCsse2 (uint32_t *pd, uint32_t *ps, uint32_t *pm, int w) -{ - uint32_t s, m, d; - - __m128i xmmAlphaLo, xmmAlphaHi; - __m128i xmmSrcLo, xmmSrcHi; - __m128i xmmDstLo, xmmDstHi; - __m128i xmmMaskLo, xmmMaskHi; - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - cachePrefetch ((__m128i*)pm); - - while (w && (unsigned long)pd & 15) - { - s = *ps++; - m = *pm++; - d = *pd; - - *pd++ = pack_1x64_32 (pixMultiply_1x64 (unpack_32_1x64 (d), - negate_1x64 (pixMultiply_1x64 (unpack_32_1x64 (m), - expandAlpha_1x64 (unpack_32_1x64 (s)))))); - w--; - } - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - cachePrefetch ((__m128i*)pm); - - while (w >= 4) - { - /* fill cache line with next memory */ - cachePrefetchNext ((__m128i*)ps); - cachePrefetchNext ((__m128i*)pd); - cachePrefetchNext ((__m128i*)pm); - - xmmDstHi = load128Aligned ((__m128i*)pd); - xmmSrcHi = load128Unaligned ((__m128i*)ps); - xmmMaskHi = load128Unaligned ((__m128i*)pm); - - unpack_128_2x128 (xmmDstHi, &xmmDstLo, &xmmDstHi); - unpack_128_2x128 (xmmSrcHi, &xmmSrcLo, &xmmSrcHi); - unpack_128_2x128 (xmmMaskHi, &xmmMaskLo, &xmmMaskHi); - - expandAlpha_2x128 (xmmSrcLo, xmmSrcHi, &xmmAlphaLo, &xmmAlphaHi); - - pixMultiply_2x128 (&xmmMaskLo, &xmmMaskHi, &xmmAlphaLo, &xmmAlphaHi, &xmmMaskLo, &xmmMaskHi); - - negate_2x128 (xmmMaskLo, xmmMaskHi, &xmmMaskLo, &xmmMaskHi); - - pixMultiply_2x128 (&xmmDstLo, &xmmDstHi, &xmmMaskLo, &xmmMaskHi, &xmmDstLo, &xmmDstHi); - - save128Aligned( (__m128i*)pd, pack_2x128_128 (xmmDstLo, xmmDstHi)); - - ps += 4; - pd += 4; - pm += 4; - w -= 4; - } - - while (w) - { - s = *ps++; - m = *pm++; - d = *pd; - - *pd++ = pack_1x64_32 (pixMultiply_1x64 (unpack_32_1x64 (d), - negate_1x64 (pixMultiply_1x64 (unpack_32_1x64 (m), - expandAlpha_1x64 (unpack_32_1x64 (s)))))); - w--; - } -} - -static force_inline uint32_t -coreCombineAtopCPixelsse2 (uint32_t src, uint32_t mask, uint32_t dst) -{ - __m64 m = unpack_32_1x64 (mask); - __m64 s = unpack_32_1x64 (src); - __m64 d = unpack_32_1x64 (dst); - __m64 sa = expandAlpha_1x64 (s); - __m64 da = expandAlpha_1x64 (d); - - s = pixMultiply_1x64 (s, m); - m = negate_1x64 (pixMultiply_1x64 (m, sa)); - - return pack_1x64_32 (pixAddMultiply_1x64 (&d, &m, &s, &da)); -} - -static force_inline void -coreCombineAtopCsse2 (uint32_t *pd, uint32_t *ps, uint32_t *pm, int w) -{ - uint32_t s, m, d; - - __m128i xmmSrcLo, xmmSrcHi; - __m128i xmmDstLo, xmmDstHi; - __m128i xmmAlphaSrcLo, xmmAlphaSrcHi; - __m128i xmmAlphaDstLo, xmmAlphaDstHi; - __m128i xmmMaskLo, xmmMaskHi; - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - cachePrefetch ((__m128i*)pm); - - while (w && (unsigned long)pd & 15) - { - s = *ps++; - m = *pm++; - d = *pd; - - *pd++ = coreCombineAtopCPixelsse2 (s, m, d); - w--; - } - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - cachePrefetch ((__m128i*)pm); - - while (w >= 4) - { - /* fill cache line with next memory */ - cachePrefetchNext ((__m128i*)ps); - cachePrefetchNext ((__m128i*)pd); - cachePrefetchNext ((__m128i*)pm); - - xmmDstHi = load128Aligned ((__m128i*)pd); - xmmSrcHi = load128Unaligned ((__m128i*)ps); - xmmMaskHi = load128Unaligned ((__m128i*)pm); - - unpack_128_2x128 (xmmDstHi, &xmmDstLo, &xmmDstHi); - unpack_128_2x128 (xmmSrcHi, &xmmSrcLo, &xmmSrcHi); - unpack_128_2x128 (xmmMaskHi, &xmmMaskLo, &xmmMaskHi); - - expandAlpha_2x128 (xmmSrcLo, xmmSrcHi, &xmmAlphaSrcLo, &xmmAlphaSrcHi); - expandAlpha_2x128 (xmmDstLo, xmmDstHi, &xmmAlphaDstLo, &xmmAlphaDstHi); - - pixMultiply_2x128 (&xmmSrcLo, &xmmSrcHi, &xmmMaskLo, &xmmMaskHi, &xmmSrcLo, &xmmSrcHi); - pixMultiply_2x128 (&xmmMaskLo, &xmmMaskHi, &xmmAlphaSrcLo, &xmmAlphaSrcHi, &xmmMaskLo, &xmmMaskHi); - - negate_2x128 (xmmMaskLo, xmmMaskHi, &xmmMaskLo, &xmmMaskHi); - - pixAddMultiply_2x128 (&xmmDstLo, &xmmDstHi, &xmmMaskLo, &xmmMaskHi, - &xmmSrcLo, &xmmSrcHi, &xmmAlphaDstLo, &xmmAlphaDstHi, - &xmmDstLo, &xmmDstHi); - - save128Aligned( (__m128i*)pd, pack_2x128_128 (xmmDstLo, xmmDstHi)); - - ps += 4; - pd += 4; - pm += 4; - w -= 4; - } - - while (w) - { - s = *ps++; - m = *pm++; - d = *pd; - - *pd++ = coreCombineAtopCPixelsse2 (s, m, d); - w--; - } -} - -static force_inline uint32_t -coreCombineReverseAtopCPixelsse2 (uint32_t src, uint32_t mask, uint32_t dst) -{ - __m64 m = unpack_32_1x64 (mask); - __m64 s = unpack_32_1x64 (src); - __m64 d = unpack_32_1x64 (dst); - - __m64 da = negate_1x64 (expandAlpha_1x64 (d)); - __m64 sa = expandAlpha_1x64 (s); - - s = pixMultiply_1x64 (s, m); - m = pixMultiply_1x64 (m, sa); - - return pack_1x64_32 (pixAddMultiply_1x64 (&d, &m, &s, &da)); -} - -static force_inline void -coreCombineReverseAtopCsse2 (uint32_t *pd, uint32_t *ps, uint32_t *pm, int w) -{ - uint32_t s, m, d; - - __m128i xmmSrcLo, xmmSrcHi; - __m128i xmmDstLo, xmmDstHi; - __m128i xmmAlphaSrcLo, xmmAlphaSrcHi; - __m128i xmmAlphaDstLo, xmmAlphaDstHi; - __m128i xmmMaskLo, xmmMaskHi; - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - cachePrefetch ((__m128i*)pm); - - while (w && (unsigned long)pd & 15) - { - s = *ps++; - m = *pm++; - d = *pd; - - *pd++ = coreCombineReverseAtopCPixelsse2 (s, m, d); - w--; - } - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - cachePrefetch ((__m128i*)pm); - - while (w >= 4) - { - /* fill cache line with next memory */ - cachePrefetchNext ((__m128i*)ps); - cachePrefetchNext ((__m128i*)pd); - cachePrefetchNext ((__m128i*)pm); - - xmmDstHi = load128Aligned ((__m128i*)pd); - xmmSrcHi = load128Unaligned ((__m128i*)ps); - xmmMaskHi = load128Unaligned ((__m128i*)pm); - - unpack_128_2x128 (xmmDstHi, &xmmDstLo, &xmmDstHi); - unpack_128_2x128 (xmmSrcHi, &xmmSrcLo, &xmmSrcHi); - unpack_128_2x128 (xmmMaskHi, &xmmMaskLo, &xmmMaskHi); - - expandAlpha_2x128 (xmmSrcLo, xmmSrcHi, &xmmAlphaSrcLo, &xmmAlphaSrcHi); - expandAlpha_2x128 (xmmDstLo, xmmDstHi, &xmmAlphaDstLo, &xmmAlphaDstHi); - - pixMultiply_2x128 (&xmmSrcLo, &xmmSrcHi, &xmmMaskLo, &xmmMaskHi, &xmmSrcLo, &xmmSrcHi); - pixMultiply_2x128 (&xmmMaskLo, &xmmMaskHi, &xmmAlphaSrcLo, &xmmAlphaSrcHi, &xmmMaskLo, &xmmMaskHi); - - negate_2x128 (xmmAlphaDstLo, xmmAlphaDstHi, &xmmAlphaDstLo, &xmmAlphaDstHi); - - pixAddMultiply_2x128 (&xmmDstLo, &xmmDstHi, &xmmMaskLo, &xmmMaskHi, - &xmmSrcLo, &xmmSrcHi, &xmmAlphaDstLo, &xmmAlphaDstHi, - &xmmDstLo, &xmmDstHi); - - save128Aligned( (__m128i*)pd, pack_2x128_128 (xmmDstLo, xmmDstHi)); - - ps += 4; - pd += 4; - pm += 4; - w -= 4; - } - - while (w) - { - s = *ps++; - m = *pm++; - d = *pd; - - *pd++ = coreCombineReverseAtopCPixelsse2 (s, m, d); - w--; - } -} - -static force_inline uint32_t -coreCombineXorCPixelsse2 (uint32_t src, uint32_t mask, uint32_t dst) -{ - __m64 a = unpack_32_1x64 (mask); - __m64 s = unpack_32_1x64 (src); - __m64 d = unpack_32_1x64 (dst); - - __m64 alphaDst = negate_1x64 (pixMultiply_1x64 (a, expandAlpha_1x64 (s))); - __m64 dest = pixMultiply_1x64 (s, a); - __m64 alphaSrc = negate_1x64 (expandAlpha_1x64 (d)); - - return pack_1x64_32 (pixAddMultiply_1x64 (&d, - &alphaDst, - &dest, - &alphaSrc)); -} - -static force_inline void -coreCombineXorCsse2 (uint32_t *pd, uint32_t *ps, uint32_t *pm, int w) -{ - uint32_t s, m, d; - - __m128i xmmSrcLo, xmmSrcHi; - __m128i xmmDstLo, xmmDstHi; - __m128i xmmAlphaSrcLo, xmmAlphaSrcHi; - __m128i xmmAlphaDstLo, xmmAlphaDstHi; - __m128i xmmMaskLo, xmmMaskHi; - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - cachePrefetch ((__m128i*)pm); - - while (w && (unsigned long)pd & 15) - { - s = *ps++; - m = *pm++; - d = *pd; - - *pd++ = coreCombineXorCPixelsse2 (s, m, d); - w--; - } - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - cachePrefetch ((__m128i*)pm); - - while (w >= 4) - { - /* fill cache line with next memory */ - cachePrefetchNext ((__m128i*)ps); - cachePrefetchNext ((__m128i*)pd); - cachePrefetchNext ((__m128i*)pm); - - xmmDstHi = load128Aligned ((__m128i*)pd); - xmmSrcHi = load128Unaligned ((__m128i*)ps); - xmmMaskHi = load128Unaligned ((__m128i*)pm); - - unpack_128_2x128 (xmmDstHi, &xmmDstLo, &xmmDstHi); - unpack_128_2x128 (xmmSrcHi, &xmmSrcLo, &xmmSrcHi); - unpack_128_2x128 (xmmMaskHi, &xmmMaskLo, &xmmMaskHi); - - expandAlpha_2x128 (xmmSrcLo, xmmSrcHi, &xmmAlphaSrcLo, &xmmAlphaSrcHi); - expandAlpha_2x128 (xmmDstLo, xmmDstHi, &xmmAlphaDstLo, &xmmAlphaDstHi); - - pixMultiply_2x128 (&xmmSrcLo, &xmmSrcHi, &xmmMaskLo, &xmmMaskHi, &xmmSrcLo, &xmmSrcHi); - pixMultiply_2x128 (&xmmMaskLo, &xmmMaskHi, &xmmAlphaSrcLo, &xmmAlphaSrcHi, &xmmMaskLo, &xmmMaskHi); - - negate_2x128 (xmmAlphaDstLo, xmmAlphaDstHi, &xmmAlphaDstLo, &xmmAlphaDstHi); - negate_2x128 (xmmMaskLo, xmmMaskHi, &xmmMaskLo, &xmmMaskHi); - - pixAddMultiply_2x128 (&xmmDstLo, &xmmDstHi, &xmmMaskLo, &xmmMaskHi, - &xmmSrcLo, &xmmSrcHi, &xmmAlphaDstLo, &xmmAlphaDstHi, - &xmmDstLo, &xmmDstHi); - - save128Aligned( (__m128i*)pd, pack_2x128_128 (xmmDstLo, xmmDstHi)); - - ps += 4; - pd += 4; - pm += 4; - w -= 4; - } - - while (w) - { - s = *ps++; - m = *pm++; - d = *pd; - - *pd++ = coreCombineXorCPixelsse2 (s, m, d); - w--; - } -} - -static force_inline void -coreCombineAddCsse2 (uint32_t *pd, uint32_t *ps, uint32_t *pm, int w) -{ - uint32_t s, m, d; - - __m128i xmmSrcLo, xmmSrcHi; - __m128i xmmDstLo, xmmDstHi; - __m128i xmmMaskLo, xmmMaskHi; - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - cachePrefetch ((__m128i*)pm); - - while (w && (unsigned long)pd & 15) - { - s = *ps++; - m = *pm++; - d = *pd; - - *pd++ = pack_1x64_32 (_mm_adds_pu8 (pixMultiply_1x64 (unpack_32_1x64 (s), - unpack_32_1x64 (m)), - unpack_32_1x64 (d))); - w--; - } - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)ps); - cachePrefetch ((__m128i*)pd); - cachePrefetch ((__m128i*)pm); - - while (w >= 4) - { - /* fill cache line with next memory */ - cachePrefetchNext ((__m128i*)ps); - cachePrefetchNext ((__m128i*)pd); - cachePrefetchNext ((__m128i*)pm); - - xmmSrcHi = load128Unaligned ((__m128i*)ps); - xmmMaskHi = load128Unaligned ((__m128i*)pm); - xmmDstHi = load128Aligned ((__m128i*)pd); - - unpack_128_2x128 (xmmSrcHi, &xmmSrcLo, &xmmSrcHi); - unpack_128_2x128 (xmmMaskHi, &xmmMaskLo, &xmmMaskHi); - unpack_128_2x128 (xmmDstHi, &xmmDstLo, &xmmDstHi); - - pixMultiply_2x128 (&xmmSrcLo, &xmmSrcHi, &xmmMaskLo, &xmmMaskHi, &xmmSrcLo, &xmmSrcHi); - - save128Aligned( (__m128i*)pd, pack_2x128_128 (_mm_adds_epu8 (xmmSrcLo, xmmDstLo), - _mm_adds_epu8 (xmmSrcHi, xmmDstHi))); - - ps += 4; - pd += 4; - pm += 4; - w -= 4; - } - - while (w) - { - s = *ps++; - m = *pm++; - d = *pd; - - *pd++ = pack_1x64_32 (_mm_adds_pu8 (pixMultiply_1x64 (unpack_32_1x64 (s), - unpack_32_1x64 (m)), - unpack_32_1x64 (d))); - w--; - } -} - -/* ------------------------------------------------------------------------------------------------- - * fbComposeSetupSSE2 - */ -static force_inline __m64 -createMask_16_64 (uint16_t mask) -{ - return _mm_set1_pi16 (mask); -} - -static force_inline __m128i -createMask_16_128 (uint16_t mask) -{ - return _mm_set1_epi16 (mask); -} - -static force_inline __m64 -createMask_2x32_64 (uint32_t mask0, uint32_t mask1) -{ - return _mm_set_pi32 (mask0, mask1); -} - -static force_inline __m128i -createMask_2x32_128 (uint32_t mask0, uint32_t mask1) -{ - return _mm_set_epi32 (mask0, mask1, mask0, mask1); -} - -/* SSE2 code patch for fbcompose.c */ - -static FASTCALL void -sse2CombineMaskU (uint32_t *dst, const uint32_t *src, int width) -{ - coreCombineReverseInUsse2 (dst, src, width); - _mm_empty(); -} - -static FASTCALL void -sse2CombineOverU (uint32_t *dst, const uint32_t *src, int width) -{ - coreCombineOverUsse2 (dst, src, width); - _mm_empty(); -} - -static FASTCALL void -sse2CombineOverReverseU (uint32_t *dst, const uint32_t *src, int width) -{ - coreCombineOverReverseUsse2 (dst, src, width); - _mm_empty(); -} - -static FASTCALL void -sse2CombineInU (uint32_t *dst, const uint32_t *src, int width) -{ - coreCombineInUsse2 (dst, src, width); - _mm_empty(); -} - -static FASTCALL void -sse2CombineInReverseU (uint32_t *dst, const uint32_t *src, int width) -{ - coreCombineReverseInUsse2 (dst, src, width); - _mm_empty(); -} - -static FASTCALL void -sse2CombineOutU (uint32_t *dst, const uint32_t *src, int width) -{ - coreCombineOutUsse2 (dst, src, width); - _mm_empty(); -} - -static FASTCALL void -sse2CombineOutReverseU (uint32_t *dst, const uint32_t *src, int width) -{ - coreCombineReverseOutUsse2 (dst, src, width); - _mm_empty(); -} - -static FASTCALL void -sse2CombineAtopU (uint32_t *dst, const uint32_t *src, int width) -{ - coreCombineAtopUsse2 (dst, src, width); - _mm_empty(); -} - -static FASTCALL void -sse2CombineAtopReverseU (uint32_t *dst, const uint32_t *src, int width) -{ - coreCombineReverseAtopUsse2 (dst, src, width); - _mm_empty(); -} - -static FASTCALL void -sse2CombineXorU (uint32_t *dst, const uint32_t *src, int width) -{ - coreCombineXorUsse2 (dst, src, width); - _mm_empty(); -} - -static FASTCALL void -sse2CombineAddU (uint32_t *dst, const uint32_t *src, int width) -{ - coreCombineAddUsse2 (dst, src, width); - _mm_empty(); -} - -static FASTCALL void -sse2CombineSaturateU (uint32_t *dst, const uint32_t *src, int width) -{ - coreCombineSaturateUsse2 (dst, src, width); - _mm_empty(); -} - -static FASTCALL void -sse2CombineSrcC (uint32_t *dst, uint32_t *src, uint32_t *mask, int width) -{ - coreCombineSrcCsse2 (dst, src, mask, width); - _mm_empty(); -} - -static FASTCALL void -sse2CombineOverC (uint32_t *dst, uint32_t *src, uint32_t *mask, int width) -{ - coreCombineOverCsse2 (dst, src, mask, width); - _mm_empty(); -} - -static FASTCALL void -sse2CombineOverReverseC (uint32_t *dst, uint32_t *src, uint32_t *mask, int width) -{ - coreCombineOverReverseCsse2 (dst, src, mask, width); - _mm_empty(); -} - -static FASTCALL void -sse2CombineInC (uint32_t *dst, uint32_t *src, uint32_t *mask, int width) -{ - coreCombineInCsse2 (dst, src, mask, width); - _mm_empty(); -} - -static FASTCALL void -sse2CombineInReverseC (uint32_t *dst, uint32_t *src, uint32_t *mask, int width) -{ - coreCombineInReverseCsse2 (dst, src, mask, width); - _mm_empty(); -} - -static FASTCALL void -sse2CombineOutC (uint32_t *dst, uint32_t *src, uint32_t *mask, int width) -{ - coreCombineOutCsse2 (dst, src, mask, width); - _mm_empty(); -} - -static FASTCALL void -sse2CombineOutReverseC (uint32_t *dst, uint32_t *src, uint32_t *mask, int width) -{ - coreCombineOutReverseCsse2 (dst, src, mask, width); - _mm_empty(); -} - -static FASTCALL void -sse2CombineAtopC (uint32_t *dst, uint32_t *src, uint32_t *mask, int width) -{ - coreCombineAtopCsse2 (dst, src, mask, width); - _mm_empty(); -} - -static FASTCALL void -sse2CombineAtopReverseC (uint32_t *dst, uint32_t *src, uint32_t *mask, int width) -{ - coreCombineReverseAtopCsse2 (dst, src, mask, width); - _mm_empty(); -} - -static FASTCALL void -sse2CombineXorC (uint32_t *dst, uint32_t *src, uint32_t *mask, int width) -{ - coreCombineXorCsse2 (dst, src, mask, width); - _mm_empty(); -} - -static FASTCALL void -sse2CombineAddC (uint32_t *dst, uint32_t *src, uint32_t *mask, int width) -{ - coreCombineAddCsse2 (dst, src, mask, width); - _mm_empty(); -} - -void -fbComposeSetupSSE2(void) -{ - static pixman_bool_t initialized = FALSE; - - if (initialized) - return; - - /* check if we have SSE2 support and initialize accordingly */ - if (pixman_have_sse2()) - { - /* SSE2 constants */ - Mask565r = createMask_2x32_128 (0x00f80000, 0x00f80000); - Mask565g1 = createMask_2x32_128 (0x00070000, 0x00070000); - Mask565g2 = createMask_2x32_128 (0x000000e0, 0x000000e0); - Mask565b = createMask_2x32_128 (0x0000001f, 0x0000001f); - MaskRed = createMask_2x32_128 (0x00f80000, 0x00f80000); - MaskGreen = createMask_2x32_128 (0x0000fc00, 0x0000fc00); - MaskBlue = createMask_2x32_128 (0x000000f8, 0x000000f8); - Mask565FixRB = createMask_2x32_128 (0x00e000e0, 0x00e000e0); - Mask565FixG = createMask_2x32_128 (0x0000c000, 0x0000c000); - Mask0080 = createMask_16_128 (0x0080); - Mask00ff = createMask_16_128 (0x00ff); - Mask0101 = createMask_16_128 (0x0101); - Maskffff = createMask_16_128 (0xffff); - Maskff000000 = createMask_2x32_128 (0xff000000, 0xff000000); - MaskAlpha = createMask_2x32_128 (0x00ff0000, 0x00000000); - - /* MMX constants */ - xMask565rgb = createMask_2x32_64 (0x000001f0, 0x003f001f); - xMask565Unpack = createMask_2x32_64 (0x00000084, 0x04100840); - - xMask0080 = createMask_16_64 (0x0080); - xMask00ff = createMask_16_64 (0x00ff); - xMask0101 = createMask_16_64 (0x0101); - xMaskAlpha = createMask_2x32_64 (0x00ff0000, 0x00000000); - - /* SSE code patch for fbcompose.c */ - pixman_composeFunctions.combineU[PIXMAN_OP_OVER] = sse2CombineOverU; - pixman_composeFunctions.combineU[PIXMAN_OP_OVER_REVERSE] = sse2CombineOverReverseU; - pixman_composeFunctions.combineU[PIXMAN_OP_IN] = sse2CombineInU; - pixman_composeFunctions.combineU[PIXMAN_OP_IN_REVERSE] = sse2CombineInReverseU; - pixman_composeFunctions.combineU[PIXMAN_OP_OUT] = sse2CombineOutU; - - pixman_composeFunctions.combineU[PIXMAN_OP_OUT_REVERSE] = sse2CombineOutReverseU; - pixman_composeFunctions.combineU[PIXMAN_OP_ATOP] = sse2CombineAtopU; - pixman_composeFunctions.combineU[PIXMAN_OP_ATOP_REVERSE] = sse2CombineAtopReverseU; - pixman_composeFunctions.combineU[PIXMAN_OP_XOR] = sse2CombineXorU; - pixman_composeFunctions.combineU[PIXMAN_OP_ADD] = sse2CombineAddU; - - pixman_composeFunctions.combineU[PIXMAN_OP_SATURATE] = sse2CombineSaturateU; - - pixman_composeFunctions.combineC[PIXMAN_OP_SRC] = sse2CombineSrcC; - pixman_composeFunctions.combineC[PIXMAN_OP_OVER] = sse2CombineOverC; - pixman_composeFunctions.combineC[PIXMAN_OP_OVER_REVERSE] = sse2CombineOverReverseC; - pixman_composeFunctions.combineC[PIXMAN_OP_IN] = sse2CombineInC; - pixman_composeFunctions.combineC[PIXMAN_OP_IN_REVERSE] = sse2CombineInReverseC; - pixman_composeFunctions.combineC[PIXMAN_OP_OUT] = sse2CombineOutC; - pixman_composeFunctions.combineC[PIXMAN_OP_OUT_REVERSE] = sse2CombineOutReverseC; - pixman_composeFunctions.combineC[PIXMAN_OP_ATOP] = sse2CombineAtopC; - pixman_composeFunctions.combineC[PIXMAN_OP_ATOP_REVERSE] = sse2CombineAtopReverseC; - pixman_composeFunctions.combineC[PIXMAN_OP_XOR] = sse2CombineXorC; - pixman_composeFunctions.combineC[PIXMAN_OP_ADD] = sse2CombineAddC; - - pixman_composeFunctions.combineMaskU = sse2CombineMaskU; - - _mm_empty(); - } - - initialized = TRUE; -} - - -/* ------------------------------------------------------------------------------------------------- - * fbCompositeSolid_nx8888 - */ - -void -fbCompositeSolid_nx8888sse2 (pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height) -{ - uint32_t src; - uint32_t *dstLine, *dst, d; - uint16_t w; - int dstStride; - __m128i xmmSrc, xmmAlpha; - __m128i xmmDst, xmmDstLo, xmmDstHi; - - fbComposeGetSolid(pSrc, src, pDst->bits.format); - - if (src >> 24 == 0) - return; - - fbComposeGetStart (pDst, xDst, yDst, uint32_t, dstStride, dstLine, 1); - - xmmSrc = expandPixel_32_1x128 (src); - xmmAlpha = expandAlpha_1x128 (xmmSrc); - - while (height--) - { - dst = dstLine; - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)dst); - - dstLine += dstStride; - w = width; - - while (w && (unsigned long)dst & 15) - { - d = *dst; - *dst++ = pack_1x64_32 (over_1x64 (_mm_movepi64_pi64 (xmmSrc), - _mm_movepi64_pi64 (xmmAlpha), - unpack_32_1x64 (d))); - w--; - } - - cachePrefetch ((__m128i*)dst); - - while (w >= 4) - { - /* fill cache line with next memory */ - cachePrefetchNext ((__m128i*)dst); - - xmmDst = load128Aligned ((__m128i*)dst); - - unpack_128_2x128 (xmmDst, &xmmDstLo, &xmmDstHi); - - over_2x128 (&xmmSrc, &xmmSrc, &xmmAlpha, &xmmAlpha, &xmmDstLo, &xmmDstHi); - - /* rebuid the 4 pixel data and save*/ - save128Aligned ((__m128i*)dst, pack_2x128_128 (xmmDstLo, xmmDstHi)); - - w -= 4; - dst += 4; - } - - while (w) - { - d = *dst; - *dst++ = pack_1x64_32 (over_1x64 (_mm_movepi64_pi64 (xmmSrc), - _mm_movepi64_pi64 (xmmAlpha), - unpack_32_1x64 (d))); - w--; - } - - } - _mm_empty(); -} - -/* ------------------------------------------------------------------------------------------------- - * fbCompositeSolid_nx0565 - */ -void -fbCompositeSolid_nx0565sse2 (pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height) -{ - uint32_t src; - uint16_t *dstLine, *dst, d; - uint16_t w; - int dstStride; - __m128i xmmSrc, xmmAlpha; - __m128i xmmDst, xmmDst0, xmmDst1, xmmDst2, xmmDst3; - - fbComposeGetSolid(pSrc, src, pDst->bits.format); - - if (src >> 24 == 0) - return; - - fbComposeGetStart (pDst, xDst, yDst, uint16_t, dstStride, dstLine, 1); - - xmmSrc = expandPixel_32_1x128 (src); - xmmAlpha = expandAlpha_1x128 (xmmSrc); - - while (height--) - { - dst = dstLine; - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)dst); - - dstLine += dstStride; - w = width; - - while (w && (unsigned long)dst & 15) - { - d = *dst; - - *dst++ = pack565_32_16 (pack_1x64_32 (over_1x64 (_mm_movepi64_pi64 (xmmSrc), - _mm_movepi64_pi64 (xmmAlpha), - expand565_16_1x64 (d)))); - w--; - } - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)dst); - - while (w >= 8) - { - /* fill cache line with next memory */ - cachePrefetchNext ((__m128i*)dst); - - xmmDst = load128Aligned ((__m128i*)dst); - - unpack565_128_4x128 (xmmDst, &xmmDst0, &xmmDst1, &xmmDst2, &xmmDst3); - - over_2x128 (&xmmSrc, &xmmSrc, &xmmAlpha, &xmmAlpha, &xmmDst0, &xmmDst1); - over_2x128 (&xmmSrc, &xmmSrc, &xmmAlpha, &xmmAlpha, &xmmDst2, &xmmDst3); - - xmmDst = pack565_4x128_128 (&xmmDst0, &xmmDst1, &xmmDst2, &xmmDst3); - save128Aligned ((__m128i*)dst, xmmDst); - - dst += 8; - w -= 8; - } - - while (w--) - { - d = *dst; - *dst++ = pack565_32_16 (pack_1x64_32 (over_1x64 (_mm_movepi64_pi64 (xmmSrc), - _mm_movepi64_pi64 (xmmAlpha), - expand565_16_1x64 (d)))); - } - } - - _mm_empty(); -} - -/* ------------------------------------------------------------------------------------------------- - * fbCompositeSolidMask_nx8888x8888C - */ - -void -fbCompositeSolidMask_nx8888x8888Csse2 (pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height) -{ - uint32_t src, srca; - uint32_t *dstLine, d; - uint32_t *maskLine, m; - uint32_t packCmp; - int dstStride, maskStride; - - __m128i xmmSrc, xmmAlpha; - __m128i xmmDst, xmmDstLo, xmmDstHi; - __m128i xmmMask, xmmMaskLo, xmmMaskHi; - - __m64 mmxSrc, mmxAlpha, mmxMask, mmxDst; - - fbComposeGetSolid(pSrc, src, pDst->bits.format); - - srca = src >> 24; - if (srca == 0) - return; - - fbComposeGetStart (pDst, xDst, yDst, uint32_t, dstStride, dstLine, 1); - fbComposeGetStart (pMask, xMask, yMask, uint32_t, maskStride, maskLine, 1); - - xmmSrc = _mm_unpacklo_epi8 (createMask_2x32_128 (src, src), _mm_setzero_si128 ()); - xmmAlpha = expandAlpha_1x128 (xmmSrc); - mmxSrc = _mm_movepi64_pi64 (xmmSrc); - mmxAlpha = _mm_movepi64_pi64 (xmmAlpha); - - while (height--) - { - int w = width; - uint32_t *pm = (uint32_t *)maskLine; - uint32_t *pd = (uint32_t *)dstLine; - - dstLine += dstStride; - maskLine += maskStride; - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)pd); - cachePrefetch ((__m128i*)pm); - - while (w && (unsigned long)pd & 15) - { - m = *pm++; - - if (m) - { - d = *pd; - mmxMask = unpack_32_1x64 (m); - mmxDst = unpack_32_1x64 (d); - - *pd = pack_1x64_32 (inOver_1x64 (&mmxSrc, - &mmxAlpha, - &mmxMask, - &mmxDst)); - } - - pd++; - w--; - } - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)pd); - cachePrefetch ((__m128i*)pm); - - while (w >= 4) - { - /* fill cache line with next memory */ - cachePrefetchNext ((__m128i*)pd); - cachePrefetchNext ((__m128i*)pm); - - xmmMask = load128Unaligned ((__m128i*)pm); - - packCmp = _mm_movemask_epi8 (_mm_cmpeq_epi32 (xmmMask, _mm_setzero_si128())); - - /* if all bits in mask are zero, packCmp are equal to 0xffff */ - if (packCmp != 0xffff) - { - xmmDst = load128Aligned ((__m128i*)pd); - - unpack_128_2x128 (xmmMask, &xmmMaskLo, &xmmMaskHi); - unpack_128_2x128 (xmmDst, &xmmDstLo, &xmmDstHi); - - inOver_2x128 (&xmmSrc, &xmmSrc, &xmmAlpha, &xmmAlpha, &xmmMaskLo, &xmmMaskHi, &xmmDstLo, &xmmDstHi); - - save128Aligned ((__m128i*)pd, pack_2x128_128 (xmmDstLo, xmmDstHi)); - } - - pd += 4; - pm += 4; - w -= 4; - } - - while (w) - { - m = *pm++; - - if (m) - { - d = *pd; - mmxMask = unpack_32_1x64 (m); - mmxDst = unpack_32_1x64 (d); - - *pd = pack_1x64_32 (inOver_1x64 (&mmxSrc, - &mmxAlpha, - &mmxMask, - &mmxDst)); - } - - pd++; - w--; - } - } - - _mm_empty(); -} - - -/* ------------------------------------------------------------------------------------------------- - * fbCompositeSrc_8888x8x8888 - */ - -void -fbCompositeSrc_8888x8x8888sse2 (pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height) -{ - uint32_t *dstLine, *dst; - uint32_t *srcLine, *src; - uint32_t mask; - uint16_t w; - int dstStride, srcStride; - - __m128i xmmMask; - __m128i xmmSrc, xmmSrcLo, xmmSrcHi; - __m128i xmmDst, xmmDstLo, xmmDstHi; - __m128i xmmAlphaLo, xmmAlphaHi; - - fbComposeGetStart (pDst, xDst, yDst, uint32_t, dstStride, dstLine, 1); - fbComposeGetStart (pSrc, xSrc, ySrc, uint32_t, srcStride, srcLine, 1); - fbComposeGetSolid (pMask, mask, pDst->bits.format); - - xmmMask = createMask_16_128 (mask >> 24); - - while (height--) - { - dst = dstLine; - dstLine += dstStride; - src = srcLine; - srcLine += srcStride; - w = width; - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)dst); - cachePrefetch ((__m128i*)src); - - while (w && (unsigned long)dst & 15) - { - uint32_t s = *src++; - uint32_t d = *dst; - - __m64 ms = unpack_32_1x64 (s); - __m64 alpha = expandAlpha_1x64 (ms); - __m64 dest = _mm_movepi64_pi64 (xmmMask); - __m64 alphaDst = unpack_32_1x64 (d); - - *dst++ = pack_1x64_32 (inOver_1x64 (&ms, - &alpha, - &dest, - &alphaDst)); - - w--; - } - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)dst); - cachePrefetch ((__m128i*)src); - - while (w >= 4) - { - /* fill cache line with next memory */ - cachePrefetchNext ((__m128i*)dst); - cachePrefetchNext ((__m128i*)src); - - xmmSrc = load128Unaligned ((__m128i*)src); - xmmDst = load128Aligned ((__m128i*)dst); - - unpack_128_2x128 (xmmSrc, &xmmSrcLo, &xmmSrcHi); - unpack_128_2x128 (xmmDst, &xmmDstLo, &xmmDstHi); - expandAlpha_2x128 (xmmSrcLo, xmmSrcHi, &xmmAlphaLo, &xmmAlphaHi); - - inOver_2x128 (&xmmSrcLo, &xmmSrcHi, &xmmAlphaLo, &xmmAlphaHi, &xmmMask, &xmmMask, &xmmDstLo, &xmmDstHi); - - save128Aligned( (__m128i*)dst, pack_2x128_128 (xmmDstLo, xmmDstHi)); - - dst += 4; - src += 4; - w -= 4; - } - - while (w) - { - uint32_t s = *src++; - uint32_t d = *dst; - - __m64 ms = unpack_32_1x64 (s); - __m64 alpha = expandAlpha_1x64 (ms); - __m64 mask = _mm_movepi64_pi64 (xmmMask); - __m64 dest = unpack_32_1x64 (d); - - *dst++ = pack_1x64_32 (inOver_1x64 (&ms, - &alpha, - &mask, - &dest)); - - w--; - } - } - - _mm_empty(); -} - -/* ------------------------------------------------------------------------------------------------- - * fbCompositeSrc_x888xnx8888 - */ -void -fbCompositeSrc_x888xnx8888sse2 (pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height) -{ - uint32_t *dstLine, *dst; - uint32_t *srcLine, *src; - uint32_t mask; - int dstStride, srcStride; - uint16_t w; - - __m128i xmmMask, xmmAlpha; - __m128i xmmSrc, xmmSrcLo, xmmSrcHi; - __m128i xmmDst, xmmDstLo, xmmDstHi; - - fbComposeGetStart (pDst, xDst, yDst, uint32_t, dstStride, dstLine, 1); - fbComposeGetStart (pSrc, xSrc, ySrc, uint32_t, srcStride, srcLine, 1); - fbComposeGetSolid (pMask, mask, pDst->bits.format); - - xmmMask = createMask_16_128 (mask >> 24); - xmmAlpha = Mask00ff; - - while (height--) - { - dst = dstLine; - dstLine += dstStride; - src = srcLine; - srcLine += srcStride; - w = width; - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)dst); - cachePrefetch ((__m128i*)src); - - while (w && (unsigned long)dst & 15) - { - uint32_t s = (*src++) | 0xff000000; - uint32_t d = *dst; - - __m64 src = unpack_32_1x64 (s); - __m64 alpha = _mm_movepi64_pi64 (xmmAlpha); - __m64 mask = _mm_movepi64_pi64 (xmmMask); - __m64 dest = unpack_32_1x64 (d); - - *dst++ = pack_1x64_32 (inOver_1x64 (&src, - &alpha, - &mask, - &dest)); - - w--; - } - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)dst); - cachePrefetch ((__m128i*)src); - - while (w >= 4) - { - /* fill cache line with next memory */ - cachePrefetchNext ((__m128i*)dst); - cachePrefetchNext ((__m128i*)src); - - xmmSrc = _mm_or_si128 (load128Unaligned ((__m128i*)src), Maskff000000); - xmmDst = load128Aligned ((__m128i*)dst); - - unpack_128_2x128 (xmmSrc, &xmmSrcLo, &xmmSrcHi); - unpack_128_2x128 (xmmDst, &xmmDstLo, &xmmDstHi); - - inOver_2x128 (&xmmSrcLo, &xmmSrcHi, &xmmAlpha, &xmmAlpha, &xmmMask, &xmmMask, &xmmDstLo, &xmmDstHi); - - save128Aligned( (__m128i*)dst, pack_2x128_128 (xmmDstLo, xmmDstHi)); - - dst += 4; - src += 4; - w -= 4; - - } - - while (w) - { - uint32_t s = (*src++) | 0xff000000; - uint32_t d = *dst; - - __m64 src = unpack_32_1x64 (s); - __m64 alpha = _mm_movepi64_pi64 (xmmAlpha); - __m64 mask = _mm_movepi64_pi64 (xmmMask); - __m64 dest = unpack_32_1x64 (d); - - *dst++ = pack_1x64_32 (inOver_1x64 (&src, - &alpha, - &mask, - &dest)); - - w--; - } - } - - _mm_empty(); -} - -/* ------------------------------------------------------------------------------------------------- - * fbCompositeSrc_8888x8888 - */ -void -fbCompositeSrc_8888x8888sse2 (pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height) -{ - int dstStride, srcStride; - uint32_t *dstLine, *dst; - uint32_t *srcLine, *src; - - fbComposeGetStart (pDst, xDst, yDst, uint32_t, dstStride, dstLine, 1); - fbComposeGetStart (pSrc, xSrc, ySrc, uint32_t, srcStride, srcLine, 1); - - dst = dstLine; - src = srcLine; - - while (height--) - { - coreCombineOverUsse2 (dst, src, width); - - dst += dstStride; - src += srcStride; - } - _mm_empty(); -} - -/* ------------------------------------------------------------------------------------------------- - * fbCompositeSrc_8888x0565 - */ -static force_inline uint16_t -fbCompositeSrc_8888x0565pixel (uint32_t src, uint16_t dst) -{ - __m64 ms; - - ms = unpack_32_1x64 (src); - return pack565_32_16( pack_1x64_32 (over_1x64 (ms, - expandAlpha_1x64 (ms), - expand565_16_1x64 (dst)))); -} - -void -fbCompositeSrc_8888x0565sse2 (pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height) -{ - uint16_t *dstLine, *dst, d; - uint32_t *srcLine, *src, s; - int dstStride, srcStride; - uint16_t w; - - __m128i xmmAlphaLo, xmmAlphaHi; - __m128i xmmSrc, xmmSrcLo, xmmSrcHi; - __m128i xmmDst, xmmDst0, xmmDst1, xmmDst2, xmmDst3; - - fbComposeGetStart (pDst, xDst, yDst, uint16_t, dstStride, dstLine, 1); - fbComposeGetStart (pSrc, xSrc, ySrc, uint32_t, srcStride, srcLine, 1); - -#if 0 - /* FIXME - * - * I copy the code from MMX one and keep the fixme. - * If it's a problem there, probably is a problem here. - */ - assert (pSrc->pDrawable == pMask->pDrawable); -#endif - - while (height--) - { - dst = dstLine; - src = srcLine; - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)src); - cachePrefetch ((__m128i*)dst); - - dstLine += dstStride; - srcLine += srcStride; - w = width; - - /* Align dst on a 16-byte boundary */ - while (w && - ((unsigned long)dst & 15)) - { - s = *src++; - d = *dst; - - *dst++ = fbCompositeSrc_8888x0565pixel (s, d); - w--; - } - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)src); - cachePrefetch ((__m128i*)dst); - - /* It's a 8 pixel loop */ - while (w >= 8) - { - /* fill cache line with next memory */ - cachePrefetchNext ((__m128i*)src); - cachePrefetchNext ((__m128i*)dst); - - /* I'm loading unaligned because I'm not sure about the address alignment. */ - xmmSrc = load128Unaligned ((__m128i*) src); - xmmDst = load128Aligned ((__m128i*) dst); - - /* Unpacking */ - unpack_128_2x128 (xmmSrc, &xmmSrcLo, &xmmSrcHi); - unpack565_128_4x128 (xmmDst, &xmmDst0, &xmmDst1, &xmmDst2, &xmmDst3); - expandAlpha_2x128 (xmmSrcLo, xmmSrcHi, &xmmAlphaLo, &xmmAlphaHi); - - /* I'm loading next 4 pixels from memory before to optimze the memory read. */ - xmmSrc = load128Unaligned ((__m128i*) (src+4)); - - over_2x128 (&xmmSrcLo, &xmmSrcHi, &xmmAlphaLo, &xmmAlphaHi, &xmmDst0, &xmmDst1); - - /* Unpacking */ - unpack_128_2x128 (xmmSrc, &xmmSrcLo, &xmmSrcHi); - expandAlpha_2x128 (xmmSrcLo, xmmSrcHi, &xmmAlphaLo, &xmmAlphaHi); - - over_2x128 (&xmmSrcLo, &xmmSrcHi, &xmmAlphaLo, &xmmAlphaHi, &xmmDst2, &xmmDst3); - - save128Aligned ((__m128i*)dst, pack565_4x128_128 (&xmmDst0, &xmmDst1, &xmmDst2, &xmmDst3)); - - w -= 8; - dst += 8; - src += 8; - } - - while (w--) - { - s = *src++; - d = *dst; - - *dst++ = fbCompositeSrc_8888x0565pixel (s, d); - } - } - - _mm_empty(); -} - -/* ------------------------------------------------------------------------------------------------- - * fbCompositeSolidMask_nx8x8888 - */ - -void -fbCompositeSolidMask_nx8x8888sse2 (pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height) -{ - uint32_t src, srca; - uint32_t *dstLine, *dst; - uint8_t *maskLine, *mask; - int dstStride, maskStride; - uint16_t w; - uint32_t m, d; - - __m128i xmmSrc, xmmAlpha, xmmDef; - __m128i xmmDst, xmmDstLo, xmmDstHi; - __m128i xmmMask, xmmMaskLo, xmmMaskHi; - - __m64 mmxSrc, mmxAlpha, mmxMask, mmxDest; - - fbComposeGetSolid(pSrc, src, pDst->bits.format); - - srca = src >> 24; - if (srca == 0) - return; - - fbComposeGetStart (pDst, xDst, yDst, uint32_t, dstStride, dstLine, 1); - fbComposeGetStart (pMask, xMask, yMask, uint8_t, maskStride, maskLine, 1); - - xmmDef = createMask_2x32_128 (src, src); - xmmSrc = expandPixel_32_1x128 (src); - xmmAlpha = expandAlpha_1x128 (xmmSrc); - mmxSrc = _mm_movepi64_pi64 (xmmSrc); - mmxAlpha = _mm_movepi64_pi64 (xmmAlpha); - - while (height--) - { - dst = dstLine; - dstLine += dstStride; - mask = maskLine; - maskLine += maskStride; - w = width; - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)mask); - cachePrefetch ((__m128i*)dst); - - while (w && (unsigned long)dst & 15) - { - uint8_t m = *mask++; - - if (m) - { - d = *dst; - mmxMask = expandPixel_8_1x64 (m); - mmxDest = unpack_32_1x64 (d); - - *dst = pack_1x64_32 (inOver_1x64 (&mmxSrc, - &mmxAlpha, - &mmxMask, - &mmxDest)); - } - - w--; - dst++; - } - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)mask); - cachePrefetch ((__m128i*)dst); - - while (w >= 4) - { - /* fill cache line with next memory */ - cachePrefetchNext ((__m128i*)mask); - cachePrefetchNext ((__m128i*)dst); - - m = *((uint32_t*)mask); - - if (srca == 0xff && m == 0xffffffff) - { - save128Aligned ((__m128i*)dst, xmmDef); - } - else if (m) - { - xmmDst = load128Aligned ((__m128i*) dst); - xmmMask = unpack_32_1x128 (m); - xmmMask = _mm_unpacklo_epi8 (xmmMask, _mm_setzero_si128()); - - /* Unpacking */ - unpack_128_2x128 (xmmDst, &xmmDstLo, &xmmDstHi); - unpack_128_2x128 (xmmMask, &xmmMaskLo, &xmmMaskHi); - - expandAlphaRev_2x128 (xmmMaskLo, xmmMaskHi, &xmmMaskLo, &xmmMaskHi); - - inOver_2x128 (&xmmSrc, &xmmSrc, &xmmAlpha, &xmmAlpha, &xmmMaskLo, &xmmMaskHi, &xmmDstLo, &xmmDstHi); - - save128Aligned ((__m128i*)dst, pack_2x128_128 (xmmDstLo, xmmDstHi)); - } - - w -= 4; - dst += 4; - mask += 4; - } - - while (w) - { - uint8_t m = *mask++; - - if (m) - { - d = *dst; - mmxMask = expandPixel_8_1x64 (m); - mmxDest = unpack_32_1x64 (d); - - *dst = pack_1x64_32 (inOver_1x64 (&mmxSrc, - &mmxAlpha, - &mmxMask, - &mmxDest)); - } - - w--; - dst++; - } - } - - _mm_empty(); -} - -/* ------------------------------------------------------------------------------------------------- - * fbCompositeSolidMask_nx8x8888 - */ - -pixman_bool_t -pixmanFillsse2 (uint32_t *bits, - int stride, - int bpp, - int x, - int y, - int width, - int height, - uint32_t data) -{ - uint32_t byte_width; - uint8_t *byte_line; - - __m128i xmmDef; - - if (bpp == 16 && (data >> 16 != (data & 0xffff))) - return FALSE; - - if (bpp != 16 && bpp != 32) - return FALSE; - - if (bpp == 16) - { - stride = stride * (int) sizeof (uint32_t) / 2; - byte_line = (uint8_t *)(((uint16_t *)bits) + stride * y + x); - byte_width = 2 * width; - stride *= 2; - } - else - { - stride = stride * (int) sizeof (uint32_t) / 4; - byte_line = (uint8_t *)(((uint32_t *)bits) + stride * y + x); - byte_width = 4 * width; - stride *= 4; - } - - cachePrefetch ((__m128i*)byte_line); - xmmDef = createMask_2x32_128 (data, data); - - while (height--) - { - int w; - uint8_t *d = byte_line; - byte_line += stride; - w = byte_width; - - - cachePrefetchNext ((__m128i*)d); - - while (w >= 2 && ((unsigned long)d & 3)) - { - *(uint16_t *)d = data; - w -= 2; - d += 2; - } - - while (w >= 4 && ((unsigned long)d & 15)) - { - *(uint32_t *)d = data; - - w -= 4; - d += 4; - } - - cachePrefetchNext ((__m128i*)d); - - while (w >= 128) - { - cachePrefetch (((__m128i*)d) + 12); - - save128Aligned ((__m128i*)(d), xmmDef); - save128Aligned ((__m128i*)(d+16), xmmDef); - save128Aligned ((__m128i*)(d+32), xmmDef); - save128Aligned ((__m128i*)(d+48), xmmDef); - save128Aligned ((__m128i*)(d+64), xmmDef); - save128Aligned ((__m128i*)(d+80), xmmDef); - save128Aligned ((__m128i*)(d+96), xmmDef); - save128Aligned ((__m128i*)(d+112), xmmDef); - - d += 128; - w -= 128; - } - - if (w >= 64) - { - cachePrefetch (((__m128i*)d) + 8); - - save128Aligned ((__m128i*)(d), xmmDef); - save128Aligned ((__m128i*)(d+16), xmmDef); - save128Aligned ((__m128i*)(d+32), xmmDef); - save128Aligned ((__m128i*)(d+48), xmmDef); - - d += 64; - w -= 64; - } - - cachePrefetchNext ((__m128i*)d); - - if (w >= 32) - { - save128Aligned ((__m128i*)(d), xmmDef); - save128Aligned ((__m128i*)(d+16), xmmDef); - - d += 32; - w -= 32; - } - - if (w >= 16) - { - save128Aligned ((__m128i*)(d), xmmDef); - - d += 16; - w -= 16; - } - - cachePrefetchNext ((__m128i*)d); - - while (w >= 4) - { - *(uint32_t *)d = data; - - w -= 4; - d += 4; - } - - if (w >= 2) - { - *(uint16_t *)d = data; - w -= 2; - d += 2; - } - } - - _mm_empty(); - return TRUE; -} - -void -fbCompositeSolidMaskSrc_nx8x8888sse2 (pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height) -{ - uint32_t src, srca; - uint32_t *dstLine, *dst; - uint8_t *maskLine, *mask; - int dstStride, maskStride; - uint16_t w; - uint32_t m; - - __m128i xmmSrc, xmmDef; - __m128i xmmMask, xmmMaskLo, xmmMaskHi; - - fbComposeGetSolid(pSrc, src, pDst->bits.format); - - srca = src >> 24; - if (srca == 0) - { - pixmanFillsse2 (pDst->bits.bits, pDst->bits.rowstride, - PIXMAN_FORMAT_BPP (pDst->bits.format), - xDst, yDst, width, height, 0); - return; - } - - fbComposeGetStart (pDst, xDst, yDst, uint32_t, dstStride, dstLine, 1); - fbComposeGetStart (pMask, xMask, yMask, uint8_t, maskStride, maskLine, 1); - - xmmDef = createMask_2x32_128 (src, src); - xmmSrc = expandPixel_32_1x128 (src); - - while (height--) - { - dst = dstLine; - dstLine += dstStride; - mask = maskLine; - maskLine += maskStride; - w = width; - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)mask); - cachePrefetch ((__m128i*)dst); - - while (w && (unsigned long)dst & 15) - { - uint8_t m = *mask++; - - if (m) - { - *dst = pack_1x64_32 (pixMultiply_1x64 (_mm_movepi64_pi64 (xmmSrc), expandPixel_8_1x64 (m))); - } - else - { - *dst = 0; - } - - w--; - dst++; - } - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)mask); - cachePrefetch ((__m128i*)dst); - - while (w >= 4) - { - /* fill cache line with next memory */ - cachePrefetchNext ((__m128i*)mask); - cachePrefetchNext ((__m128i*)dst); - - m = *((uint32_t*)mask); - - if (srca == 0xff && m == 0xffffffff) - { - save128Aligned ((__m128i*)dst, xmmDef); - } - else if (m) - { - xmmMask = unpack_32_1x128 (m); - xmmMask = _mm_unpacklo_epi8 (xmmMask, _mm_setzero_si128()); - - /* Unpacking */ - unpack_128_2x128 (xmmMask, &xmmMaskLo, &xmmMaskHi); - - expandAlphaRev_2x128 (xmmMaskLo, xmmMaskHi, &xmmMaskLo, &xmmMaskHi); - - pixMultiply_2x128 (&xmmSrc, &xmmSrc, &xmmMaskLo, &xmmMaskHi, &xmmMaskLo, &xmmMaskHi); - - save128Aligned ((__m128i*)dst, pack_2x128_128 (xmmMaskLo, xmmMaskHi)); - } - else - { - save128Aligned ((__m128i*)dst, _mm_setzero_si128()); - } - - w -= 4; - dst += 4; - mask += 4; - } - - while (w) - { - uint8_t m = *mask++; - - if (m) - { - *dst = pack_1x64_32 (pixMultiply_1x64 (_mm_movepi64_pi64 (xmmSrc), expandPixel_8_1x64 (m))); - } - else - { - *dst = 0; - } - - w--; - dst++; - } - } - - _mm_empty(); -} - -/* ------------------------------------------------------------------------------------------------- - * fbCompositeSolidMask_nx8x0565 - */ - -void -fbCompositeSolidMask_nx8x0565sse2 (pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height) -{ - uint32_t src, srca; - uint16_t *dstLine, *dst, d; - uint8_t *maskLine, *mask; - int dstStride, maskStride; - uint16_t w; - uint32_t m; - __m64 mmxSrc, mmxAlpha, mmxMask, mmxDest; - - __m128i xmmSrc, xmmAlpha; - __m128i xmmMask, xmmMaskLo, xmmMaskHi; - __m128i xmmDst, xmmDst0, xmmDst1, xmmDst2, xmmDst3; - - fbComposeGetSolid(pSrc, src, pDst->bits.format); - - srca = src >> 24; - if (srca == 0) - return; - - fbComposeGetStart (pDst, xDst, yDst, uint16_t, dstStride, dstLine, 1); - fbComposeGetStart (pMask, xMask, yMask, uint8_t, maskStride, maskLine, 1); - - xmmSrc = expandPixel_32_1x128 (src); - xmmAlpha = expandAlpha_1x128 (xmmSrc); - mmxSrc = _mm_movepi64_pi64 (xmmSrc); - mmxAlpha = _mm_movepi64_pi64 (xmmAlpha); - - while (height--) - { - dst = dstLine; - dstLine += dstStride; - mask = maskLine; - maskLine += maskStride; - w = width; - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)mask); - cachePrefetch ((__m128i*)dst); - - while (w && (unsigned long)dst & 15) - { - m = *mask++; - - if (m) - { - d = *dst; - mmxMask = expandAlphaRev_1x64 (unpack_32_1x64 (m)); - mmxDest = expand565_16_1x64 (d); - - *dst = pack565_32_16 (pack_1x64_32 (inOver_1x64 (&mmxSrc, - &mmxAlpha, - &mmxMask, - &mmxDest))); - } - - w--; - dst++; - } - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)mask); - cachePrefetch ((__m128i*)dst); - - while (w >= 8) - { - /* fill cache line with next memory */ - cachePrefetchNext ((__m128i*)mask); - cachePrefetchNext ((__m128i*)dst); - - xmmDst = load128Aligned ((__m128i*) dst); - unpack565_128_4x128 (xmmDst, &xmmDst0, &xmmDst1, &xmmDst2, &xmmDst3); - - m = *((uint32_t*)mask); - mask += 4; - - if (m) - { - xmmMask = unpack_32_1x128 (m); - xmmMask = _mm_unpacklo_epi8 (xmmMask, _mm_setzero_si128()); - - /* Unpacking */ - unpack_128_2x128 (xmmMask, &xmmMaskLo, &xmmMaskHi); - - expandAlphaRev_2x128 (xmmMaskLo, xmmMaskHi, &xmmMaskLo, &xmmMaskHi); - inOver_2x128 (&xmmSrc, &xmmSrc, &xmmAlpha, &xmmAlpha, &xmmMaskLo, &xmmMaskHi, &xmmDst0, &xmmDst1); - } - - m = *((uint32_t*)mask); - mask += 4; - - if (m) - { - xmmMask = unpack_32_1x128 (m); - xmmMask = _mm_unpacklo_epi8 (xmmMask, _mm_setzero_si128()); - - /* Unpacking */ - unpack_128_2x128 (xmmMask, &xmmMaskLo, &xmmMaskHi); - - expandAlphaRev_2x128 (xmmMaskLo, xmmMaskHi, &xmmMaskLo, &xmmMaskHi); - inOver_2x128 (&xmmSrc, &xmmSrc, &xmmAlpha, &xmmAlpha, &xmmMaskLo, &xmmMaskHi, &xmmDst2, &xmmDst3); - } - - save128Aligned ((__m128i*)dst, pack565_4x128_128 (&xmmDst0, &xmmDst1, &xmmDst2, &xmmDst3)); - - w -= 8; - dst += 8; - } - - while (w) - { - m = *mask++; - - if (m) - { - d = *dst; - mmxMask = expandAlphaRev_1x64 (unpack_32_1x64 (m)); - mmxDest = expand565_16_1x64 (d); - - *dst = pack565_32_16 (pack_1x64_32 (inOver_1x64 (&mmxSrc, - &mmxAlpha, - &mmxMask, - &mmxDest))); - } - - w--; - dst++; - } - } - - _mm_empty(); -} - -/* ------------------------------------------------------------------------------------------------- - * fbCompositeSrc_8888RevNPx0565 - */ - -void -fbCompositeSrc_8888RevNPx0565sse2 (pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height) -{ - uint16_t *dstLine, *dst, d; - uint32_t *srcLine, *src, s; - int dstStride, srcStride; - uint16_t w; - uint32_t packCmp; - - __m64 ms; - __m128i xmmSrc, xmmSrcLo, xmmSrcHi; - __m128i xmmDst, xmmDst0, xmmDst1, xmmDst2, xmmDst3; - - fbComposeGetStart (pDst, xDst, yDst, uint16_t, dstStride, dstLine, 1); - fbComposeGetStart (pSrc, xSrc, ySrc, uint32_t, srcStride, srcLine, 1); - -#if 0 - /* FIXME - * - * I copy the code from MMX one and keep the fixme. - * If it's a problem there, probably is a problem here. - */ - assert (pSrc->pDrawable == pMask->pDrawable); -#endif - - while (height--) - { - dst = dstLine; - dstLine += dstStride; - src = srcLine; - srcLine += srcStride; - w = width; - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)src); - cachePrefetch ((__m128i*)dst); - - while (w && (unsigned long)dst & 15) - { - s = *src++; - d = *dst; - - ms = unpack_32_1x64 (s); - - *dst++ = pack565_32_16 (pack_1x64_32 (overRevNonPre_1x64(ms, expand565_16_1x64 (d)))); - w--; - } - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)src); - cachePrefetch ((__m128i*)dst); - - while (w >= 8) - { - /* fill cache line with next memory */ - cachePrefetchNext ((__m128i*)src); - cachePrefetchNext ((__m128i*)dst); - - /* First round */ - xmmSrc = load128Unaligned((__m128i*)src); - xmmDst = load128Aligned ((__m128i*)dst); - - packCmp = packAlpha (xmmSrc); - - unpack565_128_4x128 (xmmDst, &xmmDst0, &xmmDst1, &xmmDst2, &xmmDst3); - unpack_128_2x128 (xmmSrc, &xmmSrcLo, &xmmSrcHi); - - /* preload next round*/ - xmmSrc = load128Unaligned((__m128i*)(src+4)); - /* preload next round*/ - - if (packCmp == 0xffffffff) - { - invertColors_2x128 (xmmSrcLo, xmmSrcHi, &xmmDst0, &xmmDst1); - } - else if (packCmp) - { - overRevNonPre_2x128 (xmmSrcLo, xmmSrcHi, &xmmDst0, &xmmDst1); - } - - /* Second round */ - packCmp = packAlpha (xmmSrc); - - unpack_128_2x128 (xmmSrc, &xmmSrcLo, &xmmSrcHi); - - if (packCmp == 0xffffffff) - { - invertColors_2x128 (xmmSrcLo, xmmSrcHi, &xmmDst2, &xmmDst3); - } - else if (packCmp) - { - overRevNonPre_2x128 (xmmSrcLo, xmmSrcHi, &xmmDst2, &xmmDst3); - } - - save128Aligned ((__m128i*)dst, pack565_4x128_128 (&xmmDst0, &xmmDst1, &xmmDst2, &xmmDst3)); - - w -= 8; - src += 8; - dst += 8; - } - - while (w) - { - s = *src++; - d = *dst; - - ms = unpack_32_1x64 (s); - - *dst++ = pack565_32_16 (pack_1x64_32 (overRevNonPre_1x64(ms, expand565_16_1x64 (d)))); - w--; - } - } - - _mm_empty(); -} - -/* "8888RevNP" is GdkPixbuf's format: ABGR, non premultiplied */ - -/* ------------------------------------------------------------------------------------------------- - * fbCompositeSrc_8888RevNPx8888 - */ - -void -fbCompositeSrc_8888RevNPx8888sse2 (pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height) -{ - uint32_t *dstLine, *dst, d; - uint32_t *srcLine, *src, s; - int dstStride, srcStride; - uint16_t w; - uint32_t packCmp; - - __m128i xmmSrcLo, xmmSrcHi; - __m128i xmmDstLo, xmmDstHi; - - fbComposeGetStart (pDst, xDst, yDst, uint32_t, dstStride, dstLine, 1); - fbComposeGetStart (pSrc, xSrc, ySrc, uint32_t, srcStride, srcLine, 1); - -#if 0 - /* FIXME - * - * I copy the code from MMX one and keep the fixme. - * If it's a problem there, probably is a problem here. - */ - assert (pSrc->pDrawable == pMask->pDrawable); -#endif - - while (height--) - { - dst = dstLine; - dstLine += dstStride; - src = srcLine; - srcLine += srcStride; - w = width; - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)src); - cachePrefetch ((__m128i*)dst); - - while (w && (unsigned long)dst & 15) - { - s = *src++; - d = *dst; - - *dst++ = pack_1x64_32 (overRevNonPre_1x64 (unpack_32_1x64 (s), unpack_32_1x64 (d))); - - w--; - } - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)src); - cachePrefetch ((__m128i*)dst); - - while (w >= 4) - { - /* fill cache line with next memory */ - cachePrefetchNext ((__m128i*)src); - cachePrefetchNext ((__m128i*)dst); - - xmmSrcHi = load128Unaligned((__m128i*)src); - - packCmp = packAlpha (xmmSrcHi); - - unpack_128_2x128 (xmmSrcHi, &xmmSrcLo, &xmmSrcHi); - - if (packCmp == 0xffffffff) - { - invertColors_2x128( xmmSrcLo, xmmSrcHi, &xmmDstLo, &xmmDstHi); - - save128Aligned ((__m128i*)dst, pack_2x128_128 (xmmDstLo, xmmDstHi)); - } - else if (packCmp) - { - xmmDstHi = load128Aligned ((__m128i*)dst); - - unpack_128_2x128 (xmmDstHi, &xmmDstLo, &xmmDstHi); - - overRevNonPre_2x128 (xmmSrcLo, xmmSrcHi, &xmmDstLo, &xmmDstHi); - - save128Aligned ((__m128i*)dst, pack_2x128_128 (xmmDstLo, xmmDstHi)); - } - - w -= 4; - dst += 4; - src += 4; - } - - while (w) - { - s = *src++; - d = *dst; - - *dst++ = pack_1x64_32 (overRevNonPre_1x64 (unpack_32_1x64 (s), unpack_32_1x64 (d))); - - w--; - } - } - - _mm_empty(); -} - -/* ------------------------------------------------------------------------------------------------- - * fbCompositeSolidMask_nx8888x0565C - */ - -void -fbCompositeSolidMask_nx8888x0565Csse2 (pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height) -{ - uint32_t src, srca; - uint16_t *dstLine, *dst, d; - uint32_t *maskLine, *mask, m; - int dstStride, maskStride; - int w; - uint32_t packCmp; - - __m128i xmmSrc, xmmAlpha; - __m128i xmmMask, xmmMaskLo, xmmMaskHi; - __m128i xmmDst, xmmDst0, xmmDst1, xmmDst2, xmmDst3; - - __m64 mmxSrc, mmxAlpha, mmxMask, mmxDest; - - fbComposeGetSolid(pSrc, src, pDst->bits.format); - - srca = src >> 24; - if (srca == 0) - return; - - fbComposeGetStart (pDst, xDst, yDst, uint16_t, dstStride, dstLine, 1); - fbComposeGetStart (pMask, xMask, yMask, uint32_t, maskStride, maskLine, 1); - - xmmSrc = expandPixel_32_1x128 (src); - xmmAlpha = expandAlpha_1x128 (xmmSrc); - mmxSrc = _mm_movepi64_pi64 (xmmSrc); - mmxAlpha = _mm_movepi64_pi64 (xmmAlpha); - - while (height--) - { - w = width; - mask = maskLine; - dst = dstLine; - maskLine += maskStride; - dstLine += dstStride; - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)mask); - cachePrefetch ((__m128i*)dst); - - while (w && ((unsigned long)dst & 15)) - { - m = *(uint32_t *) mask; - - if (m) - { - d = *dst; - mmxMask = unpack_32_1x64 (m); - mmxDest = expand565_16_1x64 (d); - - *dst = pack565_32_16 (pack_1x64_32 (inOver_1x64 (&mmxSrc, - &mmxAlpha, - &mmxMask, - &mmxDest))); - } - - w--; - dst++; - mask++; - } - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)mask); - cachePrefetch ((__m128i*)dst); - - while (w >= 8) - { - /* fill cache line with next memory */ - cachePrefetchNext ((__m128i*)mask); - cachePrefetchNext ((__m128i*)dst); - - /* First round */ - xmmMask = load128Unaligned((__m128i*)mask); - xmmDst = load128Aligned((__m128i*)dst); - - packCmp = _mm_movemask_epi8 (_mm_cmpeq_epi32 (xmmMask, _mm_setzero_si128())); - - unpack565_128_4x128 (xmmDst, &xmmDst0, &xmmDst1, &xmmDst2, &xmmDst3); - unpack_128_2x128 (xmmMask, &xmmMaskLo, &xmmMaskHi); - - /* preload next round*/ - xmmMask = load128Unaligned((__m128i*)(mask+4)); - /* preload next round*/ - - if (packCmp != 0xffff) - { - inOver_2x128(&xmmSrc, &xmmSrc, &xmmAlpha, &xmmAlpha, &xmmMaskLo, &xmmMaskHi, &xmmDst0, &xmmDst1); - } - - /* Second round */ - packCmp = _mm_movemask_epi8 (_mm_cmpeq_epi32 (xmmMask, _mm_setzero_si128())); - - unpack_128_2x128 (xmmMask, &xmmMaskLo, &xmmMaskHi); - - if (packCmp != 0xffff) - { - inOver_2x128(&xmmSrc, &xmmSrc, &xmmAlpha, &xmmAlpha, &xmmMaskLo, &xmmMaskHi, &xmmDst2, &xmmDst3); - } - - save128Aligned ((__m128i*)dst, pack565_4x128_128 (&xmmDst0, &xmmDst1, &xmmDst2, &xmmDst3)); - - w -= 8; - dst += 8; - mask += 8; - } - - while (w) - { - m = *(uint32_t *) mask; - - if (m) - { - d = *dst; - mmxMask = unpack_32_1x64 (m); - mmxDest = expand565_16_1x64 (d); - - *dst = pack565_32_16 (pack_1x64_32 (inOver_1x64 (&mmxSrc, - &mmxAlpha, - &mmxMask, - &mmxDest))); - } - - w--; - dst++; - mask++; - } - } - - _mm_empty (); -} - -/* ------------------------------------------------------------------------------------------------- - * fbCompositeIn_nx8x8 - */ - -void -fbCompositeIn_nx8x8sse2 (pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height) -{ - uint8_t *dstLine, *dst; - uint8_t *maskLine, *mask; - int dstStride, maskStride; - uint16_t w, d, m; - uint32_t src; - uint8_t sa; - - __m128i xmmAlpha; - __m128i xmmMask, xmmMaskLo, xmmMaskHi; - __m128i xmmDst, xmmDstLo, xmmDstHi; - - fbComposeGetStart (pDst, xDst, yDst, uint8_t, dstStride, dstLine, 1); - fbComposeGetStart (pMask, xMask, yMask, uint8_t, maskStride, maskLine, 1); - - fbComposeGetSolid(pSrc, src, pDst->bits.format); - - sa = src >> 24; - if (sa == 0) - return; - - xmmAlpha = expandAlpha_1x128 (expandPixel_32_1x128 (src)); - - while (height--) - { - dst = dstLine; - dstLine += dstStride; - mask = maskLine; - maskLine += maskStride; - w = width; - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)mask); - cachePrefetch ((__m128i*)dst); - - while (w && ((unsigned long)dst & 15)) - { - m = (uint32_t) *mask++; - d = (uint32_t) *dst; - - *dst++ = (uint8_t) pack_1x64_32 (pixMultiply_1x64 (pixMultiply_1x64 (_mm_movepi64_pi64 (xmmAlpha), unpack_32_1x64 (m)), - unpack_32_1x64 (d))); - w--; - } - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)mask); - cachePrefetch ((__m128i*)dst); - - while (w >= 16) - { - /* fill cache line with next memory */ - cachePrefetchNext ((__m128i*)mask); - cachePrefetchNext ((__m128i*)dst); - - xmmMask = load128Unaligned((__m128i*)mask); - xmmDst = load128Aligned((__m128i*)dst); - - unpack_128_2x128 (xmmMask, &xmmMaskLo, &xmmMaskHi); - unpack_128_2x128 (xmmDst, &xmmDstLo, &xmmDstHi); - - pixMultiply_2x128 (&xmmAlpha, &xmmAlpha, &xmmMaskLo, &xmmMaskHi, &xmmMaskLo, &xmmMaskHi); - pixMultiply_2x128 (&xmmMaskLo, &xmmMaskHi, &xmmDstLo, &xmmDstHi, &xmmDstLo, &xmmDstHi); - - save128Aligned ((__m128i*)dst, pack_2x128_128 (xmmDstLo, xmmDstHi)); - - mask += 16; - dst += 16; - w -= 16; - } - - while (w) - { - m = (uint32_t) *mask++; - d = (uint32_t) *dst; - - *dst++ = (uint8_t) pack_1x64_32 (pixMultiply_1x64 (pixMultiply_1x64 (_mm_movepi64_pi64 (xmmAlpha), unpack_32_1x64 (m)), - unpack_32_1x64 (d))); - w--; - } - } - - _mm_empty(); -} - -/* ------------------------------------------------------------------------------------------------- - * fbCompositeIn_8x8 - */ - -void -fbCompositeIn_8x8sse2 (pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height) -{ - uint8_t *dstLine, *dst; - uint8_t *srcLine, *src; - int srcStride, dstStride; - uint16_t w; - uint32_t s, d; - - __m128i xmmSrc, xmmSrcLo, xmmSrcHi; - __m128i xmmDst, xmmDstLo, xmmDstHi; - - fbComposeGetStart (pDst, xDst, yDst, uint8_t, dstStride, dstLine, 1); - fbComposeGetStart (pSrc, xSrc, ySrc, uint8_t, srcStride, srcLine, 1); - - while (height--) - { - dst = dstLine; - dstLine += dstStride; - src = srcLine; - srcLine += srcStride; - w = width; - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)src); - cachePrefetch ((__m128i*)dst); - - while (w && ((unsigned long)dst & 15)) - { - s = (uint32_t) *src++; - d = (uint32_t) *dst; - - *dst++ = (uint8_t) pack_1x64_32 (pixMultiply_1x64 (unpack_32_1x64 (s),unpack_32_1x64 (d))); - w--; - } - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)src); - cachePrefetch ((__m128i*)dst); - - while (w >= 16) - { - /* fill cache line with next memory */ - cachePrefetchNext ((__m128i*)src); - cachePrefetchNext ((__m128i*)dst); - - xmmSrc = load128Unaligned((__m128i*)src); - xmmDst = load128Aligned((__m128i*)dst); - - unpack_128_2x128 (xmmSrc, &xmmSrcLo, &xmmSrcHi); - unpack_128_2x128 (xmmDst, &xmmDstLo, &xmmDstHi); - - pixMultiply_2x128 (&xmmSrcLo, &xmmSrcHi, &xmmDstLo, &xmmDstHi, &xmmDstLo, &xmmDstHi); - - save128Aligned ((__m128i*)dst, pack_2x128_128 (xmmDstLo, xmmDstHi)); - - src += 16; - dst += 16; - w -= 16; - } - - while (w) - { - s = (uint32_t) *src++; - d = (uint32_t) *dst; - - *dst++ = (uint8_t) pack_1x64_32 (pixMultiply_1x64 (unpack_32_1x64 (s),unpack_32_1x64 (d))); - w--; - } - } - - _mm_empty (); -} - -/* ------------------------------------------------------------------------------------------------- - * fbCompositeSrcAdd_8888x8x8 - */ - -void -fbCompositeSrcAdd_8888x8x8sse2 (pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height) -{ - uint8_t *dstLine, *dst; - uint8_t *maskLine, *mask; - int dstStride, maskStride; - uint16_t w; - uint32_t src; - uint8_t sa; - uint32_t m, d; - - __m128i xmmAlpha; - __m128i xmmMask, xmmMaskLo, xmmMaskHi; - __m128i xmmDst, xmmDstLo, xmmDstHi; - - fbComposeGetStart (pDst, xDst, yDst, uint8_t, dstStride, dstLine, 1); - fbComposeGetStart (pMask, xMask, yMask, uint8_t, maskStride, maskLine, 1); - - fbComposeGetSolid(pSrc, src, pDst->bits.format); - - sa = src >> 24; - if (sa == 0) - return; - - xmmAlpha = expandAlpha_1x128 (expandPixel_32_1x128 (src)); - - while (height--) - { - dst = dstLine; - dstLine += dstStride; - mask = maskLine; - maskLine += maskStride; - w = width; - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)mask); - cachePrefetch ((__m128i*)dst); - - while (w && ((unsigned long)dst & 15)) - { - m = (uint32_t) *mask++; - d = (uint32_t) *dst; - - *dst++ = (uint8_t) pack_1x64_32 (_mm_adds_pu16 (pixMultiply_1x64 (_mm_movepi64_pi64 (xmmAlpha), unpack_32_1x64 (m)), - unpack_32_1x64 (d))); - w--; - } - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)mask); - cachePrefetch ((__m128i*)dst); - - while (w >= 16) - { - /* fill cache line with next memory */ - cachePrefetchNext ((__m128i*)mask); - cachePrefetchNext ((__m128i*)dst); - - xmmMask = load128Unaligned((__m128i*)mask); - xmmDst = load128Aligned((__m128i*)dst); - - unpack_128_2x128 (xmmMask, &xmmMaskLo, &xmmMaskHi); - unpack_128_2x128 (xmmDst, &xmmDstLo, &xmmDstHi); - - pixMultiply_2x128 (&xmmAlpha, &xmmAlpha, &xmmMaskLo, &xmmMaskHi, &xmmMaskLo, &xmmMaskHi); - - xmmDstLo = _mm_adds_epu16 (xmmMaskLo, xmmDstLo); - xmmDstHi = _mm_adds_epu16 (xmmMaskHi, xmmDstHi); - - save128Aligned ((__m128i*)dst, pack_2x128_128 (xmmDstLo, xmmDstHi)); - - mask += 16; - dst += 16; - w -= 16; - } - - while (w) - { - m = (uint32_t) *mask++; - d = (uint32_t) *dst; - - *dst++ = (uint8_t) pack_1x64_32 (_mm_adds_pu16 (pixMultiply_1x64 (_mm_movepi64_pi64 (xmmAlpha), unpack_32_1x64 (m)), - unpack_32_1x64 (d))); - w--; - } - } - - _mm_empty(); -} - -/* ------------------------------------------------------------------------------------------------- - * fbCompositeSrcAdd_8000x8000 - */ - -void -fbCompositeSrcAdd_8000x8000sse2 (pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height) -{ - uint8_t *dstLine, *dst; - uint8_t *srcLine, *src; - int dstStride, srcStride; - uint16_t w; - uint16_t t; - - fbComposeGetStart (pSrc, xSrc, ySrc, uint8_t, srcStride, srcLine, 1); - fbComposeGetStart (pDst, xDst, yDst, uint8_t, dstStride, dstLine, 1); - - while (height--) - { - dst = dstLine; - src = srcLine; - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)src); - cachePrefetch ((__m128i*)dst); - - dstLine += dstStride; - srcLine += srcStride; - w = width; - - /* Small head */ - while (w && (unsigned long)dst & 3) - { - t = (*dst) + (*src++); - *dst++ = t | (0 - (t >> 8)); - w--; - } - - coreCombineAddUsse2 ((uint32_t*)dst, (uint32_t*)src, w >> 2); - - /* Small tail */ - dst += w & 0xfffc; - src += w & 0xfffc; - - w &= 3; - - while (w) - { - t = (*dst) + (*src++); - *dst++ = t | (0 - (t >> 8)); - w--; - } - } - - _mm_empty(); -} - -/* ------------------------------------------------------------------------------------------------- - * fbCompositeSrcAdd_8888x8888 - */ -void -fbCompositeSrcAdd_8888x8888sse2 (pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height) -{ - uint32_t *dstLine, *dst; - uint32_t *srcLine, *src; - int dstStride, srcStride; - - fbComposeGetStart (pSrc, xSrc, ySrc, uint32_t, srcStride, srcLine, 1); - fbComposeGetStart (pDst, xDst, yDst, uint32_t, dstStride, dstLine, 1); - - while (height--) - { - dst = dstLine; - dstLine += dstStride; - src = srcLine; - srcLine += srcStride; - - coreCombineAddUsse2 (dst, src, width); - } - - _mm_empty(); -} - -/* ------------------------------------------------------------------------------------------------- - * fbCompositeCopyAreasse2 - */ - -pixman_bool_t -pixmanBltsse2 (uint32_t *src_bits, - uint32_t *dst_bits, - int src_stride, - int dst_stride, - int src_bpp, - int dst_bpp, - int src_x, int src_y, - int dst_x, int dst_y, - int width, int height) -{ - uint8_t * src_bytes; - uint8_t * dst_bytes; - int byte_width; - - if (src_bpp != dst_bpp) - return FALSE; - - if (src_bpp == 16) - { - src_stride = src_stride * (int) sizeof (uint32_t) / 2; - dst_stride = dst_stride * (int) sizeof (uint32_t) / 2; - src_bytes = (uint8_t *)(((uint16_t *)src_bits) + src_stride * (src_y) + (src_x)); - dst_bytes = (uint8_t *)(((uint16_t *)dst_bits) + dst_stride * (dst_y) + (dst_x)); - byte_width = 2 * width; - src_stride *= 2; - dst_stride *= 2; - } - else if (src_bpp == 32) - { - src_stride = src_stride * (int) sizeof (uint32_t) / 4; - dst_stride = dst_stride * (int) sizeof (uint32_t) / 4; - src_bytes = (uint8_t *)(((uint32_t *)src_bits) + src_stride * (src_y) + (src_x)); - dst_bytes = (uint8_t *)(((uint32_t *)dst_bits) + dst_stride * (dst_y) + (dst_x)); - byte_width = 4 * width; - src_stride *= 4; - dst_stride *= 4; - } - else - { - return FALSE; - } - - cachePrefetch ((__m128i*)src_bytes); - cachePrefetch ((__m128i*)dst_bytes); - - while (height--) - { - int w; - uint8_t *s = src_bytes; - uint8_t *d = dst_bytes; - src_bytes += src_stride; - dst_bytes += dst_stride; - w = byte_width; - - cachePrefetchNext ((__m128i*)s); - cachePrefetchNext ((__m128i*)d); - - while (w >= 2 && ((unsigned long)d & 3)) - { - *(uint16_t *)d = *(uint16_t *)s; - w -= 2; - s += 2; - d += 2; - } - - while (w >= 4 && ((unsigned long)d & 15)) - { - *(uint32_t *)d = *(uint32_t *)s; - - w -= 4; - s += 4; - d += 4; - } - - cachePrefetchNext ((__m128i*)s); - cachePrefetchNext ((__m128i*)d); - - while (w >= 64) - { - __m128i xmm0, xmm1, xmm2, xmm3; - - /* 128 bytes ahead */ - cachePrefetch (((__m128i*)s) + 8); - cachePrefetch (((__m128i*)d) + 8); - - xmm0 = load128Unaligned ((__m128i*)(s)); - xmm1 = load128Unaligned ((__m128i*)(s+16)); - xmm2 = load128Unaligned ((__m128i*)(s+32)); - xmm3 = load128Unaligned ((__m128i*)(s+48)); - - save128Aligned ((__m128i*)(d), xmm0); - save128Aligned ((__m128i*)(d+16), xmm1); - save128Aligned ((__m128i*)(d+32), xmm2); - save128Aligned ((__m128i*)(d+48), xmm3); - - s += 64; - d += 64; - w -= 64; - } - - cachePrefetchNext ((__m128i*)s); - cachePrefetchNext ((__m128i*)d); - - while (w >= 16) - { - save128Aligned ((__m128i*)d, load128Unaligned ((__m128i*)s) ); - - w -= 16; - d += 16; - s += 16; - } - - cachePrefetchNext ((__m128i*)s); - cachePrefetchNext ((__m128i*)d); - - while (w >= 4) - { - *(uint32_t *)d = *(uint32_t *)s; - - w -= 4; - s += 4; - d += 4; - } - - if (w >= 2) - { - *(uint16_t *)d = *(uint16_t *)s; - w -= 2; - s += 2; - d += 2; - } - } - - _mm_empty(); - - return TRUE; -} - -void -fbCompositeCopyAreasse2 (pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height) -{ - pixmanBltsse2 (pSrc->bits.bits, - pDst->bits.bits, - pSrc->bits.rowstride, - pDst->bits.rowstride, - PIXMAN_FORMAT_BPP (pSrc->bits.format), - PIXMAN_FORMAT_BPP (pDst->bits.format), - xSrc, ySrc, xDst, yDst, width, height); -} - -#if 0 -/* This code are buggy in MMX version, now the bug was translated to SSE2 version */ -void -fbCompositeOver_x888x8x8888sse2 (pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height) -{ - uint32_t *src, *srcLine, s; - uint32_t *dst, *dstLine, d; - uint8_t *mask, *maskLine; - uint32_t m; - int srcStride, maskStride, dstStride; - uint16_t w; - - __m128i xmmSrc, xmmSrcLo, xmmSrcHi; - __m128i xmmDst, xmmDstLo, xmmDstHi; - __m128i xmmMask, xmmMaskLo, xmmMaskHi; - - fbComposeGetStart (pDst, xDst, yDst, uint32_t, dstStride, dstLine, 1); - fbComposeGetStart (pMask, xMask, yMask, uint8_t, maskStride, maskLine, 1); - fbComposeGetStart (pSrc, xSrc, ySrc, uint32_t, srcStride, srcLine, 1); - - while (height--) - { - src = srcLine; - srcLine += srcStride; - dst = dstLine; - dstLine += dstStride; - mask = maskLine; - maskLine += maskStride; - - w = width; - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)src); - cachePrefetch ((__m128i*)dst); - cachePrefetch ((__m128i*)mask); - - while (w && (unsigned long)dst & 15) - { - s = 0xff000000 | *src++; - m = (uint32_t) *mask++; - d = *dst; - - __m64 ms = unpack_32_1x64 (s); - - if (m != 0xff) - { - ms = inOver_1x64 (ms, - xMask00ff, - expandAlphaRev_1x64 (unpack_32_1x64 (m)), - unpack_32_1x64 (d)); - } - - *dst++ = pack_1x64_32 (ms); - w--; - } - - /* call prefetch hint to optimize cache load*/ - cachePrefetch ((__m128i*)src); - cachePrefetch ((__m128i*)dst); - cachePrefetch ((__m128i*)mask); - - while (w >= 4) - { - /* fill cache line with next memory */ - cachePrefetchNext ((__m128i*)src); - cachePrefetchNext ((__m128i*)dst); - cachePrefetchNext ((__m128i*)mask); - - m = *(uint32_t*) mask; - xmmSrc = _mm_or_si128 (load128Unaligned ((__m128i*)src), Maskff000000); - - if (m == 0xffffffff) - { - save128Aligned ((__m128i*)dst, xmmSrc); - } - else - { - xmmDst = load128Aligned ((__m128i*)dst); - - xmmMask = _mm_unpacklo_epi16 (unpack_32_1x128 (m), _mm_setzero_si128()); - - unpack_128_2x128 (xmmSrc, &xmmSrcLo, &xmmSrcHi); - unpack_128_2x128 (xmmMask, &xmmMaskLo, &xmmMaskHi); - unpack_128_2x128 (xmmDst, &xmmDstLo, &xmmDstHi); - - expandAlphaRev_2x128 (xmmMaskLo, xmmMaskHi, &xmmMaskLo, &xmmMaskHi); - - inOver_2x128 (xmmSrcLo, xmmSrcHi, Mask00ff, Mask00ff, xmmMaskLo, xmmMaskHi, &xmmDstLo, &xmmDstHi); - - save128Aligned( (__m128i*)dst, pack_2x128_128 (xmmDstLo, xmmDstHi)); - } - - src += 4; - dst += 4; - mask += 4; - w -= 4; - } - - while (w) - { - m = (uint32_t) *mask++; - - if (m) - { - s = 0xff000000 | *src; - - if (m == 0xff) - { - *dst = s; - } - else - { - d = *dst; - - *dst = pack_1x64_32 (inOver_1x64 (unpack_32_1x64 (s), - xMask00ff, - expandAlphaRev_1x64 (unpack_32_1x64 (m)), - unpack_32_1x64 (d))); - } - - } - - src++; - dst++; - w--; - } - } - - _mm_empty(); -} -#endif /* #if 0 */ - -#endif /* USE_SSE2 */ diff --git a/uppdev/plugin/pixman/lib/pixman-sse2.h b/uppdev/plugin/pixman/lib/pixman-sse2.h deleted file mode 100644 index ee65f8c85..000000000 --- a/uppdev/plugin/pixman/lib/pixman-sse2.h +++ /dev/null @@ -1,358 +0,0 @@ -/* - * Copyright © 2008 Rodrigo Kumpera - * Copyright © 2008 André Tupinambá - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Red Hat not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. Red Hat makes no representations about the - * suitability of this software for any purpose. It is provided "as is" - * without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - * - * Author: Rodrigo Kumpera (kumpera@gmail.com) - * André Tupinambá (andrelrt@gmail.com) - * - * Based on work by Owen Taylor and Søren Sandmann - */ -#ifndef _PIXMAN_SSE_H_ -#define _PIXMAN_SSE_H_ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include "pixman-private.h" - -#ifdef USE_SSE2 - -#if !defined(__amd64__) && !defined(__x86_64__) -pixman_bool_t pixman_have_sse2(void); -#else -#define pixman_have_sse2() TRUE -#endif - -#else -#define pixman_have_sse2() FALSE -#endif - -#ifdef USE_SSE2 - -void fbComposeSetupSSE2(void); - -pixman_bool_t -pixmanFillsse2 (uint32_t *bits, - int stride, - int bpp, - int x, - int y, - int width, - int height, - uint32_t data); - -pixman_bool_t -pixmanBltsse2 (uint32_t *src_bits, - uint32_t *dst_bits, - int src_stride, - int dst_stride, - int src_bpp, - int dst_bpp, - int src_x, int src_y, - int dst_x, int dst_y, - int width, int height); - -void -fbCompositeSolid_nx8888sse2 (pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height); - -void -fbCompositeSolid_nx0565sse2 (pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height); - -void -fbCompositeSolidMask_nx8888x8888Csse2 (pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height); - -void -fbCompositeSrc_8888x8x8888sse2 (pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height); - -void -fbCompositeSrc_x888xnx8888sse2 (pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height); - -void -fbCompositeSrc_8888x8888sse2 (pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height); - -void -fbCompositeSrc_8888x0565sse2 (pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height); - -void -fbCompositeSolidMask_nx8x8888sse2 (pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height); - -void -fbCompositeSolidMaskSrc_nx8x8888sse2 (pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height); - -void -fbCompositeSolidMask_nx8x0565sse2 (pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height); - -void -fbCompositeSrc_8888RevNPx0565sse2 (pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height); - -void -fbCompositeSrc_8888RevNPx8888sse2 (pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height); - -void -fbCompositeSolidMask_nx8888x0565Csse2 (pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height); - -void -fbCompositeIn_nx8x8sse2 (pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height); - -void -fbCompositeIn_8x8sse2 (pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height); - -void -fbCompositeSrcAdd_8888x8x8sse2 (pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height); - - -void -fbCompositeSrcAdd_8000x8000sse2 (pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height); - -void -fbCompositeSrcAdd_8888x8888sse2 (pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height); - -void -fbCompositeCopyAreasse2 (pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height); - -void -fbCompositeOver_x888x8x8888sse2 (pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height); - -#endif /* USE_SSE2 */ - -#endif /* _PIXMAN_SSE_H_ */ diff --git a/uppdev/plugin/pixman/lib/pixman-timer.c b/uppdev/plugin/pixman/lib/pixman-timer.c deleted file mode 100644 index 90ded9540..000000000 --- a/uppdev/plugin/pixman/lib/pixman-timer.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright © 2007 Red Hat, Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Red Hat not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. Red Hat makes no representations about the - * suitability of this software for any purpose. It is provided "as is" - * without express or implied warranty. - * - * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT - * 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. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include "pixman-private.h" - -#ifdef PIXMAN_TIMER - -static PixmanTimer *timers; - -static void -dump_timers (void) -{ - PixmanTimer *timer; - - for (timer = timers; timer != NULL; timer = timer->next) - { - printf ("%s: total: %llu n: %llu avg: %f\n", - timer->name, - timer->total, - timer->n_times, - timer->total / (double)timer->n_times); - } -} - -void -pixman_timer_register (PixmanTimer *timer) -{ - static int initialized; - - int atexit(void (*function)(void)); - - if (!initialized) - { - atexit (dump_timers); - initialized = 1; - } - - timer->next = timers; - timers = timer; -} - -#endif diff --git a/uppdev/plugin/pixman/lib/pixman-transformed-accessors.c b/uppdev/plugin/pixman/lib/pixman-transformed-accessors.c deleted file mode 100644 index e9ec11969..000000000 --- a/uppdev/plugin/pixman/lib/pixman-transformed-accessors.c +++ /dev/null @@ -1,3 +0,0 @@ -#define PIXMAN_FB_ACCESSORS - -#include "pixman-transformed.c" diff --git a/uppdev/plugin/pixman/lib/pixman-transformed.c b/uppdev/plugin/pixman/lib/pixman-transformed.c deleted file mode 100644 index 278afc532..000000000 --- a/uppdev/plugin/pixman/lib/pixman-transformed.c +++ /dev/null @@ -1,615 +0,0 @@ -/* - * - * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc. - * 2005 Lars Knoll & Zack Rusin, Trolltech - * 2008 Aaron Plattner, NVIDIA Corporation - * - * 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. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS 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. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include "pixman-private.h" - -#define Alpha(x) ((x) >> 24) -#define Red(x) (((x) >> 16) & 0xff) -#define Green(x) (((x) >> 8) & 0xff) -#define Blue(x) ((x) & 0xff) - -#define Alpha64(x) ((x) >> 48) -#define Red64(x) (((x) >> 32) & 0xffff) -#define Green64(x) (((x) >> 16) & 0xffff) -#define Blue64(x) ((x) & 0xffff) - -/* - * Fetch from region strategies - */ -typedef FASTCALL uint32_t (*fetchFromRegionProc)(bits_image_t *pict, int x, int y, uint32_t *buffer, fetchPixelProc32 fetch, pixman_box32_t *box); - -/* - * There are two properties we can make use of when fetching pixels - * - * (a) Is the source clip just the image itself? - * - * (b) Do we know the coordinates of the pixel to fetch are - * within the image boundaries; - * - * Source clips are almost never used, so the important case to optimize - * for is when src_clip is false. Since inside_bounds is statically known, - * the last part of the if statement will normally be optimized away. - */ -static force_inline uint32_t -do_fetch (bits_image_t *pict, int x, int y, fetchPixelProc32 fetch, - pixman_bool_t src_clip, - pixman_bool_t inside_bounds) -{ - if (src_clip) - { - if (pixman_region32_contains_point (pict->common.src_clip, x, y,NULL)) - return fetch (pict, x, y); - else - return 0; - } - else if (inside_bounds) - { - return fetch (pict, x, y); - } - else - { - if (x >= 0 && x < pict->width && y >= 0 && y < pict->height) - return fetch (pict, x, y); - else - return 0; - } -} - -/* - * Fetching Algorithms - */ -static inline uint32_t -fetch_nearest (bits_image_t *pict, - fetchPixelProc32 fetch, - pixman_bool_t affine, - pixman_repeat_t repeat, - pixman_bool_t has_src_clip, - const pixman_vector_t *v) -{ - if (!v->vector[2]) - { - return 0; - } - else - { - int x, y; - pixman_bool_t inside_bounds; - - if (!affine) - { - x = DIV(v->vector[0], v->vector[2]); - y = DIV(v->vector[1], v->vector[2]); - } - else - { - x = v->vector[0]>>16; - y = v->vector[1]>>16; - } - - switch (repeat) - { - case PIXMAN_REPEAT_NORMAL: - x = MOD (x, pict->width); - y = MOD (y, pict->height); - inside_bounds = TRUE; - break; - - case PIXMAN_REPEAT_PAD: - x = CLIP (x, 0, pict->width-1); - y = CLIP (y, 0, pict->height-1); - inside_bounds = TRUE; - break; - - case PIXMAN_REPEAT_REFLECT: /* FIXME: this should be implemented for images */ - case PIXMAN_REPEAT_NONE: - inside_bounds = FALSE; - break; - - default: - return 0; - } - - return do_fetch (pict, x, y, fetch, has_src_clip, inside_bounds); - } -} - -static inline uint32_t -fetch_bilinear (bits_image_t *pict, - fetchPixelProc32 fetch, - pixman_bool_t affine, - pixman_repeat_t repeat, - pixman_bool_t has_src_clip, - const pixman_vector_t *v) -{ - if (!v->vector[2]) - { - return 0; - } - else - { - int x1, x2, y1, y2, distx, idistx, disty, idisty; - uint32_t tl, tr, bl, br, r; - uint32_t ft, fb; - pixman_bool_t inside_bounds; - - if (!affine) - { - pixman_fixed_48_16_t div; - div = ((pixman_fixed_48_16_t)v->vector[0] << 16)/v->vector[2]; - x1 = div >> 16; - distx = ((pixman_fixed_t)div >> 8) & 0xff; - div = ((pixman_fixed_48_16_t)v->vector[1] << 16)/v->vector[2]; - y1 = div >> 16; - disty = ((pixman_fixed_t)div >> 8) & 0xff; - } - else - { - x1 = v->vector[0] >> 16; - distx = (v->vector[0] >> 8) & 0xff; - y1 = v->vector[1] >> 16; - disty = (v->vector[1] >> 8) & 0xff; - } - x2 = x1 + 1; - y2 = y1 + 1; - - idistx = 256 - distx; - idisty = 256 - disty; - - switch (repeat) - { - case PIXMAN_REPEAT_NORMAL: - x1 = MOD (x1, pict->width); - x2 = MOD (x2, pict->width); - y1 = MOD (y1, pict->height); - y2 = MOD (y2, pict->height); - inside_bounds = TRUE; - break; - - case PIXMAN_REPEAT_PAD: - x1 = CLIP (x1, 0, pict->width-1); - x2 = CLIP (x2, 0, pict->width-1); - y1 = CLIP (y1, 0, pict->height-1); - y2 = CLIP (y2, 0, pict->height-1); - inside_bounds = TRUE; - break; - - case PIXMAN_REPEAT_REFLECT: /* FIXME: this should be implemented for images */ - case PIXMAN_REPEAT_NONE: - inside_bounds = FALSE; - break; - - default: - return 0; - } - - tl = do_fetch(pict, x1, y1, fetch, has_src_clip, inside_bounds); - tr = do_fetch(pict, x2, y1, fetch, has_src_clip, inside_bounds); - bl = do_fetch(pict, x1, y2, fetch, has_src_clip, inside_bounds); - br = do_fetch(pict, x2, y2, fetch, has_src_clip, inside_bounds); - - ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx; - fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx; - r = (((ft * idisty + fb * disty) >> 16) & 0xff); - ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx; - fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx; - r |= (((ft * idisty + fb * disty) >> 8) & 0xff00); - ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx; - fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx; - r |= (((ft * idisty + fb * disty)) & 0xff0000); - ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx; - fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx; - r |= (((ft * idisty + fb * disty) << 8) & 0xff000000); - - return r; - } -} - -static void -fbFetchTransformed_Convolution(bits_image_t * pict, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits, - pixman_bool_t affine, pixman_vector_t v, pixman_vector_t unit) -{ - fetchPixelProc32 fetch; - int i; - - pixman_fixed_t *params = pict->common.filter_params; - int32_t cwidth = pixman_fixed_to_int(params[0]); - int32_t cheight = pixman_fixed_to_int(params[1]); - int xoff = (params[0] - pixman_fixed_1) >> 1; - int yoff = (params[1] - pixman_fixed_1) >> 1; - fetch = ACCESS(pixman_fetchPixelProcForPicture32)(pict); - - params += 2; - for (i = 0; i < width; ++i) { - if (!mask || mask[i] & maskBits) - { - if (!v.vector[2]) { - *(buffer + i) = 0; - } else { - int x1, x2, y1, y2, x, y; - int32_t srtot, sgtot, sbtot, satot; - pixman_fixed_t *p = params; - - if (!affine) { - pixman_fixed_48_16_t tmp; - tmp = ((pixman_fixed_48_16_t)v.vector[0] << 16)/v.vector[2] - xoff; - x1 = pixman_fixed_to_int(tmp); - tmp = ((pixman_fixed_48_16_t)v.vector[1] << 16)/v.vector[2] - yoff; - y1 = pixman_fixed_to_int(tmp); - } else { - x1 = pixman_fixed_to_int(v.vector[0] - xoff); - y1 = pixman_fixed_to_int(v.vector[1] - yoff); - } - x2 = x1 + cwidth; - y2 = y1 + cheight; - - srtot = sgtot = sbtot = satot = 0; - - for (y = y1; y < y2; y++) { - int ty; - switch (pict->common.repeat) { - case PIXMAN_REPEAT_NORMAL: - ty = MOD (y, pict->height); - break; - case PIXMAN_REPEAT_PAD: - ty = CLIP (y, 0, pict->height-1); - break; - default: - ty = y; - } - for (x = x1; x < x2; x++) { - if (*p) { - int tx; - switch (pict->common.repeat) { - case PIXMAN_REPEAT_NORMAL: - tx = MOD (x, pict->width); - break; - case PIXMAN_REPEAT_PAD: - tx = CLIP (x, 0, pict->width-1); - break; - default: - tx = x; - } - if (pixman_region32_contains_point (pict->common.src_clip, tx, ty, NULL)) { - uint32_t c = fetch(pict, tx, ty); - - srtot += Red(c) * *p; - sgtot += Green(c) * *p; - sbtot += Blue(c) * *p; - satot += Alpha(c) * *p; - } - } - p++; - } - } - - satot >>= 16; - srtot >>= 16; - sgtot >>= 16; - sbtot >>= 16; - - if (satot < 0) satot = 0; else if (satot > 0xff) satot = 0xff; - if (srtot < 0) srtot = 0; else if (srtot > 0xff) srtot = 0xff; - if (sgtot < 0) sgtot = 0; else if (sgtot > 0xff) sgtot = 0xff; - if (sbtot < 0) sbtot = 0; else if (sbtot > 0xff) sbtot = 0xff; - - *(buffer + i) = ((satot << 24) | - (srtot << 16) | - (sgtot << 8) | - (sbtot )); - } - } - v.vector[0] += unit.vector[0]; - v.vector[1] += unit.vector[1]; - v.vector[2] += unit.vector[2]; - } -} - -static void -adjust (pixman_vector_t *v, pixman_vector_t *u, pixman_fixed_t adjustment) -{ - int delta_v = (adjustment * v->vector[2]) >> 16; - int delta_u = (adjustment * u->vector[2]) >> 16; - - v->vector[0] += delta_v; - v->vector[1] += delta_v; - - u->vector[0] += delta_u; - u->vector[1] += delta_u; -} - -void -ACCESS(fbFetchTransformed)(bits_image_t * pict, int x, int y, int width, - uint32_t *buffer, uint32_t *mask, uint32_t maskBits) -{ - uint32_t *bits; - int32_t stride; - pixman_vector_t v; - pixman_vector_t unit; - pixman_bool_t affine = TRUE; - - bits = pict->bits; - stride = pict->rowstride; - - /* reference point is the center of the pixel */ - v.vector[0] = pixman_int_to_fixed(x) + pixman_fixed_1 / 2; - v.vector[1] = pixman_int_to_fixed(y) + pixman_fixed_1 / 2; - v.vector[2] = pixman_fixed_1; - - /* when using convolution filters or PIXMAN_REPEAT_PAD one might get here without a transform */ - if (pict->common.transform) - { - if (!pixman_transform_point_3d (pict->common.transform, &v)) - return; - unit.vector[0] = pict->common.transform->matrix[0][0]; - unit.vector[1] = pict->common.transform->matrix[1][0]; - unit.vector[2] = pict->common.transform->matrix[2][0]; - - affine = (v.vector[2] == pixman_fixed_1 && unit.vector[2] == 0); - } - else - { - unit.vector[0] = pixman_fixed_1; - unit.vector[1] = 0; - unit.vector[2] = 0; - } - - /* This allows filtering code to pretend that pixels are located at integer coordinates */ - if (pict->common.filter == PIXMAN_FILTER_NEAREST || pict->common.filter == PIXMAN_FILTER_FAST) - { - fetchPixelProc32 fetch; - pixman_bool_t src_clip; - int i; - - /* Round down to closest integer, ensuring that 0.5 rounds to 0, not 1 */ - adjust (&v, &unit, - pixman_fixed_e); - - fetch = ACCESS(pixman_fetchPixelProcForPicture32)(pict); - - src_clip = pict->common.src_clip != &(pict->common.full_region); - - for ( i = 0; i < width; ++i) - { - if (!mask || mask[i] & maskBits) - *(buffer + i) = fetch_nearest (pict, fetch, affine, pict->common.repeat, src_clip, &v); - - v.vector[0] += unit.vector[0]; - v.vector[1] += unit.vector[1]; - v.vector[2] += unit.vector[2]; - } - } - else if (pict->common.filter == PIXMAN_FILTER_BILINEAR || - pict->common.filter == PIXMAN_FILTER_GOOD || - pict->common.filter == PIXMAN_FILTER_BEST) - { - pixman_bool_t src_clip; - fetchPixelProc32 fetch; - int i; - - /* Let the bilinear code pretend that pixels fall on integer coordinaters */ - adjust (&v, &unit, -(pixman_fixed_1 / 2)); - - fetch = ACCESS(pixman_fetchPixelProcForPicture32)(pict); - src_clip = pict->common.src_clip != &(pict->common.full_region); - - for (i = 0; i < width; ++i) - { - if (!mask || mask[i] & maskBits) - *(buffer + i) = fetch_bilinear (pict, fetch, affine, pict->common.repeat, src_clip, &v); - - v.vector[0] += unit.vector[0]; - v.vector[1] += unit.vector[1]; - v.vector[2] += unit.vector[2]; - } - } - else if (pict->common.filter == PIXMAN_FILTER_CONVOLUTION) - { - /* Round to closest integer, ensuring that 0.5 rounds to 0, not 1 */ - adjust (&v, &unit, - pixman_fixed_e); - - fbFetchTransformed_Convolution(pict, width, buffer, mask, maskBits, affine, v, unit); - } -} - -void -ACCESS(fbFetchTransformed64)(bits_image_t * pict, int x, int y, int width, - uint64_t *buffer, uint64_t *mask, uint32_t maskBits) -{ - // TODO: Don't lose precision for wide pictures! - uint32_t *mask8 = NULL; - - // Contract the mask image, if one exists, so that the 32-bit fetch function - // can use it. - if (mask) { - mask8 = pixman_malloc_ab(width, sizeof(uint32_t)); - pixman_contract(mask8, mask, width); - } - - // Fetch the image into the first half of buffer. - ACCESS(fbFetchTransformed)(pict, x, y, width, (uint32_t*)buffer, mask8, - maskBits); - - // Expand from 32bpp to 64bpp in place. - pixman_expand(buffer, (uint32_t*)buffer, PIXMAN_a8r8g8b8, width); - - free(mask8); -} - -#define SCANLINE_BUFFER_LENGTH 2048 - -void -ACCESS(fbFetchExternalAlpha)(bits_image_t * pict, int x, int y, int width, - uint32_t *buffer, uint32_t *mask, - uint32_t maskBits) -{ - int i; - uint32_t _alpha_buffer[SCANLINE_BUFFER_LENGTH]; - uint32_t *alpha_buffer = _alpha_buffer; - - if (!pict->common.alpha_map) { - ACCESS(fbFetchTransformed) (pict, x, y, width, buffer, mask, maskBits); - return; - } - if (width > SCANLINE_BUFFER_LENGTH) - alpha_buffer = (uint32_t *) pixman_malloc_ab (width, sizeof(uint32_t)); - - ACCESS(fbFetchTransformed)(pict, x, y, width, buffer, mask, maskBits); - ACCESS(fbFetchTransformed)((bits_image_t *)pict->common.alpha_map, x - pict->common.alpha_origin.x, - y - pict->common.alpha_origin.y, width, - alpha_buffer, mask, maskBits); - for (i = 0; i < width; ++i) { - if (!mask || mask[i] & maskBits) - { - int a = alpha_buffer[i]>>24; - *(buffer + i) = (a << 24) - | (div_255(Red(*(buffer + i)) * a) << 16) - | (div_255(Green(*(buffer + i)) * a) << 8) - | (div_255(Blue(*(buffer + i)) * a)); - } - } - - if (alpha_buffer != _alpha_buffer) - free(alpha_buffer); -} - -void -ACCESS(fbFetchExternalAlpha64)(bits_image_t * pict, int x, int y, int width, - uint64_t *buffer, uint64_t *mask, - uint32_t maskBits) -{ - int i; - uint64_t _alpha_buffer[SCANLINE_BUFFER_LENGTH]; - uint64_t *alpha_buffer = _alpha_buffer; - uint64_t maskBits64; - - if (!pict->common.alpha_map) { - ACCESS(fbFetchTransformed64) (pict, x, y, width, buffer, mask, maskBits); - return; - } - if (width > SCANLINE_BUFFER_LENGTH) - alpha_buffer = (uint64_t *) pixman_malloc_ab (width, sizeof(uint64_t)); - - ACCESS(fbFetchTransformed64)(pict, x, y, width, buffer, mask, maskBits); - ACCESS(fbFetchTransformed64)((bits_image_t *)pict->common.alpha_map, x - pict->common.alpha_origin.x, - y - pict->common.alpha_origin.y, width, - alpha_buffer, mask, maskBits); - - pixman_expand(&maskBits64, &maskBits, PIXMAN_a8r8g8b8, 1); - - for (i = 0; i < width; ++i) { - if (!mask || mask[i] & maskBits64) - { - int64_t a = alpha_buffer[i]>>48; - *(buffer + i) = (a << 48) - | (div_65535(Red64(*(buffer + i)) * a) << 32) - | (div_65535(Green64(*(buffer + i)) * a) << 16) - | (div_65535(Blue64(*(buffer + i)) * a)); - } - } - - if (alpha_buffer != _alpha_buffer) - free(alpha_buffer); -} - -void -ACCESS(fbStoreExternalAlpha)(bits_image_t * pict, int x, int y, int width, - uint32_t *buffer) -{ - uint32_t *bits, *alpha_bits; - int32_t stride, astride; - int ax, ay; - storeProc32 store; - storeProc32 astore; - const pixman_indexed_t * indexed = pict->indexed; - const pixman_indexed_t * aindexed; - - if (!pict->common.alpha_map) { - // XXX[AGP]: This should never happen! - // fbStore(pict, x, y, width, buffer); - abort(); - return; - } - - store = ACCESS(pixman_storeProcForPicture32)(pict); - astore = ACCESS(pixman_storeProcForPicture32)(pict->common.alpha_map); - aindexed = pict->common.alpha_map->indexed; - - ax = x; - ay = y; - - bits = pict->bits; - stride = pict->rowstride; - - alpha_bits = pict->common.alpha_map->bits; - astride = pict->common.alpha_map->rowstride; - - bits += y*stride; - alpha_bits += (ay - pict->common.alpha_origin.y)*astride; - - - store((pixman_image_t *)pict, bits, buffer, x, width, indexed); - astore((pixman_image_t *)pict->common.alpha_map, - alpha_bits, buffer, ax - pict->common.alpha_origin.x, width, aindexed); -} - -void -ACCESS(fbStoreExternalAlpha64)(bits_image_t * pict, int x, int y, int width, - uint64_t *buffer) -{ - uint32_t *bits, *alpha_bits; - int32_t stride, astride; - int ax, ay; - storeProc64 store; - storeProc64 astore; - const pixman_indexed_t * indexed = pict->indexed; - const pixman_indexed_t * aindexed; - - store = ACCESS(pixman_storeProcForPicture64)(pict); - astore = ACCESS(pixman_storeProcForPicture64)(pict->common.alpha_map); - aindexed = pict->common.alpha_map->indexed; - - ax = x; - ay = y; - - bits = pict->bits; - stride = pict->rowstride; - - alpha_bits = pict->common.alpha_map->bits; - astride = pict->common.alpha_map->rowstride; - - bits += y*stride; - alpha_bits += (ay - pict->common.alpha_origin.y)*astride; - - - store((pixman_image_t *)pict, bits, buffer, x, width, indexed); - astore((pixman_image_t *)pict->common.alpha_map, - alpha_bits, buffer, ax - pict->common.alpha_origin.x, width, aindexed); -} diff --git a/uppdev/plugin/pixman/lib/pixman-trap.c b/uppdev/plugin/pixman/lib/pixman-trap.c deleted file mode 100644 index 5a806ff00..000000000 --- a/uppdev/plugin/pixman/lib/pixman-trap.c +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Copyright © 2004 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. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include "pixman-private.h" - -typedef uint32_t FbBits; - -PIXMAN_EXPORT void -pixman_add_traps (pixman_image_t * image, - int16_t x_off, - int16_t y_off, - int ntrap, - pixman_trap_t *traps) -{ - int bpp; - int width; - int height; - - pixman_fixed_t x_off_fixed; - pixman_fixed_t y_off_fixed; - pixman_edge_t l, r; - pixman_fixed_t t, b; - - width = image->bits.width; - height = image->bits.height; - bpp = PIXMAN_FORMAT_BPP (image->bits.format); - - x_off_fixed = pixman_int_to_fixed(x_off); - y_off_fixed = pixman_int_to_fixed(y_off); - - while (ntrap--) - { - t = traps->top.y + y_off_fixed; - if (t < 0) - t = 0; - t = pixman_sample_ceil_y (t, bpp); - - b = traps->bot.y + y_off_fixed; - if (pixman_fixed_to_int (b) >= height) - b = pixman_int_to_fixed (height) - 1; - b = pixman_sample_floor_y (b, bpp); - - if (b >= t) - { - /* initialize edge walkers */ - pixman_edge_init (&l, bpp, t, - traps->top.l + x_off_fixed, - traps->top.y + y_off_fixed, - traps->bot.l + x_off_fixed, - traps->bot.y + y_off_fixed); - - pixman_edge_init (&r, bpp, t, - traps->top.r + x_off_fixed, - traps->top.y + y_off_fixed, - traps->bot.r + x_off_fixed, - traps->bot.y + y_off_fixed); - - pixman_rasterize_edges (image, &l, &r, t, b); - } - traps++; - } -} - -static void -dump_image (pixman_image_t *image, - const char *title) -{ - int i, j; - - if (!image->type == BITS) - { - printf ("%s is not a regular image\n", title); - } - - if (!image->bits.format == PIXMAN_a8) - { - printf ("%s is not an alpha mask\n", title); - } - - printf ("\n\n\n%s: \n", title); - - for (i = 0; i < image->bits.height; ++i) - { - uint8_t *line = - (uint8_t *)&(image->bits.bits[i * image->bits.rowstride]); - - for (j = 0; j < image->bits.width; ++j) - printf ("%c", line[j]? '#' : ' '); - - printf ("\n"); - } -} - -PIXMAN_EXPORT void -pixman_add_trapezoids (pixman_image_t *image, - int16_t x_off, - int y_off, - int ntraps, - const pixman_trapezoid_t *traps) -{ - int i; - -#if 0 - dump_image (image, "before"); -#endif - - for (i = 0; i < ntraps; ++i) - { - const pixman_trapezoid_t *trap = &(traps[i]); - - if (!pixman_trapezoid_valid (trap)) - continue; - - pixman_rasterize_trapezoid (image, trap, x_off, y_off); - } - -#if 0 - dump_image (image, "after"); -#endif -} - -PIXMAN_EXPORT void -pixman_rasterize_trapezoid (pixman_image_t * image, - const pixman_trapezoid_t *trap, - int x_off, - int y_off) -{ - int bpp; - int width; - int height; - - pixman_fixed_t x_off_fixed; - pixman_fixed_t y_off_fixed; - pixman_edge_t l, r; - pixman_fixed_t t, b; - - return_if_fail (image->type == BITS); - - if (!pixman_trapezoid_valid (trap)) - return; - - width = image->bits.width; - height = image->bits.height; - bpp = PIXMAN_FORMAT_BPP (image->bits.format); - - x_off_fixed = pixman_int_to_fixed(x_off); - y_off_fixed = pixman_int_to_fixed(y_off); - t = trap->top + y_off_fixed; - if (t < 0) - t = 0; - t = pixman_sample_ceil_y (t, bpp); - - b = trap->bottom + y_off_fixed; - if (pixman_fixed_to_int (b) >= height) - b = pixman_int_to_fixed (height) - 1; - b = pixman_sample_floor_y (b, bpp); - - if (b >= t) - { - /* initialize edge walkers */ - pixman_line_fixed_edge_init (&l, bpp, t, &trap->left, x_off, y_off); - pixman_line_fixed_edge_init (&r, bpp, t, &trap->right, x_off, y_off); - - pixman_rasterize_edges (image, &l, &r, t, b); - } -} - -#if 0 -static int -_GreaterY (pixman_point_fixed_t *a, pixman_point_fixed_t *b) -{ - if (a->y == b->y) - return a->x > b->x; - return a->y > b->y; -} - -/* - * Note that the definition of this function is a bit odd because - * of the X coordinate space (y increasing downwards). - */ -static int -_Clockwise (pixman_point_fixed_t *ref, pixman_point_fixed_t *a, pixman_point_fixed_t *b) -{ - pixman_point_fixed_t ad, bd; - - ad.x = a->x - ref->x; - ad.y = a->y - ref->y; - bd.x = b->x - ref->x; - bd.y = b->y - ref->y; - - return ((pixman_fixed_32_32_t) bd.y * ad.x - (pixman_fixed_32_32_t) ad.y * bd.x) < 0; -} - -/* FIXME -- this could be made more efficient */ -void -fbAddTriangles (pixman_image_t * pPicture, - int16_t x_off, - int16_t y_off, - int ntri, - xTriangle *tris) -{ - pixman_point_fixed_t *top, *left, *right, *tmp; - xTrapezoid trap; - - for (; ntri; ntri--, tris++) - { - top = &tris->p1; - left = &tris->p2; - right = &tris->p3; - if (_GreaterY (top, left)) { - tmp = left; left = top; top = tmp; - } - if (_GreaterY (top, right)) { - tmp = right; right = top; top = tmp; - } - if (_Clockwise (top, right, left)) { - tmp = right; right = left; left = tmp; - } - - /* - * Two cases: - * - * + + - * / \ / \ - * / \ / \ - * / + + \ - * / -- -- \ - * / -- -- \ - * / --- --- \ - * +-- --+ - */ - - trap.top = top->y; - trap.left.p1 = *top; - trap.left.p2 = *left; - trap.right.p1 = *top; - trap.right.p2 = *right; - if (right->y < left->y) - trap.bottom = right->y; - else - trap.bottom = left->y; - fbRasterizeTrapezoid (pPicture, &trap, x_off, y_off); - if (right->y < left->y) - { - trap.top = right->y; - trap.bottom = left->y; - trap.right.p1 = *right; - trap.right.p2 = *left; - } - else - { - trap.top = left->y; - trap.bottom = right->y; - trap.left.p1 = *left; - trap.left.p2 = *right; - } - fbRasterizeTrapezoid (pPicture, &trap, x_off, y_off); - } -} -#endif diff --git a/uppdev/plugin/pixman/lib/pixman-utils.c b/uppdev/plugin/pixman/lib/pixman-utils.c deleted file mode 100644 index a4a5938d7..000000000 --- a/uppdev/plugin/pixman/lib/pixman-utils.c +++ /dev/null @@ -1,581 +0,0 @@ -/* - * Copyright © 2000 SuSE, Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of SuSE not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. SuSE makes no representations about the - * suitability of this software for any purpose. It is provided "as is" - * without express or implied warranty. - * - * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE - * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Author: Keith Packard, SuSE, Inc. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include "pixman-private.h" -#include "pixman-mmx.h" -#include "pixman-sse2.h" - -#if defined(USE_SSE2) && defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__) -__attribute__((__force_align_arg_pointer__)) -#endif -PIXMAN_EXPORT pixman_bool_t -pixman_blt (uint32_t *src_bits, - uint32_t *dst_bits, - int src_stride, - int dst_stride, - int src_bpp, - int dst_bpp, - int src_x, int src_y, - int dst_x, int dst_y, - int width, int height) -{ -#ifdef USE_SSE2 - if (pixman_have_sse2()) - { - return pixmanBltsse2 (src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp, - src_x, src_y, dst_x, dst_y, width, height); - } - else -#endif -#ifdef USE_MMX - if (pixman_have_mmx()) - { - return pixman_blt_mmx (src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp, - src_x, src_y, dst_x, dst_y, width, height); - } - else -#endif - return FALSE; -} - -static void -pixman_fill8 (uint32_t *bits, - int stride, - int x, - int y, - int width, - int height, - uint32_t xor) -{ - int byte_stride = stride * (int) sizeof (uint32_t); - uint8_t *dst = (uint8_t *) bits; - uint8_t v = xor & 0xff; - int i; - - dst = dst + y * byte_stride + x; - - while (height--) - { - for (i = 0; i < width; ++i) - dst[i] = v; - - dst += byte_stride; - } -} - -static void -pixman_fill16 (uint32_t *bits, - int stride, - int x, - int y, - int width, - int height, - uint32_t xor) -{ - int short_stride = (stride * (int) sizeof (uint32_t)) / (int) sizeof (uint16_t); - uint16_t *dst = (uint16_t *)bits; - uint16_t v = xor & 0xffff; - int i; - - dst = dst + y * short_stride + x; - - while (height--) - { - for (i = 0; i < width; ++i) - dst[i] = v; - - dst += short_stride; - } -} - -static void -pixman_fill32 (uint32_t *bits, - int stride, - int x, - int y, - int width, - int height, - uint32_t xor) -{ - int i; - - bits = bits + y * stride + x; - - while (height--) - { - for (i = 0; i < width; ++i) - bits[i] = xor; - - bits += stride; - } -} - -#if defined(USE_SSE2) && defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__) -__attribute__((__force_align_arg_pointer__)) -#endif -PIXMAN_EXPORT pixman_bool_t -pixman_fill (uint32_t *bits, - int stride, - int bpp, - int x, - int y, - int width, - int height, - uint32_t xor) -{ -#if 0 - printf ("filling: %d %d %d %d (stride: %d, bpp: %d) pixel: %x\n", - x, y, width, height, stride, bpp, xor); -#endif - -#ifdef USE_SSE2 - if (pixman_have_sse2() && pixmanFillsse2 (bits, stride, bpp, x, y, width, height, xor)) - return TRUE; -#endif - -#ifdef USE_MMX - if (pixman_have_mmx() && pixman_fill_mmx (bits, stride, bpp, x, y, width, height, xor)) - return TRUE; -#endif - - switch (bpp) - { - case 8: - pixman_fill8 (bits, stride, x, y, width, height, xor); - break; - - case 16: - pixman_fill16 (bits, stride, x, y, width, height, xor); - break; - - case 32: - pixman_fill32 (bits, stride, x, y, width, height, xor); - break; - - default: - return FALSE; - break; - } - - return TRUE; -} - - -/* - * Compute the smallest value no less than y which is on a - * grid row - */ - -PIXMAN_EXPORT pixman_fixed_t -pixman_sample_ceil_y (pixman_fixed_t y, int n) -{ - pixman_fixed_t f = pixman_fixed_frac(y); - pixman_fixed_t i = pixman_fixed_floor(y); - - f = ((f + Y_FRAC_FIRST(n)) / STEP_Y_SMALL(n)) * STEP_Y_SMALL(n) + Y_FRAC_FIRST(n); - if (f > Y_FRAC_LAST(n)) - { - f = Y_FRAC_FIRST(n); - i += pixman_fixed_1; - } - return (i | f); -} - -#define _div(a,b) ((a) >= 0 ? (a) / (b) : -((-(a) + (b) - 1) / (b))) - -/* - * Compute the largest value no greater than y which is on a - * grid row - */ -PIXMAN_EXPORT pixman_fixed_t -pixman_sample_floor_y (pixman_fixed_t y, int n) -{ - pixman_fixed_t f = pixman_fixed_frac(y); - pixman_fixed_t i = pixman_fixed_floor (y); - - f = _div(f - Y_FRAC_FIRST(n), STEP_Y_SMALL(n)) * STEP_Y_SMALL(n) + Y_FRAC_FIRST(n); - if (f < Y_FRAC_FIRST(n)) - { - f = Y_FRAC_LAST(n); - i -= pixman_fixed_1; - } - return (i | f); -} - -/* - * Step an edge by any amount (including negative values) - */ -PIXMAN_EXPORT void -pixman_edge_step (pixman_edge_t *e, int n) -{ - pixman_fixed_48_16_t ne; - - e->x += n * e->stepx; - - ne = e->e + n * (pixman_fixed_48_16_t) e->dx; - - if (n >= 0) - { - if (ne > 0) - { - int nx = (ne + e->dy - 1) / e->dy; - e->e = ne - nx * (pixman_fixed_48_16_t) e->dy; - e->x += nx * e->signdx; - } - } - else - { - if (ne <= -e->dy) - { - int nx = (-ne) / e->dy; - e->e = ne + nx * (pixman_fixed_48_16_t) e->dy; - e->x -= nx * e->signdx; - } - } -} - -/* - * A private routine to initialize the multi-step - * elements of an edge structure - */ -static void -_pixman_edge_tMultiInit (pixman_edge_t *e, int n, pixman_fixed_t *stepx_p, pixman_fixed_t *dx_p) -{ - pixman_fixed_t stepx; - pixman_fixed_48_16_t ne; - - ne = n * (pixman_fixed_48_16_t) e->dx; - stepx = n * e->stepx; - if (ne > 0) - { - int nx = ne / e->dy; - ne -= nx * e->dy; - stepx += nx * e->signdx; - } - *dx_p = ne; - *stepx_p = stepx; -} - -/* - * Initialize one edge structure given the line endpoints and a - * starting y value - */ -PIXMAN_EXPORT void -pixman_edge_init (pixman_edge_t *e, - int n, - pixman_fixed_t y_start, - pixman_fixed_t x_top, - pixman_fixed_t y_top, - pixman_fixed_t x_bot, - pixman_fixed_t y_bot) -{ - pixman_fixed_t dx, dy; - - e->x = x_top; - e->e = 0; - dx = x_bot - x_top; - dy = y_bot - y_top; - e->dy = dy; - e->dx = 0; - if (dy) - { - if (dx >= 0) - { - e->signdx = 1; - e->stepx = dx / dy; - e->dx = dx % dy; - e->e = -dy; - } - else - { - e->signdx = -1; - e->stepx = -(-dx / dy); - e->dx = -dx % dy; - e->e = 0; - } - - _pixman_edge_tMultiInit (e, STEP_Y_SMALL(n), &e->stepx_small, &e->dx_small); - _pixman_edge_tMultiInit (e, STEP_Y_BIG(n), &e->stepx_big, &e->dx_big); - } - pixman_edge_step (e, y_start - y_top); -} - -/* - * Initialize one edge structure given a line, starting y value - * and a pixel offset for the line - */ -PIXMAN_EXPORT void -pixman_line_fixed_edge_init (pixman_edge_t *e, - int n, - pixman_fixed_t y, - const pixman_line_fixed_t *line, - int x_off, - int y_off) -{ - pixman_fixed_t x_off_fixed = pixman_int_to_fixed(x_off); - pixman_fixed_t y_off_fixed = pixman_int_to_fixed(y_off); - const pixman_point_fixed_t *top, *bot; - - if (line->p1.y <= line->p2.y) - { - top = &line->p1; - bot = &line->p2; - } - else - { - top = &line->p2; - bot = &line->p1; - } - pixman_edge_init (e, n, y, - top->x + x_off_fixed, - top->y + y_off_fixed, - bot->x + x_off_fixed, - bot->y + y_off_fixed); -} - -pixman_bool_t -pixman_multiply_overflows_int (unsigned int a, - unsigned int b) -{ - return a >= INT32_MAX / b; -} - -pixman_bool_t -pixman_addition_overflows_int (unsigned int a, - unsigned int b) -{ - return a > INT32_MAX - b; -} - -void * -pixman_malloc_ab(unsigned int a, - unsigned int b) -{ - if (a >= INT32_MAX / b) - return NULL; - - return malloc (a * b); -} - -void * -pixman_malloc_abc (unsigned int a, - unsigned int b, - unsigned int c) -{ - if (a >= INT32_MAX / b) - return NULL; - else if (a * b >= INT32_MAX / c) - return NULL; - else - return malloc (a * b * c); -} - - -/** - * pixman_version: - * - * Returns the version of the pixman library encoded in a single - * integer as per %PIXMAN_VERSION_ENCODE. The encoding ensures that - * later versions compare greater than earlier versions. - * - * A run-time comparison to check that pixman's version is greater than - * or equal to version X.Y.Z could be performed as follows: - * - * - * if (pixman_version() >= PIXMAN_VERSION_ENCODE(X,Y,Z)) {...} - * - * - * See also pixman_version_string() as well as the compile-time - * equivalents %PIXMAN_VERSION and %PIXMAN_VERSION_STRING. - * - * Return value: the encoded version. - **/ -PIXMAN_EXPORT int -pixman_version (void) -{ - return PIXMAN_VERSION; -} - -/** - * pixman_version_string: - * - * Returns the version of the pixman library as a human-readable string - * of the form "X.Y.Z". - * - * See also pixman_version() as well as the compile-time equivalents - * %PIXMAN_VERSION_STRING and %PIXMAN_VERSION. - * - * Return value: a string containing the version. - **/ -PIXMAN_EXPORT const char* -pixman_version_string (void) -{ - return PIXMAN_VERSION_STRING; -} - -/** - * pixman_format_supported_destination: - * @format: A pixman_format_code_t format - * - * Return value: whether the provided format code is a supported - * format for a pixman surface used as a destination in - * rendering. - * - * Currently, all pixman_format_code_t values are supported - * except for the YUV formats. - **/ -PIXMAN_EXPORT pixman_bool_t -pixman_format_supported_destination (pixman_format_code_t format) -{ - switch (format) { - /* 32 bpp formats */ - case PIXMAN_a2b10g10r10: - case PIXMAN_x2b10g10r10: - case PIXMAN_a8r8g8b8: - case PIXMAN_x8r8g8b8: - case PIXMAN_a8b8g8r8: - case PIXMAN_x8b8g8r8: - case PIXMAN_r8g8b8: - case PIXMAN_b8g8r8: - case PIXMAN_r5g6b5: - case PIXMAN_b5g6r5: - /* 16 bpp formats */ - case PIXMAN_a1r5g5b5: - case PIXMAN_x1r5g5b5: - case PIXMAN_a1b5g5r5: - case PIXMAN_x1b5g5r5: - case PIXMAN_a4r4g4b4: - case PIXMAN_x4r4g4b4: - case PIXMAN_a4b4g4r4: - case PIXMAN_x4b4g4r4: - /* 8bpp formats */ - case PIXMAN_a8: - case PIXMAN_r3g3b2: - case PIXMAN_b2g3r3: - case PIXMAN_a2r2g2b2: - case PIXMAN_a2b2g2r2: - case PIXMAN_c8: - case PIXMAN_g8: - case PIXMAN_x4a4: - /* Collides with PIXMAN_c8 - case PIXMAN_x4c4: - */ - /* Collides with PIXMAN_g8 - case PIXMAN_x4g4: - */ - /* 4bpp formats */ - case PIXMAN_a4: - case PIXMAN_r1g2b1: - case PIXMAN_b1g2r1: - case PIXMAN_a1r1g1b1: - case PIXMAN_a1b1g1r1: - case PIXMAN_c4: - case PIXMAN_g4: - /* 1bpp formats */ - case PIXMAN_a1: - case PIXMAN_g1: - return TRUE; - - /* YUV formats */ - case PIXMAN_yuy2: - case PIXMAN_yv12: - default: - return FALSE; - } -} - -/** - * pixman_format_supported_source: - * @format: A pixman_format_code_t format - * - * Return value: whether the provided format code is a supported - * format for a pixman surface used as a source in - * rendering. - * - * Currently, all pixman_format_code_t values are supported. - **/ -PIXMAN_EXPORT pixman_bool_t -pixman_format_supported_source (pixman_format_code_t format) -{ - switch (format) { - /* 32 bpp formats */ - case PIXMAN_a2b10g10r10: - case PIXMAN_x2b10g10r10: - case PIXMAN_a8r8g8b8: - case PIXMAN_x8r8g8b8: - case PIXMAN_a8b8g8r8: - case PIXMAN_x8b8g8r8: - case PIXMAN_r8g8b8: - case PIXMAN_b8g8r8: - case PIXMAN_r5g6b5: - case PIXMAN_b5g6r5: - /* 16 bpp formats */ - case PIXMAN_a1r5g5b5: - case PIXMAN_x1r5g5b5: - case PIXMAN_a1b5g5r5: - case PIXMAN_x1b5g5r5: - case PIXMAN_a4r4g4b4: - case PIXMAN_x4r4g4b4: - case PIXMAN_a4b4g4r4: - case PIXMAN_x4b4g4r4: - /* 8bpp formats */ - case PIXMAN_a8: - case PIXMAN_r3g3b2: - case PIXMAN_b2g3r3: - case PIXMAN_a2r2g2b2: - case PIXMAN_a2b2g2r2: - case PIXMAN_c8: - case PIXMAN_g8: - case PIXMAN_x4a4: - /* Collides with PIXMAN_c8 - case PIXMAN_x4c4: - */ - /* Collides with PIXMAN_g8 - case PIXMAN_x4g4: - */ - /* 4bpp formats */ - case PIXMAN_a4: - case PIXMAN_r1g2b1: - case PIXMAN_b1g2r1: - case PIXMAN_a1r1g1b1: - case PIXMAN_a1b1g1r1: - case PIXMAN_c4: - case PIXMAN_g4: - /* 1bpp formats */ - case PIXMAN_a1: - case PIXMAN_g1: - /* YUV formats */ - case PIXMAN_yuy2: - case PIXMAN_yv12: - return TRUE; - - default: - return FALSE; - } -} diff --git a/uppdev/plugin/pixman/lib/pixman-version.h b/uppdev/plugin/pixman/lib/pixman-version.h deleted file mode 100644 index 0b0c5f360..000000000 --- a/uppdev/plugin/pixman/lib/pixman-version.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright © 2008 Red Hat, Inc. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * Author: Carl D. Worth - */ - -#ifndef PIXMAN_VERSION_H__ -#define PIXMAN_VERSION_H__ - -#ifndef PIXMAN_H__ -# error pixman-version.h should only be included by pixman.h -#endif - -#define PIXMAN_VERSION_MAJOR 0 -#define PIXMAN_VERSION_MINOR 13 -#define PIXMAN_VERSION_MICRO 2 - -#define PIXMAN_VERSION_STRING "0.13.2" - -#define PIXMAN_VERSION_ENCODE(major, minor, micro) ( \ - ((major) * 10000) \ - + ((minor) * 100) \ - + ((micro) * 1)) - -#define PIXMAN_VERSION PIXMAN_VERSION_ENCODE( \ - PIXMAN_VERSION_MAJOR, \ - PIXMAN_VERSION_MINOR, \ - PIXMAN_VERSION_MICRO) - -#endif /* PIXMAN_VERSION_H__ */ diff --git a/uppdev/plugin/pixman/lib/pixman-vmx.c b/uppdev/plugin/pixman/lib/pixman-vmx.c deleted file mode 100644 index d71a9e4d3..000000000 --- a/uppdev/plugin/pixman/lib/pixman-vmx.c +++ /dev/null @@ -1,1064 +0,0 @@ -/* - * Copyright © 2007 Luca Barbato - * - * 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 Luca Barbato not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. Luca Barbato makes no representations about the - * suitability of this software for any purpose. It is provided "as is" - * without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - * - * Author: Luca Barbato (lu_zero@gentoo.org) - * - * Based on fbmmx.c by Owen Taylor, Søren Sandmann and Nicholas Miell - */ - -#include -#include "pixman-vmx.h" -#include "pixman-combine32.h" -#include - -static force_inline vector unsigned int -splat_alpha (vector unsigned int pix) { - return vec_perm (pix, pix, - (vector unsigned char)AVV(0x00,0x00,0x00,0x00, 0x04,0x04,0x04,0x04, - 0x08,0x08,0x08,0x08, 0x0C,0x0C,0x0C,0x0C)); -} - -static force_inline vector unsigned int -pix_multiply (vector unsigned int p, vector unsigned int a) -{ - vector unsigned short hi, lo, mod; - /* unpack to short */ - hi = (vector unsigned short) - vec_mergeh ((vector unsigned char)AVV(0), - (vector unsigned char)p); - mod = (vector unsigned short) - vec_mergeh ((vector unsigned char)AVV(0), - (vector unsigned char)a); - - hi = vec_mladd (hi, mod, (vector unsigned short) - AVV(0x0080,0x0080,0x0080,0x0080, - 0x0080,0x0080,0x0080,0x0080)); - - hi = vec_adds (hi, vec_sr (hi, vec_splat_u16 (8))); - - hi = vec_sr (hi, vec_splat_u16 (8)); - - /* unpack to short */ - lo = (vector unsigned short) - vec_mergel ((vector unsigned char)AVV(0), - (vector unsigned char)p); - mod = (vector unsigned short) - vec_mergel ((vector unsigned char)AVV(0), - (vector unsigned char)a); - - lo = vec_mladd (lo, mod, (vector unsigned short) - AVV(0x0080,0x0080,0x0080,0x0080, - 0x0080,0x0080,0x0080,0x0080)); - - lo = vec_adds (lo, vec_sr (lo, vec_splat_u16 (8))); - - lo = vec_sr (lo, vec_splat_u16 (8)); - - return (vector unsigned int)vec_packsu (hi, lo); -} - -static force_inline vector unsigned int -pix_add (vector unsigned int a, vector unsigned int b) -{ - return (vector unsigned int)vec_adds ((vector unsigned char)a, - (vector unsigned char)b); -} - -static force_inline vector unsigned int -pix_add_mul (vector unsigned int x, vector unsigned int a, - vector unsigned int y, vector unsigned int b) -{ - vector unsigned short hi, lo, mod, hiy, loy, mody; - - hi = (vector unsigned short) - vec_mergeh ((vector unsigned char)AVV(0), - (vector unsigned char)x); - mod = (vector unsigned short) - vec_mergeh ((vector unsigned char)AVV(0), - (vector unsigned char)a); - hiy = (vector unsigned short) - vec_mergeh ((vector unsigned char)AVV(0), - (vector unsigned char)y); - mody = (vector unsigned short) - vec_mergeh ((vector unsigned char)AVV(0), - (vector unsigned char)b); - - hi = vec_mladd (hi, mod, (vector unsigned short) - AVV(0x0080,0x0080,0x0080,0x0080, - 0x0080,0x0080,0x0080,0x0080)); - - hi = vec_mladd (hiy, mody, hi); - - hi = vec_adds (hi, vec_sr (hi, vec_splat_u16 (8))); - - hi = vec_sr (hi, vec_splat_u16 (8)); - - lo = (vector unsigned short) - vec_mergel ((vector unsigned char)AVV(0), - (vector unsigned char)x); - mod = (vector unsigned short) - vec_mergel ((vector unsigned char)AVV(0), - (vector unsigned char)a); - - loy = (vector unsigned short) - vec_mergel ((vector unsigned char)AVV(0), - (vector unsigned char)y); - mody = (vector unsigned short) - vec_mergel ((vector unsigned char)AVV(0), - (vector unsigned char)b); - - lo = vec_mladd (lo, mod, (vector unsigned short) - AVV(0x0080,0x0080,0x0080,0x0080, - 0x0080,0x0080,0x0080,0x0080)); - - lo = vec_mladd (loy, mody, lo); - - lo = vec_adds (lo, vec_sr (lo, vec_splat_u16 (8))); - - lo = vec_sr (lo, vec_splat_u16 (8)); - - return (vector unsigned int)vec_packsu (hi, lo); -} - -static force_inline vector unsigned int -negate (vector unsigned int src) -{ - return vec_nor (src, src); -} -/* dest*~srca + src */ -static force_inline vector unsigned int -over (vector unsigned int src, vector unsigned int srca, - vector unsigned int dest) -{ - vector unsigned char tmp = (vector unsigned char) - pix_multiply (dest, negate (srca)); - tmp = vec_adds ((vector unsigned char)src, tmp); - return (vector unsigned int)tmp; -} - -/* in == pix_multiply */ -#define in_over(src, srca, mask, dest) over (pix_multiply (src, mask),\ - pix_multiply (srca, mask), dest) - - -#define COMPUTE_SHIFT_MASK(source) \ - source ## _mask = vec_lvsl (0, source); - -#define COMPUTE_SHIFT_MASKS(dest, source) \ - dest ## _mask = vec_lvsl (0, dest); \ - source ## _mask = vec_lvsl (0, source); \ - store_mask = vec_lvsr (0, dest); - -#define COMPUTE_SHIFT_MASKC(dest, source, mask) \ - mask ## _mask = vec_lvsl (0, mask); \ - dest ## _mask = vec_lvsl (0, dest); \ - source ## _mask = vec_lvsl (0, source); \ - store_mask = vec_lvsr (0, dest); - -/* notice you have to declare temp vars... - * Note: tmp3 and tmp4 must remain untouched! - */ - -#define LOAD_VECTORS(dest, source) \ - tmp1 = (typeof(tmp1))vec_ld(0, source); \ - tmp2 = (typeof(tmp2))vec_ld(15, source); \ - tmp3 = (typeof(tmp3))vec_ld(0, dest); \ - v ## source = (typeof(v ## source)) \ - vec_perm(tmp1, tmp2, source ## _mask); \ - tmp4 = (typeof(tmp4))vec_ld(15, dest); \ - v ## dest = (typeof(v ## dest)) \ - vec_perm(tmp3, tmp4, dest ## _mask); - -#define LOAD_VECTORSC(dest, source, mask) \ - tmp1 = (typeof(tmp1))vec_ld(0, source); \ - tmp2 = (typeof(tmp2))vec_ld(15, source); \ - tmp3 = (typeof(tmp3))vec_ld(0, dest); \ - v ## source = (typeof(v ## source)) \ - vec_perm(tmp1, tmp2, source ## _mask); \ - tmp4 = (typeof(tmp4))vec_ld(15, dest); \ - tmp1 = (typeof(tmp1))vec_ld(0, mask); \ - v ## dest = (typeof(v ## dest)) \ - vec_perm(tmp3, tmp4, dest ## _mask); \ - tmp2 = (typeof(tmp2))vec_ld(15, mask); \ - v ## mask = (typeof(v ## mask)) \ - vec_perm(tmp1, tmp2, mask ## _mask); -#define STORE_VECTOR(dest) \ - edges = vec_perm (tmp4, tmp3, dest ## _mask); \ - tmp3 = vec_perm ((vector unsigned char)v ## dest, edges, store_mask); \ - tmp1 = vec_perm (edges, (vector unsigned char)v ## dest, store_mask); \ - vec_st ((vector unsigned int) tmp3, 15, dest ); \ - vec_st ((vector unsigned int) tmp1, 0, dest ); - -static FASTCALL void -vmxCombineMaskU (uint32_t *src, const uint32_t *msk, int width) -{ - int i; - vector unsigned int vsrc, vmsk; - vector unsigned char tmp1, tmp2, tmp3, tmp4, edges, - src_mask, msk_mask, store_mask; - - COMPUTE_SHIFT_MASKS(src, msk) - - /* printf ("%s\n",__PRETTY_FUNCTION__); */ - for (i = width/4; i > 0; i--) { - - LOAD_VECTORS(src, msk) - - vsrc = pix_multiply (vsrc, splat_alpha (vmsk)); - - STORE_VECTOR(src) - - msk+=4; - src+=4; - } - - for (i = width%4; --i >= 0;) { - uint32_t a = msk[i] >> 24; - uint32_t s = src[i]; - FbByteMul (s, a); - src[i] = s; - } -} - -static FASTCALL void -vmxCombineOverU (uint32_t *dest, const uint32_t *src, int width) -{ - int i; - vector unsigned int vdest, vsrc; - vector unsigned char tmp1, tmp2, tmp3, tmp4, edges, - dest_mask, src_mask, store_mask; - - COMPUTE_SHIFT_MASKS(dest, src) - - /* printf ("%s\n",__PRETTY_FUNCTION__); */ - for (i = width/4; i > 0; i--) { - - LOAD_VECTORS(dest, src) - - vdest = over (vsrc, splat_alpha (vsrc), vdest); - - STORE_VECTOR(dest) - - src+=4; - dest+=4; - } - - for (i = width%4; --i >=0;) { - uint32_t s = src[i]; - uint32_t d = dest[i]; - uint32_t ia = Alpha (~s); - - FbByteMulAdd (d, ia, s); - dest[i] = d; - } -} - - -static FASTCALL void -vmxCombineOverReverseU (uint32_t *dest, const uint32_t *src, int width) -{ - int i; - vector unsigned int vdest, vsrc; - vector unsigned char tmp1, tmp2, tmp3, tmp4, edges, - dest_mask, src_mask, store_mask; - - COMPUTE_SHIFT_MASKS(dest, src) - - /* printf ("%s\n",__PRETTY_FUNCTION__); */ - for (i = width/4; i > 0; i--) { - - LOAD_VECTORS(dest, src) - - vdest = over (vdest, splat_alpha (vdest) , vsrc); - - STORE_VECTOR(dest) - - src+=4; - dest+=4; - } - - for (i = width%4; --i >=0;) { - uint32_t s = src[i]; - uint32_t d = dest[i]; - uint32_t ia = Alpha (~dest[i]); - - FbByteMulAdd (s, ia, d); - dest[i] = s; - } -} - -static FASTCALL void -vmxCombineInU (uint32_t *dest, const uint32_t *src, int width) -{ - int i; - vector unsigned int vdest, vsrc; - vector unsigned char tmp1, tmp2, tmp3, tmp4, edges, - dest_mask, src_mask, store_mask; - - COMPUTE_SHIFT_MASKS(dest, src) - - /* printf ("%s\n",__PRETTY_FUNCTION__); */ - for (i = width/4; i > 0; i--) { - - LOAD_VECTORS(dest, src) - - vdest = pix_multiply (vsrc, splat_alpha (vdest)); - - STORE_VECTOR(dest) - - src+=4; - dest+=4; - } - - for (i = width%4; --i >=0;) { - - uint32_t s = src[i]; - uint32_t a = Alpha (dest[i]); - FbByteMul (s, a); - dest[i] = s; - } -} - -static FASTCALL void -vmxCombineInReverseU (uint32_t *dest, const uint32_t *src, int width) -{ - int i; - vector unsigned int vdest, vsrc; - vector unsigned char tmp1, tmp2, tmp3, tmp4, edges, - dest_mask, src_mask, store_mask; - - COMPUTE_SHIFT_MASKS(dest, src) - - /* printf ("%s\n",__PRETTY_FUNCTION__); */ - for (i = width/4; i > 0; i--) { - - LOAD_VECTORS(dest, src) - - vdest = pix_multiply (vdest, splat_alpha (vsrc)); - - STORE_VECTOR(dest) - - src+=4; - dest+=4; - } - - for (i = width%4; --i >=0;) { - uint32_t d = dest[i]; - uint32_t a = Alpha (src[i]); - FbByteMul (d, a); - dest[i] = d; - } -} - -static FASTCALL void -vmxCombineOutU (uint32_t *dest, const uint32_t *src, int width) -{ - int i; - vector unsigned int vdest, vsrc; - vector unsigned char tmp1, tmp2, tmp3, tmp4, edges, - dest_mask, src_mask, store_mask; - - COMPUTE_SHIFT_MASKS(dest, src) - - /* printf ("%s\n",__PRETTY_FUNCTION__); */ - for (i = width/4; i > 0; i--) { - - LOAD_VECTORS(dest, src) - - vdest = pix_multiply (vsrc, splat_alpha (negate (vdest))); - - STORE_VECTOR(dest) - - src+=4; - dest+=4; - } - - for (i = width%4; --i >=0;) { - uint32_t s = src[i]; - uint32_t a = Alpha (~dest[i]); - FbByteMul (s, a); - dest[i] = s; - } -} - -static FASTCALL void -vmxCombineOutReverseU (uint32_t *dest, const uint32_t *src, int width) -{ - int i; - vector unsigned int vdest, vsrc; - vector unsigned char tmp1, tmp2, tmp3, tmp4, edges, - dest_mask, src_mask, store_mask; - - COMPUTE_SHIFT_MASKS(dest, src) - - /* printf ("%s\n",__PRETTY_FUNCTION__); */ - for (i = width/4; i > 0; i--) { - - LOAD_VECTORS(dest, src) - - vdest = pix_multiply (vdest, splat_alpha (negate (vsrc))); - - STORE_VECTOR(dest) - - src+=4; - dest+=4; - } - - for (i = width%4; --i >=0;) { - uint32_t d = dest[i]; - uint32_t a = Alpha (~src[i]); - FbByteMul (d, a); - dest[i] = d; - } -} - -static FASTCALL void -vmxCombineAtopU (uint32_t *dest, const uint32_t *src, int width) -{ - int i; - vector unsigned int vdest, vsrc; - vector unsigned char tmp1, tmp2, tmp3, tmp4, edges, - dest_mask, src_mask, store_mask; - - COMPUTE_SHIFT_MASKS(dest, src) - - /* printf ("%s\n",__PRETTY_FUNCTION__); */ - for (i = width/4; i > 0; i--) { - - LOAD_VECTORS(dest, src) - - vdest = pix_add_mul (vsrc, splat_alpha (vdest), - vdest, splat_alpha (negate (vsrc))); - - STORE_VECTOR(dest) - - src+=4; - dest+=4; - } - - for (i = width%4; --i >=0;) { - uint32_t s = src[i]; - uint32_t d = dest[i]; - uint32_t dest_a = Alpha (d); - uint32_t src_ia = Alpha (~s); - - FbByteAddMul (s, dest_a, d, src_ia); - dest[i] = s; - } -} - -static FASTCALL void -vmxCombineAtopReverseU (uint32_t *dest, const uint32_t *src, int width) -{ - int i; - vector unsigned int vdest, vsrc; - vector unsigned char tmp1, tmp2, tmp3, tmp4, edges, - dest_mask, src_mask, store_mask; - - COMPUTE_SHIFT_MASKS(dest, src) - - /* printf ("%s\n",__PRETTY_FUNCTION__); */ - for (i = width/4; i > 0; i--) { - - LOAD_VECTORS(dest, src) - - vdest = pix_add_mul (vdest, splat_alpha (vsrc), - vsrc, splat_alpha (negate (vdest))); - - STORE_VECTOR(dest) - - src+=4; - dest+=4; - } - - for (i = width%4; --i >=0;) { - uint32_t s = src[i]; - uint32_t d = dest[i]; - uint32_t src_a = Alpha (s); - uint32_t dest_ia = Alpha (~d); - - FbByteAddMul (s, dest_ia, d, src_a); - dest[i] = s; - } -} - -static FASTCALL void -vmxCombineXorU (uint32_t *dest, const uint32_t *src, int width) -{ - int i; - vector unsigned int vdest, vsrc; - vector unsigned char tmp1, tmp2, tmp3, tmp4, edges, - dest_mask, src_mask, store_mask; - - COMPUTE_SHIFT_MASKS(dest, src) - - /* printf ("%s\n",__PRETTY_FUNCTION__); */ - for (i = width/4; i > 0; i--) { - - LOAD_VECTORS (dest, src) - - vdest = pix_add_mul (vsrc, splat_alpha (negate (vdest)), - vdest, splat_alpha (negate (vsrc))); - - STORE_VECTOR(dest) - - src+=4; - dest+=4; - } - - for (i = width%4; --i >=0;) { - uint32_t s = src[i]; - uint32_t d = dest[i]; - uint32_t src_ia = Alpha (~s); - uint32_t dest_ia = Alpha (~d); - - FbByteAddMul (s, dest_ia, d, src_ia); - dest[i] = s; - } -} - -static FASTCALL void -vmxCombineAddU (uint32_t *dest, const uint32_t *src, int width) -{ - int i; - vector unsigned int vdest, vsrc; - vector unsigned char tmp1, tmp2, tmp3, tmp4, edges, - dest_mask, src_mask, store_mask; - - COMPUTE_SHIFT_MASKS(dest, src) - /* printf ("%s\n",__PRETTY_FUNCTION__); */ - for (i = width/4; i > 0; i--) { - - LOAD_VECTORS(dest, src) - - vdest = pix_add (vsrc, vdest); - - STORE_VECTOR(dest) - - src+=4; - dest+=4; - } - - for (i = width%4; --i >=0;) { - uint32_t s = src[i]; - uint32_t d = dest[i]; - FbByteAdd (d, s); - dest[i] = d; - } -} - -static FASTCALL void -vmxCombineSrcC (uint32_t *dest, uint32_t *src, uint32_t *mask, int width) -{ - int i; - vector unsigned int vdest, vsrc, vmask; - vector unsigned char tmp1, tmp2, tmp3, tmp4, edges, - dest_mask, mask_mask, src_mask, store_mask; - - COMPUTE_SHIFT_MASKC(dest, src, mask); - /* printf ("%s\n",__PRETTY_FUNCTION__); */ - for (i = width/4; i > 0; i--) { - - LOAD_VECTORSC(dest, src, mask) - - vdest = pix_multiply (vsrc, vmask); - - STORE_VECTOR(dest) - - mask+=4; - src+=4; - dest+=4; - } - - for (i = width%4; --i >=0;) { - uint32_t a = mask[i]; - uint32_t s = src[i]; - FbByteMulC (s, a); - dest[i] = s; - } -} - -static FASTCALL void -vmxCombineOverC (uint32_t *dest, uint32_t *src, uint32_t *mask, int width) -{ - int i; - vector unsigned int vdest, vsrc, vmask; - vector unsigned char tmp1, tmp2, tmp3, tmp4, edges, - dest_mask, mask_mask, src_mask, store_mask; - - COMPUTE_SHIFT_MASKC(dest, src, mask); - /* printf ("%s\n",__PRETTY_FUNCTION__); */ - for (i = width/4; i > 0; i--) { - - LOAD_VECTORSC(dest, src, mask) - - vdest = in_over (vsrc, splat_alpha (vsrc), vmask, vdest); - - STORE_VECTOR(dest) - - mask+=4; - src+=4; - dest+=4; - } - - for (i = width%4; --i >=0;) { - uint32_t a = mask[i]; - uint32_t s = src[i]; - uint32_t d = dest[i]; - FbByteMulC (s, a); - FbByteMulAddC (d, ~a, s); - dest[i] = d; - } -} - -static FASTCALL void -vmxCombineOverReverseC (uint32_t *dest, uint32_t *src, uint32_t *mask, int width) -{ - int i; - vector unsigned int vdest, vsrc, vmask; - vector unsigned char tmp1, tmp2, tmp3, tmp4, edges, - dest_mask, mask_mask, src_mask, store_mask; - - COMPUTE_SHIFT_MASKC(dest, src, mask); - /* printf("%s\n",__PRETTY_FUNCTION__); */ - for (i = width/4; i > 0; i--) { - - LOAD_VECTORSC (dest, src, mask) - - vdest = over (vdest, splat_alpha (vdest), pix_multiply (vsrc, vmask)); - - STORE_VECTOR(dest) - - mask+=4; - src+=4; - dest+=4; - } - - for (i = width%4; --i >=0;) { - uint32_t a = mask[i]; - uint32_t s = src[i]; - uint32_t d = dest[i]; - uint32_t da = Alpha (d); - FbByteMulC (s, a); - FbByteMulAddC (s, ~da, d); - dest[i] = s; - } -} - -static FASTCALL void -vmxCombineInC (uint32_t *dest, uint32_t *src, uint32_t *mask, int width) -{ - int i; - vector unsigned int vdest, vsrc, vmask; - vector unsigned char tmp1, tmp2, tmp3, tmp4, edges, - dest_mask, mask_mask, src_mask, store_mask; - - COMPUTE_SHIFT_MASKC(dest, src, mask) - - /* printf ("%s\n",__PRETTY_FUNCTION__); */ - for (i = width/4; i > 0; i--) { - - LOAD_VECTORSC(dest, src, mask) - - vdest = pix_multiply (pix_multiply (vsrc, vmask), splat_alpha (vdest)); - - STORE_VECTOR(dest) - - src+=4; - dest+=4; - mask+=4; - } - - for (i = width%4; --i >=0;) { - uint32_t a = mask[i]; - uint32_t s = src[i]; - uint32_t da = Alpha (dest[i]); - FbByteMul (s, a); - FbByteMul (s, da); - dest[i] = s; - } -} - -static FASTCALL void -vmxCombineInReverseC (uint32_t *dest, uint32_t *src, uint32_t *mask, int width) -{ - int i; - vector unsigned int vdest, vsrc, vmask; - vector unsigned char tmp1, tmp2, tmp3, tmp4, edges, - dest_mask, mask_mask, src_mask, store_mask; - - COMPUTE_SHIFT_MASKC(dest, src, mask) - - /* printf ("%s\n",__PRETTY_FUNCTION__); */ - for (i = width/4; i > 0; i--) { - - LOAD_VECTORSC(dest, src, mask) - - vdest = pix_multiply (vdest, pix_multiply (vmask, splat_alpha (vsrc))); - - STORE_VECTOR(dest) - - src+=4; - dest+=4; - mask+=4; - } - - for (i = width%4; --i >=0;) { - uint32_t a = mask[i]; - uint32_t d = dest[i]; - uint32_t sa = Alpha (src[i]); - FbByteMul (a, sa); - FbByteMulC (d, a); - dest[i] = d; - } -} - -static FASTCALL void -vmxCombineOutC (uint32_t *dest, uint32_t *src, uint32_t *mask, int width) -{ - int i; - vector unsigned int vdest, vsrc, vmask; - vector unsigned char tmp1, tmp2, tmp3, tmp4, edges, - dest_mask, mask_mask, src_mask, store_mask; - - COMPUTE_SHIFT_MASKC(dest, src, mask) - - /* printf ("%s\n",__PRETTY_FUNCTION__); */ - for (i = width/4; i > 0; i--) { - - LOAD_VECTORSC(dest, src, mask) - - vdest = pix_multiply (pix_multiply (vsrc, vmask), splat_alpha (vdest)); - - STORE_VECTOR(dest) - - src+=4; - dest+=4; - mask+=4; - } - - for (i = width%4; --i >=0;) { - uint32_t a = mask[i]; - uint32_t s = src[i]; - uint32_t d = dest[i]; - uint32_t da = Alpha (~d); - FbByteMulC (s, a); - FbByteMulC (s, da); - dest[i] = s; - } -} - -static FASTCALL void -vmxCombineOutReverseC (uint32_t *dest, uint32_t *src, uint32_t *mask, int width) -{ - int i; - vector unsigned int vdest, vsrc, vmask; - vector unsigned char tmp1, tmp2, tmp3, tmp4, edges, - dest_mask, mask_mask, src_mask, store_mask; - - COMPUTE_SHIFT_MASKC(dest, src, mask) - - /* printf ("%s\n",__PRETTY_FUNCTION__); */ - for (i = width/4; i > 0; i--) { - - LOAD_VECTORSC(dest, src, mask) - - vdest = pix_multiply (vdest, - negate (pix_multiply (vmask, splat_alpha (vsrc)))); - - STORE_VECTOR(dest) - - src+=4; - dest+=4; - mask+=4; - } - - for (i = width%4; --i >=0;) { - uint32_t a = mask[i]; - uint32_t s = src[i]; - uint32_t d = dest[i]; - uint32_t sa = Alpha (s); - FbByteMulC (a, sa); - FbByteMulC (d, ~a); - dest[i] = d; - } -} - -static FASTCALL void -vmxCombineAtopC (uint32_t *dest, uint32_t *src, uint32_t *mask, int width) -{ - int i; - vector unsigned int vdest, vsrc, vmask; - vector unsigned char tmp1, tmp2, tmp3, tmp4, edges, - dest_mask, mask_mask, src_mask, store_mask; - - COMPUTE_SHIFT_MASKC(dest, src, mask) - - /* printf ("%s\n",__PRETTY_FUNCTION__); */ - for (i = width/4; i > 0; i--) { - - LOAD_VECTORSC(dest, src, mask) - - vdest = pix_add_mul (pix_multiply (vsrc, vmask), splat_alpha (vdest), - vdest, - negate (pix_multiply (vmask, - splat_alpha (vmask)))); - - STORE_VECTOR(dest) - - src+=4; - dest+=4; - mask+=4; - } - - for (i = width%4; --i >=0;) { - uint32_t a = mask[i]; - uint32_t s = src[i]; - uint32_t d = dest[i]; - uint32_t sa = Alpha (s); - uint32_t da = Alpha (d); - - FbByteMulC (s, a); - FbByteMul (a, sa); - FbByteAddMulC (d, ~a, s, da); - dest[i] = d; - } -} - -static FASTCALL void -vmxCombineAtopReverseC (uint32_t *dest, uint32_t *src, uint32_t *mask, int width) -{ - int i; - vector unsigned int vdest, vsrc, vmask; - vector unsigned char tmp1, tmp2, tmp3, tmp4, edges, - dest_mask, mask_mask, src_mask, store_mask; - - COMPUTE_SHIFT_MASKC(dest, src, mask) - - /* printf ("%s\n",__PRETTY_FUNCTION__); */ - for (i = width/4; i > 0; i--) { - - LOAD_VECTORSC(dest, src, mask) - - vdest = pix_add_mul (vdest, - pix_multiply (vmask, splat_alpha (vsrc)), - pix_multiply (vsrc, vmask), - negate (splat_alpha (vdest))); - - STORE_VECTOR(dest) - - src+=4; - dest+=4; - mask+=4; - } - - for (i = width%4; --i >=0;) { - uint32_t a = mask[i]; - uint32_t s = src[i]; - uint32_t d = dest[i]; - uint32_t sa = Alpha (s); - uint32_t da = Alpha (d); - - FbByteMulC (s, a); - FbByteMul (a, sa); - FbByteAddMulC (d, a, s, ~da); - dest[i] = d; - } -} - -static FASTCALL void -vmxCombineXorC (uint32_t *dest, uint32_t *src, uint32_t *mask, int width) -{ - int i; - vector unsigned int vdest, vsrc, vmask; - vector unsigned char tmp1, tmp2, tmp3, tmp4, edges, - dest_mask, mask_mask, src_mask, store_mask; - - COMPUTE_SHIFT_MASKC(dest, src, mask) - - /* printf ("%s\n",__PRETTY_FUNCTION__); */ - for (i = width/4; i > 0; i--) { - - LOAD_VECTORSC(dest, src, mask) - - vdest = pix_add_mul (vdest, - negate (pix_multiply (vmask, splat_alpha (vsrc))), - pix_multiply (vsrc, vmask), - negate (splat_alpha (vdest))); - - STORE_VECTOR(dest) - - src+=4; - dest+=4; - mask+=4; - } - - for (i = width%4; --i >=0;) { - uint32_t a = mask[i]; - uint32_t s = src[i]; - uint32_t d = dest[i]; - uint32_t sa = Alpha (s); - uint32_t da = Alpha (d); - - FbByteMulC (s, a); - FbByteMul (a, sa); - FbByteAddMulC (d, ~a, s, ~da); - dest[i] = d; - } -} - -static FASTCALL void -vmxCombineAddC (uint32_t *dest, uint32_t *src, uint32_t *mask, int width) -{ - int i; - vector unsigned int vdest, vsrc, vmask; - vector unsigned char tmp1, tmp2, tmp3, tmp4, edges, - dest_mask, mask_mask, src_mask, store_mask; - - COMPUTE_SHIFT_MASKC(dest, src, mask) - - /* printf ("%s\n",__PRETTY_FUNCTION__); */ - for (i = width/4; i > 0; i--) { - - LOAD_VECTORSC(dest, src, mask) - - vdest = pix_add (pix_multiply (vsrc, vmask), vdest); - - STORE_VECTOR(dest) - - src+=4; - dest+=4; - mask+=4; - } - - for (i = width%4; --i >=0;) { - uint32_t a = mask[i]; - uint32_t s = src[i]; - uint32_t d = dest[i]; - - FbByteMulC (s, a); - FbByteAdd (s, d); - dest[i] = s; - } -} - - -#if 0 -void -fbCompositeSolid_nx8888vmx (pixman_operator_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height) -{ - uint32_t src; - uint32_t *dstLine, *dst; - int dstStride; - - fbComposeGetSolid (pSrc, pDst, src); - - if (src >> 24 == 0) - return; - - fbComposeGetStart (pDst, xDst, yDst, uint32_t, dstStride, dstLine, 1); - - while (height--) - { - dst = dstLine; - dstLine += dstStride; - /* XXX vmxCombineOverU (dst, src, width); */ - } -} - -void -fbCompositeSolid_nx0565vmx (pixman_operator_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height) -{ - uint32_t src; - uint16_t *dstLine, *dst; - uint16_t w; - int dstStride; - - fbComposeGetSolid (pSrc, pDst, src); - - if (src >> 24 == 0) - return; - - fbComposeGetStart (pDst, xDst, yDst, uint16_t, dstStride, dstLine, 1); - - while (height--) - { - dst = dstLine; - dstLine += dstStride; - vmxCombineOverU565(dst, src, width); - } -} - -#endif - -void fbComposeSetupVMX (void) -{ - /* check if we have VMX support and initialize accordingly */ - if (pixman_have_vmx ()) { - pixman_composeFunctions.combineU[PIXMAN_OP_OVER] = vmxCombineOverU; - pixman_composeFunctions.combineU[PIXMAN_OP_OVER_REVERSE] = vmxCombineOverReverseU; - pixman_composeFunctions.combineU[PIXMAN_OP_IN] = vmxCombineInU; - pixman_composeFunctions.combineU[PIXMAN_OP_IN_REVERSE] = vmxCombineInReverseU; - pixman_composeFunctions.combineU[PIXMAN_OP_OUT] = vmxCombineOutU; - pixman_composeFunctions.combineU[PIXMAN_OP_OUT_REVERSE] = vmxCombineOutReverseU; - pixman_composeFunctions.combineU[PIXMAN_OP_ATOP] = vmxCombineAtopU; - pixman_composeFunctions.combineU[PIXMAN_OP_ATOP_REVERSE] = vmxCombineAtopReverseU; - pixman_composeFunctions.combineU[PIXMAN_OP_XOR] = vmxCombineXorU; - pixman_composeFunctions.combineU[PIXMAN_OP_ADD] = vmxCombineAddU; - - pixman_composeFunctions.combineC[PIXMAN_OP_SRC] = vmxCombineSrcC; - pixman_composeFunctions.combineC[PIXMAN_OP_OVER] = vmxCombineOverC; - pixman_composeFunctions.combineC[PIXMAN_OP_OVER_REVERSE] = vmxCombineOverReverseC; - pixman_composeFunctions.combineC[PIXMAN_OP_IN] = vmxCombineInC; - pixman_composeFunctions.combineC[PIXMAN_OP_IN_REVERSE] = vmxCombineInReverseC; - pixman_composeFunctions.combineC[PIXMAN_OP_OUT] = vmxCombineOutC; - pixman_composeFunctions.combineC[PIXMAN_OP_OUT_REVERSE] = vmxCombineOutReverseC; - pixman_composeFunctions.combineC[PIXMAN_OP_ATOP] = vmxCombineAtopC; - pixman_composeFunctions.combineC[PIXMAN_OP_ATOP_REVERSE] = vmxCombineAtopReverseC; - pixman_composeFunctions.combineC[PIXMAN_OP_XOR] = vmxCombineXorC; - pixman_composeFunctions.combineC[PIXMAN_OP_ADD] = vmxCombineAddC; - - pixman_composeFunctions.combineMaskU = vmxCombineMaskU; - } -} diff --git a/uppdev/plugin/pixman/lib/pixman-vmx.h b/uppdev/plugin/pixman/lib/pixman-vmx.h deleted file mode 100644 index 4aa59ebf9..000000000 --- a/uppdev/plugin/pixman/lib/pixman-vmx.h +++ /dev/null @@ -1,308 +0,0 @@ -/* - * Copyright © 2007 Luca Barbato - * - * 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 Luca Barbato not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. Luca Barbato makes no representations about the - * suitability of this software for any purpose. It is provided "as is" - * without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - * - * Author: Luca Barbato (lu_zero@gentoo.org) - * - * Based on work by Owen Taylor, Søren Sandmann and Lars Knoll - */ - -#include "pixman-private.h" - -#ifdef USE_VMX - -pixman_bool_t pixman_have_vmx(void); - -#else -#define pixman_have_vmx() FALSE -#endif - -#ifdef USE_VMX - -#define AVV(x...) {x} - -void fbComposeSetupVMX (void); - -#if 0 -void fbCompositeIn_nx8x8vmx (pixman_operator_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, - INT16 xDst, - INT16 yDst, - CARD16 width, - CARD16 height); - -void fbCompositeSolidMask_nx8888x0565Cvmx (pixman_operator_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, - INT16 xDst, - INT16 yDst, - CARD16 width, - CARD16 height); - -void fbCompositeSrcAdd_8888x8888vmx (pixman_operator_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, - INT16 xDst, - INT16 yDst, - CARD16 width, - CARD16 height); - -void fbCompositeSolidMask_nx8888x8888Cvmx (pixman_operator_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, - INT16 xDst, - INT16 yDst, - CARD16 width, - CARD16 height); - -void fbCompositeSolidMask_nx8x8888vmx (pixman_operator_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, - INT16 xDst, - INT16 yDst, - CARD16 width, - CARD16 height); - -void fbCompositeSolidMaskSrc_nx8x8888vmx (pixman_operator_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, - INT16 xDst, - INT16 yDst, - CARD16 width, - CARD16 height); - -void fbCompositeSrcAdd_8888x8x8vmx (pixman_operator_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, - INT16 xDst, - INT16 yDst, - CARD16 width, - CARD16 height); - -void fbCompositeIn_8x8vmx (pixman_operator_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, - INT16 xDst, - INT16 yDst, - CARD16 width, - CARD16 height); - -void fbCompositeSrcAdd_8000x8000vmx (pixman_operator_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, - INT16 xDst, - INT16 yDst, - CARD16 width, - CARD16 height); - -void fbCompositeSrc_8888RevNPx8888vmx (pixman_operator_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, - INT16 xDst, - INT16 yDst, - CARD16 width, - CARD16 height); - -void fbCompositeSrc_8888x0565vmx (pixman_operator_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, - INT16 xDst, - INT16 yDst, - CARD16 width, - CARD16 height); - -void fbCompositeSrc_8888RevNPx0565vmx (pixman_operator_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, - INT16 xDst, - INT16 yDst, - CARD16 width, - CARD16 height); - -void fbCompositeSolid_nx8888vmx (pixman_operator_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, - INT16 xDst, - INT16 yDst, - CARD16 width, - CARD16 height); - -void fbCompositeSolid_nx0565vmx (pixman_operator_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, - INT16 xDst, - INT16 yDst, - CARD16 width, - CARD16 height); - -void fbCompositeSolidMask_nx8x0565vmx (pixman_operator_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, - INT16 xDst, - INT16 yDst, - CARD16 width, - CARD16 height); - -void fbCompositeSrc_x888x8x8888vmx (pixman_operator_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, - INT16 xDst, - INT16 yDst, - CARD16 width, - CARD16 height); - -void fbCompositeSrc_8888x8x8888vmx (pixman_operator_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, - INT16 xDst, - INT16 yDst, - CARD16 width, - CARD16 height); - -void fbCompositeSrc_8888x8888vmx (pixman_operator_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, - INT16 xDst, - INT16 yDst, - CARD16 width, - CARD16 height); - -pixman_bool_t fbCopyAreavmx (FbPixels *pSrc, - FbPixels *pDst, - int src_x, - int src_y, - int dst_x, - int dst_y, - int width, - int height); - -void fbCompositeCopyAreavmx (pixman_operator_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, - INT16 xDst, - INT16 yDst, - CARD16 width, - CARD16 height); - -pixman_bool_t fbSolidFillvmx (FbPixels *pDraw, - int x, - int y, - int width, - int height, - FbBits xor); -#endif -#endif /* USE_VMX */ diff --git a/uppdev/plugin/pixman/lib/pixman.h b/uppdev/plugin/pixman/lib/pixman.h deleted file mode 100644 index 0019ea1d2..000000000 --- a/uppdev/plugin/pixman/lib/pixman.h +++ /dev/null @@ -1,901 +0,0 @@ -/*********************************************************** - -Copyright 1987, 1998 The Open Group - -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. - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall not be -used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization from The Open Group. - -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -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 Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL 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. - -******************************************************************/ -/* - * Copyright © 1998, 2004 Keith Packard - * Copyright 2007 Red Hat, Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of 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. - */ - -#ifndef PIXMAN_H__ -#define PIXMAN_H__ - -#include - -/* - * Standard integers - */ -#if defined (_SVR4) || defined (SVR4) || defined (__OpenBSD__) || defined (_sgi) || defined (__sun) || defined (sun) || defined (__digital__) -# include -#elif defined (_MSC_VER) -typedef __int8 int8_t; -typedef unsigned __int8 uint8_t; -typedef __int16 int16_t; -typedef unsigned __int16 uint16_t; -typedef __int32 int32_t; -typedef unsigned __int32 uint32_t; -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; -#elif defined (_AIX) -# include -#else -# include -#endif - -/* - * Boolean - */ -typedef int pixman_bool_t; - -/* - * Fixpoint numbers - */ -typedef int64_t pixman_fixed_32_32_t; -typedef pixman_fixed_32_32_t pixman_fixed_48_16_t; -typedef uint32_t pixman_fixed_1_31_t; -typedef uint32_t pixman_fixed_1_16_t; -typedef int32_t pixman_fixed_16_16_t; -typedef pixman_fixed_16_16_t pixman_fixed_t; - -#define pixman_fixed_e ((pixman_fixed_t) 1) -#define pixman_fixed_1 (pixman_int_to_fixed(1)) -#define pixman_fixed_1_minus_e (pixman_fixed_1 - pixman_fixed_e) -#define pixman_fixed_to_int(f) ((int) ((f) >> 16)) -#define pixman_int_to_fixed(i) ((pixman_fixed_t) ((i) << 16)) -#define pixman_fixed_to_double(f) (double) ((f) / (double) pixman_fixed_1) -#define pixman_double_to_fixed(d) ((pixman_fixed_t) ((d) * 65536.0)) -#define pixman_fixed_frac(f) ((f) & pixman_fixed_1_minus_e) -#define pixman_fixed_floor(f) ((f) & ~pixman_fixed_1_minus_e) -#define pixman_fixed_ceil(f) pixman_fixed_floor ((f) + pixman_fixed_1_minus_e) -#define pixman_fixed_fraction(f) ((f) & pixman_fixed_1_minus_e) -#define pixman_fixed_mod_2(f) ((f) & (pixman_fixed1 | pixman_fixed_1_minus_e)) -#define pixman_max_fixed_48_16 ((pixman_fixed_48_16_t) 0x7fffffff) -#define pixman_min_fixed_48_16 (-((pixman_fixed_48_16_t) 1 << 31)) - -/* - * Misc structs - */ -typedef struct pixman_color pixman_color_t; -typedef struct pixman_point_fixed pixman_point_fixed_t; -typedef struct pixman_line_fixed pixman_line_fixed_t; -typedef struct pixman_vector pixman_vector_t; -typedef struct pixman_transform pixman_transform_t; - -struct pixman_color -{ - uint16_t red; - uint16_t green; - uint16_t blue; - uint16_t alpha; -}; - -struct pixman_point_fixed -{ - pixman_fixed_t x; - pixman_fixed_t y; -}; - -struct pixman_line_fixed -{ - pixman_point_fixed_t p1, p2; -}; - -/* - * Fixed point matrices - */ - -struct pixman_vector -{ - pixman_fixed_t vector[3]; -}; - -struct pixman_transform -{ - pixman_fixed_t matrix[3][3]; -}; - -/* forward declaration (sorry) */ -struct pixman_box16; - -void -pixman_transform_init_identity(struct pixman_transform *matrix); - -pixman_bool_t -pixman_transform_point_3d (const struct pixman_transform *transform, - struct pixman_vector *vector); - -pixman_bool_t -pixman_transform_point(const struct pixman_transform *transform, - struct pixman_vector *vector); - -pixman_bool_t -pixman_transform_multiply (struct pixman_transform *dst, - const struct pixman_transform *l, - const struct pixman_transform *r); - -void -pixman_transform_init_scale (struct pixman_transform *t, - pixman_fixed_t sx, - pixman_fixed_t sy); - -pixman_bool_t -pixman_transform_scale(struct pixman_transform *forward, - struct pixman_transform *reverse, - pixman_fixed_t sx, pixman_fixed_t sy); - -void -pixman_transform_init_rotate(struct pixman_transform *t, - pixman_fixed_t cos, - pixman_fixed_t sin); - -pixman_bool_t -pixman_transform_rotate(struct pixman_transform *forward, - struct pixman_transform *reverse, - pixman_fixed_t c, pixman_fixed_t s); - -void -pixman_transform_init_translate(struct pixman_transform *t, - pixman_fixed_t tx, pixman_fixed_t ty); - - -pixman_bool_t -pixman_transform_translate(struct pixman_transform *forward, - struct pixman_transform *reverse, - pixman_fixed_t tx, pixman_fixed_t ty); - -pixman_bool_t -pixman_transform_bounds(const struct pixman_transform *matrix, - struct pixman_box16 *b); - - -pixman_bool_t -pixman_transform_invert (struct pixman_transform *dst, - const struct pixman_transform *src); - -pixman_bool_t -pixman_transform_is_identity(const struct pixman_transform *t); - -pixman_bool_t -pixman_transform_is_scale(const struct pixman_transform *t); - -pixman_bool_t -pixman_transform_is_int_translate(const struct pixman_transform *t); - -pixman_bool_t -pixman_transform_is_inverse (const struct pixman_transform *a, - const struct pixman_transform *b); - - -/* - * Floating point matrices - */ -struct pixman_f_vector { - double v[3]; -}; - -struct pixman_f_transform { - double m[3][3]; -}; - -pixman_bool_t -pixman_transform_from_pixman_f_transform (struct pixman_transform *t, - const struct pixman_f_transform *ft); - -void -pixman_f_transform_from_pixman_transform (struct pixman_f_transform *ft, - const struct pixman_transform *t); - -pixman_bool_t -pixman_transform_from_pixman_f_transform (struct pixman_transform *t, - const struct pixman_f_transform *ft); - -pixman_bool_t -pixman_f_transform_invert (struct pixman_f_transform *dst, - const struct pixman_f_transform *src); - -pixman_bool_t -pixman_f_transform_point (const struct pixman_f_transform *t, - struct pixman_f_vector *v); - -void -pixman_f_transform_point_3d (const struct pixman_f_transform *t, - struct pixman_f_vector *v); - - -void -pixman_f_transform_multiply (struct pixman_f_transform *dst, - const struct pixman_f_transform *l, - const struct pixman_f_transform *r); - -void -pixman_f_transform_init_scale (struct pixman_f_transform *t, double sx, double sy); - -pixman_bool_t -pixman_f_transform_scale (struct pixman_f_transform *forward, - struct pixman_f_transform *reverse, - double sx, double sy); - -void -pixman_f_transform_init_rotate (struct pixman_f_transform *t, double cos, double sin); - -pixman_bool_t -pixman_f_transform_rotate (struct pixman_f_transform *forward, - struct pixman_f_transform *reverse, - double c, double s); - -void -pixman_f_transform_init_translate (struct pixman_f_transform *t, double tx, double ty); - -pixman_bool_t -pixman_f_transform_translate (struct pixman_f_transform *forward, - struct pixman_f_transform *reverse, - double tx, double ty); - -pixman_bool_t -pixman_f_transform_bounds (const struct pixman_f_transform *t, struct pixman_box16 *b); - -void -pixman_f_transform_init_identity (struct pixman_f_transform *t); - -/* Don't blame me, blame XRender */ -typedef enum -{ - PIXMAN_REPEAT_NONE, - PIXMAN_REPEAT_NORMAL, - PIXMAN_REPEAT_PAD, - PIXMAN_REPEAT_REFLECT -} pixman_repeat_t; - -typedef enum -{ - PIXMAN_FILTER_FAST, - PIXMAN_FILTER_GOOD, - PIXMAN_FILTER_BEST, - PIXMAN_FILTER_NEAREST, - PIXMAN_FILTER_BILINEAR, - PIXMAN_FILTER_CONVOLUTION -} pixman_filter_t; - -typedef enum -{ - PIXMAN_OP_CLEAR = 0x00, - PIXMAN_OP_SRC = 0x01, - PIXMAN_OP_DST = 0x02, - PIXMAN_OP_OVER = 0x03, - PIXMAN_OP_OVER_REVERSE = 0x04, - PIXMAN_OP_IN = 0x05, - PIXMAN_OP_IN_REVERSE = 0x06, - PIXMAN_OP_OUT = 0x07, - PIXMAN_OP_OUT_REVERSE = 0x08, - PIXMAN_OP_ATOP = 0x09, - PIXMAN_OP_ATOP_REVERSE = 0x0a, - PIXMAN_OP_XOR = 0x0b, - PIXMAN_OP_ADD = 0x0c, - PIXMAN_OP_SATURATE = 0x0d, - - PIXMAN_OP_DISJOINT_CLEAR = 0x10, - PIXMAN_OP_DISJOINT_SRC = 0x11, - PIXMAN_OP_DISJOINT_DST = 0x12, - PIXMAN_OP_DISJOINT_OVER = 0x13, - PIXMAN_OP_DISJOINT_OVER_REVERSE = 0x14, - PIXMAN_OP_DISJOINT_IN = 0x15, - PIXMAN_OP_DISJOINT_IN_REVERSE = 0x16, - PIXMAN_OP_DISJOINT_OUT = 0x17, - PIXMAN_OP_DISJOINT_OUT_REVERSE = 0x18, - PIXMAN_OP_DISJOINT_ATOP = 0x19, - PIXMAN_OP_DISJOINT_ATOP_REVERSE = 0x1a, - PIXMAN_OP_DISJOINT_XOR = 0x1b, - - PIXMAN_OP_CONJOINT_CLEAR = 0x20, - PIXMAN_OP_CONJOINT_SRC = 0x21, - PIXMAN_OP_CONJOINT_DST = 0x22, - PIXMAN_OP_CONJOINT_OVER = 0x23, - PIXMAN_OP_CONJOINT_OVER_REVERSE = 0x24, - PIXMAN_OP_CONJOINT_IN = 0x25, - PIXMAN_OP_CONJOINT_IN_REVERSE = 0x26, - PIXMAN_OP_CONJOINT_OUT = 0x27, - PIXMAN_OP_CONJOINT_OUT_REVERSE = 0x28, - PIXMAN_OP_CONJOINT_ATOP = 0x29, - PIXMAN_OP_CONJOINT_ATOP_REVERSE = 0x2a, - PIXMAN_OP_CONJOINT_XOR = 0x2b, - - PIXMAN_OP_NONE -} pixman_op_t; - -/* - * Regions - */ -typedef struct pixman_region16_data pixman_region16_data_t; -typedef struct pixman_box16 pixman_box16_t; -typedef struct pixman_rectangle16 pixman_rectangle16_t; -typedef struct pixman_region16 pixman_region16_t; - -struct pixman_region16_data { - long size; - long numRects; -/* pixman_box16_t rects[size]; in memory but not explicitly declared */ -}; - -struct pixman_rectangle16 -{ - int16_t x, y; - uint16_t width, height; -}; - -struct pixman_box16 -{ - int16_t x1, y1, x2, y2; -}; - -struct pixman_region16 -{ - pixman_box16_t extents; - pixman_region16_data_t *data; -}; - -typedef enum -{ - PIXMAN_REGION_OUT, - PIXMAN_REGION_IN, - PIXMAN_REGION_PART -} pixman_region_overlap_t; - -/* This function exists only to make it possible to preserve the X ABI - it should - * go away at first opportunity. - */ -void pixman_region_set_static_pointers (pixman_box16_t *empty_box, - pixman_region16_data_t *empty_data, - pixman_region16_data_t *broken_data); - - -/* creation/destruction */ -void pixman_region_init (pixman_region16_t *region); -void pixman_region_init_rect (pixman_region16_t *region, - int x, - int y, - unsigned int width, - unsigned int height); -pixman_bool_t pixman_region_init_rects (pixman_region16_t *region, - pixman_box16_t *boxes, - int count); -void pixman_region_init_with_extents (pixman_region16_t *region, - pixman_box16_t *extents); -void pixman_region_fini (pixman_region16_t *region); - - -/* manipulation */ -void pixman_region_translate (pixman_region16_t *region, - int x, - int y); -pixman_bool_t pixman_region_copy (pixman_region16_t *dest, - pixman_region16_t *source); -pixman_bool_t pixman_region_intersect (pixman_region16_t *newReg, - pixman_region16_t *reg1, - pixman_region16_t *reg2); -pixman_bool_t pixman_region_union (pixman_region16_t *newReg, - pixman_region16_t *reg1, - pixman_region16_t *reg2); -pixman_bool_t pixman_region_union_rect (pixman_region16_t *dest, - pixman_region16_t *source, - int x, - int y, - unsigned int width, - unsigned int height); -pixman_bool_t pixman_region_subtract (pixman_region16_t *regD, - pixman_region16_t *regM, - pixman_region16_t *regS); -pixman_bool_t pixman_region_inverse (pixman_region16_t *newReg, - pixman_region16_t *reg1, - pixman_box16_t *invRect); -pixman_bool_t pixman_region_contains_point (pixman_region16_t *region, - int x, - int y, - pixman_box16_t *box); -pixman_region_overlap_t pixman_region_contains_rectangle (pixman_region16_t *pixman_region16_t, - pixman_box16_t *prect); -pixman_bool_t pixman_region_not_empty (pixman_region16_t *region); -pixman_box16_t * pixman_region_extents (pixman_region16_t *region); -int pixman_region_n_rects (pixman_region16_t *region); -pixman_box16_t * pixman_region_rectangles (pixman_region16_t *region, - int *n_rects); -pixman_bool_t pixman_region_equal (pixman_region16_t *region1, - pixman_region16_t *region2); -pixman_bool_t pixman_region_selfcheck (pixman_region16_t *region); -void pixman_region_reset (pixman_region16_t *region, - pixman_box16_t *box); - -/* - * 32 bit regions - */ -typedef struct pixman_region32_data pixman_region32_data_t; -typedef struct pixman_box32 pixman_box32_t; -typedef struct pixman_rectangle32 pixman_rectangle32_t; -typedef struct pixman_region32 pixman_region32_t; - -struct pixman_region32_data { - long size; - long numRects; -/* pixman_box32_t rects[size]; in memory but not explicitly declared */ -}; - -struct pixman_rectangle32 -{ - int32_t x, y; - uint32_t width, height; -}; - -struct pixman_box32 -{ - int32_t x1, y1, x2, y2; -}; - -struct pixman_region32 -{ - pixman_box32_t extents; - pixman_region32_data_t *data; -}; - -/* creation/destruction */ -void pixman_region32_init (pixman_region32_t *region); -void pixman_region32_init_rect (pixman_region32_t *region, - int x, - int y, - unsigned int width, - unsigned int height); -pixman_bool_t pixman_region32_init_rects (pixman_region32_t *region, - pixman_box32_t *boxes, - int count); -void pixman_region32_init_with_extents (pixman_region32_t *region, - pixman_box32_t *extents); -void pixman_region32_fini (pixman_region32_t *region); - - -/* manipulation */ -void pixman_region32_translate (pixman_region32_t *region, - int x, - int y); -pixman_bool_t pixman_region32_copy (pixman_region32_t *dest, - pixman_region32_t *source); -pixman_bool_t pixman_region32_intersect (pixman_region32_t *newReg, - pixman_region32_t *reg1, - pixman_region32_t *reg2); -pixman_bool_t pixman_region32_union (pixman_region32_t *newReg, - pixman_region32_t *reg1, - pixman_region32_t *reg2); -pixman_bool_t pixman_region32_union_rect (pixman_region32_t *dest, - pixman_region32_t *source, - int x, - int y, - unsigned int width, - unsigned int height); -pixman_bool_t pixman_region32_subtract (pixman_region32_t *regD, - pixman_region32_t *regM, - pixman_region32_t *regS); -pixman_bool_t pixman_region32_inverse (pixman_region32_t *newReg, - pixman_region32_t *reg1, - pixman_box32_t *invRect); -pixman_bool_t pixman_region32_contains_point (pixman_region32_t *region, - int x, - int y, - pixman_box32_t *box); -pixman_region_overlap_t pixman_region32_contains_rectangle (pixman_region32_t *region, - pixman_box32_t *prect); -pixman_bool_t pixman_region32_not_empty (pixman_region32_t *region); -pixman_box32_t * pixman_region32_extents (pixman_region32_t *region); -int pixman_region32_n_rects (pixman_region32_t *region); -pixman_box32_t * pixman_region32_rectangles (pixman_region32_t *region, - int *n_rects); -pixman_bool_t pixman_region32_equal (pixman_region32_t *region1, - pixman_region32_t *region2); -pixman_bool_t pixman_region32_selfcheck (pixman_region32_t *region); -void pixman_region32_reset (pixman_region32_t *region, - pixman_box32_t *box); - - -/* Copy / Fill / Misc */ -pixman_bool_t pixman_blt (uint32_t *src_bits, - uint32_t *dst_bits, - int src_stride, - int dst_stride, - int src_bpp, - int dst_bpp, - int src_x, - int src_y, - int dst_x, - int dst_y, - int width, - int height); -pixman_bool_t pixman_fill (uint32_t *bits, - int stride, - int bpp, - int x, - int y, - int width, - int height, - uint32_t _xor); - -int pixman_version (void); -const char* pixman_version_string (void); - -/* - * Images - */ -typedef union pixman_image pixman_image_t; -typedef struct pixman_indexed pixman_indexed_t; -typedef struct pixman_gradient_stop pixman_gradient_stop_t; - -typedef uint32_t (* pixman_read_memory_func_t) (const void *src, int size); -typedef void (* pixman_write_memory_func_t) (void *dst, uint32_t value, int size); - -struct pixman_gradient_stop { - pixman_fixed_t x; - pixman_color_t color; -}; - -#define PIXMAN_MAX_INDEXED 256 /* XXX depth must be <= 8 */ - -#if PIXMAN_MAX_INDEXED <= 256 -typedef uint8_t pixman_index_type; -#endif - -struct pixman_indexed -{ - pixman_bool_t color; - uint32_t rgba[PIXMAN_MAX_INDEXED]; - pixman_index_type ent[32768]; -}; - -/* - * While the protocol is generous in format support, the - * sample implementation allows only packed RGB and GBR - * representations for data to simplify software rendering, - */ -#define PIXMAN_FORMAT(bpp,type,a,r,g,b) (((bpp) << 24) | \ - ((type) << 16) | \ - ((a) << 12) | \ - ((r) << 8) | \ - ((g) << 4) | \ - ((b))) - -#define PIXMAN_FORMAT_BPP(f) (((f) >> 24) ) -#define PIXMAN_FORMAT_TYPE(f) (((f) >> 16) & 0xff) -#define PIXMAN_FORMAT_A(f) (((f) >> 12) & 0x0f) -#define PIXMAN_FORMAT_R(f) (((f) >> 8) & 0x0f) -#define PIXMAN_FORMAT_G(f) (((f) >> 4) & 0x0f) -#define PIXMAN_FORMAT_B(f) (((f) ) & 0x0f) -#define PIXMAN_FORMAT_RGB(f) (((f) ) & 0xfff) -#define PIXMAN_FORMAT_VIS(f) (((f) ) & 0xffff) -#define PIXMAN_FORMAT_DEPTH(f) (PIXMAN_FORMAT_A(f) + \ - PIXMAN_FORMAT_R(f) + \ - PIXMAN_FORMAT_G(f) + \ - PIXMAN_FORMAT_B(f)) - -#define PIXMAN_TYPE_OTHER 0 -#define PIXMAN_TYPE_A 1 -#define PIXMAN_TYPE_ARGB 2 -#define PIXMAN_TYPE_ABGR 3 -#define PIXMAN_TYPE_COLOR 4 -#define PIXMAN_TYPE_GRAY 5 -#define PIXMAN_TYPE_YUY2 6 -#define PIXMAN_TYPE_YV12 7 - -#define PIXMAN_FORMAT_COLOR(f) (PIXMAN_FORMAT_TYPE(f) & 2) - -/* 32bpp formats */ -typedef enum { - PIXMAN_a8r8g8b8 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ARGB,8,8,8,8), - PIXMAN_x8r8g8b8 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ARGB,0,8,8,8), - PIXMAN_a8b8g8r8 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ABGR,8,8,8,8), - PIXMAN_x8b8g8r8 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ABGR,0,8,8,8), - PIXMAN_x2b10g10r10 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ABGR,0,10,10,10), - PIXMAN_a2b10g10r10 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ABGR,2,10,10,10), - -/* 24bpp formats */ - PIXMAN_r8g8b8 = PIXMAN_FORMAT(24,PIXMAN_TYPE_ARGB,0,8,8,8), - PIXMAN_b8g8r8 = PIXMAN_FORMAT(24,PIXMAN_TYPE_ABGR,0,8,8,8), - -/* 16bpp formats */ - PIXMAN_r5g6b5 = PIXMAN_FORMAT(16,PIXMAN_TYPE_ARGB,0,5,6,5), - PIXMAN_b5g6r5 = PIXMAN_FORMAT(16,PIXMAN_TYPE_ABGR,0,5,6,5), - - PIXMAN_a1r5g5b5 = PIXMAN_FORMAT(16,PIXMAN_TYPE_ARGB,1,5,5,5), - PIXMAN_x1r5g5b5 = PIXMAN_FORMAT(16,PIXMAN_TYPE_ARGB,0,5,5,5), - PIXMAN_a1b5g5r5 = PIXMAN_FORMAT(16,PIXMAN_TYPE_ABGR,1,5,5,5), - PIXMAN_x1b5g5r5 = PIXMAN_FORMAT(16,PIXMAN_TYPE_ABGR,0,5,5,5), - PIXMAN_a4r4g4b4 = PIXMAN_FORMAT(16,PIXMAN_TYPE_ARGB,4,4,4,4), - PIXMAN_x4r4g4b4 = PIXMAN_FORMAT(16,PIXMAN_TYPE_ARGB,0,4,4,4), - PIXMAN_a4b4g4r4 = PIXMAN_FORMAT(16,PIXMAN_TYPE_ABGR,4,4,4,4), - PIXMAN_x4b4g4r4 = PIXMAN_FORMAT(16,PIXMAN_TYPE_ABGR,0,4,4,4), - -/* 8bpp formats */ - PIXMAN_a8 = PIXMAN_FORMAT(8,PIXMAN_TYPE_A,8,0,0,0), - PIXMAN_r3g3b2 = PIXMAN_FORMAT(8,PIXMAN_TYPE_ARGB,0,3,3,2), - PIXMAN_b2g3r3 = PIXMAN_FORMAT(8,PIXMAN_TYPE_ABGR,0,3,3,2), - PIXMAN_a2r2g2b2 = PIXMAN_FORMAT(8,PIXMAN_TYPE_ARGB,2,2,2,2), - PIXMAN_a2b2g2r2 = PIXMAN_FORMAT(8,PIXMAN_TYPE_ABGR,2,2,2,2), - - PIXMAN_c8 = PIXMAN_FORMAT(8,PIXMAN_TYPE_COLOR,0,0,0,0), - PIXMAN_g8 = PIXMAN_FORMAT(8,PIXMAN_TYPE_GRAY,0,0,0,0), - - PIXMAN_x4a4 = PIXMAN_FORMAT(8,PIXMAN_TYPE_A,4,0,0,0), - - PIXMAN_x4c4 = PIXMAN_FORMAT(8,PIXMAN_TYPE_COLOR,0,0,0,0), - PIXMAN_x4g4 = PIXMAN_FORMAT(8,PIXMAN_TYPE_GRAY,0,0,0,0), - -/* 4bpp formats */ - PIXMAN_a4 = PIXMAN_FORMAT(4,PIXMAN_TYPE_A,4,0,0,0), - PIXMAN_r1g2b1 = PIXMAN_FORMAT(4,PIXMAN_TYPE_ARGB,0,1,2,1), - PIXMAN_b1g2r1 = PIXMAN_FORMAT(4,PIXMAN_TYPE_ABGR,0,1,2,1), - PIXMAN_a1r1g1b1 = PIXMAN_FORMAT(4,PIXMAN_TYPE_ARGB,1,1,1,1), - PIXMAN_a1b1g1r1 = PIXMAN_FORMAT(4,PIXMAN_TYPE_ABGR,1,1,1,1), - - PIXMAN_c4 = PIXMAN_FORMAT(4,PIXMAN_TYPE_COLOR,0,0,0,0), - PIXMAN_g4 = PIXMAN_FORMAT(4,PIXMAN_TYPE_GRAY,0,0,0,0), - -/* 1bpp formats */ - PIXMAN_a1 = PIXMAN_FORMAT(1,PIXMAN_TYPE_A,1,0,0,0), - - PIXMAN_g1 = PIXMAN_FORMAT(1,PIXMAN_TYPE_GRAY,0,0,0,0), - -/* YUV formats */ - PIXMAN_yuy2 = PIXMAN_FORMAT(16,PIXMAN_TYPE_YUY2,0,0,0,0), - PIXMAN_yv12 = PIXMAN_FORMAT(12,PIXMAN_TYPE_YV12,0,0,0,0) -} pixman_format_code_t; - -/* Querying supported format values. */ -pixman_bool_t pixman_format_supported_destination (pixman_format_code_t format); -pixman_bool_t pixman_format_supported_source (pixman_format_code_t format); - -/* Constructors */ -pixman_image_t *pixman_image_create_solid_fill (pixman_color_t *color); -pixman_image_t *pixman_image_create_linear_gradient (pixman_point_fixed_t *p1, - pixman_point_fixed_t *p2, - const pixman_gradient_stop_t *stops, - int n_stops); -pixman_image_t *pixman_image_create_radial_gradient (pixman_point_fixed_t *inner, - pixman_point_fixed_t *outer, - pixman_fixed_t inner_radius, - pixman_fixed_t outer_radius, - const pixman_gradient_stop_t *stops, - int n_stops); -pixman_image_t *pixman_image_create_conical_gradient (pixman_point_fixed_t *center, - pixman_fixed_t angle, - const pixman_gradient_stop_t *stops, - int n_stops); -pixman_image_t *pixman_image_create_bits (pixman_format_code_t format, - int width, - int height, - uint32_t *bits, - int rowstride_bytes); - -/* Destructor */ -pixman_image_t *pixman_image_ref (pixman_image_t *image); -pixman_bool_t pixman_image_unref (pixman_image_t *image); - - -/* Set properties */ -pixman_bool_t pixman_image_set_clip_region (pixman_image_t *image, - pixman_region16_t *region); -pixman_bool_t pixman_image_set_clip_region32 (pixman_image_t *image, - pixman_region32_t *region); -void pixman_image_set_has_client_clip (pixman_image_t *image, - pixman_bool_t clien_clip); -pixman_bool_t pixman_image_set_transform (pixman_image_t *image, - const pixman_transform_t *transform); -void pixman_image_set_repeat (pixman_image_t *image, - pixman_repeat_t repeat); -pixman_bool_t pixman_image_set_filter (pixman_image_t *image, - pixman_filter_t filter, - const pixman_fixed_t *filter_params, - int n_filter_params); -void pixman_image_set_source_clipping (pixman_image_t *image, - pixman_bool_t source_clipping); -void pixman_image_set_alpha_map (pixman_image_t *image, - pixman_image_t *alpha_map, - int16_t x, - int16_t y); -void pixman_image_set_component_alpha (pixman_image_t *image, - pixman_bool_t component_alpha); -void pixman_image_set_accessors (pixman_image_t *image, - pixman_read_memory_func_t read_func, - pixman_write_memory_func_t write_func); -void pixman_image_set_indexed (pixman_image_t *image, - const pixman_indexed_t *indexed); -uint32_t *pixman_image_get_data (pixman_image_t *image); -int pixman_image_get_width (pixman_image_t *image); -int pixman_image_get_height (pixman_image_t *image); -int pixman_image_get_stride (pixman_image_t *image); -int pixman_image_get_depth (pixman_image_t *image); -pixman_bool_t pixman_image_fill_rectangles (pixman_op_t op, - pixman_image_t *image, - pixman_color_t *color, - int n_rects, - const pixman_rectangle16_t *rects); - -/* Composite */ -pixman_bool_t pixman_compute_composite_region (pixman_region16_t *pRegion, - pixman_image_t *pSrc, - pixman_image_t *pMask, - pixman_image_t *pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height); -void pixman_image_composite (pixman_op_t op, - pixman_image_t *src, - pixman_image_t *mask, - pixman_image_t *dest, - int16_t src_x, - int16_t src_y, - int16_t mask_x, - int16_t mask_y, - int16_t dest_x, - int16_t dest_y, - uint16_t width, - uint16_t height); - -/* - * Trapezoids - */ -typedef struct pixman_edge pixman_edge_t; -typedef struct pixman_trapezoid pixman_trapezoid_t; -typedef struct pixman_trap pixman_trap_t; -typedef struct pixman_span_fix pixman_span_fix_t; - -/* - * An edge structure. This represents a single polygon edge - * and can be quickly stepped across small or large gaps in the - * sample grid - */ -struct pixman_edge -{ - pixman_fixed_t x; - pixman_fixed_t e; - pixman_fixed_t stepx; - pixman_fixed_t signdx; - pixman_fixed_t dy; - pixman_fixed_t dx; - - pixman_fixed_t stepx_small; - pixman_fixed_t stepx_big; - pixman_fixed_t dx_small; - pixman_fixed_t dx_big; -}; - -struct pixman_trapezoid -{ - pixman_fixed_t top, bottom; - pixman_line_fixed_t left, right; -}; - - -/* whether 't' is a well defined not obviously empty trapezoid */ -#define pixman_trapezoid_valid(t) \ - ((t)->left.p1.y != (t)->left.p2.y && \ - (t)->right.p1.y != (t)->right.p2.y && \ - (int) ((t)->bottom - (t)->top) > 0) - -struct pixman_span_fix -{ - pixman_fixed_t l, r, y; -}; - -struct pixman_trap -{ - pixman_span_fix_t top, bot; -}; - -pixman_fixed_t pixman_sample_ceil_y (pixman_fixed_t y, - int bpp); -pixman_fixed_t pixman_sample_floor_y (pixman_fixed_t y, - int bpp); -void pixman_edge_step (pixman_edge_t *e, - int n); -void pixman_edge_init (pixman_edge_t *e, - int bpp, - pixman_fixed_t y_start, - pixman_fixed_t x_top, - pixman_fixed_t y_top, - pixman_fixed_t x_bot, - pixman_fixed_t y_bot); -void pixman_line_fixed_edge_init (pixman_edge_t *e, - int bpp, - pixman_fixed_t y, - const pixman_line_fixed_t *line, - int x_off, - int y_off); -void pixman_rasterize_edges (pixman_image_t *image, - pixman_edge_t *l, - pixman_edge_t *r, - pixman_fixed_t t, - pixman_fixed_t b); -void pixman_add_traps (pixman_image_t *image, - int16_t x_off, - int16_t y_off, - int ntrap, - pixman_trap_t *traps); -void pixman_add_trapezoids (pixman_image_t *image, - int16_t x_off, - int y_off, - int ntraps, - const pixman_trapezoid_t *traps); -void pixman_rasterize_trapezoid (pixman_image_t *image, - const pixman_trapezoid_t *trap, - int x_off, - int y_off); - - -#endif /* PIXMAN_H__ */ diff --git a/uppdev/plugin/pixman/pixman.upp b/uppdev/plugin/pixman/pixman.upp deleted file mode 100644 index a9b5755f6..000000000 --- a/uppdev/plugin/pixman/pixman.upp +++ /dev/null @@ -1,10 +0,0 @@ -options - -I"./lib", - -DPACKAGE="Pixman"; - -file - pixmanlib1.c, - pixmanlib2.c, - pixmanlib3.c, - pixmanlib4.c; - diff --git a/uppdev/plugin/pixman/pixmanlib1.c b/uppdev/plugin/pixman/pixmanlib1.c deleted file mode 100644 index 6c81344d5..000000000 --- a/uppdev/plugin/pixman/pixmanlib1.c +++ /dev/null @@ -1,17 +0,0 @@ -#ifdef flagWIN32 - -#include "lib/pixman-access.c" -#include "lib/pixman-combine32.c" -#include "lib/pixman-compose.c" -#include "lib/pixman-compute-region.c" -#include "lib/pixman-edge.c" -#include "lib/pixman-matrix.c" -#include "lib/pixman-pict.c" -#include "lib/pixman-region16.c" -#include "lib/pixman-source.c" -#include "lib/pixman-timer.c" -#include "lib/pixman-trap.c" -#include "lib/pixman-utils.c" -//#include "lib/pixman-mmx.c" - -#endif diff --git a/uppdev/plugin/pixman/pixmanlib2.c b/uppdev/plugin/pixman/pixmanlib2.c deleted file mode 100644 index 86561d1b9..000000000 --- a/uppdev/plugin/pixman/pixmanlib2.c +++ /dev/null @@ -1,9 +0,0 @@ -#ifdef flagWIN32 - -#include "lib/pixman-access-accessors.c" -#include "lib/pixman-compose-accessors.c" -#include "lib/pixman-edge-accessors.c" -#include "lib/pixman-transformed-accessors.c" -#include "lib/pixman-region32.c" - -#endif diff --git a/uppdev/plugin/pixman/pixmanlib3.c b/uppdev/plugin/pixman/pixmanlib3.c deleted file mode 100644 index 51a8a66bb..000000000 --- a/uppdev/plugin/pixman/pixmanlib3.c +++ /dev/null @@ -1,5 +0,0 @@ -#ifdef flagWIN32 - -#include "lib/pixman-combine64.c" - -#endif diff --git a/uppdev/plugin/pixman/pixmanlib4.c b/uppdev/plugin/pixman/pixmanlib4.c deleted file mode 100644 index 02e484c57..000000000 --- a/uppdev/plugin/pixman/pixmanlib4.c +++ /dev/null @@ -1,6 +0,0 @@ -#ifdef flagWIN32 - -#include "lib/pixman-image.c" -#include "lib/pixman-transformed.c" - -#endif diff --git a/uppdev/plugin/png/Copying b/uppdev/plugin/png/Copying deleted file mode 100644 index f135f3633..000000000 --- a/uppdev/plugin/png/Copying +++ /dev/null @@ -1,21 +0,0 @@ -Copyright 1998-2008 The U++ Project. All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted -provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this list of - conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright notice, this list of - conditions and the following disclaimer in the documentation and/or other materials - provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE U++ PROJECT ``AS IS'' AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FREEBSD PROJECT OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED -AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED -OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/uppdev/plugin/png/init b/uppdev/plugin/png/init deleted file mode 100644 index d4472d82a..000000000 --- a/uppdev/plugin/png/init +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef _plugin_png_icpp_init_stub -#define _plugin_png_icpp_init_stub -#include "Core/init" -#include "Draw/init" -#define BLITZ_INDEX__ F585606bdfc1a4410cdf2298bd78a9203 -#include "pngreg.icpp" -#undef BLITZ_INDEX__ -#endif diff --git a/uppdev/plugin/png/lib/CHANGES b/uppdev/plugin/png/lib/CHANGES deleted file mode 100644 index 18ef48e24..000000000 --- a/uppdev/plugin/png/lib/CHANGES +++ /dev/null @@ -1,1995 +0,0 @@ - -CHANGES - changes for libpng - -version 0.2 - added reader into png.h - fixed small problems in stub file - -version 0.3 - added pull reader - split up pngwrite.c to several files - added pnglib.txt - added example.c - cleaned up writer, adding a few new transformations - fixed some bugs in writer - interfaced with zlib 0.5 - added K&R support - added check for 64 KB blocks for 16 bit machines - -version 0.4 - cleaned up code and commented code - simplified time handling into png_time - created png_color_16 and png_color_8 to handle color needs - cleaned up color type defines - fixed various bugs - made various names more consistent - interfaced with zlib 0.71 - cleaned up zTXt reader and writer (using zlib's Reset functions) - split transformations into pngrtran.c and pngwtran.c - -version 0.5 - interfaced with zlib 0.8 - fixed many reading and writing bugs - saved using 3 spaces instead of tabs - -version 0.6 - added png_large_malloc() and png_large_free() - added png_size_t - cleaned up some compiler warnings - added png_start_read_image() - -version 0.7 - cleaned up lots of bugs - finished dithering and other stuff - added test program - changed name from pnglib to libpng - -version 0.71 [June, 1995] - changed pngtest.png for zlib 0.93 - fixed error in libpng.txt and example.c - -version 0.8 - cleaned up some bugs - added png_set_filler() - split up pngstub.c into pngmem.c, pngio.c, and pngerror.c - added #define's to remove unwanted code - moved png_info_init() to png.c - added old_size into png_realloc() - added functions to manually set filtering and compression info - changed compression parameters based on image type - optimized filter selection code - added version info - changed external functions passing floats to doubles (k&r problems?) - put all the configurable stuff in pngconf.h - enabled png_set_shift to work with paletted images on read - added png_read_update_info() - updates info structure with - transformations - -version 0.81 [August, 1995] - incorporated Tim Wegner's medium model code (thanks, Tim) - -version 0.82 [September, 1995] - [unspecified changes] - -version 0.85 [December, 1995] - added more medium model code (almost everything's a far) - added i/o, error, and memory callback functions - fixed some bugs (16 bit, 4 bit interlaced, etc.) - added first run progressive reader (barely tested) - -version 0.86 [January, 1996] - fixed bugs - improved documentation - -version 0.87 [January, 1996] - fixed medium model bugs - fixed other bugs introduced in 0.85 and 0.86 - added some minor documentation - -version 0.88 [January, 1996] - fixed progressive bugs - replaced tabs with spaces - cleaned up documentation - added callbacks for read/write and warning/error functions - -version 0.89 [July, 1996] - added new initialization API to make libpng work better with shared libs - we now have png_create_read_struct(), png_create_write_struct(), - png_create_info_struct(), png_destroy_read_struct(), and - png_destroy_write_struct() instead of the separate calls to - malloc and png_read_init(), png_info_init(), and png_write_init() - changed warning/error callback functions to fix bug - this means you - should use the new initialization API if you were using the old - png_set_message_fn() calls, and that the old API no longer exists - so that people are aware that they need to change their code - changed filter selection API to allow selection of multiple filters - since it didn't work in previous versions of libpng anyways - optimized filter selection code - fixed png_set_background() to allow using an arbitrary RGB color for - paletted images - fixed gamma and background correction for paletted images, so - png_correct_palette is not needed unless you are correcting an - external palette (you will need to #define PNG_CORRECT_PALETTE_SUPPORTED - in pngconf.h) - if nobody uses this, it may disappear in the future. - fixed bug with Borland 64K memory allocation (Alexander Lehmann) - fixed bug in interlace handling (Smarasderagd, I think) - added more error checking for writing and image to reduce invalid files - separated read and write functions so that they won't both be linked - into a binary when only reading or writing functionality is used - new pngtest image also has interlacing and zTXt - updated documentation to reflect new API - -version 0.90 [January, 1997] - made CRC errors/warnings on critical and ancillary chunks configurable - libpng will use the zlib CRC routines by (compile-time) default - changed DOS small/medium model memory support - needs zlib 1.04 (Tim Wegner) - added external C++ wrapper statements to png.h (Gilles Dauphin) - allow PNG file to be read when some or all of file signature has already - been read from the beginning of the stream. ****This affects the size - of info_struct and invalidates all programs that use a shared libpng**** - fixed png_filler() declarations - fixed? background color conversions - fixed order of error function pointers to match documentation - current chunk name is now available in png_struct to reduce the number - of nearly identical error messages (will simplify multi-lingual - support when available) - try to get ready for unknown-chunk callback functions: - - previously read critical chunks are flagged, so the chunk handling - routines can determine if the chunk is in the right place - - all chunk handling routines have the same prototypes, so we will - be able to handle all chunks via a callback mechanism - try to fix Linux "setjmp" buffer size problems - removed png_large_malloc, png_large_free, and png_realloc functions. - -version 0.95 [March, 1997] - fixed bug in pngwutil.c allocating "up_row" twice and "avg_row" never - fixed bug in PNG file signature compares when start != 0 - changed parameter type of png_set_filler(...filler...) from png_byte - to png_uint_32 - added test for MACOS to ensure that both math.h and fp.h are not #included - added macros for libpng to be compiled as a Windows DLL (Andreas Kupries) - added "packswap" transformation, which changes the endianness of - packed-pixel bytes (Kevin Bracey) - added "strip_alpha" transformation, which removes the alpha channel of - input images without using it (not necessarily a good idea) - added "swap_alpha" transformation, which puts the alpha channel in front - of the color bytes instead of after - removed all implicit variable tests which assume NULL == 0 (I think) - changed several variables to "png_size_t" to show 16/32-bit limitations - added new pCAL chunk read/write support - added experimental filter selection weighting (Greg Roelofs) - removed old png_set_rgbx() and png_set_xrgb() functions that have been - obsolete for about 2 years now (use png_set_filler() instead) - added macros to read 16- and 32-bit ints directly from buffer, to be - used only on those systems that support it (namely PowerPC and 680x0) - With some testing, this may become the default for MACOS/PPC systems. - only calculate CRC on data if we are going to use it - added macros for zTXt compression type PNG_zTXt_COMPRESSION_??? - added macros for simple libpng debugging output selectable at compile time - removed PNG_READ_END_MODE in progressive reader (Smarasderagd) - more description of info_struct in libpng.txt and png.h - more instructions in example.c - more chunk types tested in pngtest.c - renamed pngrcb.c to pngset.c, and all png_read_ functions to be - png_set_. We now have corresponding png_get_ - functions in pngget.c to get information in info_ptr. This isolates - the application from the internal organization of png_info_struct - (good for shared library implementations). - -version 0.96 [May, 1997] - fixed serious bug with < 8bpp images introduced in 0.95 - fixed 256-color transparency bug (Greg Roelofs) - fixed up documentation (Greg Roelofs, Laszlo Nyul) - fixed "error" in pngconf.h for Linux setjmp() behaviour - fixed DOS medium model support (Tim Wegner) - fixed png_check_keyword() for case with error in static string text - added read of CRC after IEND chunk for embedded PNGs (Laszlo Nyul) - added typecasts to quiet compiler errors - added more debugging info - -version 0.97 [January, 1998] - removed PNG_USE_OWN_CRC capability - relocated png_set_crc_action from pngrutil.c to pngrtran.c - fixed typecasts of "new_key", etc. (Andreas Dilger) - added RFC 1152 [sic] date support - fixed bug in gamma handling of 4-bit grayscale - added 2-bit grayscale gamma handling (Glenn R-P) - added more typecasts. 65536L becomes (png_uint_32)65536L, etc. (Glenn R-P) - minor corrections in libpng.txt - added simple sRGB support (Glenn R-P) - easier conditional compiling, e.g. define PNG_READ/WRITE_NOT_FULLY_SUPPORTED; - all configurable options can be selected from command-line instead - of having to edit pngconf.h (Glenn R-P) - fixed memory leak in pngwrite.c (free info_ptr->text) (Glenn R-P) - added more conditions for png_do_background, to avoid changing - black pixels to background when a background is supplied and - no pixels are transparent - repaired PNG_NO_STDIO behaviour - tested NODIV support and made it default behaviour (Greg Roelofs) - added "-m" option and PNGTEST_DEBUG_MEMORY to pngtest (John Bowler) - regularized version numbering scheme and bumped shared-library major - version number to 2 to avoid problems with libpng 0.89 apps (Greg Roelofs) - -version 0.98 [January, 1998] - cleaned up some typos in libpng.txt and in code documentation - fixed memory leaks in pCAL chunk processing (Glenn R-P and John Bowler) - cosmetic change "display_gamma" to "screen_gamma" in pngrtran.c - changed recommendation about file_gamma for PC images to .51 from .45, - in example.c and libpng.txt, added comments to distinguish between - screen_gamma, viewing_gamma, and display_gamma. - changed all references to RFC1152 to read RFC1123 and changed the - PNG_TIME_RFC1152_SUPPORTED macro to PNG_TIME_RFC1123_SUPPORTED - added png_invert_alpha capability (Glenn R-P -- suggestion by Jon Vincent) - changed srgb_intent from png_byte to int to avoid compiler bugs - -version 0.99 [January 30, 1998] - free info_ptr->text instead of end_info_ptr->text in pngread.c (John Bowler) - fixed a longstanding "packswap" bug in pngtrans.c - fixed some inconsistencies in pngconf.h that prevented compiling with - PNG_READ_GAMMA_SUPPORTED and PNG_READ_hIST_SUPPORTED undefined - fixed some typos and made other minor rearrangement of libpng.txt (Andreas) - changed recommendation about file_gamma for PC images to .50 from .51 in - example.c and libpng.txt, and changed file_gamma for sRGB images to .45 - added a number of functions to access information from the png structure - png_get_image_height(), etc. (Glenn R-P, suggestion by Brad Pettit) - added TARGET_MACOS similar to zlib-1.0.8 - define PNG_ALWAYS_EXTERN when __MWERKS__ && WIN32 are defined - added type casting to all png_malloc() function calls -version 0.99a [January 31, 1998] - Added type casts and parentheses to all returns that return a value.(Tim W.) -version 0.99b [February 4, 1998] - Added type cast png_uint_32 on malloc function calls where needed. - Changed type of num_hist from png_uint_32 to int (same as num_palette). - Added checks for rowbytes overflow, in case png_size_t is less than 32 bits. - Renamed makefile.elf to makefile.lnx. -version 0.99c [February 7, 1998] - More type casting. Removed erroneous overflow test in pngmem.c. - Added png_buffered_memcpy() and png_buffered_memset(), apply them to rowbytes. - Added UNIX manual pages libpng.3 (incorporating libpng.txt) and png.5. -version 0.99d [February 11, 1998] - Renamed "far_to_near()" "png_far_to_near()" - Revised libpng.3 - Version 99c "buffered" operations didn't work as intended. Replaced them - with png_memcpy_check() and png_memset_check(). - Added many "if (png_ptr == NULL) return" to quell compiler warnings about - unused png_ptr, mostly in pngget.c and pngset.c. - Check for overlength tRNS chunk present when indexed-color PLTE is read. - Cleaned up spelling errors in libpng.3/libpng.txt - Corrected a problem with png_get_tRNS() which returned undefined trans array -version 0.99e [February 28, 1998] - Corrected png_get_tRNS() again. - Add parentheses for easier reading of pngget.c, fixed "||" should be "&&". - Touched up example.c to make more of it compileable, although the entire - file still can't be compiled (Willem van Schaik) - Fixed a bug in png_do_shift() (Bryan Tsai) - Added a space in png.h prototype for png_write_chunk_start() - Replaced pngtest.png with one created with zlib 1.1.1 - Changed pngtest to report PASS even when file size is different (Jean-loup G.) - Corrected some logic errors in png_do_invert_alpha() (Chris Patterson) -version 0.99f [March 5, 1998] - Corrected a bug in pngpread() introduced in version 99c (Kevin Bracey) - Moved makefiles into a "scripts" directory, and added INSTALL instruction file - Added makefile.os2 and pngos2.def (A. Zabolotny) and makefile.s2x (W. Sebok) - Added pointers to "note on libpng versions" in makefile.lnx and README - Added row callback feature when reading and writing nonprogressive rows - and added a test of this feature in pngtest.c - Added user transform callbacks, with test of the feature in pngtest.c -version 0.99g [March 6, 1998, morning] - Minor changes to pngtest.c to suppress compiler warnings. - Removed "beta" language from documentation. -version 0.99h [March 6, 1998, evening] - Minor changes to previous minor changes to pngtest.c - Changed PNG_READ_NOT_FULLY_SUPPORTED to PNG_READ_TRANSFORMS_NOT_SUPPORTED - and added PNG_PROGRESSIVE_READ_NOT_SUPPORTED macro - Added user transform capability - -version 1.00 [March 7, 1998] - Changed several typedefs in pngrutil.c - Added makefile.wat (Pawel Mrochen), updated makefile.tc3 (Willem van Schaik) - replaced "while(1)" with "for(;;)" - added PNGARG() to prototypes in pngtest.c and removed some prototypes - updated some of the makefiles (Tom Lane) - changed some typedefs (s_start, etc.) in pngrutil.c - fixed dimensions of "short_months" array in pngwrite.c - Replaced ansi2knr.c with the one from jpeg-v6 - -version 1.0.0 [March 8, 1998] - Changed name from 1.00 to 1.0.0 (Adam Costello) - Added smakefile.ppc (with SCOPTIONS.ppc) for Amiga PPC (Andreas Kleinert) -version 1.0.0a [March 9, 1998] - Fixed three bugs in pngrtran.c to make gamma+background handling consistent - (Greg Roelofs) - Changed format of the PNG_LIBPNG_VER integer to xyyzz instead of xyz - for major, minor, and bugfix releases. This is 10001. (Adam Costello, - Tom Lane) - Make months range from 1-12 in png_convert_to_rfc1123 -version 1.0.0b [March 13, 1998] - Quieted compiler complaints about two empty "for" loops in pngrutil.c - Minor changes to makefile.s2x - Removed #ifdef/#endif around a png_free() in pngread.c - -version 1.0.1 [March 14, 1998] - Changed makefile.s2x to reduce security risk of using a relative pathname - Fixed some typos in the documentation (Greg). - Fixed a problem with value of "channels" returned by png_read_update_info() -version 1.0.1a [April 21, 1998] - Optimized Paeth calculations by replacing abs() function calls with intrinsics - plus other loop optimizations. Improves avg decoding speed by about 20%. - Commented out i386istic "align" compiler flags in makefile.lnx. - Reduced the default warning level in some makefiles, to make them consistent. - Removed references to IJG and JPEG in the ansi2knr.c copyright statement. - Fixed a bug in png_do_strip_filler with XXRRGGBB => RRGGBB transformation. - Added grayscale and 16-bit capability to png_do_read_filler(). - Fixed a bug in pngset.c, introduced in version 0.99c, that sets rowbytes - too large when writing an image with bit_depth < 8 (Bob Dellaca). - Corrected some bugs in the experimental weighted filtering heuristics. - Moved a misplaced pngrutil code block that truncates tRNS if it has more - than num_palette entries -- test was done before num_palette was defined. - Fixed a png_convert_to_rfc1123() bug that converts day 31 to 0 (Steve Eddins). - Changed compiler flags in makefile.wat for better optimization (Pawel Mrochen). -version 1.0.1b [May 2, 1998] - Relocated png_do_gray_to_rgb() within png_do_read_transformations() (Greg). - Relocated the png_composite macros from pngrtran.c to png.h (Greg). - Added makefile.sco (contributed by Mike Hopkirk). - Fixed two bugs (missing definitions of "istop") introduced in libpng-1.0.1a. - Fixed a bug in pngrtran.c that would set channels=5 under some circumstances. - More work on the Paeth-filtering, achieving imperceptible speedup (A Kleinert). - More work on loop optimization which may help when compiled with C++ compilers. - Added warnings when people try to use transforms they've defined out. - Collapsed 4 "i" and "c" loops into single "i" loops in pngrtran and pngwtran. - Revised paragraph about png_set_expand() in libpng.txt and libpng.3 (Greg) -version 1.0.1c [May 11, 1998] - Fixed a bug in pngrtran.c (introduced in libpng-1.0.1a) where the masks for - filler bytes should have been 0xff instead of 0xf. - Added max_pixel_depth=32 in pngrutil.c when using FILLER with palette images. - Moved PNG_WRITE_WEIGHTED_FILTER_SUPPORTED and PNG_WRITE_FLUSH_SUPPORTED - out of the PNG_WRITE_TRANSFORMS_NOT_SUPPORTED block of pngconf.h - Added "PNG_NO_WRITE_TRANSFORMS" etc., as alternatives for *_NOT_SUPPORTED, - for consistency, in pngconf.h - Added individual "ifndef PNG_NO_[CAPABILITY]" in pngconf.h to make it easier - to remove unwanted capabilities via the compile line - Made some corrections to grammar (which, it's) in documentation (Greg). - Corrected example.c, use of row_pointers in png_write_image(). -version 1.0.1d [May 24, 1998] - Corrected several statements that used side effects illegally in pngrutil.c - and pngtrans.c, that were introduced in version 1.0.1b - Revised png_read_rows() to avoid repeated if-testing for NULL (A Kleinert) - More corrections to example.c, use of row_pointers in png_write_image() - and png_read_rows(). - Added pngdll.mak and pngdef.pas to scripts directory, contributed by - Bob Dellaca, to make a png32bd.dll with Borland C++ 4.5 - Fixed error in example.c with png_set_text: num_text is 3, not 2 (Guido V.) - Changed several loops from count-down to count-up, for consistency. -version 1.0.1e [June 6, 1998] - Revised libpng.txt and libpng.3 description of png_set_read|write_fn(), and - added warnings when people try to set png_read_fn and png_write_fn in - the same structure. - Added a test such that png_do_gamma will be done when num_trans==0 - for truecolor images that have defined a background. This corrects an - error that was introduced in libpng-0.90 that can cause gamma processing - to be skipped. - Added tests in png.h to include "trans" and "trans_values" in structures - when PNG_READ_BACKGROUND_SUPPORTED or PNG_READ_EXPAND_SUPPORTED is defined. - Add png_free(png_ptr->time_buffer) in png_destroy_read_struct() - Moved png_convert_to_rfc_1123() from pngwrite.c to png.c - Added capability for user-provided malloc_fn() and free_fn() functions, - and revised pngtest.c to demonstrate their use, replacing the - PNGTEST_DEBUG_MEM feature. - Added makefile.w32, for Microsoft C++ 4.0 and later (Tim Wegner). - -version 1.0.2 [June 14, 1998] - Fixed two bugs in makefile.bor . -version 1.0.2a [December 30, 1998] - Replaced and extended code that was removed from png_set_filler() in 1.0.1a. - Fixed a bug in png_do_filler() that made it fail to write filler bytes in - the left-most pixel of each row (Kevin Bracey). - Changed "static pngcharp tIME_string" to "static char tIME_string[30]" - in pngtest.c (Duncan Simpson). - Fixed a bug in pngtest.c that caused pngtest to try to write a tIME chunk - even when no tIME chunk was present in the source file. - Fixed a problem in pngrutil.c: gray_to_rgb didn't always work with 16-bit. - Fixed a problem in png_read_push_finish_row(), which would not skip some - passes that it should skip, for images that are less than 3 pixels high. - Interchanged the order of calls to png_do_swap() and png_do_shift() - in pngwtran.c (John Cromer). - Added #ifdef PNG_DEBUG/#endif surrounding use of PNG_DEBUG in png.h . - Changed "bad adaptive filter type" from error to warning in pngrutil.c . - Fixed a documentation error about default filtering with 8-bit indexed-color. - Separated the PNG_NO_STDIO macro into PNG_NO_STDIO and PNG_NO_CONSOLE_IO - (L. Peter Deutsch). - Added png_set_rgb_to_gray() and png_get_rgb_to_gray_status() functions. - Added png_get_copyright() and png_get_header_version() functions. - Revised comments on png_set_progressive_read_fn() in libpng.txt and example.c - Added information about debugging in libpng.txt and libpng.3 . - Changed "ln -sf" to "ln -s -f" in makefile.s2x, makefile.lnx, and makefile.sco. - Removed lines after Dynamic Dependencies" in makefile.aco . - Revised makefile.dec to make a shared library (Jeremie Petit). - Removed trailing blanks from all files. -version 1.0.2a [January 6, 1999] - Removed misplaced #endif and #ifdef PNG_NO_EXTERN near the end of png.h - Added "if" tests to silence complaints about unused png_ptr in png.h and png.c - Changed "check_if_png" function in example.c to return true (nonzero) if PNG. - Changed libpng.txt to demonstrate png_sig_cmp() instead of png_check_sig() - which is obsolete. - -version 1.0.3 [January 14, 1999] - Added makefile.hux, for Hewlett Packard HPUX 10.20 and 11.00 (Jim Rice) - Added a statement of Y2K compliance in png.h, libpng.3, and Y2KINFO. -version 1.0.3a [August 12, 1999] - Added check for PNG_READ_INTERLACE_SUPPORTED in pngread.c; issue a warning - if an attempt is made to read an interlaced image when it's not supported. - Added check if png_ptr->trans is defined before freeing it in pngread.c - Modified the Y2K statement to include versions back to version 0.71 - Fixed a bug in the check for valid IHDR bit_depth/color_types in pngrutil.c - Modified makefile.wat (added -zp8 flag, ".symbolic", changed some comments) - Replaced leading blanks with tab characters in makefile.hux - Changed "dworkin.wustl.edu" to "ccrc.wustl.edu" in various documents. - Changed (float)red and (float)green to (double)red, (double)green - in png_set_rgb_to_gray() to avoid "promotion" problems in AIX. - Fixed a bug in pngconf.h that omitted when PNG_DEBUG==0 (K Bracey). - Reformatted libpng.3 and libpngpf.3 with proper fonts (script by J. vanZandt). - Updated documentation to refer to the PNG-1.2 specification. - Removed ansi2knr.c and left pointers to the latest source for ansi2knr.c - in makefile.knr, INSTALL, and README (L. Peter Deutsch) - Fixed bugs in calculation of the length of rowbytes when adding alpha - channels to 16-bit images, in pngrtran.c (Chris Nokleberg) - Added function png_set_user_transform_info() to store user_transform_ptr, - user_depth, and user_channels into the png_struct, and a function - png_get_user_transform_ptr() to retrieve the pointer (Chris Nokleberg) - Added function png_set_empty_plte_permitted() to make libpng useable - in MNG applications. - Corrected the typedef for png_free_ptr in png.h (Jesse Jones). - Correct gamma with srgb is 45455 instead of 45000 in pngrutil.c, to be - consistent with PNG-1.2, and allow variance of 500 before complaining. - Added assembler code contributed by Intel in file pngvcrd.c and modified - makefile.w32 to use it (Nirav Chhatrapati, INTEL Corporation, Gilles Vollant) - Changed "ln -s -f" to "ln -f -s" in the makefiles to make Solaris happy. - Added some aliases for png_set_expand() in pngrtran.c, namely - png_set_expand_PLTE(), png_set_expand_depth(), and png_set_expand_tRNS() - (Greg Roelofs, in "PNG: The Definitive Guide"). - Added makefile.beo for BEOS on X86, contributed by Sander Stok. -version 1.0.3b [August 26, 1999] - Replaced 2147483647L several places with PNG_MAX_UINT macro, defined in png.h - Changed leading blanks to tabs in all makefiles. - Define PNG_USE_PNGVCRD in makefile.w32, to get MMX assembler code. - Made alternate versions of png_set_expand() in pngrtran.c, namely - png_set_gray_1_2_4_to_8, png_set_palette_to_rgb, and png_set_tRNS_to_alpha - (Greg Roelofs, in "PNG: The Definitive Guide"). Deleted the 1.0.3a aliases. - Relocated start of 'extern "C"' block in png.h so it doesn't include pngconf.h - Revised calculation of num_blocks in pngmem.c to avoid a potentially - negative shift distance, whose results are undefined in the C language. - Added a check in pngset.c to prevent writing multiple tIME chunks. - Added a check in pngwrite.c to detect invalid small window_bits sizes. -version 1.0.3d [September 4, 1999] - Fixed type casting of igamma in pngrutil.c - Added new png_expand functions to scripts/pngdef.pas and pngos2.def - Added a demo read_user_transform_fn that examines the row filters in pngtest.c - -version 1.0.4 [September 24, 1999] - Define PNG_ALWAYS_EXTERN in pngconf.h if __STDC__ is defined - Delete #define PNG_INTERNAL and include "png.h" from pngasmrd.h - Made several minor corrections to pngtest.c - Renamed the makefiles with longer but more user friendly extensions. - Copied the PNG copyright and license to a separate LICENSE file. - Revised documentation, png.h, and example.c to remove reference to - "viewing_gamma" which no longer appears in the PNG specification. - Revised pngvcrd.c to use MMX code for interlacing only on the final pass. - Updated pngvcrd.c to use the faster C filter algorithms from libpng-1.0.1a - Split makefile.win32vc into two versions, makefile.vcawin32 (uses MMX - assembler code) and makefile.vcwin32 (doesn't). - Added a CPU timing report to pngtest.c (enabled by defining PNGTEST_TIMING) - Added a copy of pngnow.png to the distribution. -version 1.0.4a [September 25, 1999] - Increase max_pixel_depth in pngrutil.c if a user transform needs it. - Changed several division operations to right-shifts in pngvcrd.c -version 1.0.4b [September 30, 1999] - Added parentheses in line 3732 of pngvcrd.c - Added a comment in makefile.linux warning about buggy -O3 in pgcc 2.95.1 -version 1.0.4c [October 1, 1999] - Added a "png_check_version" function in png.c and pngtest.c that will generate - a helpful compiler error if an old png.h is found in the search path. - Changed type of png_user_transform_depth|channels from int to png_byte. -version 1.0.4d [October 6, 1999] - Changed 0.45 to 0.45455 in png_set_sRGB() - Removed unused PLTE entries from pngnow.png - Re-enabled some parts of pngvcrd.c (png_combine_row) that work properly. -version 1.0.4e [October 10, 1999] - Fixed sign error in pngvcrd.c (Greg Roelofs) - Replaced some instances of memcpy with simple assignments in pngvcrd (GR-P) -version 1.0.4f [October 15, 1999] - Surrounded example.c code with #if 0 .. #endif to prevent people from - inadvertently trying to compile it. - Changed png_get_header_version() from a function to a macro in png.h - Added type casting mostly in pngrtran.c and pngwtran.c - Removed some pointless "ptr = NULL" in pngmem.c - Added a "contrib" directory containing the source code from Greg's book. - -version 1.0.5 [October 15, 1999] - Minor editing of the INSTALL and README files. -version 1.0.5a [October 23, 1999] - Added contrib/pngsuite and contrib/pngminus (Willem van Schaik) - Fixed a typo in the png_set_sRGB() function call in example.c (Jan Nijtmans) - Further optimization and bugfix of pngvcrd.c - Revised pngset.c so that it does not allocate or free memory in the user's - text_ptr structure. Instead, it makes its own copy. - Created separate write_end_info_struct in pngtest.c for a more severe test. - Added code in pngwrite.c to free info_ptr->text[i].key to stop a memory leak. -version 1.0.5b [November 23, 1999] - Moved PNG_FLAG_HAVE_CHUNK_HEADER, PNG_FLAG_BACKGROUND_IS_GRAY and - PNG_FLAG_WROTE_tIME from flags to mode. - Added png_write_info_before_PLTE() function. - Fixed some typecasting in contrib/gregbook/*.c - Updated scripts/makevms.com and added makevms.com to contrib/gregbook - and contrib/pngminus (Martin Zinser) -version 1.0.5c [November 26, 1999] - Moved png_get_header_version from png.h to png.c, to accommodate ansi2knr. - Removed all global arrays (according to PNG_NO_GLOBAL_ARRAYS macro), to - accommodate making DLL's: Moved usr_png_ver from global variable to function - png_get_header_ver() in png.c. Moved png_sig to png_sig_bytes in png.c and - eliminated use of png_sig in pngwutil.c. Moved the various png_CHNK arrays - into pngtypes.h. Eliminated use of global png_pass arrays. Declared the - png_CHNK and png_pass arrays to be "const". Made the global arrays - available to applications (although none are used in libpng itself) when - PNG_NO_GLOBAL_ARRAYS is not defined or when PNG_GLOBAL_ARRAYS is defined. - Removed some extraneous "-I" from contrib/pngminus/makefile.std - Changed the PNG_sRGB_INTENT macros in png.h to be consistent with PNG-1.2. - Change PNG_SRGB_INTENT to PNG_sRGB_INTENT in libpng.txt and libpng.3 -version 1.0.5d [November 29, 1999] - Add type cast (png_const_charp) two places in png.c - Eliminated pngtypes.h; use macros instead to declare PNG_CHNK arrays. - Renamed "PNG_GLOBAL_ARRAYS" to "PNG_USE_GLOBAL_ARRAYS" and made available - to applications a macro "PNG_USE_LOCAL_ARRAYS". - #ifdef out all the new declarations when PNG_USE_GLOBAL_ARRAYS is defined. - Added PNG_EXPORT_VAR macro to accommodate making DLL's. -version 1.0.5e [November 30, 1999] - Added iCCP, iTXt, and sPLT support; added "lang" member to the png_text - structure; refactored the inflate/deflate support to make adding new chunks - with trailing compressed parts easier in the future, and added new functions - png_free_iCCP, png_free_pCAL, png_free_sPLT, png_free_text, png_get_iCCP, - png_get_spalettes, png_set_iCCP, png_set_spalettes (Eric S. Raymond). - NOTE: Applications that write text chunks MUST define png_text->lang - before calling png_set_text(). It must be set to NULL if you want to - write tEXt or zTXt chunks. If you want your application to be able to - run with older versions of libpng, use - - #ifdef PNG_iTXt_SUPPORTED - png_text[i].lang = NULL; - #endif - - Changed png_get_oFFs() and png_set_oFFs() to use signed rather than unsigned - offsets (Eric S. Raymond). - Combined PNG_READ_cHNK_SUPPORTED and PNG_WRITE_cHNK_SUPPORTED macros into - PNG_cHNK_SUPPORTED and combined the three types of PNG_text_SUPPORTED - macros, leaving the separate macros also available. - Removed comments on #endifs at the end of many short, non-nested #if-blocks. -version 1.0.5f [December 6, 1999] - Changed makefile.solaris to issue a warning about potential problems when - the ucb "ld" is in the path ahead of the ccs "ld". - Removed "- [date]" from the "synopsis" line in libpng.3 and libpngpf.3. - Added sCAL chunk support (Eric S. Raymond). -version 1.0.5g [December 7, 1999] - Fixed "png_free_spallettes" typo in png.h - Added code to handle new chunks in pngpread.c - Moved PNG_CHNK string macro definitions outside of PNG_NO_EXTERN block - Added "translated_key" to png_text structure and png_write_iTXt(). - Added code in pngwrite.c to work around a newly discovered zlib bug. -version 1.0.5h [December 10, 1999] - NOTE: regarding the note for version 1.0.5e, the following must also - be included in your code: - png_text[i].translated_key = NULL; - Unknown chunk handling is now supported. - Option to eliminate all floating point support was added. Some new - fixed-point functions such as png_set_gAMA_fixed() were added. - Expanded tabs and removed trailing blanks in source files. -version 1.0.5i [December 13, 1999] - Added some type casts to silence compiler warnings. - Renamed "png_free_spalette" to "png_free_spalettes" for consistency. - Removed leading blanks from a #define in pngvcrd.c - Added some parameters to the new png_set_keep_unknown_chunks() function. - Added a test for up->location != 0 in the first instance of writing - unknown chunks in pngwrite.c - Changed "num" to "i" in png_free_spalettes() and png_free_unknowns() to - prevent recursion. - Added png_free_hIST() function. - Various patches to fix bugs in the sCAL and integer cHRM processing, - and to add some convenience macros for use with sCAL. -version 1.0.5j [December 21, 1999] - Changed "unit" parameter of png_write_sCAL from png_byte to int, to work - around buggy compilers. - Added new type "png_fixed_point" for integers that hold float*100000 values - Restored backward compatibility of tEXt/zTXt chunk processing: - Restored the first four members of png_text to the same order as v.1.0.5d. - Added members "lang_key" and "itxt_length" to png_text struct. Set - text_length=0 when "text" contains iTXt data. Use the "compression" - member to distinguish among tEXt/zTXt/iTXt types. Added - PNG_ITXT_COMPRESSION_NONE (1) and PNG_ITXT_COMPRESSION_zTXt(2) macros. - The "Note" above, about backward incompatibility of libpng-1.0.5e, no - longer applies. - Fixed png_read|write_iTXt() to read|write parameters in the right order, - and to write the iTXt chunk after IDAT if it appears in the end_ptr. - Added pnggccrd.c, version of pngvcrd.c Intel assembler for gcc (Greg Roelofs) - Reversed the order of trying to write floating-point and fixed-point gAMA. -version 1.0.5k [December 27, 1999] - Added many parentheses, e.g., "if (a && b & c)" becomes "if (a && (b & c))" - Added png_handle_as_unknown() function (Glenn) - Added png_free_chunk_list() function and chunk_list and num_chunk_list members - of png_ptr. - Eliminated erroneous warnings about multiple sPLT chunks and sPLT-after-PLTE. - Fixed a libpng-1.0.5h bug in pngrutil.c that was issuing erroneous warnings - about ignoring incorrect gAMA with sRGB (gAMA was in fact not ignored) - Added png_free_tRNS(); png_set_tRNS() now malloc's its own trans array (ESR). - Define png_get_int_32 when oFFs chunk is supported as well as when pCAL is. - Changed type of proflen from png_int_32 to png_uint_32 in png_get_iCCP(). -version 1.0.5l [January 1, 2000] - Added functions png_set_read_user_chunk_fn() and png_get_user_chunk_ptr() - for setting a callback function to handle unknown chunks and for - retrieving the associated user pointer (Glenn). -version 1.0.5m [January 7, 2000] - Added high-level functions png_read_png(), png_write_png(), png_free_pixels(). -version 1.0.5n [January 9, 2000] - Added png_free_PLTE() function, and modified png_set_PLTE() to malloc its - own memory for info_ptr->palette. This makes it safe for the calling - application to free its copy of the palette any time after it calls - png_set_PLTE(). -version 1.0.5o [January 20, 2000] - Cosmetic changes only (removed some trailing blanks and TABs) -version 1.0.5p [January 31, 2000] - Renamed pngdll.mak to makefile.bd32 - Cosmetic changes in pngtest.c -version 1.0.5q [February 5, 2000] - Relocated the makefile.solaris warning about PATH problems. - Fixed pngvcrd.c bug by pushing/popping registers in mmxsupport (Bruce Oberg) - Revised makefile.gcmmx - Added PNG_SETJMP_SUPPORTED, PNG_SETJMP_NOT_SUPPORTED, and PNG_ABORT() macros -version 1.0.5r [February 7, 2000] - Removed superfluous prototype for png_get_itxt from png.h - Fixed a bug in pngrtran.c that improperly expanded the background color. - Return *num_text=0 from png_get_text() when appropriate, and fix documentation - of png_get_text() in libpng.txt/libpng.3. -version 1.0.5s [February 18, 2000] - Added "png_jmp_env()" macro to pngconf.h, to help people migrate to the - new error handler that's planned for the next libpng release, and changed - example.c, pngtest.c, and contrib programs to use this macro. - Revised some of the DLL-export macros in pngconf.h (Greg Roelofs) - Fixed a bug in png_read_png() that caused it to fail to expand some images - that it should have expanded. - Fixed some mistakes in the unused and undocumented INCH_CONVERSIONS functions - in pngget.c - Changed the allocation of palette, history, and trans arrays back to - the version 1.0.5 method (linking instead of copying) which restores - backward compatibility with version 1.0.5. Added some remarks about - that in example.c. Added "free_me" member to info_ptr and png_ptr - and added png_free_data() function. - Updated makefile.linux and makefile.gccmmx to make directories conditionally. - Made cosmetic changes to pngasmrd.h - Added png_set_rows() and png_get_rows(), for use with png_read|write_png(). - Modified png_read_png() to allocate info_ptr->row_pointers only if it - hasn't already been allocated. -version 1.0.5t [March 4, 2000] - Changed png_jmp_env() migration aiding macro to png_jmpbuf(). - Fixed "interlace" typo (should be "interlaced") in contrib/gregbook/read2-x.c - Fixed bug with use of PNG_BEFORE_IHDR bit in png_ptr->mode, introduced when - PNG_FLAG_HAVE_CHUNK_HEADER was moved into png_ptr->mode in version 1.0.5b - Files in contrib/gregbook were revised to use png_jmpbuf() and to select - a 24-bit visual if one is available, and to allow abbreviated options. - Files in contrib/pngminus were revised to use the png_jmpbuf() macro. - Removed spaces in makefile.linux and makefile.gcmmx, introduced in 1.0.5s -version 1.0.5u [March 5, 2000] - Simplified the code that detects old png.h in png.c and pngtest.c - Renamed png_spalette (_p, _pp) to png_sPLT_t (_tp, _tpp) - Increased precision of rgb_to_gray calculations from 8 to 15 bits and - added png_set_rgb_to_gray_fixed() function. - Added makefile.bc32 (32-bit Borland C++, C mode) -version 1.0.5v [March 11, 2000] - Added some parentheses to the png_jmpbuf macro definition. - Updated references to the zlib home page, which has moved to freesoftware.com. - Corrected bugs in documentation regarding png_read_row() and png_write_row(). - Updated documentation of png_rgb_to_gray calculations in libpng.3/libpng.txt. - Renamed makefile.borland,turboc3 back to makefile.bor,tc3 as in version 1.0.3, - revised borland makefiles; added makefile.ibmvac3 and makefile.gcc (Cosmin) - -version 1.0.6 [March 20, 2000] - Minor revisions of makefile.bor, libpng.txt, and gregbook/rpng2-win.c - Added makefile.sggcc (SGI IRIX with gcc) -version 1.0.6d [April 7, 2000] - Changed sprintf() to strcpy() in png_write_sCAL_s() to work without STDIO - Added data_length parameter to png_decompress_chunk() function - Revised documentation to remove reference to abandoned png_free_chnk functions - Fixed an error in png_rgb_to_gray_fixed() - Revised example.c, usage of png_destroy_write_struct(). - Renamed makefile.ibmvac3 to makefile.ibmc, added libpng.icc IBM project file - Added a check for info_ptr->free_me&PNG_FREE_TEXT when freeing text in png.c - Simplify png_sig_bytes() function to remove use of non-ISO-C strdup(). -version 1.0.6e [April 9, 2000] - Added png_data_freer() function. - In the code that checks for over-length tRNS chunks, added check of - info_ptr->num_trans as well as png_ptr->num_trans (Matthias Benckmann) - Minor revisions of libpng.txt/libpng.3. - Check for existing data and free it if the free_me flag is set, in png_set_*() - and png_handle_*(). - Only define PNG_WEIGHTED_FILTERS_SUPPORTED when PNG_FLOATING_POINT_SUPPORTED - is defined. - Changed several instances of PNG_NO_CONSOLE_ID to PNG_NO_STDIO in pngrutil.c - and mentioned the purposes of the two macros in libpng.txt/libpng.3. -version 1.0.6f [April 14, 2000] - Revised png_set_iCCP() and png_set_rows() to avoid prematurely freeing data. - Add checks in png_set_text() for NULL members of the input text structure. - Revised libpng.txt/libpng.3. - Removed superfluous prototype for png_set_itxt from png.h - Removed "else" from pngread.c, after png_error(), and changed "0" to "length". - Changed several png_errors about malformed ancillary chunks to png_warnings. -version 1.0.6g [April 24, 2000] - Added png_pass-* arrays to pnggccrd.c when PNG_USE_LOCAL_ARRAYS is defined. - Relocated paragraph about png_set_background() in libpng.3/libpng.txt - and other revisions (Matthias Benckmann) - Relocated info_ptr->free_me, png_ptr->free_me, and other info_ptr and - png_ptr members to restore binary compatibility with libpng-1.0.5 - (breaks compatibility with libpng-1.0.6). -version 1.0.6h [April 24, 2000] - Changed shared library so-number pattern from 2.x.y.z to xy.z (this builds - libpng.so.10 & libpng.so.10.6h instead of libpng.so.2 & libpng.so.2.1.0.6h) - This is a temporary change for test purposes. -version 1.0.6i [May 2, 2000] - Rearranged some members at the end of png_info and png_struct, to put - unknown_chunks_num and free_me within the original size of the png_structs - and free_me, png_read_user_fn, and png_free_fn within the original png_info, - because some old applications allocate the structs directly instead of - using png_create_*(). - Added documentation of user memory functions in libpng.txt/libpng.3 - Modified png_read_png so that it will use user_allocated row_pointers - if present, unless free_me directs that it be freed, and added description - of the use of png_set_rows() and png_get_rows() in libpng.txt/libpng.3. - Added PNG_LEGACY_SUPPORTED macro, and #ifdef out all new (since version - 1.00) members of png_struct and png_info, to regain binary compatibility - when you define this macro. Capabilities lost in this event - are user transforms (new in version 1.0.0),the user transform pointer - (new in version 1.0.2), rgb_to_gray (new in 1.0.5), iCCP, sCAL, sPLT, - the high-level interface, and unknown chunks support (all new in 1.0.6). - This was necessary because of old applications that allocate the structs - directly as authors were instructed to do in libpng-0.88 and earlier, - instead of using png_create_*(). - Added modes PNG_CREATED_READ_STRUCT and PNG_CREATED_WRITE_STRUCT which - can be used to detect codes that directly allocate the structs, and - code to check these modes in png_read_init() and png_write_init() and - generate a libpng error if the modes aren't set and PNG_LEGACY_SUPPORTED - was not defined. - Added makefile.intel and updated makefile.watcom (Pawel Mrochen) -version 1.0.6j [May 3, 2000] - Overloaded png_read_init() and png_write_init() with macros that convert - calls to png_read_init_2() or png_write_init_2() that check the version - and structure sizes. -version 1.0.7beta11 [May 7, 2000] - Removed the new PNG_CREATED_READ_STRUCT and PNG_CREATED_WRITE_STRUCT modes - which are no longer used. - Eliminated the three new members of png_text when PNG_LEGACY_SUPPORTED is - defined or when neither PNG_READ_iTXt_SUPPORTED nor PNG_WRITE_iTXT_SUPPORTED - is defined. - Made PNG_NO_READ|WRITE_iTXt the default setting, to avoid memory - overrun when old applications fill the info_ptr->text structure directly. - Added PNGAPI macro, and added it to the definitions of all exported functions. - Relocated version macro definitions ahead of the includes of zlib.h and - pngconf.h in png.h. -version 1.0.7beta12 [May 12, 2000] - Revised pngset.c to avoid a problem with expanding the png_debug macro. - Deleted some extraneous defines from pngconf.h - Made PNG_NO_CONSOLE_IO the default condition when PNG_BUILD_DLL is defined. - Use MSC _RPTn debugging instead of fprintf if _MSC_VER is defined. - Added png_access_version_number() function. - Check for mask&PNG_FREE_CHNK (for TEXT, SCAL, PCAL) in png_free_data(). - Expanded libpng.3/libpng.txt information about png_data_freer(). -version 1.0.7beta14 [May 17, 2000] (beta13 was not published) - Changed pnggccrd.c and pngvcrd.c to handle bad adaptive filter types as - warnings instead of errors, as pngrutil.c does. - Set the PNG_INFO_IDAT valid flag in png_set_rows() so png_write_png() - will actually write IDATs. - Made the default PNG_USE_LOCAL_ARRAYS depend on PNG_DLL instead of WIN32. - Make png_free_data() ignore its final parameter except when freeing data - that can have multiple instances (text, sPLT, unknowns). - Fixed a new bug in png_set_rows(). - Removed info_ptr->valid tests from png_free_data(), as in version 1.0.5. - Added png_set_invalid() function. - Fixed incorrect illustrations of png_destroy_write_struct() in example.c. -version 1.0.7beta15 [May 30, 2000] - Revised the deliberately erroneous Linux setjmp code in pngconf.h to produce - fewer error messages. - Rearranged checks for Z_OK to check the most likely path first in pngpread.c - and pngwutil.c. - Added checks in pngtest.c for png_create_*() returning NULL, and mentioned - in libpng.txt/libpng.3 the need for applications to check this. - Changed names of png_default_*() functions in pngtest to pngtest_*(). - Changed return type of png_get_x|y_offset_*() from png_uint_32 to png_int_32. - Fixed some bugs in the unused PNG_INCH_CONVERSIONS functions in pngget.c - Set each pointer to NULL after freeing it in png_free_data(). - Worked around a problem in pngconf.h; AIX's strings.h defines an "index" - macro that conflicts with libpng's png_color_16.index. (Dimitri Papadapoulos) - Added "msvc" directory with MSVC++ project files (Simon-Pierre Cadieux). -version 1.0.7beta16 [June 4, 2000] - Revised the workaround of AIX string.h "index" bug. - Added a check for overlength PLTE chunk in pngrutil.c. - Added PNG_NO_POINTER_INDEXING macro to use array-indexing instead of pointer - indexing in pngrutil.c and pngwutil.c to accommodate a buggy compiler. - Added a warning in png_decompress_chunk() when it runs out of data, e.g. - when it tries to read an erroneous PhotoShop iCCP chunk. - Added PNG_USE_DLL macro. - Revised the copyright/disclaimer/license notice. - Added contrib/msvctest directory -version 1.0.7rc1 [June 9, 2000] - Corrected the definition of PNG_TRANSFORM_INVERT_ALPHA (0x0400 not 0x0200) - Added contrib/visupng directory (Willem van Schaik) -version 1.0.7beta18 [June 23, 2000] - Revised PNGAPI definition, and pngvcrd.c to work with __GCC__ - and do not redefine PNGAPI if it is passed in via a compiler directive. - Revised visupng/PngFile.c to remove returns from within the Try block. - Removed leading underscores from "_PNG_H" and "_PNG_SAVE_BSD_SOURCE" macros. - Updated contrib/visupng/cexcept.h to version 1.0.0. - Fixed bugs in pngwrite.c and pngwutil.c that prevented writing iCCP chunks. -version 1.0.7rc2 [June 28, 2000] - Updated license to include disclaimers required by UCITA. - Fixed "DJBPP" typo in pnggccrd.c introduced in beta18. - -version 1.0.7 [July 1, 2000] - Revised the definition of "trans_values" in libpng.3/libpng.txt -version 1.0.8beta1 [July 8, 2000] - Added png_free(png_ptr, key) two places in pngpread.c to stop memory leaks. - Changed PNG_NO_STDIO to PNG_NO_CONSOLE_IO, several places in pngrutil.c and - pngwutil.c. - Changed PNG_EXPORT_VAR to use PNG_IMPEXP, in pngconf.h. - Removed unused "#include " from png.c - Added WindowsCE support. - Revised pnggccrd.c to work with gcc-2.95.2 and in the Cygwin environment. -version 1.0.8beta2 [July 10, 2000] - Added project files to the wince directory and made further revisions - of pngtest.c, pngrio.c, and pngwio.c in support of WindowsCE. -version 1.0.8beta3 [July 11, 2000] - Only set the PNG_FLAG_FREE_TRNS or PNG_FREE_TRNS flag in png_handle_tRNS() - for indexed-color input files to avoid potential double-freeing trans array - under some unusual conditions; problem was introduced in version 1.0.6f. - Further revisions to pngtest.c and files in the wince subdirectory. -version 1.0.8beta4 [July 14, 2000] - Added the files pngbar.png and pngbar.jpg to the distribution. - Added makefile.cygwin, and cygwin support in pngconf.h - Added PNG_NO_ZALLOC_ZERO macro (makes png_zalloc skip zeroing memory) -version 1.0.8rc1 [July 16, 2000] - Revised png_debug() macros and statements to eliminate compiler warnings. - -version 1.0.8 [July 24, 2000] - Added png_flush() in pngwrite.c, after png_write_IEND(). - Updated makefile.hpux to build a shared library. -version 1.0.9beta1 [November 10, 2000] - Fixed typo in scripts/makefile.hpux - Updated makevms.com in scripts and contrib/* and contrib/* (Martin Zinser) - Fixed seqence-point bug in contrib/pngminus/png2pnm (Martin Zinser) - Changed "cdrom.com" in documentation to "libpng.org" - Revised pnggccrd.c to get it all working, and updated makefile.gcmmx (Greg). - Changed type of "params" from voidp to png_voidp in png_read|write_png(). - Make sure PNGAPI and PNG_IMPEXP are defined in pngconf.h. - Revised the 3 instances of WRITEFILE in pngtest.c. - Relocated "msvc" and "wince" project subdirectories into "dll" subdirectory. - Updated png.rc in dll/msvc project - Revised makefile.dec to define and use LIBPATH and INCPATH - Increased size of global png_libpng_ver[] array from 12 to 18 chars. - Made global png_libpng_ver[], png_sig[] and png_pass_*[] arrays const. - Removed duplicate png_crc_finish() from png_handle_bKGD() function. - Added a warning when application calls png_read_update_info() multiple times. - Revised makefile.cygwin - Fixed bugs in iCCP support in pngrutil.c and pngwutil.c. - Replaced png_set_empty_plte_permitted() with png_permit_mng_features(). -version 1.0.9beta2 [November 19, 2000] - Renamed the "dll" subdirectory "projects". - Added borland project files to "projects" subdirectory. - Set VS_FF_PRERELEASE and VS_FF_PATCHED flags in msvc/png.rc when appropriate. - Add error message in png_set_compression_buffer_size() when malloc fails. -version 1.0.9beta3 [November 23, 2000] - Revised PNG_LIBPNG_BUILD_TYPE macro in png.h, used in the msvc project. - Removed the png_flush() in pngwrite.c that crashes some applications - that don't set png_output_flush_fn. - Added makefile.macosx and makefile.aix to scripts directory. -version 1.0.9beta4 [December 1, 2000] - Change png_chunk_warning to png_warning in png_check_keyword(). - Increased the first part of msg buffer from 16 to 18 in png_chunk_error(). -version 1.0.9beta5 [December 15, 2000] - Added support for filter method 64 (for PNG datastreams embedded in MNG). -version 1.0.9beta6 [December 18, 2000] - Revised png_set_filter() to accept filter method 64 when appropriate. - Added new PNG_HAVE_PNG_SIGNATURE bit to png_ptr->mode and use it to - help prevent applications from using MNG features in PNG datastreams. - Added png_permit_mng_features() function. - Revised libpng.3/libpng.txt. Changed "filter type" to "filter method". -version 1.0.9rc1 [December 23, 2000] - Revised test for PNG_HAVE_PNG_SIGNATURE in pngrutil.c - Fixed error handling of unknown compression type in png_decompress_chunk(). - In pngconf.h, define __cdecl when _MSC_VER is defined. -version 1.0.9beta7 [December 28, 2000] - Changed PNG_TEXT_COMPRESSION_zTXt to PNG_COMPRESSION_TYPE_BASE several places. - Revised memory management in png_set_hIST and png_handle_hIST in a backward - compatible manner. PLTE and tRNS were revised similarly. - Revised the iCCP chunk reader to ignore trailing garbage. -version 1.0.9beta8 [January 12, 2001] - Moved pngasmrd.h into pngconf.h. - Improved handling of out-of-spec garbage iCCP chunks generated by PhotoShop. -version 1.0.9beta9 [January 15, 2001] - Added png_set_invalid, png_permit_mng_features, and png_mmx_supported to - wince and msvc project module definition files. - Minor revision of makefile.cygwin. - Fixed bug with progressive reading of narrow interlaced images in pngpread.c -version 1.0.9beta10 [January 16, 2001] - Do not typedef png_FILE_p in pngconf.h when PNG_NO_STDIO is defined. - Fixed "png_mmx_supported" typo in project definition files. -version 1.0.9beta11 [January 19, 2001] - Updated makefile.sgi to make shared library. - Removed png_mmx_support() function and disabled PNG_MNG_FEATURES_SUPPORTED - by default, for the benefit of DLL forward compatibility. These will - be re-enabled in version 1.2.0. -version 1.0.9rc2 [January 22, 2001] - Revised cygwin support. - -version 1.0.9 [January 31, 2001] - Added check of cygwin's ALL_STATIC in pngconf.h - Added "-nommx" parameter to contrib/gregbook/rpng2-win and rpng2-x demos. -version 1.0.10beta1 [March 14, 2001] - Revised makefile.dec, makefile.sgi, and makefile.sggcc; added makefile.hpgcc. - Reformatted libpng.3 to eliminate bad line breaks. - Added checks for _mmx_supported in the read_filter_row function of pnggccrd.c - Added prototype for png_mmx_support() near the top of pnggccrd.c - Moved some error checking from png_handle_IHDR to png_set_IHDR. - Added PNG_NO_READ_SUPPORTED and PNG_NO_WRITE_SUPPORTED macros. - Revised png_mmx_support() function in pnggccrd.c - Restored version 1.0.8 PNG_WRITE_EMPTY_PLTE_SUPPORTED behavior in pngwutil.c - Fixed memory leak in contrib/visupng/PngFile.c - Fixed bugs in png_combine_row() in pnggccrd.c and pngvcrd.c (C version) - Added warnings when retrieving or setting gamma=0. - Increased the first part of msg buffer from 16 to 18 in png_chunk_warning(). -version 1.0.10rc1 [March 23, 2001] - Changed all instances of memcpy, strcpy, and strlen to png_memcpy, png_strcpy, - and png_strlen. - Revised png_mmx_supported() function in pnggccrd.c to return proper value. - Fixed bug in progressive reading (pngpread.c) with small images (height < 8). - -version 1.0.10 [March 30, 2001] - Deleted extraneous space (introduced in 1.0.9) from line 42 of makefile.cygwin - Added beos project files (Chris Herborth) -version 1.0.11beta1 [April 3, 2001] - Added type casts on several png_malloc() calls (Dimitri Papadapoulos). - Removed a no-longer needed AIX work-around from pngconf.h - Changed several "//" single-line comments to C-style in pnggccrd.c -version 1.0.11beta2 [April 11, 2001] - Removed PNGAPI from several functions whose prototypes did not have PNGAPI. - Updated scripts/pngos2.def -version 1.0.11beta3 [April 14, 2001] - Added checking the results of many instances of png_malloc() for NULL -version 1.0.11beta4 [April 20, 2001] - Undid the changes from version 1.0.11beta3. Added a check for NULL return - from user's malloc_fn(). - Removed some useless type casts of the NULL pointer. - Added makefile.netbsd - -version 1.0.11 [April 27, 2001] - Revised makefile.netbsd -version 1.0.12beta1 [May 14, 2001] - Test for Windows platform in pngconf.h when including malloc.h (Emmanuel Blot) - Updated makefile.cygwin and handling of Cygwin's ALL_STATIC in pngconf.h - Added some never-to-be-executed code in pnggccrd.c to quiet compiler warnings. - Eliminated the png_error about apps using png_read|write_init(). Instead, - libpng will reallocate the png_struct and info_struct if they are too small. - This retains future binary compatibility for old applications written for - libpng-0.88 and earlier. -version 1.2.0beta1 [May 6, 2001] - Bumped DLLNUM to 2. - Re-enabled PNG_MNG_FEATURES_SUPPORTED and enabled PNG_ASSEMBLER_CODE_SUPPORTED - by default. - Added runtime selection of MMX features. - Added png_set_strip_error_numbers function and related macros. -version 1.2.0beta2 [May 7, 2001] - Finished merging 1.2.0beta1 with version 1.0.11 - Added a check for attempts to read or write PLTE in grayscale PNG datastreams. -version 1.2.0beta3 [May 17, 2001] - Enabled user memory function by default. - Modified png_create_struct so it passes user mem_ptr to user memory allocator. - Increased png_mng_features flag from png_byte to png_uint_32. - Bumped shared-library (so-number) and dll-number to 3. -version 1.2.0beta4 [June 23, 2001] - Check for missing profile length field in iCCP chunk and free chunk_data - in case of truncated iCCP chunk. - Bumped shared-library number to 3 in makefile.sgi and makefile.sggcc - Bumped dll-number from 2 to 3 in makefile.cygwin - Revised contrib/gregbook/rpng*-x.c to avoid a memory leak and to exit cleanly - if user attempts to run it on an 8-bit display. - Updated contrib/gregbook - Use png_malloc instead of png_zalloc to allocate palette in pngset.c - Updated makefile.ibmc - Added some typecasts to eliminate gcc 3.0 warnings. Changed prototypes - of png_write_oFFS width and height from png_uint_32 to png_int_32. - Updated example.c - Revised prototypes for png_debug_malloc and png_debug_free in pngtest.c -version 1.2.0beta5 [August 8, 2001] - Revised contrib/gregbook - Revised makefile.gcmmx - Revised pnggccrd.c to conditionally compile some thread-unsafe code only - when PNG_THREAD_UNSAFE_OK is defined. - Added tests to prevent pngwutil.c from writing a bKGD or tRNS chunk with - value exceeding 2^bit_depth-1 - Revised makefile.sgi and makefile.sggcc - Replaced calls to fprintf(stderr,...) with png_warning() in pnggccrd.c - Removed restriction that do_invert_mono only operate on 1-bit opaque files - -version 1.2.0 [September 1, 2001] - Changed a png_warning() to png_debug() in pnggccrd.c - Fixed contrib/gregbook/rpng-x.c, rpng2-x.c to avoid crash with XFreeGC(). -version 1.2.1beta1 [October 19, 2001] - Revised makefile.std in contrib/pngminus - Include background_1 in png_struct regardless of gamma support. - Revised makefile.netbsd and makefile.macosx, added makefile.darwin. - Revised example.c to provide more details about using row_callback(). -version 1.2.1beta2 [October 25, 2001] - Added type cast to each NULL appearing in a function call, except for - WINCE functions. - Added makefile.so9. -version 1.2.1beta3 [October 27, 2001] - Removed type casts from all NULLs. - Simplified png_create_struct_2(). -version 1.2.1beta4 [November 7, 2001] - Revised png_create_info_struct() and png_creat_struct_2(). - Added error message if png_write_info() was omitted. - Type cast NULLs appearing in function calls when _NO_PROTO or - PNG_TYPECAST_NULL is defined. -version 1.2.1rc1 [November 24, 2001] - Type cast NULLs appearing in function calls except when PNG_NO_TYPECAST_NULL - is defined. - Changed typecast of "size" argument to png_size_t in pngmem.c calls to - the user malloc_fn, to agree with the prototype in png.h - Added a pop/push operation to pnggccrd.c, to preserve Eflag (Maxim Sobolev) - Updated makefile.sgi to recognize LIBPATH and INCPATH. - Updated various makefiles so "make clean" does not remove previous major - version of the shared library. -version 1.2.1rc2 [December 4, 2001] - Always allocate 256-entry internal palette, hist, and trans arrays, to - avoid out-of-bounds memory reference caused by invalid PNG datastreams. - Added a check for prefix_length > data_length in iCCP chunk handler. - -version 1.2.1 [December 7, 2001] - None. -version 1.2.2beta1 [February 22, 2002] - Fixed a bug with reading the length of iCCP profiles (Larry Reeves). - Revised makefile.linux, makefile.gcmmx, and makefile.sgi to generate - libpng.a, libpng12.so (not libpng.so.3), and libpng12/png.h - Revised makefile.darwin to remove "-undefined suppress" option. - Added checks for gamma and chromaticity values over 21474.83, which exceed - the limit for PNG unsigned 32-bit integers when encoded. - Revised calls to png_create_read_struct() and png_create_write_struct() - for simpler debugging. - Revised png_zalloc() so zlib handles errors (uses PNG_FLAG_MALLOC_NULL_MEM_OK) -version 1.2.2beta2 [February 23, 2002] - Check chunk_length and idat_size for invalid (over PNG_MAX_UINT) lengths. - Check for invalid image dimensions in png_get_IHDR. - Added missing "fi;" in the install target of the SGI makefiles. - Added install-static to all makefiles that make shared libraries. - Always do gamma compensation when image is partially transparent. -version 1.2.2beta3 [March 7, 2002] - Compute background.gray and background_1.gray even when color_type is RGB - in case image gets reduced to gray later. - Modified shared-library makefiles to install pkgconfig/libpngNN.pc. - Export (with PNGAPI) png_zalloc, png_zfree, and png_handle_as_unknown - Removed unused png_write_destroy_info prototype from png.h - Eliminated incorrect use of width_mmx from pnggccrd.c in pixel_bytes == 8 case - Added install-shared target to all makefiles that make shared libraries. - Stopped a double free of palette, hist, and trans when not using free_me. - Added makefile.32sunu for Sun Ultra 32 and makefile.64sunu for Sun Ultra 64. -version 1.2.2beta4 [March 8, 2002] - Compute background.gray and background_1.gray even when color_type is RGB - in case image gets reduced to gray later (Jason Summers). - Relocated a misplaced /bin/rm in the "install-shared" makefile targets - Added PNG_1_0_X macro which can be used to build a 1.0.x-compatible library. -version 1.2.2beta5 [March 26, 2002] - Added missing PNGAPI to several function definitions. - Check for invalid bit_depth or color_type in png_get_IHDR(), and - check for missing PLTE or IHDR in png_push_read_chunk() (Matthias Clasen). - Revised iTXt support to accept NULL for lang and lang_key. - Compute gamma for color components of background even when color_type is gray. - Changed "()" to "{}" in scripts/libpng.pc.in. - Revised makefiles to put png.h and pngconf.h only in $prefix/include/libpngNN - Revised makefiles to make symlink to libpng.so.NN in addition to libpngNN.so -version 1.2.2beta6 [March 31, 2002] -version 1.0.13beta1 [March 31, 2002] - Prevent png_zalloc() from trying to memset memory that it failed to acquire. - Add typecasts of PNG_MAX_UINT in pngset_cHRM_fixed() (Matt Holgate). - Ensure that the right function (user or default) is used to free the - png_struct after an error in png_create_read_struct_2(). -version 1.2.2rc1 [April 7, 2002] -version 1.0.13rc1 [April 7, 2002] - Save the ebx register in pnggccrd.c (Sami Farin) - Add "mem_ptr = png_ptr->mem_ptr" in png_destroy_write_struct() (Paul Gardner). - Updated makefiles to put headers in include/libpng and remove old include/*.h. - -version 1.2.2 [April 15, 2002] -version 1.0.13 [April 15, 2002] - Revised description of png_set_filter() in libpng.3/libpng.txt. - Revised makefile.netbsd and added makefile.neNNbsd and makefile.freebsd -version 1.0.13patch01 [April 17, 2002] -version 1.2.2patch01 [April 17, 2002] - Changed ${PNGMAJ}.${PNGVER} bug to ${PNGVER} in makefile.sgi and makefile.sggcc - Fixed VER -> PNGVER typo in makefile.macosx and added install-static to install - Added install: target to makefile.32sunu and makefile.64sunu -version 1.0.13patch03 [April 18, 2002] -version 1.2.2patch03 [April 18, 2002] - Revised 15 makefiles to link libpng.a to libpngNN.a and the include libpng - subdirectory to libpngNN subdirectory without the full pathname. - Moved generation of libpng.pc from "install" to "all" in 15 makefiles. -version 1.2.3rc1 [April 28, 2002] - Added install-man target to 15 makefiles (Dimitri Papadopolous-Orfanos). - Added $(DESTDIR) feature to 24 makefiles (Tim Mooney) - Fixed bug with $prefix, should be $(prefix) in makefile.hpux. - Updated cygwin-specific portion of pngconf.h and revised makefile.cygwin - Added a link from libpngNN.pc to libpng.pc in 15 makefiles. - Added links from include/libpngNN/*.h to include/*.h in 24 makefiles. - Revised makefile.darwin to make relative links without full pathname. - Added setjmp() at the end of png_create_*_struct_2() in case user forgets - to put one in their application. - Restored png_zalloc() and png_zfree() prototypes to version 1.2.1 and - removed them from module definition files. -version 1.2.3rc2 [May 1, 2002] - Fixed bug in reporting number of channels in pngget.c and pngset.c, - that was introduced in version 1.2.2beta5. - Exported png_zalloc(), png_zfree(), png_default_read(), png_default_write(), - png_default_flush(), and png_push_fill_buffer() and included them in - module definition files. - Added "libpng.pc" dependency to the "install-shared" target in 15 makefiles. -version 1.2.3rc3 [May 1, 2002] - Revised prototype for png_default_flush() - Remove old libpng.pc and libpngNN.pc before installing new ones. -version 1.2.3rc4 [May 2, 2002] - Typos in *.def files (png_default_read|write -> png_default_read|write_data) - In makefiles, changed rm libpng.NN.pc to rm libpngNN.pc - Added libpng-config and libpngNN-config and modified makefiles to install them. - Changed $(MANPATH) to $(DESTDIR)$(MANPATH) in makefiles - Added "Win32 DLL VB" configuration to projects/msvc/libpng.dsp -version 1.2.3rc5 [May 11, 2002] - Changed "error" and "message" in prototypes to "error_message" and - "warning_message" to avoid namespace conflict. - Revised 15 makefiles to build libpng-config from libpng-config-*.in - Once more restored png_zalloc and png_zfree to regular nonexported form. - Restored png_default_read|write_data, png_default_flush, png_read_fill_buffer - to nonexported form, but with PNGAPI, and removed them from module def files. -version 1.2.3rc6 [May 14, 2002] - Removed "PNGAPI" from png_zalloc() and png_zfree() in png.c - Changed "Gz" to "Gd" in projects/msvc/libpng.dsp and zlib.dsp. - Removed leftover libpng-config "sed" script from four makefiles. - Revised libpng-config creating script in 16 makefiles. - -version 1.2.3 [May 22, 2002] - Revised libpng-config target in makefile.cygwin. - Removed description of png_set_mem_fn() from documentation. - Revised makefile.freebsd. - Minor cosmetic changes to 15 makefiles, e.g., $(DI) = $(DESTDIR)/$(INCDIR). - Revised projects/msvc/README.txt - Changed -lpng to -lpngNN in LDFLAGS in several makefiles. -version 1.2.4beta1 [May 24, 2002] - Added libpng.pc and libpng-config to "all:" target in 16 makefiles. - Fixed bug in 16 makefiles: $(DESTDIR)/$(LIBPATH) to $(DESTDIR)$(LIBPATH) - Added missing "\" before closing double quote in makefile.gcmmx. - Plugged various memory leaks; added png_malloc_warn() and png_set_text_2() - functions. -version 1.2.4beta2 [June 25, 2002] - Plugged memory leak of png_ptr->current_text (Matt Holgate). - Check for buffer overflow before reading CRC in pngpread.c (Warwick Allison) - Added -soname to the loader flags in makefile.dec, makefile.sgi, and - makefile.sggcc. - Added "test-installed" target to makefile.linux, makefile.gcmmx, - makefile.sgi, and makefile.sggcc. -version 1.2.4beta3 [June 28, 2002] - Plugged memory leak of row_buf in pngtest.c when there is a png_error(). - Detect buffer overflow in pngpread.c when IDAT is corrupted with extra data. - Added "test-installed" target to makefile.32sunu, makefile.64sunu, - makefile.beos, makefile.darwin, makefile.dec, makefile.macosx, - makefile.solaris, makefile.hpux, makefile.hpgcc, and makefile.so9. -version 1.2.4rc1 and 1.0.14rc1 [July 2, 2002] - Added "test-installed" target to makefile.cygwin and makefile.sco. - Revised pnggccrd.c to be able to back out version 1.0.x via PNG_1_0_X macro. - -version 1.2.4 and 1.0.14 [July 8, 2002] - Changed png_warning() to png_error() when width is too large to process. -version 1.2.4patch01 [July 20, 2002] - Revised makefile.cygwin to use DLL number 12 instead of 13. -version 1.2.5beta1 [August 6, 2002] - Added code to contrib/gregbook/readpng2.c to ignore unused chunks. - Replaced toucan.png in contrib/gregbook (it has been corrupt since 1.0.11) - Removed some stray *.o files from contrib/gregbook. - Changed png_error() to png_warning() about "Too much data" in pngpread.c - and about "Extra compressed data" in pngrutil.c. - Prevent png_ptr->pass from exceeding 7 in png_push_finish_row(). - Updated makefile.hpgcc - Updated png.c and pnggccrd.c handling of return from png_mmx_support() -version 1.2.5beta2 [August 15, 2002] - Only issue png_warning() about "Too much data" in pngpread.c when avail_in - is nonzero. - Updated makefiles to install a separate libpng.so.3 with its own rpath. -version 1.2.5rc1 and 1.0.15rc1 [August 24, 2002] - Revised makefiles to not remove previous minor versions of shared libraries. -version 1.2.5rc2 and 1.0.15rc2 [September 16, 2002] - Revised 13 makefiles to remove "-lz" and "-L$(ZLIBLIB)", etc., from shared - library loader directive. - Added missing "$OBJSDLL" line to makefile.gcmmx. - Added missing "; fi" to makefile.32sunu. -version 1.2.5rc3 and 1.0.15rc3 [September 18, 2002] - Revised libpng-config script. - -version 1.2.5 and 1.0.15 [October 3, 2002] - Revised makefile.macosx, makefile.darwin, makefile.hpgcc, and makefile.hpux, - and makefile.aix. - Relocated two misplaced PNGAPI lines in pngtest.c -version 1.2.6beta1 [October 22, 2002] - Commented out warning about uninitialized mmx_support in pnggccrd.c. - Changed "IBMCPP__" flag to "__IBMCPP__" in pngconf.h. - Relocated two more misplaced PNGAPI lines in pngtest.c - Fixed memory overrun bug in png_do_read_filler() with 16-bit datastreams, - introduced in version 1.0.2. - Revised makefile.macosx, makefile.dec, makefile.aix, and makefile.32sunu. -version 1.2.6beta2 [November 1, 2002] - Added libpng-config "--ldopts" output. - Added "AR=ar" and "ARFLAGS=rc" and changed "ar rc" to "$(AR) $(ARFLAGS)" - in makefiles. -version 1.2.6beta3 [July 18, 2004] - Reverted makefile changes from version 1.2.6beta2 and some of the changes - from version 1.2.6beta1; these will be postponed until version 1.2.7. - Version 1.2.6 is going to be a simple bugfix release. - Changed the one instance of "ln -sf" to "ln -f -s" in each Sun makefile. - Fixed potential overrun in pngerror.c by using strncpy instead of memcpy. - Added "#!/bin/sh" at the top of configure, for recognition of the - 'x' flag under Cygwin (Cosmin). - Optimized vacuous tests that silence compiler warnings, in png.c (Cosmin). - Added support for PNG_USER_CONFIG, in pngconf.h (Cosmin). - Fixed the special memory handler for Borland C under DOS, in pngmem.c - (Cosmin). - Removed some spurious assignments in pngrutil.c (Cosmin). - Replaced 65536 with 65536L, and 0xffff with 0xffffL, to silence warnings - on 16-bit platforms (Cosmin). - Enclosed shift op expressions in parentheses, to silence warnings (Cosmin). - Used proper type png_fixed_point, to avoid problems on 16-bit platforms, - in png_handle_sRGB() (Cosmin). - Added compression_type to png_struct, and optimized the window size - inside the deflate stream (Cosmin). - Fixed definition of isnonalpha(), in pngerror.c and pngrutil.c (Cosmin). - Fixed handling of unknown chunks that come after IDAT (Cosmin). - Allowed png_error() and png_warning() to work even if png_ptr == NULL - (Cosmin). - Replaced row_info->rowbytes with row_bytes in png_write_find_filter() - (Cosmin). - Fixed definition of PNG_LIBPNG_VER_DLLNUM (Simon-Pierre). - Used PNG_LIBPNG_VER and PNG_LIBPNG_VER_STRING instead of the hardcoded - values in png.c (Simon-Pierre, Cosmin). - Initialized png_libpng_ver[] with PNG_LIBPNG_VER_STRING (Simon-Pierre). - Replaced PNG_LIBPNG_VER_MAJOR with PNG_LIBPNG_VER_DLLNUM in png.rc - (Simon-Pierre). - Moved the definition of PNG_HEADER_VERSION_STRING near the definitions - of the other PNG_LIBPNG_VER_... symbols in png.h (Cosmin). - Relocated #ifndef PNGAPI guards in pngconf.h (Simon-Pierre, Cosmin). - Updated scripts/makefile.vc(a)win32 (Cosmin). - Updated the MSVC project (Simon-Pierre, Cosmin). - Updated the Borland C++ Builder project (Cosmin). - Avoided access to asm_flags in pngvcrd.c, if PNG_1_0_X is defined (Cosmin). - Commented out warning about uninitialized mmx_support in pngvcrd.c (Cosmin). - Removed scripts/makefile.bd32 and scripts/pngdef.pas (Cosmin). - Added extra guard around inclusion of Turbo C memory headers, in pngconf.h - (Cosmin). - Renamed projects/msvc/ to projects/visualc6/, and projects/borland/ to - projects/cbuilder5/ (Cosmin). - Moved projects/visualc6/png32ms.def to scripts/pngw32.def, - and projects/visualc6/png.rc to scripts/pngw32.rc (Cosmin). - Added projects/visualc6/pngtest.dsp; removed contrib/msvctest/ (Cosmin). - Changed line endings to DOS style in cbuilder5 and visualc6 files, even - in the tar.* distributions (Cosmin). - Updated contrib/visupng/VisualPng.dsp (Cosmin). - Updated contrib/visupng/cexcept.h to version 2.0.0 (Cosmin). - Added a separate distribution with "configure" and supporting files (Junichi). -version 1.2.6beta4 [July 28, 2004] - Added user ability to change png_size_t via a PNG_SIZE_T macro. - Added png_sizeof() and png_convert_size() functions. - Added PNG_SIZE_MAX (maximum value of a png_size_t variable. - Added check in png_malloc_default() for (size_t)size != (png_uint_32)size - which would indicate an overflow. - Changed sPLT failure action from png_error to png_warning and abandon chunk. - Changed sCAL and iCCP failures from png_error to png_warning and abandon. - Added png_get_uint_31(png_ptr, buf) function. - Added PNG_UINT_32_MAX macro. - Renamed PNG_MAX_UINT to PNG_UINT_31_MAX. - Made png_zalloc() issue a png_warning and return NULL on potential - overflow. - Turn on PNG_NO_ZALLOC_ZERO by default in version 1.2.x - Revised "clobber list" in pnggccrd.c so it will compile under gcc-3.4. - Revised Borland portion of png_malloc() to return NULL or issue - png_error() according to setting of PNG_FLAG_MALLOC_NULL_MEM_OK. - Added PNG_NO_SEQUENTIAL_READ_SUPPORTED macro to conditionally remove - sequential read support. - Added some "#if PNG_WRITE_SUPPORTED" blocks. - #ifdef'ed out some redundancy in png_malloc_default(). - Use png_malloc instead of png_zalloc to allocate the pallete. -version 1.0.16rc1 and 1.2.6rc1 [August 4, 2004] - Fixed buffer overflow vulnerability in png_handle_tRNS() - Fixed integer arithmetic overflow vulnerability in png_read_png(). - Fixed some harmless bugs in png_handle_sBIT, etc, that would cause - duplicate chunk types to go undetected. - Fixed some timestamps in the -config version - Rearranged order of processing of color types in png_handle_tRNS(). - Added ROWBYTES macro to calculate rowbytes without integer overflow. - Updated makefile.darwin and removed makefile.macosx from scripts directory. - Imposed default one million column, one-million row limits on the image - dimensions, and added png_set_user_limits() function to override them. - Revised use of PNG_SET_USER_LIMITS_SUPPORTED macro. - Fixed wrong cast of returns from png_get_user_width|height_max(). - Changed some "keep the compiler happy" from empty statements to returns, - Revised libpng.txt to remove 1.2.x stuff from the 1.0.x distribution -version 1.0.16rc2 and 1.2.6rc2 [August 7, 2004] - Revised makefile.darwin and makefile.solaris. Removed makefile.macosx. - Revised pngtest's png_debug_malloc() to use png_malloc() instead of - png_malloc_default() which is not supposed to be exported. - Fixed off-by-one error in one of the conversions to PNG_ROWBYTES() in - pngpread.c. Bug was introduced in 1.2.6rc1. - Fixed bug in RGB to RGBX transformation introduced in 1.2.6rc1. - Fixed old bug in RGB to Gray transformation. - Fixed problem with 64-bit compilers by casting arguments to abs() - to png_int_32. - Changed "ln -sf" to "ln -f -s" in three makefiles (solaris, sco, so9). - Changed "HANDLE_CHUNK_*" to "PNG_HANDLE_CHUNK_*" (Cosmin) - Added "-@/bin/rm -f $(DL)/$(LIBNAME).so.$(PNGMAJ)" to 15 *NIX makefiles. - Added code to update the row_info->colortype in png_do_read_filler() (MSB). -version 1.0.16rc3 and 1.2.6rc3 [August 9, 2004] - Eliminated use of "abs()" in testing cHRM and gAMA values, to avoid - trouble with some 64-bit compilers. Created PNG_OUT_OF_RANGE() macro. - Revised documentation of png_set_keep_unknown_chunks(). - Check handle_as_unknown status in pngpread.c, as in pngread.c previously. - Moved "PNG_HANDLE_CHUNK_*" macros out of PNG_INTERNAL section of png.h - Added "rim" definitions for CONST4 and CONST6 in pnggccrd.c -version 1.0.16rc4 and 1.2.6rc4 [August 10, 2004] - Fixed mistake in pngtest.c introduced in 1.2.6rc2 (declaration of - "pinfo" was out of place). -version 1.0.16rc5 and 1.2.6rc5 [August 10, 2004] - Moved "PNG_HANDLE_CHUNK_*" macros out of PNG_ASSEMBLER_CODE_SUPPORTED - section of png.h where they were inadvertently placed in version rc3. - -version 1.2.6 and 1.0.16 [August 15, 2004] - Revised pngtest so memory allocation testing is only done when PNG_DEBUG==1. -version 1.2.7beta1 [August 26, 2004] - Removed unused pngasmrd.h file. - Removed references to uu.net for archived files. Added references to - PNG Spec (second edition) and the PNG ISO/IEC Standard. - Added "test-dd" target in 15 makefiles, to run pngtest in DESTDIR. - Fixed bug with "optimized window size" in the IDAT datastream, that - causes libpng to write PNG files with incorrect zlib header bytes. -version 1.2.7beta2 [August 28, 2004] - Fixed bug with sCAL chunk and big-endian machines (David Munro). - Undid new code added in 1.2.6rc2 to update the color_type in - png_set_filler(). - Added png_set_add_alpha() that updates color type. -version 1.0.17rc1 and 1.2.7rc1 [September 4, 2004] - Revised png_set_strip_filler() to not remove alpha if color_type has alpha. - -version 1.2.7 and 1.0.17 [September 12, 2004] - Added makefile.hp64 - Changed projects/msvc/png32ms.def to scripts/png32ms.def in makefile.cygwin -version 1.2.8beta1 [November 1, 2004] - Fixed bug in png_text_compress() that would fail to complete a large block. - Fixed bug, introduced in libpng-1.2.7, that overruns a buffer during - strip alpha operation in png_do_strip_filler(). - Added PNG_1_2_X definition in pngconf.h - #ifdef out png_info_init in png.c and png_read_init in pngread.c (as of 1.3.0) -version 1.2.8beta2 [November 2, 2004] - Reduce color_type to a nonalpha type after strip alpha operation in - png_do_strip_filler(). -version 1.2.8beta3 [November 3, 2004] - Revised definitions of PNG_MAX_UINT_32, PNG_MAX_SIZE, and PNG_MAXSUM -version 1.2.8beta4 [November 12, 2004] - Fixed (again) definition of PNG_LIBPNG_VER_DLLNUM in png.h (Cosmin). - Added PNG_LIBPNG_BUILD_PRIVATE in png.h (Cosmin). - Set png_ptr->zstream.data_type to Z_BINARY, to avoid unnecessary detection - of data type in deflate (Cosmin). - Deprecated but continue to support SPECIALBUILD and PRIVATEBUILD in favor of - PNG_LIBPNG_BUILD_SPECIAL_STRING and PNG_LIBPNG_BUILD_PRIVATE_STRING. -version 1.2.8beta5 [November 20, 2004] - Use png_ptr->flags instead of png_ptr->transformations to pass - PNG_STRIP_ALPHA info to png_do_strip_filler(), to preserve ABI - compatibility. - Revised handling of SPECIALBUILD, PRIVATEBUILD, - PNG_LIBPNG_BUILD_SPECIAL_STRING and PNG_LIBPNG_BUILD_PRIVATE_STRING. -version 1.2.8rc1 [November 24, 2004] - Moved handling of BUILD macros from pngconf.h to png.h - Added definition of PNG_LIBPNG_BASE_TYPE in png.h, inadvertently - omitted from beta5. - Revised scripts/pngw32.rc - Despammed mailing addresses by masking "@" with "at". - Inadvertently installed a supposedly faster test version of pngrutil.c -version 1.2.8rc2 [November 26, 2004] - Added two missing "\" in png.h - Change tests in pngread.c and pngpread.c to - if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA)) - png_do_read_transformations(png_ptr); -version 1.2.8rc3 [November 28, 2004] - Reverted pngrutil.c to version libpng-1.2.8beta5. - Added scripts/makefile.elf with supporting code in pngconf.h for symbol - versioning (John Bowler). -version 1.2.8rc4 [November 29, 2004] - Added projects/visualc7 (Simon-pierre). -version 1.2.8rc5 [November 29, 2004] - Fixed new typo in scripts/pngw32.rc - -version 1.2.8 [December 3, 2004] - Removed projects/visualc7, added projects/visualc71. - -version 1.2.9beta1 [February 21, 2006] - - Initialized some structure members in pngwutil.c to avoid gcc-4.0.0 complaints - Revised man page and libpng.txt to make it clear that one should not call - png_read_end or png_write_end after png_read_png or png_write_png. - Updated references to png-mng-implement mailing list. - Fixed an incorrect typecast in pngrutil.c - Added PNG_NO_READ_SUPPORTED conditional for making a write-only library. - Added PNG_NO_WRITE_INTERLACING_SUPPORTED conditional. - Optimized alpha-inversion loops in pngwtran.c - Moved test for nonzero gamma outside of png_build_gamma_table() in pngrtran.c - Make sure num_trans is <= 256 before copying data in png_set_tRNS(). - Make sure num_palette is <= 256 before copying data in png_set_PLTE(). - Interchanged order of write_swap_alpha and write_invert_alpha transforms. - Added parentheses in the definition of PNG_LIBPNG_BUILD_TYPE (Cosmin). - Optimized zlib window flag (CINFO) in contrib/pngsuite/*.png (Cosmin). - Updated scripts/makefile.bc32 for Borland C++ 5.6 (Cosmin). - Exported png_get_uint_32, png_save_uint_32, png_get_uint_16, png_save_uint_16, - png_get_int_32, png_save_int_32, png_get_uint_31 (Cosmin). - Added type cast (png_byte) in png_write_sCAL() (Cosmin). - Fixed scripts/makefile.cygwin (Christian Biesinger, Cosmin). - Default iTXt support was inadvertently enabled. - -version 1.2.9beta2 [February 21, 2006] - - Check for png_rgb_to_gray and png_gray_to_rgb read transformations before - checking for png_read_dither in pngrtran.c - Revised checking of chromaticity limits to accommodate extended RGB - colorspace (John Denker). - Changed line endings in some of the project files to CRLF, even in the - "Unix" tar distributions (Cosmin). - Made png_get_int_32 and png_save_int_32 always available (Cosmin). - Updated scripts/pngos2.def, scripts/pngw32.def and projects/wince/png32ce.def - with the newly exported functions. - Eliminated distributions without the "configure" script. - Updated INSTALL instructions. - -version 1.2.9beta3 [February 24, 2006] - - Fixed CRCRLF line endings in contrib/visupng/VisualPng.dsp - Made libpng.pc respect EXEC_PREFIX (D. P. Kreil, J. Bowler) - Removed reference to pngasmrd.h from Makefile.am - Renamed CHANGES to ChangeLog. - Renamed LICENSE to COPYING. - Renamed ANNOUNCE to NEWS. - Created AUTHORS file. - -version 1.2.9beta4 [March 3, 2006] - - Changed definition of PKGCONFIG from $prefix/lib to $libdir in configure.ac - Reverted to filenames LICENSE and ANNOUNCE; removed AUTHORS and COPYING. - Removed newline from the end of some error and warning messages. - Removed test for sqrt() from configure.ac and configure. - Made swap tables in pngtrans.c PNG_CONST (Carlo Bramix). - Disabled default iTXt support that was inadvertently enabled in - libpng-1.2.9beta1. - Added "OS2" to list of systems that don't need underscores, in pnggccrd.c - Removed libpng version and date from *.c files. - -version 1.2.9beta5 [March 4, 2006] - Removed trailing blanks from source files. - Put version and date of latest change in each source file, and changed - copyright year accordingly. - More cleanup of configure.ac, Makefile.ac, and associated scripts. - Restored scripts/makefile.elf which was inadvertently deleted. - -version 1.2.9beta6 [March 6, 2006] - Fixed typo (22) in configuration files. - -version 1.2.9beta7 [March 7, 2006] - Removed libpng.vers and libpng.sym from libpng12_la_SOURCES in Makefile.am - Fixed inconsistent #ifdef's around png_sig_bytes() and png_set_sCAL_s() - in png.h. - Updated makefile.elf as suggested by debian. - Made cosmetic changes to some makefiles, adding LN_SF and other macros. - Made some makefiles accept "exec_prefix". - -version 1.2.9beta8 [March 9, 2006] - Fixed some "#if defined (..." which should be "#if defined(..." - Bug introduced in libpng-1.2.8. - Fixed inconsistency in definition of png_default_read_data() - Restored blank that was lost from makefile.sggcc "clean" target in beta7. - Revised calculation of "current" and "major" for irix in ltmain.sh - Changed "mkdir" to "MKDIR_P" in some makefiles. - Separated PNG_EXPAND and PNG_EXPAND_tRNS. - Added png_set_expand_gray_1_2_4_to_8() and deprecated - png_set_gray_1_2_4_to_8() which also expands tRNS to alpha. - -version 1.2.9beta9 [March 10, 2006] - Include "config.h" in pngconf.h when available. - Added some checks for NULL png_ptr or NULL info_ptr (timeless) - -version 1.2.9beta10 [March 20, 2006] - Removed extra CR from contrib/visualpng/VisualPng.dsw (Cosmin) - Made pnggccrd.c PIC-compliant (Christian Aichinger). - Added makefile.mingw (Wolfgang Glas). - Revised pngconf.h MMX checking. - -version 1.2.9beta11 [March 22, 2006] - Fixed out-of-order declaration in pngwrite.c that was introduced in beta9 - Simplified some makefiles by using LIBSO, LIBSOMAJ, and LIBSOVER macros. - -version 1.2.9rc1 [March 31, 2006] - Defined PNG_USER_PRIVATEBUILD when including "pngusr.h" (Cosmin). - Removed nonsensical assertion check from pngtest.c (Cosmin). - -version 1.2.9 [April 14, 2006] - Revised makefile.beos and added "none" selector in ltmain.sh - -version 1.2.10beta1 [April 15, 2006] - Renamed "config.h" to "png_conf.h" and revised Makefile.am to add - -DPNG_BUILDING_LIBPNG to compile directive, and modified pngconf.h - to include png_conf.h only when PNG_BUILDING_LIBPNG is defined. - -version 1.2.10beta2 [April 15, 2006] - Manually updated Makefile.in and configure. Changed png_conf.h.in - back to config.h. - -version 1.2.10beta3 [April 15, 2006] - Change png_conf.h back to config.h in pngconf.h. - -version 1.2.10beta4 [April 16, 2006] - Change PNG_BUILDING_LIBPNG to PNG_CONFIGURE_LIBPNG in config/Makefile*. - -version 1.2.10beta5 [April 16, 2006] - Added a configure check for compiling assembler code in pnggccrd.c - -version 1.2.10beta6 [April 17, 2006] - Revised the configure check for pnggccrd.c - Moved -DPNG_CONFIGURE_LIBPNG into @LIBPNG_DEFINES@ - Added @LIBPNG_DEFINES@ to arguments when building libpng.sym - -version 1.2.10beta7 [April 18, 2006] - Change "exec_prefix=$prefix" to "exec_prefix=$(prefix)" in makefiles. - -version 1.2.10rc1 [April 19, 2006] - Ensure pngconf.h doesn't define both PNG_USE_PNGGCCRD and PNG_USE_PNGVCRD - Fixed "LN_FS" typo in makefile.sco and makefile.solaris. - -version 1.2.10rc2 [April 20, 2006] - Added a backslash between -DPNG_CONFIGURE_LIBPNG and -DPNG_NO_ASSEMBLER_CODE - in configure.ac and configure - Made the configure warning about versioned symbols less arrogant. - -version 1.2.10rc3 [April 21, 2006] - Added a note in libpng.txt that png_set_sig_bytes(8) can be used when - writing an embedded PNG without the 8-byte signature. - Revised makefiles and configure to avoid making links to libpng.so.* - -version 1.2.10 [April 23, 2006] - Reverted configure to "rc2" state. - -version 1.2.11beta1 [May 31, 2006] - scripts/libpng.pc.in contained "configure" style version info and would - not work with makefiles. - The shared-library makefiles were linking to libpng.so.0 instead of - libpng.so.3 compatibility as the library. - -version 1.2.11beta2 [June 2, 2006] - Increased sprintf buffer from 50 to 52 chars in pngrutil.c to avoid - buffer overflow. - Fixed bug in example.c (png_set_palette_rgb -> png_set_palette_to_rgb) - -version 1.2.11beta3 [June 5, 2006] - Prepended "#! /bin/sh" to ltmail.sh and contrib/pngminus/*.sh (Cosmin). - Removed the accidental leftover Makefile.in~ (Cosmin). - Avoided potential buffer overflow and optimized buffer in - png_write_sCAL(), png_write_sCAL_s() (Cosmin). - Removed the include directories and libraries from CFLAGS and LDFLAGS - in scripts/makefile.gcc (Nelson A. de Oliveira, Cosmin). - -version 1.2.11beta4 [June 6, 2006] - Allow zero-length IDAT chunks after the entire zlib datastream, but not - after another intervening chunk type. - -version 1.0.19rc1, 1.2.11rc1 [June 13, 2006] - Deleted extraneous square brackets from [config.h] in configure.ac - -version 1.0.19rc2, 1.2.11rc2 [June 14, 2006] - Added prototypes for PNG_INCH_CONVERSIONS functions to png.h - Revised INSTALL and autogen.sh - Fixed typo in several makefiles (-W1 should be -Wl) - Added typedef for png_int_32 and png_uint_32 on 64-bit systems. - -version 1.0.19rc3, 1.2.11rc3 [June 15, 2006] - Removed the new typedefs for 64-bit systems (delay until version 1.4.0) - Added one zero element to png_gamma_shift[] array in pngrtran.c to avoid - reading out of bounds. - -version 1.0.19rc4, 1.2.11rc4 [June 15, 2006] - Really removed the new typedefs for 64-bit systems. - -version 1.0.19rc5, 1.2.11rc5 [June 22, 2006] - Removed png_sig_bytes entry from scripts/pngw32.def - -version 1.0.19, 1.2.11 [June 26, 2006] - None. - -version 1.0.20, 1.2.12 [June 27, 2006] - Really increased sprintf buffer from 50 to 52 chars in pngrutil.c to avoid - buffer overflow. - -version 1.2.13beta1 [October 2, 2006] - Removed AC_FUNC_MALLOC from configure.ac - Work around Intel-Mac compiler bug by setting PNG_NO_MMX_CODE in pngconf.h - Change "logical" to "bitwise" throughout documentation. - Detect and fix attempt to write wrong iCCP profile length. - -version 1.0.21, 1.2.13 [November 14, 2006] - Fix potential buffer overflow in sPLT chunk handler. - Fix Makefile.am to not try to link to noexistent files. - Check all exported functions for NULL png_ptr. - -version 1.2.14beta1 [November 17, 2006] - Relocated three misplaced tests for NULL png_ptr. - Built Makefile.in with automake-1.9.6 instead of 1.9.2. - Build configure with autoconf-2.60 instead of 2.59 - -version 1.2.14beta2 [November 17, 2006] - Added some typecasts in png_zalloc(). - -version 1.2.14rc1 [November 20, 2006] - Changed "strtod" to "png_strtod" in pngrutil.c - -version 1.0.22, 1.2.14 [November 27, 2006] - Added missing "$(srcdir)" in Makefile.am and Makefile.in - -version 1.2.15beta1 [December 3, 2006] - Generated configure with autoconf-2.61 instead of 2.60 - Revised configure.ac to update libpng.pc and libpng-config. - -version 1.2.15beta2 [December 3, 2006] - Always export MMX asm functions, just stubs if not building pnggccrd.c - -version 1.2.15beta3 [December 4, 2006] - Add "png_bytep" typecast to profile while calculating length in pngwutil.c - -version 1.2.15beta4 [December 7, 2006] - Added scripts/CMakeLists.txt - Changed PNG_NO_ASSEMBLER_CODE to PNG_NO_MMX_CODE in scripts, like 1.4.0beta - -version 1.2.15beta5 [December 7, 2006] - Changed some instances of PNG_ASSEMBLER_* to PNG_MMX_* in pnggccrd.c - Revised scripts/CMakeLists.txt - -version 1.2.15beta6 [December 13, 2006] - Revised scripts/CMakeLists.txt and configure.ac - -version 1.2.15rc1 [December 18, 2006] - Revised scripts/CMakeLists.txt - -version 1.2.15rc2 [December 21, 2006] - Added conditional #undef jmpbuf in pngtest.c to undo #define in AIX headers. - Added scripts/makefile.nommx - -version 1.2.15rc3 [December 25, 2006] - Fixed shared library numbering error that was intruduced in 1.2.15beta6. - -version 1.2.15rc4 [December 27, 2006] - Fixed handling of rgb_to_gray when png_ptr->color.gray isn't set. - -version 1.2.15rc5 [December 31, 2006] - Revised handling of rgb_to_gray. - -version 1.0.23, 1.2.15 [January 5, 2007] - Added some (unsigned long) typecasts in pngtest.c to avoid printing errors. - -version 1.2.16beta1 [January 6, 2007] - Fix bugs in makefile.nommx - -version 1.2.16beta2 [January 16, 2007] - Revised scripts/CMakeLists.txt - -version 1.0.24, 1.2.16 [January 31, 2007] - No changes. - -version 1.2.17beta1 [March 6, 2007] - Revised scripts/CMakeLists.txt to install both shared and static libraries. - Deleted a redundant line from pngset.c. - -version 1.2.17beta2 [April 26, 2007] - Relocated misplaced test for png_ptr == NULL in pngpread.c - Change "==" to "&" for testing PNG_RGB_TO_GRAY_ERR & PNG_RGB_TO_GRAY_WARN - flags. - Changed remaining instances of PNG_ASSEMBLER_* to PNG_MMX_* - Added pngerror() when write_IHDR fails in deflateInit2(). - Added "const" to some array declarations. - Mention examples of libpng usage in the libpng*.txt and libpng.3 documents. - -version 1.2.17rc1 [May 4, 2007] - No changes. - -version 1.2.17rc2 [May 8, 2007] - Moved several PNG_HAVE_* macros out of PNG_INTERNAL because applications - calling set_unknown_chunk_location() need them. - Changed transformation flag from PNG_EXPAND_tRNS to PNG_EXPAND in - png_set_expand_gray_1_2_4_to_8(). - Added png_ptr->unknown_chunk to hold working unknown chunk data, so it - can be free'ed in case of error. Revised unknown chunk handling in - pngrutil.c and pngpread.c to use this structure. - -version 1.2.17rc3 [May 8, 2007] - Revised symbol-handling in configure script. - -version 1.2.17rc4 [May 10, 2007] - Revised unknown chunk handling to avoid storing unknown critical chunks. - -version 1.0.25 [May 15, 2007] -version 1.2.17 [May 15, 2007] - Added "png_ptr->num_trans=0" before error return in png_handle_tRNS, - to eliminate a vulnerability (CVE-2007-2445, CERT VU#684664) - -version 1.0.26 [May 15, 2007] -version 1.2.18 [May 15, 2007] - Reverted the libpng-1.2.17rc3 change to symbol-handling in configure script - -version 1.2.19beta1 [May 18, 2007] - Changed "const static" to "static PNG_CONST" everywhere, mostly undoing - change of libpng-1.2.17beta2. Changed other "const" to "PNG_CONST" - Changed some handling of unused parameters, to avoid compiler warnings. - "if (unused == NULL) return;" becomes "unused = unused". - -version 1.2.19beta2 [May 18, 2007] - Only use the valid bits of tRNS value in png_do_expand() (Brian Cartier) - -version 1.2.19beta3 [May 19, 2007] - Add some "png_byte" typecasts in png_check_keyword() and write new_key - instead of key in zTXt chunk (Kevin Ryde). - -version 1.2.19beta4 [May 21, 2007] - Add png_snprintf() function and use it in place of sprint() for improved - defense against buffer overflows. - -version 1.2.19beta5 [May 21, 2007] - Fixed png_handle_tRNS() to only use the valid bits of tRNS value. - Changed handling of more unused parameters, to avoid compiler warnings. - Removed some PNG_CONST in pngwutil.c to avoid compiler warnings. - -version 1.2.19beta6 [May 22, 2007] - Added some #ifdef PNG_MMX_CODE_SUPPORTED where needed in pngvcrd.c - Added a special "_MSC_VER" case that defines png_snprintf to _snprintf - -version 1.2.19beta7 [May 22, 2007] - Squelched png_squelch_warnings() in pnggccrd.c and added an - #ifdef PNG_MMX_CODE_SUPPORTED block around the declarations that caused - the warnings that png_squelch_warnings was squelching. - -version 1.2.19beta8 [May 22, 2007] - Removed __MMX__ from test in pngconf.h. - -version 1.2.19beta9 [May 23, 2007] - Made png_squelch_warnings() available via PNG_SQUELCH_WARNINGS macro. - Revised png_squelch_warnings() so it might work. - Updated makefile.sgcc and makefile.solaris; added makefile.solaris-x86. - -version 1.2.19beta10 [May 24, 2007] - Resquelched png_squelch_warnings(), use "__attribute__((used))" instead. - -version 1.2.19beta11 [May 28, 2007] - Return 0 from png_get_sPLT() and png_get_unknown_chunks() if png_ptr is NULL; - changed three remaining instances of png_strcpy() to png_strncpy() (David - Hill). - Make test for NULL row_buf at the beginning of png_do_read_transformations - unconditional. - -version 1.2.19beta12 [May 28, 2007] - Revised pnggccrd.c. - -version 1.2.19beta13 [June 14, 2007] - Prefer PNG_USE_PNGVCRD when _MSC_VER is defined in pngconf.h - -version 1.2.19beta14 [June 16, 2007] - Fix bug with handling of 16-bit transparency, introduced in 1.2.19beta2 - -version 1.2.19beta15 [June 17, 2007] - Revised pnggccrd.c. - -version 1.2.19beta16 [June 18, 2007] - Revised pnggccrd.c again. - Updated contrib/gregbook. - Changed '#include "pnggccrd.c"' to 'include "$srcdir/pnggccrd.c"' - in configure.ac - -version 1.2.19beta17 [June 19, 2007] - Revised many of the makefiles, to set -DPNG_NO_MMX_CODE where needed - and to not use -O3 unless -DPNG_NO_MMX_CODE is also set. - -version 1.2.19beta18 [June 23, 2007] - Replaced some C++ style comments with C style comments in pnggccrd.c. - Copied optimized C code from pnggccrd.c to pngrutil.c, removed dependency - on pnggccrd.o from many makefiles. - Added sl and dylib to list of extensions be installed by Makefile.am - -version 1.2.19beta19 [June 28, 2007] - Fixed testing PNG_RGB_TO_GRAY_ERR & PNG_RGB_TO_GRAY_WARN in pngrtran.c - More cleanup of pnggccrd.c and pngvcrd.c - -version 1.2.19beta20 [June 29, 2007] - Rebuilt Makefile.in and configure using libtool-1.5.24. - Fixed typo in pnggccrd.c - -version 1.2.19beta21 [June 30, 2007] - More revision of pnggccrd.c - Added "test" target to Makefile.in and Makefile.am - -version 1.2.19beta22 [July 3, 2007] - Added info about pngrutil/pnggccrd/pngvcrd to png_get_header_version() - Fix type definition of dummy_value_a, b in pnggccrd.c - -version 1.2.19beta23 [July 10, 2007] - Revert change to type definition of dummy_value_a, b in pnggccrd.c - Make sure __PIC__ is defined in pnggccrd.c when PIC is defined. - Require gcc-4.1 or better to use PNG_HAVE_MMX_FILTER_ROW on x86_64 platforms - -version 1.2.19beta24 [July 14, 2007] - Added PNG_NO_READ_FILTER, PNG_NO_WRITE_FILTER, PNG_NO_WARNING macros. - Added contrib/pngminim to demonstrate building minimal encoder and decoder - -version 1.2.19beta25 [July 15, 2007] - Removed the new PNG_NO_READ_FILTER macro since it would make the library - unable to read valid PNG files, and filtering is at the heart of the - PNG format. - -version 1.2.19beta26 [July 16, 2007] - Changed "png_free(str)" to "png_free(png_ptr,str)" in pngrutil.c WinCE - code (Yves Piguet). This bug was introduced in libpng-1.2.14. - Updated scripts/CMakeLists.txt - Relocated a misplaced #endif in pnggccrd.c - -version 1.2.19beta27 [July 17, 2007] - Fixed incorrect stride and number of bytes copied (was 4 instead of - 6 bytes) in the cleanup loop of pnggccrd.c and pngvcrd.c for handling - the end of 48-bit interlaced rows (Glenn R-P). - -version 1.2.19beta28 [July 19, 2007] - Removed requirement for gcc-4.1 or better to use PNG_HAVE_MMX_FILTER_ROW - on x86_64 platforms - Added png_warning() in pngrutil.c for short iCCP, iTXt, sPLT, or zTXT chunks. - Revised pngtest.c so warnings are displayed regardless of PNG_NO_STDIO. - -version 1.2.19beta29 [July 20, 2007] - Fix typo in pnggccrd.c (%%eax should be %%ax in secondloop48) - -version 1.2.19beta30 [July 26, 2007] - Revised pnggccrd.c - -version 1.2.19beta31 [July 27, 2007] - Fix typos in pnggccrd.c - -version 1.0.27rc1 and 1.2.19rc1 [July 31, 2007] - Disable PNG_MMX_CODE_SUPPORTED when PNG_ASSEMBLER_CODE_SUPPORTED is off. - Enable PNG_MMX_READ_FILTER_* by default, except when gcc-3.x is being - used (they were inadvertently disabled in libpng-1.2.19beta23). - Fix some debugging statements in pnggccrd.c and pngrutil.c - Added information about disabling the MMX code in libpng documentation. - -version 1.0.27rc2 and 1.2.19rc2 [August 4, 2007] - Removed some "#if 0" blocks. - Made a global struct local in pngvcrd.c to make it thread safe. - Issue a png_error() if application attempts to transform a row tht - has not been initialized. - -version 1.0.27rc3 and 1.2.19rc3 [August 9, 2007] - Slightly revised pngvcrd.c - -version 1.0.27rc4 and 1.2.19rc4 [August 9, 2007] - Revised pnggccrd.c debugging change of rc1, which was broken. - Revised scripts/CMakeLists.txt - Change default to PNG_NO_GLOBAL_ARRAYS for MSVC. - Turn off PNG_FLAG_ROW_INIT flag when setting transforms that expand pixels. - -version 1.0.27rc5 and 1.2.19rc5 [August 10, 2007] - Fix typo (missing '"') in pnggccrd.c - Revise handling of png_strtod in recent versions of WINCE - -version 1.0.27rc6 and 1.2.19rc6 [August 15, 2007] - Fix typo (missing ',') in contrib/gregbook/readpng2.c - Undid row initialization error exit added to rc2 and rc4. - -version 1.0.27 and 1.2.19 [August 18, 2007] - Conditionally restored row initialization error exit. - -version 1.2.20beta01 [August 19, 2007] - Fixed problem with compiling pnggccrd.c on Intel-Apple platforms. - Added PNG_NO_ERROR_TEXT feature, with demo in contrib/pngminim - Removed define PNG_WARN_UNINITIALIZED_ROW 1 /* 0: warning; 1: error */ - because it caused some trouble. - -version 1.2.20beta02 [August 20, 2007] - Avoid compiling pnggccrd.c on Intel-Apple platforms. - -version 1.2.20beta03 [August 20, 2007] - Added "/D PNG_NO_MMX_CODE" to the non-mmx builds of projects/visualc6 - and visualc71. - -version 1.2.20beta04 [August 21, 2007] - Revised pngvcrd.c for improved efficiency (Steve Snyder). - -version 1.2.20rc1 [August 23, 2007] - Revised pngconf.h to set PNG_NO_MMX_CODE for gcc-3.x compilers. - -version 1.2.20rc2 [August 27, 2007] - Revised scripts/CMakeLists.txt - Revised #ifdefs to ensure one and only one of pnggccrd.c, pngvcrd.c, - or part of pngrutil.c is selected. - -version 1.2.20rc3 [August 30, 2007] - Remove a little more code in pngwutil.c when PNG_NO_WRITE_FILTER is selected. - Added /D _CRT_SECURE_NO_WARNINGS to visual6c and visualc71 projects. - Compile png_mmx_support() in png.c even when PNG_NO_MMX_CODE is defined. - Restored a "superfluous" #ifdef that was removed from 1.2.20rc2 pnggccrd.c, - breaking the png_mmx_support() function. - -version 1.2.20rc4 [September 1, 2007] - Removed Intel contributions (MMX, Optimized C). - -version 1.2.20rc5 [September 2, 2007] - Restored configure and Makefile.in to rc3 and put a snippet of code in - pnggccrd.c, to ensure configure makes the same PNG_NO_MMX_CODE selection - -version 1.2.20rc6 [September 2, 2007] - Fixed bugs in scripts/CMakeLists.txt - Removed pngvcrd.c references from msvc projects. - -version 1.0.28 and 1.2.20 [September 8, 2007] - Removed "(NO READ SUPPORT)" from png_get_header_version() string. - -version 1.2.21beta1 [September 14, 2007] - Fixed various mistakes reported by George Cook and Jeff Phillips: - logical vs bitwise NOT in pngrtran.c, bug introduced in 1.2.19rc2 - 16-bit cheap transparency expansion, bug introduced in 1.2.19beta2 - errors with sizeof(unknown_chunk.name), bugs introduced in 1.2.19beta11 - <= compare with unsigned var in pngset.c, should be ==. - -version 1.2.21beta2 [September 18, 2007] - Removed some extraneous typecasts. - -version 1.2.21rc1 [September 25, 2007] - Fixed potential out-of-bounds reads in png_handle_pCAL() and - png_handle_ztXt() ("flayer" results reported by Tavis Ormandy). - -version 1.2.21rc2 [September 26, 2007] - Fixed potential out-of-bounds reads in png_handle_sCAL(), - png_handle_iTXt(), and png_push_read_tEXt(). - Remove some PNG_CONST declarations from pngwutil.c to avoid compiler warnings - Revised makefiles to update paths in libpng.pc properly. - -version 1.2.21rc3 [September 27, 2007] - Revised makefiles to update "Libs" in libpng.pc properly. - -version 1.0.29 and 1.2.21rc3 [October 4, 2007] - No changes. - -version 1.2.22beta1 [October 4, 2007] - Again, fixed logical vs bitwise NOT in pngrtran.c, bug introduced - in 1.2.19rc2 - -version 1.2.22beta2 [October 5, 2007] - Fixed string length error in pngset.c (caused crashes while decoding iCCP) - Add terminating NULL after each instance of png_strncpy(). - -version 1.2.22beta3 [October 6, 2007] - Fix two off-by-one terminating NULL after png_strncpy(). - -version 1.2.22beta4 [October 7, 2007] - Changed some 0 to '\0'. - -version 1.0.30rc1 and 1.2.22rc1 [October 8, 2007] - No changes. - -version 1.0.30 and 1.2.22 [October 13, 2007] - No changes. - -Send comments/corrections/commendations to png-mng-implement at lists.sf.net -(subscription required; visit -https://lists.sourceforge.net/lists/listinfo/png-mng-implement -to subscribe) -or to glennrp at users.sourceforge.net - -Glenn R-P diff --git a/uppdev/plugin/png/lib/INSTALL b/uppdev/plugin/png/lib/INSTALL deleted file mode 100644 index 7718f9653..000000000 --- a/uppdev/plugin/png/lib/INSTALL +++ /dev/null @@ -1,199 +0,0 @@ - -Installing libpng version 1.2.22 - October 13, 2007 - -On Unix/Linux and similar systems, you can simply type - - ./configure [--prefix=/path] - make check - make install - -and ignore the rest of this document. - -If configure does not work on your system and you have a reasonably -up-to-date set of tools, running ./autogen.sh before running ./configure -may fix the problem. You can also run the individual commands in -autogen.sh with the --force option, if supported by your version of -the tools. If you run 'libtoolize --force', though, this will replace -the distributed, patched, version of ltmain.sh with an unpatched version -and your shared library builds may fail to produce libraries with the -correct version numbers. - -Instead, you can use one of the custom-built makefiles in the -"scripts" directory - - cp scripts/makefile.system makefile - make test - make install - -Or you can use one of the "projects" in the "projects" directory. - -If you want to use "cmake" (see www.cmake.org), copy CMakeLists.txt -from the "scripts" directory to this directory and type - - cmake . [-DPNG_MMX=YES] -DCMAKE_INSTALL_PREFIX=/path - make - make install - -Before installing libpng, you must first install zlib, if it -is not already on your system. zlib can usually be found -wherever you got libpng. zlib can be placed in another directory, -at the same level as libpng. - -If your system already has a preinstalled zlib you will still need -to have access to the zlib.h and zconf.h include files that -correspond to the version of zlib that's installed. - -You can rename the directories that you downloaded (they -might be called "libpng-1.2.22" or "lpng109" and "zlib-1.2.1" -or "zlib121") so that you have directories called "zlib" and "libpng". - -Your directory structure should look like this: - - .. (the parent directory) - libpng (this directory) - INSTALL (this file) - README - *.h - *.c - contrib - gregbook - pngminus - pngsuite - visupng - projects - beos - c5builder (Borland) - visualc6 (msvc) - netware.txt - wince.txt - scripts - makefile.* - pngtest.png - etc. - zlib - README - *.h - *.c - contrib - etc. - -If the line endings in the files look funny, you may wish to get the other -distribution of libpng. It is available in both tar.gz (UNIX style line -endings) and zip (DOS style line endings) formats. - -If you are building libpng with MSVC, you can enter the -libpng projects\visualc6 directory and follow the instructions in -projects\visualc6\README.txt. - -You can build libpng for WindowsCE by downloading and installing -the projects\wince directory as instructed in the projects\wince.txt file, and -then following the instructions in the README* files. Similarly, you can -build libpng for Netware or Beos as instructed in projects\netware.txt -or projects\beos. - -Else enter the zlib directory and follow the instructions in zlib/README, -then come back here and run "configure" or choose the appropriate -makefile.sys in the scripts directory. - -The files that are presently available in the scripts directory -include - - CMakeLists.txt => "cmake" script - makefile.std => Generic UNIX makefile (cc, creates static libpng.a) - makefile.elf => Linux/ELF makefile symbol versioning, - gcc, creates libpng12.so.0.1.2.22) - makefile.linux => Linux/ELF makefile - (gcc, creates libpng12.so.0.1.2.22) - makefile.gcc => Generic makefile (gcc, creates static libpng.a) - makefile.knr => Archaic UNIX Makefile that converts files with - ansi2knr (Requires ansi2knr.c from - ftp://ftp.cs.wisc.edu/ghost) - makefile.aix => AIX/gcc makefile - makefile.cygwin => Cygwin/gcc makefile - makefile.darwin => Darwin makefile, can use on MacosX - makefile.dec => DEC Alpha UNIX makefile - makefile.freebsd => FreeBSD makefile - makefile.hpgcc => HPUX makefile using gcc - makefile.hpux => HPUX (10.20 and 11.00) makefile - makefile.hp64 => HPUX (10.20 and 11.00) makefile, 64-bit - makefile.ibmc => IBM C/C++ version 3.x for Win32 and OS/2 (static) - makefile.intel => Intel C/C++ version 4.0 and later - libpng.icc => Project file for IBM VisualAge/C++ version 4.0 or later - makefile.netbsd => NetBSD/cc makefile, uses PNGGCCRD, makes libpng.so. - makefile.ne12bsd => NetBSD/cc makefile, uses PNGGCCRD, - makes libpng12.so - makefile.openbsd => OpenBSD makefile - makefile.sgi => Silicon Graphics IRIX makefile (cc, creates static lib) - makefile.sggcc => Silicon Graphics (gcc, - creates libpng12.so.0.1.2.22) - makefile.sunos => Sun makefile - makefile.solaris => Solaris 2.X makefile (gcc, - creates libpng12.so.0.1.2.22) - makefile.solaris-x86 => Solaris/intelMMX 2.X makefile (gcc, - creates libpng12.so.0.1.2.22) - makefile.so9 => Solaris 9 makefile (gcc, - creates libpng12.so.0.1.2.22) - makefile.32sunu => Sun Ultra 32-bit makefile - makefile.64sunu => Sun Ultra 64-bit makefile - makefile.sco => For SCO OSr5 ELF and Unixware 7 with Native cc - makefile.mips => MIPS makefile - makefile.acorn => Acorn makefile - makefile.amiga => Amiga makefile - smakefile.ppc => AMIGA smakefile for SAS C V6.58/7.00 PPC compiler - (Requires SCOPTIONS, copied from scripts/SCOPTIONS.ppc) - makefile.atari => Atari makefile - makefile.beos => BEOS makefile for X86 - makefile.bor => Borland makefile (uses bcc) - makefile.bc32 => 32-bit Borland C++ (all modules compiled in C mode) - makefile.tc3 => Turbo C 3.0 makefile - makefile.dj2 => DJGPP 2 makefile - makefile.msc => Microsoft C makefile - makefile.vcwin32 => makefile for Microsoft Visual C++ 4.0 and later - makefile.os2 => OS/2 Makefile (gcc and emx, requires pngos2.def) - pngos2.def => OS/2 module definition file used by makefile.os2 - makefile.watcom => Watcom 10a+ Makefile, 32-bit flat memory model - makevms.com => VMS build script - descrip.mms => VMS makefile for MMS or MMK - SCOPTIONS.ppc => Used with smakefile.ppc - -Copy the file (or files) that you need from the -scripts directory into this directory, for example - - MSDOS example: copy scripts\makefile.msc makefile - UNIX example: cp scripts/makefile.std makefile - -Read the makefile to see if you need to change any source or -target directories to match your preferences. - -Then read pngconf.h to see if you want to make any configuration -changes. - -Then just run "make" which will create the libpng library in -this directory and "make test" which will run a quick test that reads -the "pngtest.png" file and writes a "pngout.png" file that should be -identical to it. Look for "9782 zero samples" in the output of the -test. For more confidence, you can run another test by typing -"pngtest pngnow.png" and looking for "289 zero samples" in the output. -Also, you can run "pngtest -m contrib/pngsuite/*.png" and compare -your output with the result shown in contrib/pngsuite/README. - -Most of the makefiles will allow you to run "make install" to -put the library in its final resting place (if you want to -do that, run "make install" in the zlib directory first if necessary). -Some also allow you to run "make test-installed" after you have -run "make install". - -If you encounter a compiler error message complaining about the -lines - __png.h__ already includes setjmp.h; - __dont__ include it again.; -This means you have compiled another module that includes setjmp.h, -which is hazardous because the two modules might not include exactly -the same setjmp.h. If you are sure that you know what you are doing -and that they are exactly the same, then you can comment out or -delete the two lines. Better yet, use the cexcept interface -instead, as demonstrated in contrib/visupng of the libpng distribution. - -Further information can be found in the README and libpng.txt -files, in the individual makefiles, in png.h, and the manual pages -libpng.3 and png.5. diff --git a/uppdev/plugin/png/lib/KNOWNBUG b/uppdev/plugin/png/lib/KNOWNBUG deleted file mode 100644 index 20221d56f..000000000 --- a/uppdev/plugin/png/lib/KNOWNBUG +++ /dev/null @@ -1,21 +0,0 @@ - -Known bugs in libpng version 1.2.22 - -1. February 23, 2006: The custom makefiles don't build libpng with -lz. - - STATUS: This is a subject of debate. The change will probably be made - as a part of a major overhaul of the makefiles in libpng version 1.3.0. - -2. February 24, 2006: The Makefile generated by the "configure" script - fails to install symbolic links - libpng12.so => libpng12.so.0.1.2.9betaN - that are generated by the custom makefiles. - -3. September 4, 2007: There is a report that pngtest crashes on MacOS 10. - - STATUS: workarounds are - 1) Compile without optimization (crashes are observed with - -arch i386 and -O2 or -O3, using gcc-4.0.1. - 2) Compile pngtest.c with PNG_DEBUG defined (the bug goes away if - you try to look at it). - 3) Ignore the crash. The library itself seems to be OK. diff --git a/uppdev/plugin/png/lib/LICENSE b/uppdev/plugin/png/lib/LICENSE deleted file mode 100644 index c702d1b28..000000000 --- a/uppdev/plugin/png/lib/LICENSE +++ /dev/null @@ -1,109 +0,0 @@ - -This copy of the libpng notices is provided for your convenience. In case of -any discrepancy between this copy and the notices in the file png.h that is -included in the libpng distribution, the latter shall prevail. - -COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: - -If you modify libpng you may insert additional notices immediately following -this sentence. - -libpng versions 1.2.6, August 15, 2004, through 1.2.22, October 13, 2007, are -Copyright (c) 2004, 2006-2007 Glenn Randers-Pehrson, and are -distributed according to the same disclaimer and license as libpng-1.2.5 -with the following individual added to the list of Contributing Authors - - Cosmin Truta - -libpng versions 1.0.7, July 1, 2000, through 1.2.5 - October 3, 2002, are -Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are -distributed according to the same disclaimer and license as libpng-1.0.6 -with the following individuals added to the list of Contributing Authors - - Simon-Pierre Cadieux - Eric S. Raymond - Gilles Vollant - -and with the following additions to the disclaimer: - - There is no warranty against interference with your enjoyment of the - library or against infringement. There is no warranty that our - efforts or the library will fulfill any of your particular purposes - or needs. This library is provided with all faults, and the entire - risk of satisfactory quality, performance, accuracy, and effort is with - the user. - -libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are -Copyright (c) 1998, 1999 Glenn Randers-Pehrson, and are -distributed according to the same disclaimer and license as libpng-0.96, -with the following individuals added to the list of Contributing Authors: - - Tom Lane - Glenn Randers-Pehrson - Willem van Schaik - -libpng versions 0.89, June 1996, through 0.96, May 1997, are -Copyright (c) 1996, 1997 Andreas Dilger -Distributed according to the same disclaimer and license as libpng-0.88, -with the following individuals added to the list of Contributing Authors: - - John Bowler - Kevin Bracey - Sam Bushell - Magnus Holmgren - Greg Roelofs - Tom Tanner - -libpng versions 0.5, May 1995, through 0.88, January 1996, are -Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. - -For the purposes of this copyright and license, "Contributing Authors" -is defined as the following set of individuals: - - Andreas Dilger - Dave Martindale - Guy Eric Schalnat - Paul Schmidt - Tim Wegner - -The PNG Reference Library is supplied "AS IS". The Contributing Authors -and Group 42, Inc. disclaim all warranties, expressed or implied, -including, without limitation, the warranties of merchantability and of -fitness for any purpose. The Contributing Authors and Group 42, Inc. -assume no liability for direct, indirect, incidental, special, exemplary, -or consequential damages, which may result from the use of the PNG -Reference Library, even if advised of the possibility of such damage. - -Permission is hereby granted to use, copy, modify, and distribute this -source code, or portions hereof, for any purpose, without fee, subject -to the following restrictions: - -1. The origin of this source code must not be misrepresented. - -2. Altered versions must be plainly marked as such and must not - be misrepresented as being the original source. - -3. This Copyright notice may not be removed or altered from any - source or altered source distribution. - -The Contributing Authors and Group 42, Inc. specifically permit, without -fee, and encourage the use of this source code as a component to -supporting the PNG file format in commercial products. If you use this -source code in a product, acknowledgment is not required but would be -appreciated. - - -A "png_get_copyright" function is available, for convenient use in "about" -boxes and the like: - - printf("%s",png_get_copyright(NULL)); - -Also, the PNG logo (in PNG format, of course) is supplied in the -files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31). - -Libpng is OSI Certified Open Source Software. OSI Certified Open Source is a -certification mark of the Open Source Initiative. - -Glenn Randers-Pehrson -glennrp at users.sourceforge.net -October 13, 2007 diff --git a/uppdev/plugin/png/lib/README b/uppdev/plugin/png/lib/README deleted file mode 100644 index ee6084ac5..000000000 --- a/uppdev/plugin/png/lib/README +++ /dev/null @@ -1,263 +0,0 @@ -README for libpng version 1.2.22 - October 13, 2007 (shared library 12.0) -See the note about version numbers near the top of png.h - -See INSTALL for instructions on how to install libpng. - -Libpng comes in several distribution formats. Get libpng-*.tar.gz -or libpng-*.tar.bz2 if you want UNIX-style line endings in the text -files, or lpng*.zip if you want DOS-style line endings. - -Version 0.89 was the first official release of libpng. Don't let the -fact that it's the first release fool you. The libpng library has been in -extensive use and testing since mid-1995. By late 1997 it had -finally gotten to the stage where there hadn't been significant -changes to the API in some time, and people have a bad feeling about -libraries with versions < 1.0. Version 1.0.0 was released in -March 1998. - -**** -Note that some of the changes to the png_info structure render this -version of the library binary incompatible with libpng-0.89 or -earlier versions if you are using a shared library. The type of the -"filler" parameter for png_set_filler() has changed from png_byte to -png_uint_32, which will affect shared-library applications that use -this function. - -To avoid problems with changes to the internals of png_info_struct, -new APIs have been made available in 0.95 to avoid direct application -access to info_ptr. These functions are the png_set_ and -png_get_ functions. These functions should be used when -accessing/storing the info_struct data, rather than manipulating it -directly, to avoid such problems in the future. - -It is important to note that the APIs do not make current programs -that access the info struct directly incompatible with the new -library. However, it is strongly suggested that new programs use -the new APIs (as shown in example.c and pngtest.c), and older programs -be converted to the new format, to facilitate upgrades in the future. -**** - -Additions since 0.90 include the ability to compile libpng as a -Windows DLL, and new APIs for accessing data in the info struct. -Experimental functions include the ability to set weighting and cost -factors for row filter selection, direct reads of integers from buffers -on big-endian processors that support misaligned data access, faster -methods of doing alpha composition, and more accurate 16->8 bit color -conversion. - -The additions since 0.89 include the ability to read from a PNG stream -which has had some (or all) of the signature bytes read by the calling -application. This also allows the reading of embedded PNG streams that -do not have the PNG file signature. As well, it is now possible to set -the library action on the detection of chunk CRC errors. It is possible -to set different actions based on whether the CRC error occurred in a -critical or an ancillary chunk. - -The changes made to the library, and bugs fixed are based on discussions -on the PNG-implement mailing list -and not on material submitted privately to Guy, Andreas, or Glenn. They will -forward any good suggestions to the list. - -For a detailed description on using libpng, read libpng.txt. For -examples of libpng in a program, see example.c and pngtest.c. For usage -information and restrictions (what little they are) on libpng, see -png.h. For a description on using zlib (the compression library used by -libpng) and zlib's restrictions, see zlib.h - -I have included a general makefile, as well as several machine and -compiler specific ones, but you may have to modify one for your own needs. - -You should use zlib 1.0.4 or later to run this, but it MAY work with -versions as old as zlib 0.95. Even so, there are bugs in older zlib -versions which can cause the output of invalid compression streams for -some images. You will definitely need zlib 1.0.4 or later if you are -taking advantage of the MS-DOS "far" structure allocation for the small -and medium memory models. You should also note that zlib is a -compression library that is useful for more things than just PNG files. -You can use zlib as a drop-in replacement for fread() and fwrite() if -you are so inclined. - -zlib should be available at the same place that libpng is, or at. -ftp://ftp.info-zip.org/pub/infozip/zlib - -You may also want a copy of the PNG specification. It is available -as an RFC, a W3C Recommendation, and an ISO/IEC Standard. You can find -these at http://www.libpng.org/pub/png/documents/ - -This code is currently being archived at libpng.sf.net in the -[DOWNLOAD] area, and on CompuServe, Lib 20 (PNG SUPPORT) -at GO GRAPHSUP. If you can't find it in any of those places, -e-mail me, and I'll help you find it. - -If you have any code changes, requests, problems, etc., please e-mail -them to me. Also, I'd appreciate any make files or project files, -and any modifications you needed to make to get libpng to compile, -along with a #define variable to tell what compiler/system you are on. -If you needed to add transformations to libpng, or wish libpng would -provide the image in a different way, drop me a note (and code, if -possible), so I can consider supporting the transformation. -Finally, if you get any warning messages when compiling libpng -(note: not zlib), and they are easy to fix, I'd appreciate the -fix. Please mention "libpng" somewhere in the subject line. Thanks. - -This release was created and will be supported by myself (of course -based in a large way on Guy's and Andreas' earlier work), and the PNG group. - -Send comments/corrections/commendations to png-mng-implement at lists.sf.net -(subscription required; visit -https://lists.sourceforge.net/lists/listinfo/png-mng-implement -to subscribe) or to glennrp at users.sourceforge.net - -You can't reach Guy, the original libpng author, at the addresses -given in previous versions of this document. He and Andreas will read mail -addressed to the png-implement list, however. - -Please do not send general questions about PNG. Send them to -the (png-list at ccrc.wustl.edu, subscription required, write to -majordomo at ccrc.wustl.edu with "subscribe png-list" in your message). -On the other hand, -please do not send libpng questions to that address, send them to me -or to the png-implement list. I'll -get them in the end anyway. If you have a question about something -in the PNG specification that is related to using libpng, send it -to me. Send me any questions that start with "I was using libpng, -and ...". If in doubt, send questions to me. I'll bounce them -to others, if necessary. - -Please do not send suggestions on how to change PNG. We have -been discussing PNG for nine years now, and it is official and -finished. If you have suggestions for libpng, however, I'll -gladly listen. Even if your suggestion is not used immediately, -it may be used later. - -Files in this distribution: - - ANNOUNCE => Announcement of this version, with recent changes - CHANGES => Description of changes between libpng versions - KNOWNBUG => List of known bugs and deficiencies - LICENSE => License to use and redistribute libpng - README => This file - TODO => Things not implemented in the current library - Y2KINFO => Statement of Y2K compliance - example.c => Example code for using libpng functions - libpng-*-*-diff.txt => Diff from previous release - libpng.3 => manual page for libpng (includes libpng.txt) - libpng.txt => Description of libpng and its functions - libpngpf.3 => manual page for libpng's private functions - png.5 => manual page for the PNG format - png.c => Basic interface functions common to library - png.h => Library function and interface declarations - pngconf.h => System specific library configuration - pngerror.c => Error/warning message I/O functions - pngget.c => Functions for retrieving info from struct - pngmem.c => Memory handling functions - pngbar.png => PNG logo, 88x31 - pngnow.png => PNG logo, 98x31 - pngpread.c => Progressive reading functions - pngread.c => Read data/helper high-level functions - pngrio.c => Lowest-level data read I/O functions - pngrtran.c => Read data transformation functions - pngrutil.c => Read data utility functions - pngset.c => Functions for storing data into the info_struct - pngtest.c => Library test program - pngtest.png => Library test sample image - pngtrans.c => Common data transformation functions - pngwio.c => Lowest-level write I/O functions - pngwrite.c => High-level write functions - pngwtran.c => Write data transformations - pngwutil.c => Write utility functions - contrib => Contributions - gregbook => source code for PNG reading and writing, from - Greg Roelofs' "PNG: The Definitive Guide", - O'Reilly, 1999 - msvctest => Builds and runs pngtest using a MSVC workspace - pngminus => Simple pnm2png and png2pnm programs - pngsuite => Test images - visupng => Contains a MSVC workspace for VisualPng - projects => Contains project files and workspaces for building DLL - beos => Contains a Beos workspace for building libpng - c5builder => Contains a Borland workspace for building libpng - and zlib - visualc6 => Contains a Microsoft Visual C++ (MSVC) workspace - for building libpng and zlib - netware.txt => Contains instructions for downloading a set of - project files for building libpng and zlib on - Netware. - wince.txt => Contains instructions for downloading a Microsoft - Visual C++ (Windows CD Toolkit) workspace for - building libpng and zlib on WindowsCE - scripts => Directory containing scripts for building libpng: - descrip.mms => VMS makefile for MMS or MMK - makefile.std => Generic UNIX makefile (cc, creates static libpng.a) - makefile.elf => Linux/ELF makefile symbol versioning, - gcc, creates libpng12.so.0.1.2.22) - makefile.linux => Linux/ELF makefile - (gcc, creates libpng12.so.0.1.2.22) - makefile.gcmmx => Linux/ELF makefile - (gcc, creates libpng12.so.0.1.2.22, - uses assembler code tuned for Intel MMX platform) - makefile.gcc => Generic makefile (gcc, creates static libpng.a) - makefile.knr => Archaic UNIX Makefile that converts files with - ansi2knr (Requires ansi2knr.c from - ftp://ftp.cs.wisc.edu/ghost) - makefile.aix => AIX makefile - makefile.cygwin => Cygwin/gcc makefile - makefile.darwin => Darwin makefile - makefile.dec => DEC Alpha UNIX makefile - makefile.freebsd => FreeBSD makefile - makefile.hpgcc => HPUX makefile using gcc - makefile.hpux => HPUX (10.20 and 11.00) makefile - makefile.hp64 => HPUX (10.20 and 11.00) makefile, 64 bit - makefile.ibmc => IBM C/C++ version 3.x for Win32 and OS/2 (static) - makefile.intel => Intel C/C++ version 4.0 and later - libpng.icc => Project file, IBM VisualAge/C++ 4.0 or later - makefile.netbsd => NetBSD/cc makefile, PNGGCCRD, makes libpng.so. - makefile.ne12bsd => NetBSD/cc makefile, PNGGCCRD, makes libpng12.so - makefile.openbsd => OpenBSD makefile - makefile.sgi => Silicon Graphics IRIX (cc, creates static lib) - makefile.sggcc => Silicon Graphics - (gcc, creates libpng12.so.0.1.2.22) - makefile.sunos => Sun makefile - makefile.solaris => Solaris 2.X makefile - (gcc, creates libpng12.so.0.1.2.22) - makefile.so9 => Solaris 9 makefile - (gcc, creates libpng12.so.0.1.2.22) - makefile.32sunu => Sun Ultra 32-bit makefile - makefile.64sunu => Sun Ultra 64-bit makefile - makefile.sco => For SCO OSr5 ELF and Unixware 7 with Native cc - makefile.mips => MIPS makefile - makefile.acorn => Acorn makefile - makefile.amiga => Amiga makefile - smakefile.ppc => AMIGA smakefile for SAS C V6.58/7.00 PPC - compiler (Requires SCOPTIONS, copied from - scripts/SCOPTIONS.ppc) - makefile.atari => Atari makefile - makefile.beos => BEOS makefile for X86 - makefile.bor => Borland makefile (uses bcc) - makefile.bc32 => 32-bit Borland C++ (all modules compiled in C mode) - makefile.tc3 => Turbo C 3.0 makefile - makefile.dj2 => DJGPP 2 makefile - makefile.msc => Microsoft C makefile - makefile.vcawin32=> makefile for Microsoft Visual C++ 5.0 and - later (uses assembler code tuned for Intel MMX - platform) - makefile.vcwin32 => makefile for Microsoft Visual C++ 4.0 and - later (does not use assembler code) - makefile.os2 => OS/2 Makefile (gcc and emx, requires pngos2.def) - pngos2.def => OS/2 module definition file used by makefile.os2 - makefile.watcom => Watcom 10a+ Makefile, 32-bit flat memory model - makevms.com => VMS build script - SCOPTIONS.ppc => Used with smakefile.ppc - -Good luck, and happy coding. - --Glenn Randers-Pehrson (current maintainer) - Internet: glennrp at users.sourceforge.net - --Andreas Eric Dilger (former maintainer, 1996-1997) - Internet: adilger at enel.ucalgary.ca - Web: http://www-mddsp.enel.ucalgary.ca/People/adilger/ - --Guy Eric Schalnat (original author and former maintainer, 1995-1996) - (formerly of Group 42, Inc) - Internet: gschal at infinet.com diff --git a/uppdev/plugin/png/lib/example.c b/uppdev/plugin/png/lib/example.c deleted file mode 100644 index 2db293a30..000000000 --- a/uppdev/plugin/png/lib/example.c +++ /dev/null @@ -1,814 +0,0 @@ - -#if 0 /* in case someone actually tries to compile this */ - -/* example.c - an example of using libpng - * Last changed in libpng 1.2.1 December 7, 2001. - * This file has been placed in the public domain by the authors. - * Maintained 1998-2007 Glenn Randers-Pehrson - * Maintained 1996, 1997 Andreas Dilger) - * Written 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - */ - -/* This is an example of how to use libpng to read and write PNG files. - * The file libpng.txt is much more verbose then this. If you have not - * read it, do so first. This was designed to be a starting point of an - * implementation. This is not officially part of libpng, is hereby placed - * in the public domain, and therefore does not require a copyright notice. - * - * This file does not currently compile, because it is missing certain - * parts, like allocating memory to hold an image. You will have to - * supply these parts to get it to compile. For an example of a minimal - * working PNG reader/writer, see pngtest.c, included in this distribution; - * see also the programs in the contrib directory. - */ - -#include "png.h" - - /* The png_jmpbuf() macro, used in error handling, became available in - * libpng version 1.0.6. If you want to be able to run your code with older - * versions of libpng, you must define the macro yourself (but only if it - * is not already defined by libpng!). - */ - -#ifndef png_jmpbuf -# define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) -#endif - -/* Check to see if a file is a PNG file using png_sig_cmp(). png_sig_cmp() - * returns zero if the image is a PNG and nonzero if it isn't a PNG. - * - * The function check_if_png() shown here, but not used, returns nonzero (true) - * if the file can be opened and is a PNG, 0 (false) otherwise. - * - * If this call is successful, and you are going to keep the file open, - * you should call png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK); once - * you have created the png_ptr, so that libpng knows your application - * has read that many bytes from the start of the file. Make sure you - * don't call png_set_sig_bytes() with more than 8 bytes read or give it - * an incorrect number of bytes read, or you will either have read too - * many bytes (your fault), or you are telling libpng to read the wrong - * number of magic bytes (also your fault). - * - * Many applications already read the first 2 or 4 bytes from the start - * of the image to determine the file type, so it would be easiest just - * to pass the bytes to png_sig_cmp() or even skip that if you know - * you have a PNG file, and call png_set_sig_bytes(). - */ -#define PNG_BYTES_TO_CHECK 4 -int check_if_png(char *file_name, FILE **fp) -{ - char buf[PNG_BYTES_TO_CHECK]; - - /* Open the prospective PNG file. */ - if ((*fp = fopen(file_name, "rb")) == NULL) - return 0; - - /* Read in some of the signature bytes */ - if (fread(buf, 1, PNG_BYTES_TO_CHECK, *fp) != PNG_BYTES_TO_CHECK) - return 0; - - /* Compare the first PNG_BYTES_TO_CHECK bytes of the signature. - Return nonzero (true) if they match */ - - return(!png_sig_cmp(buf, (png_size_t)0, PNG_BYTES_TO_CHECK)); -} - -/* Read a PNG file. You may want to return an error code if the read - * fails (depending upon the failure). There are two "prototypes" given - * here - one where we are given the filename, and we need to open the - * file, and the other where we are given an open file (possibly with - * some or all of the magic bytes read - see comments above). - */ -#ifdef open_file /* prototype 1 */ -void read_png(char *file_name) /* We need to open the file */ -{ - png_structp png_ptr; - png_infop info_ptr; - unsigned int sig_read = 0; - png_uint_32 width, height; - int bit_depth, color_type, interlace_type; - FILE *fp; - - if ((fp = fopen(file_name, "rb")) == NULL) - return (ERROR); -#else no_open_file /* prototype 2 */ -void read_png(FILE *fp, unsigned int sig_read) /* file is already open */ -{ - png_structp png_ptr; - png_infop info_ptr; - png_uint_32 width, height; - int bit_depth, color_type, interlace_type; -#endif no_open_file /* only use one prototype! */ - - /* Create and initialize the png_struct with the desired error handler - * functions. If you want to use the default stderr and longjump method, - * you can supply NULL for the last three parameters. We also supply the - * the compiler header file version, so that we know if the application - * was compiled with a compatible version of the library. REQUIRED - */ - png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, - png_voidp user_error_ptr, user_error_fn, user_warning_fn); - - if (png_ptr == NULL) - { - fclose(fp); - return (ERROR); - } - - /* Allocate/initialize the memory for image information. REQUIRED. */ - info_ptr = png_create_info_struct(png_ptr); - if (info_ptr == NULL) - { - fclose(fp); - png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL); - return (ERROR); - } - - /* Set error handling if you are using the setjmp/longjmp method (this is - * the normal method of doing things with libpng). REQUIRED unless you - * set up your own error handlers in the png_create_read_struct() earlier. - */ - - if (setjmp(png_jmpbuf(png_ptr))) - { - /* Free all of the memory associated with the png_ptr and info_ptr */ - png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); - fclose(fp); - /* If we get here, we had a problem reading the file */ - return (ERROR); - } - - /* One of the following I/O initialization methods is REQUIRED */ -#ifdef streams /* PNG file I/O method 1 */ - /* Set up the input control if you are using standard C streams */ - png_init_io(png_ptr, fp); - -#else no_streams /* PNG file I/O method 2 */ - /* If you are using replacement read functions, instead of calling - * png_init_io() here you would call: - */ - png_set_read_fn(png_ptr, (void *)user_io_ptr, user_read_fn); - /* where user_io_ptr is a structure you want available to the callbacks */ -#endif no_streams /* Use only one I/O method! */ - - /* If we have already read some of the signature */ - png_set_sig_bytes(png_ptr, sig_read); - -#ifdef hilevel - /* - * If you have enough memory to read in the entire image at once, - * and you need to specify only transforms that can be controlled - * with one of the PNG_TRANSFORM_* bits (this presently excludes - * dithering, filling, setting background, and doing gamma - * adjustment), then you can read the entire image (including - * pixels) into the info structure with this call: - */ - png_read_png(png_ptr, info_ptr, png_transforms, png_voidp_NULL); -#else - /* OK, you're doing it the hard way, with the lower-level functions */ - - /* The call to png_read_info() gives us all of the information from the - * PNG file before the first IDAT (image data chunk). REQUIRED - */ - png_read_info(png_ptr, info_ptr); - - png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, - &interlace_type, int_p_NULL, int_p_NULL); - -/* Set up the data transformations you want. Note that these are all - * optional. Only call them if you want/need them. Many of the - * transformations only work on specific types of images, and many - * are mutually exclusive. - */ - - /* tell libpng to strip 16 bit/color files down to 8 bits/color */ - png_set_strip_16(png_ptr); - - /* Strip alpha bytes from the input data without combining with the - * background (not recommended). - */ - png_set_strip_alpha(png_ptr); - - /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single - * byte into separate bytes (useful for paletted and grayscale images). - */ - png_set_packing(png_ptr); - - /* Change the order of packed pixels to least significant bit first - * (not useful if you are using png_set_packing). */ - png_set_packswap(png_ptr); - - /* Expand paletted colors into true RGB triplets */ - if (color_type == PNG_COLOR_TYPE_PALETTE) - png_set_palette_to_rgb(png_ptr); - - /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */ - if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) - png_set_gray_1_2_4_to_8(png_ptr); - - /* Expand paletted or RGB images with transparency to full alpha channels - * so the data will be available as RGBA quartets. - */ - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) - png_set_tRNS_to_alpha(png_ptr); - - /* Set the background color to draw transparent and alpha images over. - * It is possible to set the red, green, and blue components directly - * for paletted images instead of supplying a palette index. Note that - * even if the PNG file supplies a background, you are not required to - * use it - you should use the (solid) application background if it has one. - */ - - png_color_16 my_background, *image_background; - - if (png_get_bKGD(png_ptr, info_ptr, &image_background)) - png_set_background(png_ptr, image_background, - PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); - else - png_set_background(png_ptr, &my_background, - PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); - - /* Some suggestions as to how to get a screen gamma value */ - - /* Note that screen gamma is the display_exponent, which includes - * the CRT_exponent and any correction for viewing conditions */ - if (/* We have a user-defined screen gamma value */) - { - screen_gamma = user-defined screen_gamma; - } - /* This is one way that applications share the same screen gamma value */ - else if ((gamma_str = getenv("SCREEN_GAMMA")) != NULL) - { - screen_gamma = atof(gamma_str); - } - /* If we don't have another value */ - else - { - screen_gamma = 2.2; /* A good guess for a PC monitors in a dimly - lit room */ - screen_gamma = 1.7 or 1.0; /* A good guess for Mac systems */ - } - - /* Tell libpng to handle the gamma conversion for you. The final call - * is a good guess for PC generated images, but it should be configurable - * by the user at run time by the user. It is strongly suggested that - * your application support gamma correction. - */ - - int intent; - - if (png_get_sRGB(png_ptr, info_ptr, &intent)) - png_set_gamma(png_ptr, screen_gamma, 0.45455); - else - { - double image_gamma; - if (png_get_gAMA(png_ptr, info_ptr, &image_gamma)) - png_set_gamma(png_ptr, screen_gamma, image_gamma); - else - png_set_gamma(png_ptr, screen_gamma, 0.45455); - } - - /* Dither RGB files down to 8 bit palette or reduce palettes - * to the number of colors available on your screen. - */ - if (color_type & PNG_COLOR_MASK_COLOR) - { - int num_palette; - png_colorp palette; - - /* This reduces the image to the application supplied palette */ - if (/* we have our own palette */) - { - /* An array of colors to which the image should be dithered */ - png_color std_color_cube[MAX_SCREEN_COLORS]; - - png_set_dither(png_ptr, std_color_cube, MAX_SCREEN_COLORS, - MAX_SCREEN_COLORS, png_uint_16p_NULL, 0); - } - /* This reduces the image to the palette supplied in the file */ - else if (png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette)) - { - png_uint_16p histogram = NULL; - - png_get_hIST(png_ptr, info_ptr, &histogram); - - png_set_dither(png_ptr, palette, num_palette, - max_screen_colors, histogram, 0); - } - } - - /* invert monochrome files to have 0 as white and 1 as black */ - png_set_invert_mono(png_ptr); - - /* If you want to shift the pixel values from the range [0,255] or - * [0,65535] to the original [0,7] or [0,31], or whatever range the - * colors were originally in: - */ - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT)) - { - png_color_8p sig_bit; - - png_get_sBIT(png_ptr, info_ptr, &sig_bit); - png_set_shift(png_ptr, sig_bit); - } - - /* flip the RGB pixels to BGR (or RGBA to BGRA) */ - if (color_type & PNG_COLOR_MASK_COLOR) - png_set_bgr(png_ptr); - - /* swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */ - png_set_swap_alpha(png_ptr); - - /* swap bytes of 16 bit files to least significant byte first */ - png_set_swap(png_ptr); - - /* Add filler (or alpha) byte (before/after each RGB triplet) */ - png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); - - /* Turn on interlace handling. REQUIRED if you are not using - * png_read_image(). To see how to handle interlacing passes, - * see the png_read_row() method below: - */ - number_passes = png_set_interlace_handling(png_ptr); - - /* Optional call to gamma correct and add the background to the palette - * and update info structure. REQUIRED if you are expecting libpng to - * update the palette for you (ie you selected such a transform above). - */ - png_read_update_info(png_ptr, info_ptr); - - /* Allocate the memory to hold the image using the fields of info_ptr. */ - - /* The easiest way to read the image: */ - png_bytep row_pointers[height]; - - for (row = 0; row < height; row++) - { - row_pointers[row] = png_malloc(png_ptr, png_get_rowbytes(png_ptr, - info_ptr)); - } - - /* Now it's time to read the image. One of these methods is REQUIRED */ -#ifdef entire /* Read the entire image in one go */ - png_read_image(png_ptr, row_pointers); - -#else no_entire /* Read the image one or more scanlines at a time */ - /* The other way to read images - deal with interlacing: */ - - for (pass = 0; pass < number_passes; pass++) - { -#ifdef single /* Read the image a single row at a time */ - for (y = 0; y < height; y++) - { - png_read_rows(png_ptr, &row_pointers[y], png_bytepp_NULL, 1); - } - -#else no_single /* Read the image several rows at a time */ - for (y = 0; y < height; y += number_of_rows) - { -#ifdef sparkle /* Read the image using the "sparkle" effect. */ - png_read_rows(png_ptr, &row_pointers[y], png_bytepp_NULL, - number_of_rows); -#else no_sparkle /* Read the image using the "rectangle" effect */ - png_read_rows(png_ptr, png_bytepp_NULL, &row_pointers[y], - number_of_rows); -#endif no_sparkle /* use only one of these two methods */ - } - - /* if you want to display the image after every pass, do - so here */ -#endif no_single /* use only one of these two methods */ - } -#endif no_entire /* use only one of these two methods */ - - /* read rest of file, and get additional chunks in info_ptr - REQUIRED */ - png_read_end(png_ptr, info_ptr); -#endif hilevel - - /* At this point you have read the entire image */ - - /* clean up after the read, and free any memory allocated - REQUIRED */ - png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); - - /* close the file */ - fclose(fp); - - /* that's it */ - return (OK); -} - -/* progressively read a file */ - -int -initialize_png_reader(png_structp *png_ptr, png_infop *info_ptr) -{ - /* Create and initialize the png_struct with the desired error handler - * functions. If you want to use the default stderr and longjump method, - * you can supply NULL for the last three parameters. We also check that - * the library version is compatible in case we are using dynamically - * linked libraries. - */ - *png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, - png_voidp user_error_ptr, user_error_fn, user_warning_fn); - - if (*png_ptr == NULL) - { - *info_ptr = NULL; - return (ERROR); - } - - *info_ptr = png_create_info_struct(png_ptr); - - if (*info_ptr == NULL) - { - png_destroy_read_struct(png_ptr, info_ptr, png_infopp_NULL); - return (ERROR); - } - - if (setjmp(png_jmpbuf((*png_ptr)))) - { - png_destroy_read_struct(png_ptr, info_ptr, png_infopp_NULL); - return (ERROR); - } - - /* This one's new. You will need to provide all three - * function callbacks, even if you aren't using them all. - * If you aren't using all functions, you can specify NULL - * parameters. Even when all three functions are NULL, - * you need to call png_set_progressive_read_fn(). - * These functions shouldn't be dependent on global or - * static variables if you are decoding several images - * simultaneously. You should store stream specific data - * in a separate struct, given as the second parameter, - * and retrieve the pointer from inside the callbacks using - * the function png_get_progressive_ptr(png_ptr). - */ - png_set_progressive_read_fn(*png_ptr, (void *)stream_data, - info_callback, row_callback, end_callback); - - return (OK); -} - -int -process_data(png_structp *png_ptr, png_infop *info_ptr, - png_bytep buffer, png_uint_32 length) -{ - if (setjmp(png_jmpbuf((*png_ptr)))) - { - /* Free the png_ptr and info_ptr memory on error */ - png_destroy_read_struct(png_ptr, info_ptr, png_infopp_NULL); - return (ERROR); - } - - /* This one's new also. Simply give it chunks of data as - * they arrive from the data stream (in order, of course). - * On Segmented machines, don't give it any more than 64K. - * The library seems to run fine with sizes of 4K, although - * you can give it much less if necessary (I assume you can - * give it chunks of 1 byte, but I haven't tried with less - * than 256 bytes yet). When this function returns, you may - * want to display any rows that were generated in the row - * callback, if you aren't already displaying them there. - */ - png_process_data(*png_ptr, *info_ptr, buffer, length); - return (OK); -} - -info_callback(png_structp png_ptr, png_infop info) -{ -/* do any setup here, including setting any of the transformations - * mentioned in the Reading PNG files section. For now, you _must_ - * call either png_start_read_image() or png_read_update_info() - * after all the transformations are set (even if you don't set - * any). You may start getting rows before png_process_data() - * returns, so this is your last chance to prepare for that. - */ -} - -row_callback(png_structp png_ptr, png_bytep new_row, - png_uint_32 row_num, int pass) -{ -/* - * This function is called for every row in the image. If the - * image is interlaced, and you turned on the interlace handler, - * this function will be called for every row in every pass. - * - * In this function you will receive a pointer to new row data from - * libpng called new_row that is to replace a corresponding row (of - * the same data format) in a buffer allocated by your application. - * - * The new row data pointer new_row may be NULL, indicating there is - * no new data to be replaced (in cases of interlace loading). - * - * If new_row is not NULL then you need to call - * png_progressive_combine_row() to replace the corresponding row as - * shown below: - */ - /* Check if row_num is in bounds. */ - if((row_num >= 0) && (row_num < height)) - { - /* Get pointer to corresponding row in our - * PNG read buffer. - */ - png_bytep old_row = ((png_bytep *)our_data)[row_num]; - - /* If both rows are allocated then copy the new row - * data to the corresponding row data. - */ - if((old_row != NULL) && (new_row != NULL)) - png_progressive_combine_row(png_ptr, old_row, new_row); - } -/* - * The rows and passes are called in order, so you don't really - * need the row_num and pass, but I'm supplying them because it - * may make your life easier. - * - * For the non-NULL rows of interlaced images, you must call - * png_progressive_combine_row() passing in the new row and the - * old row, as demonstrated above. You can call this function for - * NULL rows (it will just return) and for non-interlaced images - * (it just does the png_memcpy for you) if it will make the code - * easier. Thus, you can just do this for all cases: - */ - - png_progressive_combine_row(png_ptr, old_row, new_row); - -/* where old_row is what was displayed for previous rows. Note - * that the first pass (pass == 0 really) will completely cover - * the old row, so the rows do not have to be initialized. After - * the first pass (and only for interlaced images), you will have - * to pass the current row as new_row, and the function will combine - * the old row and the new row. - */ -} - -end_callback(png_structp png_ptr, png_infop info) -{ -/* this function is called when the whole image has been read, - * including any chunks after the image (up to and including - * the IEND). You will usually have the same info chunk as you - * had in the header, although some data may have been added - * to the comments and time fields. - * - * Most people won't do much here, perhaps setting a flag that - * marks the image as finished. - */ -} - -/* write a png file */ -void write_png(char *file_name /* , ... other image information ... */) -{ - FILE *fp; - png_structp png_ptr; - png_infop info_ptr; - png_colorp palette; - - /* open the file */ - fp = fopen(file_name, "wb"); - if (fp == NULL) - return (ERROR); - - /* Create and initialize the png_struct with the desired error handler - * functions. If you want to use the default stderr and longjump method, - * you can supply NULL for the last three parameters. We also check that - * the library version is compatible with the one used at compile time, - * in case we are using dynamically linked libraries. REQUIRED. - */ - png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, - png_voidp user_error_ptr, user_error_fn, user_warning_fn); - - if (png_ptr == NULL) - { - fclose(fp); - return (ERROR); - } - - /* Allocate/initialize the image information data. REQUIRED */ - info_ptr = png_create_info_struct(png_ptr); - if (info_ptr == NULL) - { - fclose(fp); - png_destroy_write_struct(&png_ptr, png_infopp_NULL); - return (ERROR); - } - - /* Set error handling. REQUIRED if you aren't supplying your own - * error handling functions in the png_create_write_struct() call. - */ - if (setjmp(png_jmpbuf(png_ptr))) - { - /* If we get here, we had a problem reading the file */ - fclose(fp); - png_destroy_write_struct(&png_ptr, &info_ptr); - return (ERROR); - } - - /* One of the following I/O initialization functions is REQUIRED */ -#ifdef streams /* I/O initialization method 1 */ - /* set up the output control if you are using standard C streams */ - png_init_io(png_ptr, fp); -#else no_streams /* I/O initialization method 2 */ - /* If you are using replacement read functions, instead of calling - * png_init_io() here you would call */ - png_set_write_fn(png_ptr, (void *)user_io_ptr, user_write_fn, - user_IO_flush_function); - /* where user_io_ptr is a structure you want available to the callbacks */ -#endif no_streams /* only use one initialization method */ - -#ifdef hilevel - /* This is the easy way. Use it if you already have all the - * image info living info in the structure. You could "|" many - * PNG_TRANSFORM flags into the png_transforms integer here. - */ - png_write_png(png_ptr, info_ptr, png_transforms, png_voidp_NULL); -#else - /* This is the hard way */ - - /* Set the image information here. Width and height are up to 2^31, - * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on - * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY, - * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB, - * or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or - * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST - * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED - */ - png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, PNG_COLOR_TYPE_???, - PNG_INTERLACE_????, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); - - /* set the palette if there is one. REQUIRED for indexed-color images */ - palette = (png_colorp)png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH - * png_sizeof (png_color)); - /* ... set palette colors ... */ - png_set_PLTE(png_ptr, info_ptr, palette, PNG_MAX_PALETTE_LENGTH); - /* You must not free palette here, because png_set_PLTE only makes a link to - the palette that you malloced. Wait until you are about to destroy - the png structure. */ - - /* optional significant bit chunk */ - /* if we are dealing with a grayscale image then */ - sig_bit.gray = true_bit_depth; - /* otherwise, if we are dealing with a color image then */ - sig_bit.red = true_red_bit_depth; - sig_bit.green = true_green_bit_depth; - sig_bit.blue = true_blue_bit_depth; - /* if the image has an alpha channel then */ - sig_bit.alpha = true_alpha_bit_depth; - png_set_sBIT(png_ptr, info_ptr, sig_bit); - - - /* Optional gamma chunk is strongly suggested if you have any guess - * as to the correct gamma of the image. - */ - png_set_gAMA(png_ptr, info_ptr, gamma); - - /* Optionally write comments into the image */ - text_ptr[0].key = "Title"; - text_ptr[0].text = "Mona Lisa"; - text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE; - text_ptr[1].key = "Author"; - text_ptr[1].text = "Leonardo DaVinci"; - text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE; - text_ptr[2].key = "Description"; - text_ptr[2].text = ""; - text_ptr[2].compression = PNG_TEXT_COMPRESSION_zTXt; -#ifdef PNG_iTXt_SUPPORTED - text_ptr[0].lang = NULL; - text_ptr[1].lang = NULL; - text_ptr[2].lang = NULL; -#endif - png_set_text(png_ptr, info_ptr, text_ptr, 3); - - /* other optional chunks like cHRM, bKGD, tRNS, tIME, oFFs, pHYs, */ - /* note that if sRGB is present the gAMA and cHRM chunks must be ignored - * on read and must be written in accordance with the sRGB profile */ - - /* Write the file header information. REQUIRED */ - png_write_info(png_ptr, info_ptr); - - /* If you want, you can write the info in two steps, in case you need to - * write your private chunk ahead of PLTE: - * - * png_write_info_before_PLTE(write_ptr, write_info_ptr); - * write_my_chunk(); - * png_write_info(png_ptr, info_ptr); - * - * However, given the level of known- and unknown-chunk support in 1.1.0 - * and up, this should no longer be necessary. - */ - - /* Once we write out the header, the compression type on the text - * chunks gets changed to PNG_TEXT_COMPRESSION_NONE_WR or - * PNG_TEXT_COMPRESSION_zTXt_WR, so it doesn't get written out again - * at the end. - */ - - /* set up the transformations you want. Note that these are - * all optional. Only call them if you want them. - */ - - /* invert monochrome pixels */ - png_set_invert_mono(png_ptr); - - /* Shift the pixels up to a legal bit depth and fill in - * as appropriate to correctly scale the image. - */ - png_set_shift(png_ptr, &sig_bit); - - /* pack pixels into bytes */ - png_set_packing(png_ptr); - - /* swap location of alpha bytes from ARGB to RGBA */ - png_set_swap_alpha(png_ptr); - - /* Get rid of filler (OR ALPHA) bytes, pack XRGB/RGBX/ARGB/RGBA into - * RGB (4 channels -> 3 channels). The second parameter is not used. - */ - png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); - - /* flip BGR pixels to RGB */ - png_set_bgr(png_ptr); - - /* swap bytes of 16-bit files to most significant byte first */ - png_set_swap(png_ptr); - - /* swap bits of 1, 2, 4 bit packed pixel formats */ - png_set_packswap(png_ptr); - - /* turn on interlace handling if you are not using png_write_image() */ - if (interlacing) - number_passes = png_set_interlace_handling(png_ptr); - else - number_passes = 1; - - /* The easiest way to write the image (you may have a different memory - * layout, however, so choose what fits your needs best). You need to - * use the first method if you aren't handling interlacing yourself. - */ - png_uint_32 k, height, width; - png_byte image[height][width*bytes_per_pixel]; - png_bytep row_pointers[height]; - - if (height > PNG_UINT_32_MAX/png_sizeof(png_bytep)) - png_error (png_ptr, "Image is too tall to process in memory"); - - for (k = 0; k < height; k++) - row_pointers[k] = image + k*width*bytes_per_pixel; - - /* One of the following output methods is REQUIRED */ -#ifdef entire /* write out the entire image data in one call */ - png_write_image(png_ptr, row_pointers); - - /* the other way to write the image - deal with interlacing */ - -#else no_entire /* write out the image data by one or more scanlines */ - /* The number of passes is either 1 for non-interlaced images, - * or 7 for interlaced images. - */ - for (pass = 0; pass < number_passes; pass++) - { - /* Write a few rows at a time. */ - png_write_rows(png_ptr, &row_pointers[first_row], number_of_rows); - - /* If you are only writing one row at a time, this works */ - for (y = 0; y < height; y++) - { - png_write_rows(png_ptr, &row_pointers[y], 1); - } - } -#endif no_entire /* use only one output method */ - - /* You can write optional chunks like tEXt, zTXt, and tIME at the end - * as well. Shouldn't be necessary in 1.1.0 and up as all the public - * chunks are supported and you can use png_set_unknown_chunks() to - * register unknown chunks into the info structure to be written out. - */ - - /* It is REQUIRED to call this to finish writing the rest of the file */ - png_write_end(png_ptr, info_ptr); -#endif hilevel - - /* If you png_malloced a palette, free it here (don't free info_ptr->palette, - as recommended in versions 1.0.5m and earlier of this example; if - libpng mallocs info_ptr->palette, libpng will free it). If you - allocated it with malloc() instead of png_malloc(), use free() instead - of png_free(). */ - png_free(png_ptr, palette); - palette=NULL; - - /* Similarly, if you png_malloced any data that you passed in with - png_set_something(), such as a hist or trans array, free it here, - when you can be sure that libpng is through with it. */ - png_free(png_ptr, trans); - trans=NULL; - - /* clean up after the write, and free any memory allocated */ - png_destroy_write_struct(&png_ptr, &info_ptr); - - /* close the file */ - fclose(fp); - - /* that's it */ - return (OK); -} - -#endif /* if 0 */ diff --git a/uppdev/plugin/png/lib/libpng-1.2.22.txt b/uppdev/plugin/png/lib/libpng-1.2.22.txt deleted file mode 100644 index f59e2522d..000000000 --- a/uppdev/plugin/png/lib/libpng-1.2.22.txt +++ /dev/null @@ -1,2851 +0,0 @@ -libpng.txt - A description on how to use and modify libpng - - libpng version 1.2.22 - October 13, 2007 - Updated and distributed by Glenn Randers-Pehrson - - Copyright (c) 1998-2007 Glenn Randers-Pehrson - For conditions of distribution and use, see copyright - notice in png.h. - - based on: - - libpng 1.0 beta 6 version 0.96 May 28, 1997 - Updated and distributed by Andreas Dilger - Copyright (c) 1996, 1997 Andreas Dilger - - libpng 1.0 beta 2 - version 0.88 January 26, 1996 - For conditions of distribution and use, see copyright - notice in png.h. Copyright (c) 1995, 1996 Guy Eric - Schalnat, Group 42, Inc. - - Updated/rewritten per request in the libpng FAQ - Copyright (c) 1995, 1996 Frank J. T. Wojcik - December 18, 1995 & January 20, 1996 - -I. Introduction - -This file describes how to use and modify the PNG reference library -(known as libpng) for your own use. There are five sections to this -file: introduction, structures, reading, writing, and modification and -configuration notes for various special platforms. In addition to this -file, example.c is a good starting point for using the library, as -it is heavily commented and should include everything most people -will need. We assume that libpng is already installed; see the -INSTALL file for instructions on how to install libpng. - -For examples of libpng usage, see the files "example.c", "pngtest.c", -and the files in the "contrib" directory, all of which are included in the -libpng distribution. - -Libpng was written as a companion to the PNG specification, as a way -of reducing the amount of time and effort it takes to support the PNG -file format in application programs. - -The PNG specification (second edition), November 2003, is available as -a W3C Recommendation and as an ISO Standard (ISO/IEC 15948:2003 (E)) at - - -The PNG-1.0 specification is available -as RFC 2083 and as a -W3C Recommendation . Some -additional chunks are described in the special-purpose public chunks -documents at . - -Other information -about PNG, and the latest version of libpng, can be found at the PNG home -page, . - -Most users will not have to modify the library significantly; advanced -users may want to modify it more. All attempts were made to make it as -complete as possible, while keeping the code easy to understand. -Currently, this library only supports C. Support for other languages -is being considered. - -Libpng has been designed to handle multiple sessions at one time, -to be easily modifiable, to be portable to the vast majority of -machines (ANSI, K&R, 16-, 32-, and 64-bit) available, and to be easy -to use. The ultimate goal of libpng is to promote the acceptance of -the PNG file format in whatever way possible. While there is still -work to be done (see the TODO file), libpng should cover the -majority of the needs of its users. - -Libpng uses zlib for its compression and decompression of PNG files. -Further information about zlib, and the latest version of zlib, can -be found at the zlib home page, . -The zlib compression utility is a general purpose utility that is -useful for more than PNG files, and can be used without libpng. -See the documentation delivered with zlib for more details. -You can usually find the source files for the zlib utility wherever you -find the libpng source files. - -Libpng is thread safe, provided the threads are using different -instances of the structures. Each thread should have its own -png_struct and png_info instances, and thus its own image. -Libpng does not protect itself against two threads using the -same instance of a structure. - -II. Structures - -There are two main structures that are important to libpng, png_struct -and png_info. The first, png_struct, is an internal structure that -will not, for the most part, be used by a user except as the first -variable passed to every libpng function call. - -The png_info structure is designed to provide information about the -PNG file. At one time, the fields of png_info were intended to be -directly accessible to the user. However, this tended to cause problems -with applications using dynamically loaded libraries, and as a result -a set of interface functions for png_info (the png_get_*() and png_set_*() -functions) was developed. The fields of png_info are still available for -older applications, but it is suggested that applications use the new -interfaces if at all possible. - -Applications that do make direct access to the members of png_struct (except -for png_ptr->jmpbuf) must be recompiled whenever the library is updated, -and applications that make direct access to the members of png_info must -be recompiled if they were compiled or loaded with libpng version 1.0.6, -in which the members were in a different order. In version 1.0.7, the -members of the png_info structure reverted to the old order, as they were -in versions 0.97c through 1.0.5. Starting with version 2.0.0, both -structures are going to be hidden, and the contents of the structures will -only be accessible through the png_get/png_set functions. - -The png.h header file is an invaluable reference for programming with libpng. -And while I'm on the topic, make sure you include the libpng header file: - -#include - -III. Reading - -We'll now walk you through the possible functions to call when reading -in a PNG file sequentially, briefly explaining the syntax and purpose -of each one. See example.c and png.h for more detail. While -progressive reading is covered in the next section, you will still -need some of the functions discussed in this section to read a PNG -file. - -Setup - -You will want to do the I/O initialization(*) before you get into libpng, -so if it doesn't work, you don't have much to undo. Of course, you -will also want to insure that you are, in fact, dealing with a PNG -file. Libpng provides a simple check to see if a file is a PNG file. -To use it, pass in the first 1 to 8 bytes of the file to the function -png_sig_cmp(), and it will return 0 if the bytes match the corresponding -bytes of the PNG signature, or nonzero otherwise. Of course, the more bytes -you pass in, the greater the accuracy of the prediction. - -If you are intending to keep the file pointer open for use in libpng, -you must ensure you don't read more than 8 bytes from the beginning -of the file, and you also have to make a call to png_set_sig_bytes_read() -with the number of bytes you read from the beginning. Libpng will -then only check the bytes (if any) that your program didn't read. - -(*): If you are not using the standard I/O functions, you will need -to replace them with custom functions. See the discussion under -Customizing libpng. - - - FILE *fp = fopen(file_name, "rb"); - if (!fp) - { - return (ERROR); - } - fread(header, 1, number, fp); - is_png = !png_sig_cmp(header, 0, number); - if (!is_png) - { - return (NOT_PNG); - } - - -Next, png_struct and png_info need to be allocated and initialized. In -order to ensure that the size of these structures is correct even with a -dynamically linked libpng, there are functions to initialize and -allocate the structures. We also pass the library version, optional -pointers to error handling functions, and a pointer to a data struct for -use by the error functions, if necessary (the pointer and functions can -be NULL if the default error handlers are to be used). See the section -on Changes to Libpng below regarding the old initialization functions. -The structure allocation functions quietly return NULL if they fail to -create the structure, so your application should check for that. - - png_structp png_ptr = png_create_read_struct - (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, - user_error_fn, user_warning_fn); - if (!png_ptr) - return (ERROR); - - png_infop info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) - { - png_destroy_read_struct(&png_ptr, - (png_infopp)NULL, (png_infopp)NULL); - return (ERROR); - } - - png_infop end_info = png_create_info_struct(png_ptr); - if (!end_info) - { - png_destroy_read_struct(&png_ptr, &info_ptr, - (png_infopp)NULL); - return (ERROR); - } - -If you want to use your own memory allocation routines, -define PNG_USER_MEM_SUPPORTED and use -png_create_read_struct_2() instead of png_create_read_struct(): - - png_structp png_ptr = png_create_read_struct_2 - (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, - user_error_fn, user_warning_fn, (png_voidp) - user_mem_ptr, user_malloc_fn, user_free_fn); - -The error handling routines passed to png_create_read_struct() -and the memory alloc/free routines passed to png_create_struct_2() -are only necessary if you are not using the libpng supplied error -handling and memory alloc/free functions. - -When libpng encounters an error, it expects to longjmp back -to your routine. Therefore, you will need to call setjmp and pass -your png_jmpbuf(png_ptr). If you read the file from different -routines, you will need to update the jmpbuf field every time you enter -a new routine that will call a png_*() function. - -See your documentation of setjmp/longjmp for your compiler for more -information on setjmp/longjmp. See the discussion on libpng error -handling in the Customizing Libpng section below for more information -on the libpng error handling. If an error occurs, and libpng longjmp's -back to your setjmp, you will want to call png_destroy_read_struct() to -free any memory. - - if (setjmp(png_jmpbuf(png_ptr))) - { - png_destroy_read_struct(&png_ptr, &info_ptr, - &end_info); - fclose(fp); - return (ERROR); - } - -If you would rather avoid the complexity of setjmp/longjmp issues, -you can compile libpng with PNG_SETJMP_NOT_SUPPORTED, in which case -errors will result in a call to PNG_ABORT() which defaults to abort(). - -Now you need to set up the input code. The default for libpng is to -use the C function fread(). If you use this, you will need to pass a -valid FILE * in the function png_init_io(). Be sure that the file is -opened in binary mode. If you wish to handle reading data in another -way, you need not call the png_init_io() function, but you must then -implement the libpng I/O methods discussed in the Customizing Libpng -section below. - - png_init_io(png_ptr, fp); - -If you had previously opened the file and read any of the signature from -the beginning in order to see if this was a PNG file, you need to let -libpng know that there are some bytes missing from the start of the file. - - png_set_sig_bytes(png_ptr, number); - -Setting up callback code - -You can set up a callback function to handle any unknown chunks in the -input stream. You must supply the function - - read_chunk_callback(png_ptr ptr, - png_unknown_chunkp chunk); - { - /* The unknown chunk structure contains your - chunk data: */ - png_byte name[5]; - png_byte *data; - png_size_t size; - /* Note that libpng has already taken care of - the CRC handling */ - - /* put your code here. Return one of the - following: */ - - return (-n); /* chunk had an error */ - return (0); /* did not recognize */ - return (n); /* success */ - } - -(You can give your function another name that you like instead of -"read_chunk_callback") - -To inform libpng about your function, use - - png_set_read_user_chunk_fn(png_ptr, user_chunk_ptr, - read_chunk_callback); - -This names not only the callback function, but also a user pointer that -you can retrieve with - - png_get_user_chunk_ptr(png_ptr); - -At this point, you can set up a callback function that will be -called after each row has been read, which you can use to control -a progress meter or the like. It's demonstrated in pngtest.c. -You must supply a function - - void read_row_callback(png_ptr ptr, png_uint_32 row, - int pass); - { - /* put your code here */ - } - -(You can give it another name that you like instead of "read_row_callback") - -To inform libpng about your function, use - - png_set_read_status_fn(png_ptr, read_row_callback); - -Width and height limits - -The PNG specification allows the width and height of an image to be as -large as 2^31-1 (0x7fffffff), or about 2.147 billion rows and columns. -Since very few applications really need to process such large images, -we have imposed an arbitrary 1-million limit on rows and columns. -Larger images will be rejected immediately with a png_error() call. If -you wish to override this limit, you can use - - png_set_user_limits(png_ptr, width_max, height_max); - -to set your own limits, or use width_max = height_max = 0x7fffffffL -to allow all valid dimensions (libpng may reject some very large images -anyway because of potential buffer overflow conditions). - -You should put this statement after you create the PNG structure and -before calling png_read_info(), png_read_png(), or png_process_data(). -If you need to retrieve the limits that are being applied, use - - width_max = png_get_user_width_max(png_ptr); - height_max = png_get_user_height_max(png_ptr); - -Unknown-chunk handling - -Now you get to set the way the library processes unknown chunks in the -input PNG stream. Both known and unknown chunks will be read. Normal -behavior is that known chunks will be parsed into information in -various info_ptr members; unknown chunks will be discarded. To change -this, you can call: - - png_set_keep_unknown_chunks(png_ptr, keep, - chunk_list, num_chunks); - keep - 0: do not handle as unknown - 1: do not keep - 2: keep only if safe-to-copy - 3: keep even if unsafe-to-copy - You can use these definitions: - PNG_HANDLE_CHUNK_AS_DEFAULT 0 - PNG_HANDLE_CHUNK_NEVER 1 - PNG_HANDLE_CHUNK_IF_SAFE 2 - PNG_HANDLE_CHUNK_ALWAYS 3 - chunk_list - list of chunks affected (a byte string, - five bytes per chunk, NULL or '\0' if - num_chunks is 0) - num_chunks - number of chunks affected; if 0, all - unknown chunks are affected. If nonzero, - only the chunks in the list are affected - -Unknown chunks declared in this way will be saved as raw data onto a -list of png_unknown_chunk structures. If a chunk that is normally -known to libpng is named in the list, it will be handled as unknown, -according to the "keep" directive. If a chunk is named in successive -instances of png_set_keep_unknown_chunks(), the final instance will -take precedence. The IHDR and IEND chunks should not be named in -chunk_list; if they are, libpng will process them normally anyway. - -The high-level read interface - -At this point there are two ways to proceed; through the high-level -read interface, or through a sequence of low-level read operations. -You can use the high-level interface if (a) you are willing to read -the entire image into memory, and (b) the input transformations -you want to do are limited to the following set: - - PNG_TRANSFORM_IDENTITY No transformation - PNG_TRANSFORM_STRIP_16 Strip 16-bit samples to - 8 bits - PNG_TRANSFORM_STRIP_ALPHA Discard the alpha channel - PNG_TRANSFORM_PACKING Expand 1, 2 and 4-bit - samples to bytes - PNG_TRANSFORM_PACKSWAP Change order of packed - pixels to LSB first - PNG_TRANSFORM_EXPAND Perform set_expand() - PNG_TRANSFORM_INVERT_MONO Invert monochrome images - PNG_TRANSFORM_SHIFT Normalize pixels to the - sBIT depth - PNG_TRANSFORM_BGR Flip RGB to BGR, RGBA - to BGRA - PNG_TRANSFORM_SWAP_ALPHA Flip RGBA to ARGB or GA - to AG - PNG_TRANSFORM_INVERT_ALPHA Change alpha from opacity - to transparency - PNG_TRANSFORM_SWAP_ENDIAN Byte-swap 16-bit samples - -(This excludes setting a background color, doing gamma transformation, -dithering, and setting filler.) If this is the case, simply do this: - - png_read_png(png_ptr, info_ptr, png_transforms, NULL) - -where png_transforms is an integer containing the bitwise OR of -some set of transformation flags. This call is equivalent to png_read_info(), -followed the set of transformations indicated by the transform mask, -then png_read_image(), and finally png_read_end(). - -(The final parameter of this call is not yet used. Someday it might point -to transformation parameters required by some future input transform.) - -You must use png_transforms and not call any png_set_transform() functions -when you use png_read_png(). - -After you have called png_read_png(), you can retrieve the image data -with - - row_pointers = png_get_rows(png_ptr, info_ptr); - -where row_pointers is an array of pointers to the pixel data for each row: - - png_bytep row_pointers[height]; - -If you know your image size and pixel size ahead of time, you can allocate -row_pointers prior to calling png_read_png() with - - if (height > PNG_UINT_32_MAX/png_sizeof(png_byte)) - png_error (png_ptr, - "Image is too tall to process in memory"); - if (width > PNG_UINT_32_MAX/pixel_size) - png_error (png_ptr, - "Image is too wide to process in memory"); - row_pointers = png_malloc(png_ptr, - height*png_sizeof(png_bytep)); - for (int i=0; i) and -png_get_(png_ptr, info_ptr, ...) functions return non-zero if the -data has been read, or zero if it is missing. The parameters to the -png_get_ are set directly if they are simple data types, or a pointer -into the info_ptr is returned for any complex types. - - png_get_PLTE(png_ptr, info_ptr, &palette, - &num_palette); - palette - the palette for the file - (array of png_color) - num_palette - number of entries in the palette - - png_get_gAMA(png_ptr, info_ptr, &gamma); - gamma - the gamma the file is written - at (PNG_INFO_gAMA) - - png_get_sRGB(png_ptr, info_ptr, &srgb_intent); - srgb_intent - the rendering intent (PNG_INFO_sRGB) - The presence of the sRGB chunk - means that the pixel data is in the - sRGB color space. This chunk also - implies specific values of gAMA and - cHRM. - - png_get_iCCP(png_ptr, info_ptr, &name, - &compression_type, &profile, &proflen); - name - The profile name. - compression - The compression type; always - PNG_COMPRESSION_TYPE_BASE for PNG 1.0. - You may give NULL to this argument to - ignore it. - profile - International Color Consortium color - profile data. May contain NULs. - proflen - length of profile data in bytes. - - png_get_sBIT(png_ptr, info_ptr, &sig_bit); - sig_bit - the number of significant bits for - (PNG_INFO_sBIT) each of the gray, - red, green, and blue channels, - whichever are appropriate for the - given color type (png_color_16) - - png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, - &trans_values); - trans - array of transparent entries for - palette (PNG_INFO_tRNS) - trans_values - graylevel or color sample values of - the single transparent color for - non-paletted images (PNG_INFO_tRNS) - num_trans - number of transparent entries - (PNG_INFO_tRNS) - - png_get_hIST(png_ptr, info_ptr, &hist); - (PNG_INFO_hIST) - hist - histogram of palette (array of - png_uint_16) - - png_get_tIME(png_ptr, info_ptr, &mod_time); - mod_time - time image was last modified - (PNG_VALID_tIME) - - png_get_bKGD(png_ptr, info_ptr, &background); - background - background color (PNG_VALID_bKGD) - valid 16-bit red, green and blue - values, regardless of color_type - - num_comments = png_get_text(png_ptr, info_ptr, - &text_ptr, &num_text); - num_comments - number of comments - text_ptr - array of png_text holding image - comments - text_ptr[i].compression - type of compression used - on "text" PNG_TEXT_COMPRESSION_NONE - PNG_TEXT_COMPRESSION_zTXt - PNG_ITXT_COMPRESSION_NONE - PNG_ITXT_COMPRESSION_zTXt - text_ptr[i].key - keyword for comment. Must contain - 1-79 characters. - text_ptr[i].text - text comments for current - keyword. Can be empty. - text_ptr[i].text_length - length of text string, - after decompression, 0 for iTXt - text_ptr[i].itxt_length - length of itxt string, - after decompression, 0 for tEXt/zTXt - text_ptr[i].lang - language of comment (empty - string for unknown). - text_ptr[i].lang_key - keyword in UTF-8 - (empty string for unknown). - num_text - number of comments (same as - num_comments; you can put NULL here - to avoid the duplication) - Note while png_set_text() will accept text, language, - and translated keywords that can be NULL pointers, the - structure returned by png_get_text will always contain - regular zero-terminated C strings. They might be - empty strings but they will never be NULL pointers. - - num_spalettes = png_get_sPLT(png_ptr, info_ptr, - &palette_ptr); - palette_ptr - array of palette structures holding - contents of one or more sPLT chunks - read. - num_spalettes - number of sPLT chunks read. - - png_get_oFFs(png_ptr, info_ptr, &offset_x, &offset_y, - &unit_type); - offset_x - positive offset from the left edge - of the screen - offset_y - positive offset from the top edge - of the screen - unit_type - PNG_OFFSET_PIXEL, PNG_OFFSET_MICROMETER - - png_get_pHYs(png_ptr, info_ptr, &res_x, &res_y, - &unit_type); - res_x - pixels/unit physical resolution in - x direction - res_y - pixels/unit physical resolution in - x direction - unit_type - PNG_RESOLUTION_UNKNOWN, - PNG_RESOLUTION_METER - - png_get_sCAL(png_ptr, info_ptr, &unit, &width, - &height) - unit - physical scale units (an integer) - width - width of a pixel in physical scale units - height - height of a pixel in physical scale units - (width and height are doubles) - - png_get_sCAL_s(png_ptr, info_ptr, &unit, &width, - &height) - unit - physical scale units (an integer) - width - width of a pixel in physical scale units - height - height of a pixel in physical scale units - (width and height are strings like "2.54") - - num_unknown_chunks = png_get_unknown_chunks(png_ptr, - info_ptr, &unknowns) - unknowns - array of png_unknown_chunk - structures holding unknown chunks - unknowns[i].name - name of unknown chunk - unknowns[i].data - data of unknown chunk - unknowns[i].size - size of unknown chunk's data - unknowns[i].location - position of chunk in file - - The value of "i" corresponds to the order in which the - chunks were read from the PNG file or inserted with the - png_set_unknown_chunks() function. - -The data from the pHYs chunk can be retrieved in several convenient -forms: - - res_x = png_get_x_pixels_per_meter(png_ptr, - info_ptr) - res_y = png_get_y_pixels_per_meter(png_ptr, - info_ptr) - res_x_and_y = png_get_pixels_per_meter(png_ptr, - info_ptr) - res_x = png_get_x_pixels_per_inch(png_ptr, - info_ptr) - res_y = png_get_y_pixels_per_inch(png_ptr, - info_ptr) - res_x_and_y = png_get_pixels_per_inch(png_ptr, - info_ptr) - aspect_ratio = png_get_pixel_aspect_ratio(png_ptr, - info_ptr) - - (Each of these returns 0 [signifying "unknown"] if - the data is not present or if res_x is 0; - res_x_and_y is 0 if res_x != res_y) - -The data from the oFFs chunk can be retrieved in several convenient -forms: - - x_offset = png_get_x_offset_microns(png_ptr, info_ptr); - y_offset = png_get_y_offset_microns(png_ptr, info_ptr); - x_offset = png_get_x_offset_inches(png_ptr, info_ptr); - y_offset = png_get_y_offset_inches(png_ptr, info_ptr); - - (Each of these returns 0 [signifying "unknown" if both - x and y are 0] if the data is not present or if the - chunk is present but the unit is the pixel) - -For more information, see the png_info definition in png.h and the -PNG specification for chunk contents. Be careful with trusting -rowbytes, as some of the transformations could increase the space -needed to hold a row (expand, filler, gray_to_rgb, etc.). -See png_read_update_info(), below. - -A quick word about text_ptr and num_text. PNG stores comments in -keyword/text pairs, one pair per chunk, with no limit on the number -of text chunks, and a 2^31 byte limit on their size. While there are -suggested keywords, there is no requirement to restrict the use to these -strings. It is strongly suggested that keywords and text be sensible -to humans (that's the point), so don't use abbreviations. Non-printing -symbols are not allowed. See the PNG specification for more details. -There is also no requirement to have text after the keyword. - -Keywords should be limited to 79 Latin-1 characters without leading or -trailing spaces, but non-consecutive spaces are allowed within the -keyword. It is possible to have the same keyword any number of times. -The text_ptr is an array of png_text structures, each holding a -pointer to a language string, a pointer to a keyword and a pointer to -a text string. The text string, language code, and translated -keyword may be empty or NULL pointers. The keyword/text -pairs are put into the array in the order that they are received. -However, some or all of the text chunks may be after the image, so, to -make sure you have read all the text chunks, don't mess with these -until after you read the stuff after the image. This will be -mentioned again below in the discussion that goes with png_read_end(). - -Input transformations - -After you've read the header information, you can set up the library -to handle any special transformations of the image data. The various -ways to transform the data will be described in the order that they -should occur. This is important, as some of these change the color -type and/or bit depth of the data, and some others only work on -certain color types and bit depths. Even though each transformation -checks to see if it has data that it can do something with, you should -make sure to only enable a transformation if it will be valid for the -data. For example, don't swap red and blue on grayscale data. - -The colors used for the background and transparency values should be -supplied in the same format/depth as the current image data. They -are stored in the same format/depth as the image data in a bKGD or tRNS -chunk, so this is what libpng expects for this data. The colors are -transformed to keep in sync with the image data when an application -calls the png_read_update_info() routine (see below). - -Data will be decoded into the supplied row buffers packed into bytes -unless the library has been told to transform it into another format. -For example, 4 bit/pixel paletted or grayscale data will be returned -2 pixels/byte with the leftmost pixel in the high-order bits of the -byte, unless png_set_packing() is called. 8-bit RGB data will be stored -in RGB RGB RGB format unless png_set_filler() or png_set_add_alpha() -is called to insert filler bytes, either before or after each RGB triplet. -16-bit RGB data will be returned RRGGBB RRGGBB, with the most significant -byte of the color value first, unless png_set_strip_16() is called to -transform it to regular RGB RGB triplets, or png_set_filler() or -png_set_add alpha() is called to insert filler bytes, either before or -after each RRGGBB triplet. Similarly, 8-bit or 16-bit grayscale data can -be modified with -png_set_filler(), png_set_add_alpha(), or png_set_strip_16(). - -The following code transforms grayscale images of less than 8 to 8 bits, -changes paletted images to RGB, and adds a full alpha channel if there is -transparency information in a tRNS chunk. This is most useful on -grayscale images with bit depths of 2 or 4 or if there is a multiple-image -viewing application that wishes to treat all images in the same way. - - if (color_type == PNG_COLOR_TYPE_PALETTE) - png_set_palette_to_rgb(png_ptr); - - if (color_type == PNG_COLOR_TYPE_GRAY && - bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr); - - if (png_get_valid(png_ptr, info_ptr, - PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); - -These three functions are actually aliases for png_set_expand(), added -in libpng version 1.0.4, with the function names expanded to improve code -readability. In some future version they may actually do different -things. - -As of libpng version 1.2.9, png_set_expand_gray_1_2_4_to_8() was -added. It expands the sample depth without changing tRNS to alpha. -At the same time, png_set_gray_1_2_4_to_8() was deprecated, and it -will be removed from a future version. - -PNG can have files with 16 bits per channel. If you only can handle -8 bits per channel, this will strip the pixels down to 8 bit. - - if (bit_depth == 16) - png_set_strip_16(png_ptr); - -If, for some reason, you don't need the alpha channel on an image, -and you want to remove it rather than combining it with the background -(but the image author certainly had in mind that you *would* combine -it with the background, so that's what you should probably do): - - if (color_type & PNG_COLOR_MASK_ALPHA) - png_set_strip_alpha(png_ptr); - -In PNG files, the alpha channel in an image -is the level of opacity. If you need the alpha channel in an image to -be the level of transparency instead of opacity, you can invert the -alpha channel (or the tRNS chunk data) after it's read, so that 0 is -fully opaque and 255 (in 8-bit or paletted images) or 65535 (in 16-bit -images) is fully transparent, with - - png_set_invert_alpha(png_ptr); - -PNG files pack pixels of bit depths 1, 2, and 4 into bytes as small as -they can, resulting in, for example, 8 pixels per byte for 1 bit -files. This code expands to 1 pixel per byte without changing the -values of the pixels: - - if (bit_depth < 8) - png_set_packing(png_ptr); - -PNG files have possible bit depths of 1, 2, 4, 8, and 16. All pixels -stored in a PNG image have been "scaled" or "shifted" up to the next -higher possible bit depth (e.g. from 5 bits/sample in the range [0,31] to -8 bits/sample in the range [0, 255]). However, it is also possible to -convert the PNG pixel data back to the original bit depth of the image. -This call reduces the pixels back down to the original bit depth: - - png_color_8p sig_bit; - - if (png_get_sBIT(png_ptr, info_ptr, &sig_bit)) - png_set_shift(png_ptr, sig_bit); - -PNG files store 3-color pixels in red, green, blue order. This code -changes the storage of the pixels to blue, green, red: - - if (color_type == PNG_COLOR_TYPE_RGB || - color_type == PNG_COLOR_TYPE_RGB_ALPHA) - png_set_bgr(png_ptr); - -PNG files store RGB pixels packed into 3 or 6 bytes. This code expands them -into 4 or 8 bytes for windowing systems that need them in this format: - - if (color_type == PNG_COLOR_TYPE_RGB) - png_set_filler(png_ptr, filler, PNG_FILLER_BEFORE); - -where "filler" is the 8 or 16-bit number to fill with, and the location is -either PNG_FILLER_BEFORE or PNG_FILLER_AFTER, depending upon whether -you want the filler before the RGB or after. This transformation -does not affect images that already have full alpha channels. To add an -opaque alpha channel, use filler=0xff or 0xffff and PNG_FILLER_AFTER which -will generate RGBA pixels. - -Note that png_set_filler() does not change the color type. If you want -to do that, you can add a true alpha channel with - - if (color_type == PNG_COLOR_TYPE_RGB || - color_type == PNG_COLOR_TYPE_GRAY) - png_set_add_alpha(png_ptr, filler, PNG_FILLER_AFTER); - -where "filler" contains the alpha value to assign to each pixel. -This function was added in libpng-1.2.7. - -If you are reading an image with an alpha channel, and you need the -data as ARGB instead of the normal PNG format RGBA: - - if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) - png_set_swap_alpha(png_ptr); - -For some uses, you may want a grayscale image to be represented as -RGB. This code will do that conversion: - - if (color_type == PNG_COLOR_TYPE_GRAY || - color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - png_set_gray_to_rgb(png_ptr); - -Conversely, you can convert an RGB or RGBA image to grayscale or grayscale -with alpha. - - if (color_type == PNG_COLOR_TYPE_RGB || - color_type == PNG_COLOR_TYPE_RGB_ALPHA) - png_set_rgb_to_gray_fixed(png_ptr, error_action, - int red_weight, int green_weight); - - error_action = 1: silently do the conversion - error_action = 2: issue a warning if the original - image has any pixel where - red != green or red != blue - error_action = 3: issue an error and abort the - conversion if the original - image has any pixel where - red != green or red != blue - - red_weight: weight of red component times 100000 - green_weight: weight of green component times 100000 - If either weight is negative, default - weights (21268, 71514) are used. - -If you have set error_action = 1 or 2, you can -later check whether the image really was gray, after processing -the image rows, with the png_get_rgb_to_gray_status(png_ptr) function. -It will return a png_byte that is zero if the image was gray or -1 if there were any non-gray pixels. bKGD and sBIT data -will be silently converted to grayscale, using the green channel -data, regardless of the error_action setting. - -With red_weight+green_weight<=100000, -the normalized graylevel is computed: - - int rw = red_weight * 65536; - int gw = green_weight * 65536; - int bw = 65536 - (rw + gw); - gray = (rw*red + gw*green + bw*blue)/65536; - -The default values approximate those recommended in the Charles -Poynton's Color FAQ, -Copyright (c) 1998-01-04 Charles Poynton - - Y = 0.212671 * R + 0.715160 * G + 0.072169 * B - -Libpng approximates this with - - Y = 0.21268 * R + 0.7151 * G + 0.07217 * B - -which can be expressed with integers as - - Y = (6969 * R + 23434 * G + 2365 * B)/32768 - -The calculation is done in a linear colorspace, if the image gamma -is known. - -If you have a grayscale and you are using png_set_expand_depth(), -png_set_expand(), or png_set_gray_to_rgb to change to truecolor or to -a higher bit-depth, you must either supply the background color as a gray -value at the original file bit-depth (need_expand = 1) or else supply the -background color as an RGB triplet at the final, expanded bit depth -(need_expand = 0). Similarly, if you are reading a paletted image, you -must either supply the background color as a palette index (need_expand = 1) -or as an RGB triplet that may or may not be in the palette (need_expand = 0). - - png_color_16 my_background; - png_color_16p image_background; - - if (png_get_bKGD(png_ptr, info_ptr, &image_background)) - png_set_background(png_ptr, image_background, - PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); - else - png_set_background(png_ptr, &my_background, - PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); - -The png_set_background() function tells libpng to composite images -with alpha or simple transparency against the supplied background -color. If the PNG file contains a bKGD chunk (PNG_INFO_bKGD valid), -you may use this color, or supply another color more suitable for -the current display (e.g., the background color from a web page). You -need to tell libpng whether the color is in the gamma space of the -display (PNG_BACKGROUND_GAMMA_SCREEN for colors you supply), the file -(PNG_BACKGROUND_GAMMA_FILE for colors from the bKGD chunk), or one -that is neither of these gammas (PNG_BACKGROUND_GAMMA_UNIQUE - I don't -know why anyone would use this, but it's here). - -To properly display PNG images on any kind of system, the application needs -to know what the display gamma is. Ideally, the user will know this, and -the application will allow them to set it. One method of allowing the user -to set the display gamma separately for each system is to check for a -SCREEN_GAMMA or DISPLAY_GAMMA environment variable, which will hopefully be -correctly set. - -Note that display_gamma is the overall gamma correction required to produce -pleasing results, which depends on the lighting conditions in the surrounding -environment. In a dim or brightly lit room, no compensation other than -the physical gamma exponent of the monitor is needed, while in a dark room -a slightly smaller exponent is better. - - double gamma, screen_gamma; - - if (/* We have a user-defined screen - gamma value */) - { - screen_gamma = user_defined_screen_gamma; - } - /* One way that applications can share the same - screen gamma value */ - else if ((gamma_str = getenv("SCREEN_GAMMA")) - != NULL) - { - screen_gamma = (double)atof(gamma_str); - } - /* If we don't have another value */ - else - { - screen_gamma = 2.2; /* A good guess for a - PC monitor in a bright office or a dim room */ - screen_gamma = 2.0; /* A good guess for a - PC monitor in a dark room */ - screen_gamma = 1.7 or 1.0; /* A good - guess for Mac systems */ - } - -The png_set_gamma() function handles gamma transformations of the data. -Pass both the file gamma and the current screen_gamma. If the file does -not have a gamma value, you can pass one anyway if you have an idea what -it is (usually 0.45455 is a good guess for GIF images on PCs). Note -that file gammas are inverted from screen gammas. See the discussions -on gamma in the PNG specification for an excellent description of what -gamma is, and why all applications should support it. It is strongly -recommended that PNG viewers support gamma correction. - - if (png_get_gAMA(png_ptr, info_ptr, &gamma)) - png_set_gamma(png_ptr, screen_gamma, gamma); - else - png_set_gamma(png_ptr, screen_gamma, 0.45455); - -If you need to reduce an RGB file to a paletted file, or if a paletted -file has more entries then will fit on your screen, png_set_dither() -will do that. Note that this is a simple match dither that merely -finds the closest color available. This should work fairly well with -optimized palettes, and fairly badly with linear color cubes. If you -pass a palette that is larger then maximum_colors, the file will -reduce the number of colors in the palette so it will fit into -maximum_colors. If there is a histogram, it will use it to make -more intelligent choices when reducing the palette. If there is no -histogram, it may not do as good a job. - - if (color_type & PNG_COLOR_MASK_COLOR) - { - if (png_get_valid(png_ptr, info_ptr, - PNG_INFO_PLTE)) - { - png_uint_16p histogram = NULL; - - png_get_hIST(png_ptr, info_ptr, - &histogram); - png_set_dither(png_ptr, palette, num_palette, - max_screen_colors, histogram, 1); - } - else - { - png_color std_color_cube[MAX_SCREEN_COLORS] = - { ... colors ... }; - - png_set_dither(png_ptr, std_color_cube, - MAX_SCREEN_COLORS, MAX_SCREEN_COLORS, - NULL,0); - } - } - -PNG files describe monochrome as black being zero and white being one. -The following code will reverse this (make black be one and white be -zero): - - if (bit_depth == 1 && color_type == PNG_COLOR_TYPE_GRAY) - png_set_invert_mono(png_ptr); - -This function can also be used to invert grayscale and gray-alpha images: - - if (color_type == PNG_COLOR_TYPE_GRAY || - color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - png_set_invert_mono(png_ptr); - -PNG files store 16 bit pixels in network byte order (big-endian, -ie. most significant bits first). This code changes the storage to the -other way (little-endian, i.e. least significant bits first, the -way PCs store them): - - if (bit_depth == 16) - png_set_swap(png_ptr); - -If you are using packed-pixel images (1, 2, or 4 bits/pixel), and you -need to change the order the pixels are packed into bytes, you can use: - - if (bit_depth < 8) - png_set_packswap(png_ptr); - -Finally, you can write your own transformation function if none of -the existing ones meets your needs. This is done by setting a callback -with - - png_set_read_user_transform_fn(png_ptr, - read_transform_fn); - -You must supply the function - - void read_transform_fn(png_ptr ptr, row_info_ptr - row_info, png_bytep data) - -See pngtest.c for a working example. Your function will be called -after all of the other transformations have been processed. - -You can also set up a pointer to a user structure for use by your -callback function, and you can inform libpng that your transform -function will change the number of channels or bit depth with the -function - - png_set_user_transform_info(png_ptr, user_ptr, - user_depth, user_channels); - -The user's application, not libpng, is responsible for allocating and -freeing any memory required for the user structure. - -You can retrieve the pointer via the function -png_get_user_transform_ptr(). For example: - - voidp read_user_transform_ptr = - png_get_user_transform_ptr(png_ptr); - -The last thing to handle is interlacing; this is covered in detail below, -but you must call the function here if you want libpng to handle expansion -of the interlaced image. - - number_of_passes = png_set_interlace_handling(png_ptr); - -After setting the transformations, libpng can update your png_info -structure to reflect any transformations you've requested with this -call. This is most useful to update the info structure's rowbytes -field so you can use it to allocate your image memory. This function -will also update your palette with the correct screen_gamma and -background if these have been given with the calls above. - - png_read_update_info(png_ptr, info_ptr); - -After you call png_read_update_info(), you can allocate any -memory you need to hold the image. The row data is simply -raw byte data for all forms of images. As the actual allocation -varies among applications, no example will be given. If you -are allocating one large chunk, you will need to build an -array of pointers to each row, as it will be needed for some -of the functions below. - -Reading image data - -After you've allocated memory, you can read the image data. -The simplest way to do this is in one function call. If you are -allocating enough memory to hold the whole image, you can just -call png_read_image() and libpng will read in all the image data -and put it in the memory area supplied. You will need to pass in -an array of pointers to each row. - -This function automatically handles interlacing, so you don't need -to call png_set_interlace_handling() or call this function multiple -times, or any of that other stuff necessary with png_read_rows(). - - png_read_image(png_ptr, row_pointers); - -where row_pointers is: - - png_bytep row_pointers[height]; - -You can point to void or char or whatever you use for pixels. - -If you don't want to read in the whole image at once, you can -use png_read_rows() instead. If there is no interlacing (check -interlace_type == PNG_INTERLACE_NONE), this is simple: - - png_read_rows(png_ptr, row_pointers, NULL, - number_of_rows); - -where row_pointers is the same as in the png_read_image() call. - -If you are doing this just one row at a time, you can do this with -a single row_pointer instead of an array of row_pointers: - - png_bytep row_pointer = row; - png_read_row(png_ptr, row_pointer, NULL); - -If the file is interlaced (interlace_type != 0 in the IHDR chunk), things -get somewhat harder. The only current (PNG Specification version 1.2) -interlacing type for PNG is (interlace_type == PNG_INTERLACE_ADAM7) -is a somewhat complicated 2D interlace scheme, known as Adam7, that -breaks down an image into seven smaller images of varying size, based -on an 8x8 grid. - -libpng can fill out those images or it can give them to you "as is". -If you want them filled out, there are two ways to do that. The one -mentioned in the PNG specification is to expand each pixel to cover -those pixels that have not been read yet (the "rectangle" method). -This results in a blocky image for the first pass, which gradually -smooths out as more pixels are read. The other method is the "sparkle" -method, where pixels are drawn only in their final locations, with the -rest of the image remaining whatever colors they were initialized to -before the start of the read. The first method usually looks better, -but tends to be slower, as there are more pixels to put in the rows. - -If you don't want libpng to handle the interlacing details, just call -png_read_rows() seven times to read in all seven images. Each of the -images is a valid image by itself, or they can all be combined on an -8x8 grid to form a single image (although if you intend to combine them -you would be far better off using the libpng interlace handling). - -The first pass will return an image 1/8 as wide as the entire image -(every 8th column starting in column 0) and 1/8 as high as the original -(every 8th row starting in row 0), the second will be 1/8 as wide -(starting in column 4) and 1/8 as high (also starting in row 0). The -third pass will be 1/4 as wide (every 4th pixel starting in column 0) and -1/8 as high (every 8th row starting in row 4), and the fourth pass will -be 1/4 as wide and 1/4 as high (every 4th column starting in column 2, -and every 4th row starting in row 0). The fifth pass will return an -image 1/2 as wide, and 1/4 as high (starting at column 0 and row 2), -while the sixth pass will be 1/2 as wide and 1/2 as high as the original -(starting in column 1 and row 0). The seventh and final pass will be as -wide as the original, and 1/2 as high, containing all of the odd -numbered scanlines. Phew! - -If you want libpng to expand the images, call this before calling -png_start_read_image() or png_read_update_info(): - - if (interlace_type == PNG_INTERLACE_ADAM7) - number_of_passes - = png_set_interlace_handling(png_ptr); - -This will return the number of passes needed. Currently, this -is seven, but may change if another interlace type is added. -This function can be called even if the file is not interlaced, -where it will return one pass. - -If you are not going to display the image after each pass, but are -going to wait until the entire image is read in, use the sparkle -effect. This effect is faster and the end result of either method -is exactly the same. If you are planning on displaying the image -after each pass, the "rectangle" effect is generally considered the -better looking one. - -If you only want the "sparkle" effect, just call png_read_rows() as -normal, with the third parameter NULL. Make sure you make pass over -the image number_of_passes times, and you don't change the data in the -rows between calls. You can change the locations of the data, just -not the data. Each pass only writes the pixels appropriate for that -pass, and assumes the data from previous passes is still valid. - - png_read_rows(png_ptr, row_pointers, NULL, - number_of_rows); - -If you only want the first effect (the rectangles), do the same as -before except pass the row buffer in the third parameter, and leave -the second parameter NULL. - - png_read_rows(png_ptr, NULL, row_pointers, - number_of_rows); - -Finishing a sequential read - -After you are finished reading the image through the -low-level interface, you can finish reading the file. If you are -interested in comments or time, which may be stored either before or -after the image data, you should pass the separate png_info struct if -you want to keep the comments from before and after the image -separate. If you are not interested, you can pass NULL. - - png_read_end(png_ptr, end_info); - -When you are done, you can free all memory allocated by libpng like this: - - png_destroy_read_struct(&png_ptr, &info_ptr, - &end_info); - -It is also possible to individually free the info_ptr members that -point to libpng-allocated storage with the following function: - - png_free_data(png_ptr, info_ptr, mask, seq) - mask - identifies data to be freed, a mask - containing the bitwise OR of one or - more of - PNG_FREE_PLTE, PNG_FREE_TRNS, - PNG_FREE_HIST, PNG_FREE_ICCP, - PNG_FREE_PCAL, PNG_FREE_ROWS, - PNG_FREE_SCAL, PNG_FREE_SPLT, - PNG_FREE_TEXT, PNG_FREE_UNKN, - or simply PNG_FREE_ALL - seq - sequence number of item to be freed - (-1 for all items) - -This function may be safely called when the relevant storage has -already been freed, or has not yet been allocated, or was allocated -by the user and not by libpng, and will in those -cases do nothing. The "seq" parameter is ignored if only one item -of the selected data type, such as PLTE, is allowed. If "seq" is not --1, and multiple items are allowed for the data type identified in -the mask, such as text or sPLT, only the n'th item in the structure -is freed, where n is "seq". - -The default behavior is only to free data that was allocated internally -by libpng. This can be changed, so that libpng will not free the data, -or so that it will free data that was allocated by the user with png_malloc() -or png_zalloc() and passed in via a png_set_*() function, with - - png_data_freer(png_ptr, info_ptr, freer, mask) - mask - which data elements are affected - same choices as in png_free_data() - freer - one of - PNG_DESTROY_WILL_FREE_DATA - PNG_SET_WILL_FREE_DATA - PNG_USER_WILL_FREE_DATA - -This function only affects data that has already been allocated. -You can call this function after reading the PNG data but before calling -any png_set_*() functions, to control whether the user or the png_set_*() -function is responsible for freeing any existing data that might be present, -and again after the png_set_*() functions to control whether the user -or png_destroy_*() is supposed to free the data. When the user assumes -responsibility for libpng-allocated data, the application must use -png_free() to free it, and when the user transfers responsibility to libpng -for data that the user has allocated, the user must have used png_malloc() -or png_zalloc() to allocate it. - -If you allocated your row_pointers in a single block, as suggested above in -the description of the high level read interface, you must not transfer -responsibility for freeing it to the png_set_rows or png_read_destroy function, -because they would also try to free the individual row_pointers[i]. - -If you allocated text_ptr.text, text_ptr.lang, and text_ptr.translated_keyword -separately, do not transfer responsibility for freeing text_ptr to libpng, -because when libpng fills a png_text structure it combines these members with -the key member, and png_free_data() will free only text_ptr.key. Similarly, -if you transfer responsibility for free'ing text_ptr from libpng to your -application, your application must not separately free those members. - -The png_free_data() function will turn off the "valid" flag for anything -it frees. If you need to turn the flag off for a chunk that was freed by your -application instead of by libpng, you can use - - png_set_invalid(png_ptr, info_ptr, mask); - mask - identifies the chunks to be made invalid, - containing the bitwise OR of one or - more of - PNG_INFO_gAMA, PNG_INFO_sBIT, - PNG_INFO_cHRM, PNG_INFO_PLTE, - PNG_INFO_tRNS, PNG_INFO_bKGD, - PNG_INFO_hIST, PNG_INFO_pHYs, - PNG_INFO_oFFs, PNG_INFO_tIME, - PNG_INFO_pCAL, PNG_INFO_sRGB, - PNG_INFO_iCCP, PNG_INFO_sPLT, - PNG_INFO_sCAL, PNG_INFO_IDAT - -For a more compact example of reading a PNG image, see the file example.c. - -Reading PNG files progressively - -The progressive reader is slightly different then the non-progressive -reader. Instead of calling png_read_info(), png_read_rows(), and -png_read_end(), you make one call to png_process_data(), which calls -callbacks when it has the info, a row, or the end of the image. You -set up these callbacks with png_set_progressive_read_fn(). You don't -have to worry about the input/output functions of libpng, as you are -giving the library the data directly in png_process_data(). I will -assume that you have read the section on reading PNG files above, -so I will only highlight the differences (although I will show -all of the code). - -png_structp png_ptr; -png_infop info_ptr; - - /* An example code fragment of how you would - initialize the progressive reader in your - application. */ - int - initialize_png_reader() - { - png_ptr = png_create_read_struct - (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, - user_error_fn, user_warning_fn); - if (!png_ptr) - return (ERROR); - info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) - { - png_destroy_read_struct(&png_ptr, (png_infopp)NULL, - (png_infopp)NULL); - return (ERROR); - } - - if (setjmp(png_jmpbuf(png_ptr))) - { - png_destroy_read_struct(&png_ptr, &info_ptr, - (png_infopp)NULL); - return (ERROR); - } - - /* This one's new. You can provide functions - to be called when the header info is valid, - when each row is completed, and when the image - is finished. If you aren't using all functions, - you can specify NULL parameters. Even when all - three functions are NULL, you need to call - png_set_progressive_read_fn(). You can use - any struct as the user_ptr (cast to a void pointer - for the function call), and retrieve the pointer - from inside the callbacks using the function - - png_get_progressive_ptr(png_ptr); - - which will return a void pointer, which you have - to cast appropriately. - */ - png_set_progressive_read_fn(png_ptr, (void *)user_ptr, - info_callback, row_callback, end_callback); - - return 0; - } - - /* A code fragment that you call as you receive blocks - of data */ - int - process_data(png_bytep buffer, png_uint_32 length) - { - if (setjmp(png_jmpbuf(png_ptr))) - { - png_destroy_read_struct(&png_ptr, &info_ptr, - (png_infopp)NULL); - return (ERROR); - } - - /* This one's new also. Simply give it a chunk - of data from the file stream (in order, of - course). On machines with segmented memory - models machines, don't give it any more than - 64K. The library seems to run fine with sizes - of 4K. Although you can give it much less if - necessary (I assume you can give it chunks of - 1 byte, I haven't tried less then 256 bytes - yet). When this function returns, you may - want to display any rows that were generated - in the row callback if you don't already do - so there. - */ - png_process_data(png_ptr, info_ptr, buffer, length); - return 0; - } - - /* This function is called (as set by - png_set_progressive_read_fn() above) when enough data - has been supplied so all of the header has been - read. - */ - void - info_callback(png_structp png_ptr, png_infop info) - { - /* Do any setup here, including setting any of - the transformations mentioned in the Reading - PNG files section. For now, you _must_ call - either png_start_read_image() or - png_read_update_info() after all the - transformations are set (even if you don't set - any). You may start getting rows before - png_process_data() returns, so this is your - last chance to prepare for that. - */ - } - - /* This function is called when each row of image - data is complete */ - void - row_callback(png_structp png_ptr, png_bytep new_row, - png_uint_32 row_num, int pass) - { - /* If the image is interlaced, and you turned - on the interlace handler, this function will - be called for every row in every pass. Some - of these rows will not be changed from the - previous pass. When the row is not changed, - the new_row variable will be NULL. The rows - and passes are called in order, so you don't - really need the row_num and pass, but I'm - supplying them because it may make your life - easier. - - For the non-NULL rows of interlaced images, - you must call png_progressive_combine_row() - passing in the row and the old row. You can - call this function for NULL rows (it will just - return) and for non-interlaced images (it just - does the memcpy for you) if it will make the - code easier. Thus, you can just do this for - all cases: - */ - - png_progressive_combine_row(png_ptr, old_row, - new_row); - - /* where old_row is what was displayed for - previously for the row. Note that the first - pass (pass == 0, really) will completely cover - the old row, so the rows do not have to be - initialized. After the first pass (and only - for interlaced images), you will have to pass - the current row, and the function will combine - the old row and the new row. - */ - } - - void - end_callback(png_structp png_ptr, png_infop info) - { - /* This function is called after the whole image - has been read, including any chunks after the - image (up to and including the IEND). You - will usually have the same info chunk as you - had in the header, although some data may have - been added to the comments and time fields. - - Most people won't do much here, perhaps setting - a flag that marks the image as finished. - */ - } - - - -IV. Writing - -Much of this is very similar to reading. However, everything of -importance is repeated here, so you won't have to constantly look -back up in the reading section to understand writing. - -Setup - -You will want to do the I/O initialization before you get into libpng, -so if it doesn't work, you don't have anything to undo. If you are not -using the standard I/O functions, you will need to replace them with -custom writing functions. See the discussion under Customizing libpng. - - FILE *fp = fopen(file_name, "wb"); - if (!fp) - { - return (ERROR); - } - -Next, png_struct and png_info need to be allocated and initialized. -As these can be both relatively large, you may not want to store these -on the stack, unless you have stack space to spare. Of course, you -will want to check if they return NULL. If you are also reading, -you won't want to name your read structure and your write structure -both "png_ptr"; you can call them anything you like, such as -"read_ptr" and "write_ptr". Look at pngtest.c, for example. - - png_structp png_ptr = png_create_write_struct - (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, - user_error_fn, user_warning_fn); - if (!png_ptr) - return (ERROR); - - png_infop info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) - { - png_destroy_write_struct(&png_ptr, - (png_infopp)NULL); - return (ERROR); - } - -If you want to use your own memory allocation routines, -define PNG_USER_MEM_SUPPORTED and use -png_create_write_struct_2() instead of png_create_write_struct(): - - png_structp png_ptr = png_create_write_struct_2 - (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, - user_error_fn, user_warning_fn, (png_voidp) - user_mem_ptr, user_malloc_fn, user_free_fn); - -After you have these structures, you will need to set up the -error handling. When libpng encounters an error, it expects to -longjmp() back to your routine. Therefore, you will need to call -setjmp() and pass the png_jmpbuf(png_ptr). If you -write the file from different routines, you will need to update -the png_jmpbuf(png_ptr) every time you enter a new routine that will -call a png_*() function. See your documentation of setjmp/longjmp -for your compiler for more information on setjmp/longjmp. See -the discussion on libpng error handling in the Customizing Libpng -section below for more information on the libpng error handling. - - if (setjmp(png_jmpbuf(png_ptr))) - { - png_destroy_write_struct(&png_ptr, &info_ptr); - fclose(fp); - return (ERROR); - } - ... - return; - -If you would rather avoid the complexity of setjmp/longjmp issues, -you can compile libpng with PNG_SETJMP_NOT_SUPPORTED, in which case -errors will result in a call to PNG_ABORT() which defaults to abort(). - -Now you need to set up the output code. The default for libpng is to -use the C function fwrite(). If you use this, you will need to pass a -valid FILE * in the function png_init_io(). Be sure that the file is -opened in binary mode. Again, if you wish to handle writing data in -another way, see the discussion on libpng I/O handling in the Customizing -Libpng section below. - - png_init_io(png_ptr, fp); - -If you are embedding your PNG into a datastream such as MNG, and don't -want libpng to write the 8-byte signature, or if you have already -written the signature in your application, use - - png_set_sig_bytes(png_ptr, 8); - -to inform libpng that it should not write a signature. - -Write callbacks - -At this point, you can set up a callback function that will be -called after each row has been written, which you can use to control -a progress meter or the like. It's demonstrated in pngtest.c. -You must supply a function - - void write_row_callback(png_ptr, png_uint_32 row, - int pass); - { - /* put your code here */ - } - -(You can give it another name that you like instead of "write_row_callback") - -To inform libpng about your function, use - - png_set_write_status_fn(png_ptr, write_row_callback); - -You now have the option of modifying how the compression library will -run. The following functions are mainly for testing, but may be useful -in some cases, like if you need to write PNG files extremely fast and -are willing to give up some compression, or if you want to get the -maximum possible compression at the expense of slower writing. If you -have no special needs in this area, let the library do what it wants by -not calling this function at all, as it has been tuned to deliver a good -speed/compression ratio. The second parameter to png_set_filter() is -the filter method, for which the only valid values are 0 (as of the -July 1999 PNG specification, version 1.2) or 64 (if you are writing -a PNG datastream that is to be embedded in a MNG datastream). The third -parameter is a flag that indicates which filter type(s) are to be tested -for each scanline. See the PNG specification for details on the specific filter -types. - - - /* turn on or off filtering, and/or choose - specific filters. You can use either a single - PNG_FILTER_VALUE_NAME or the bitwise OR of one - or more PNG_FILTER_NAME masks. */ - png_set_filter(png_ptr, 0, - PNG_FILTER_NONE | PNG_FILTER_VALUE_NONE | - PNG_FILTER_SUB | PNG_FILTER_VALUE_SUB | - PNG_FILTER_UP | PNG_FILTER_VALUE_UP | - PNG_FILTER_AVE | PNG_FILTER_VALUE_AVE | - PNG_FILTER_PAETH | PNG_FILTER_VALUE_PAETH| - PNG_ALL_FILTERS); - -If an application -wants to start and stop using particular filters during compression, -it should start out with all of the filters (to ensure that the previous -row of pixels will be stored in case it's needed later), and then add -and remove them after the start of compression. - -If you are writing a PNG datastream that is to be embedded in a MNG -datastream, the second parameter can be either 0 or 64. - -The png_set_compression_*() functions interface to the zlib compression -library, and should mostly be ignored unless you really know what you are -doing. The only generally useful call is png_set_compression_level() -which changes how much time zlib spends on trying to compress the image -data. See the Compression Library (zlib.h and algorithm.txt, distributed -with zlib) for details on the compression levels. - - /* set the zlib compression level */ - png_set_compression_level(png_ptr, - Z_BEST_COMPRESSION); - - /* set other zlib parameters */ - png_set_compression_mem_level(png_ptr, 8); - png_set_compression_strategy(png_ptr, - Z_DEFAULT_STRATEGY); - png_set_compression_window_bits(png_ptr, 15); - png_set_compression_method(png_ptr, 8); - png_set_compression_buffer_size(png_ptr, 8192) - -extern PNG_EXPORT(void,png_set_zbuf_size) - -Setting the contents of info for output - -You now need to fill in the png_info structure with all the data you -wish to write before the actual image. Note that the only thing you -are allowed to write after the image is the text chunks and the time -chunk (as of PNG Specification 1.2, anyway). See png_write_end() and -the latest PNG specification for more information on that. If you -wish to write them before the image, fill them in now, and flag that -data as being valid. If you want to wait until after the data, don't -fill them until png_write_end(). For all the fields in png_info and -their data types, see png.h. For explanations of what the fields -contain, see the PNG specification. - -Some of the more important parts of the png_info are: - - png_set_IHDR(png_ptr, info_ptr, width, height, - bit_depth, color_type, interlace_type, - compression_type, filter_method) - width - holds the width of the image - in pixels (up to 2^31). - height - holds the height of the image - in pixels (up to 2^31). - bit_depth - holds the bit depth of one of the - image channels. - (valid values are 1, 2, 4, 8, 16 - and depend also on the - color_type. See also significant - bits (sBIT) below). - color_type - describes which color/alpha - channels are present. - PNG_COLOR_TYPE_GRAY - (bit depths 1, 2, 4, 8, 16) - PNG_COLOR_TYPE_GRAY_ALPHA - (bit depths 8, 16) - PNG_COLOR_TYPE_PALETTE - (bit depths 1, 2, 4, 8) - PNG_COLOR_TYPE_RGB - (bit_depths 8, 16) - PNG_COLOR_TYPE_RGB_ALPHA - (bit_depths 8, 16) - - PNG_COLOR_MASK_PALETTE - PNG_COLOR_MASK_COLOR - PNG_COLOR_MASK_ALPHA - - interlace_type - PNG_INTERLACE_NONE or - PNG_INTERLACE_ADAM7 - compression_type - (must be - PNG_COMPRESSION_TYPE_DEFAULT) - filter_method - (must be PNG_FILTER_TYPE_DEFAULT - or, if you are writing a PNG to - be embedded in a MNG datastream, - can also be - PNG_INTRAPIXEL_DIFFERENCING) - - png_set_PLTE(png_ptr, info_ptr, palette, - num_palette); - palette - the palette for the file - (array of png_color) - num_palette - number of entries in the palette - - png_set_gAMA(png_ptr, info_ptr, gamma); - gamma - the gamma the image was created - at (PNG_INFO_gAMA) - - png_set_sRGB(png_ptr, info_ptr, srgb_intent); - srgb_intent - the rendering intent - (PNG_INFO_sRGB) The presence of - the sRGB chunk means that the pixel - data is in the sRGB color space. - This chunk also implies specific - values of gAMA and cHRM. Rendering - intent is the CSS-1 property that - has been defined by the International - Color Consortium - (http://www.color.org). - It can be one of - PNG_sRGB_INTENT_SATURATION, - PNG_sRGB_INTENT_PERCEPTUAL, - PNG_sRGB_INTENT_ABSOLUTE, or - PNG_sRGB_INTENT_RELATIVE. - - - png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, - srgb_intent); - srgb_intent - the rendering intent - (PNG_INFO_sRGB) The presence of the - sRGB chunk means that the pixel - data is in the sRGB color space. - This function also causes gAMA and - cHRM chunks with the specific values - that are consistent with sRGB to be - written. - - png_set_iCCP(png_ptr, info_ptr, name, compression_type, - profile, proflen); - name - The profile name. - compression - The compression type; always - PNG_COMPRESSION_TYPE_BASE for PNG 1.0. - You may give NULL to this argument to - ignore it. - profile - International Color Consortium color - profile data. May contain NULs. - proflen - length of profile data in bytes. - - png_set_sBIT(png_ptr, info_ptr, sig_bit); - sig_bit - the number of significant bits for - (PNG_INFO_sBIT) each of the gray, red, - green, and blue channels, whichever are - appropriate for the given color type - (png_color_16) - - png_set_tRNS(png_ptr, info_ptr, trans, num_trans, - trans_values); - trans - array of transparent entries for - palette (PNG_INFO_tRNS) - trans_values - graylevel or color sample values of - the single transparent color for - non-paletted images (PNG_INFO_tRNS) - num_trans - number of transparent entries - (PNG_INFO_tRNS) - - png_set_hIST(png_ptr, info_ptr, hist); - (PNG_INFO_hIST) - hist - histogram of palette (array of - png_uint_16) - - png_set_tIME(png_ptr, info_ptr, mod_time); - mod_time - time image was last modified - (PNG_VALID_tIME) - - png_set_bKGD(png_ptr, info_ptr, background); - background - background color (PNG_VALID_bKGD) - - png_set_text(png_ptr, info_ptr, text_ptr, num_text); - text_ptr - array of png_text holding image - comments - text_ptr[i].compression - type of compression used - on "text" PNG_TEXT_COMPRESSION_NONE - PNG_TEXT_COMPRESSION_zTXt - PNG_ITXT_COMPRESSION_NONE - PNG_ITXT_COMPRESSION_zTXt - text_ptr[i].key - keyword for comment. Must contain - 1-79 characters. - text_ptr[i].text - text comments for current - keyword. Can be NULL or empty. - text_ptr[i].text_length - length of text string, - after decompression, 0 for iTXt - text_ptr[i].itxt_length - length of itxt string, - after decompression, 0 for tEXt/zTXt - text_ptr[i].lang - language of comment (NULL or - empty for unknown). - text_ptr[i].translated_keyword - keyword in UTF-8 (NULL - or empty for unknown). - num_text - number of comments - - png_set_sPLT(png_ptr, info_ptr, &palette_ptr, - num_spalettes); - palette_ptr - array of png_sPLT_struct structures - to be added to the list of palettes - in the info structure. - num_spalettes - number of palette structures to be - added. - - png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, - unit_type); - offset_x - positive offset from the left - edge of the screen - offset_y - positive offset from the top - edge of the screen - unit_type - PNG_OFFSET_PIXEL, PNG_OFFSET_MICROMETER - - png_set_pHYs(png_ptr, info_ptr, res_x, res_y, - unit_type); - res_x - pixels/unit physical resolution - in x direction - res_y - pixels/unit physical resolution - in y direction - unit_type - PNG_RESOLUTION_UNKNOWN, - PNG_RESOLUTION_METER - - png_set_sCAL(png_ptr, info_ptr, unit, width, height) - unit - physical scale units (an integer) - width - width of a pixel in physical scale units - height - height of a pixel in physical scale units - (width and height are doubles) - - png_set_sCAL_s(png_ptr, info_ptr, unit, width, height) - unit - physical scale units (an integer) - width - width of a pixel in physical scale units - height - height of a pixel in physical scale units - (width and height are strings like "2.54") - - png_set_unknown_chunks(png_ptr, info_ptr, &unknowns, - num_unknowns) - unknowns - array of png_unknown_chunk - structures holding unknown chunks - unknowns[i].name - name of unknown chunk - unknowns[i].data - data of unknown chunk - unknowns[i].size - size of unknown chunk's data - unknowns[i].location - position to write chunk in file - 0: do not write chunk - PNG_HAVE_IHDR: before PLTE - PNG_HAVE_PLTE: before IDAT - PNG_AFTER_IDAT: after IDAT - -The "location" member is set automatically according to -what part of the output file has already been written. -You can change its value after calling png_set_unknown_chunks() -as demonstrated in pngtest.c. Within each of the "locations", -the chunks are sequenced according to their position in the -structure (that is, the value of "i", which is the order in which -the chunk was either read from the input file or defined with -png_set_unknown_chunks). - -A quick word about text and num_text. text is an array of png_text -structures. num_text is the number of valid structures in the array. -Each png_text structure holds a language code, a keyword, a text value, -and a compression type. - -The compression types have the same valid numbers as the compression -types of the image data. Currently, the only valid number is zero. -However, you can store text either compressed or uncompressed, unlike -images, which always have to be compressed. So if you don't want the -text compressed, set the compression type to PNG_TEXT_COMPRESSION_NONE. -Because tEXt and zTXt chunks don't have a language field, if you -specify PNG_TEXT_COMPRESSION_NONE or PNG_TEXT_COMPRESSION_zTXt -any language code or translated keyword will not be written out. - -Until text gets around 1000 bytes, it is not worth compressing it. -After the text has been written out to the file, the compression type -is set to PNG_TEXT_COMPRESSION_NONE_WR or PNG_TEXT_COMPRESSION_zTXt_WR, -so that it isn't written out again at the end (in case you are calling -png_write_end() with the same struct. - -The keywords that are given in the PNG Specification are: - - Title Short (one line) title or - caption for image - Author Name of image's creator - Description Description of image (possibly long) - Copyright Copyright notice - Creation Time Time of original image creation - (usually RFC 1123 format, see below) - Software Software used to create the image - Disclaimer Legal disclaimer - Warning Warning of nature of content - Source Device used to create the image - Comment Miscellaneous comment; conversion - from other image format - -The keyword-text pairs work like this. Keywords should be short -simple descriptions of what the comment is about. Some typical -keywords are found in the PNG specification, as is some recommendations -on keywords. You can repeat keywords in a file. You can even write -some text before the image and some after. For example, you may want -to put a description of the image before the image, but leave the -disclaimer until after, so viewers working over modem connections -don't have to wait for the disclaimer to go over the modem before -they start seeing the image. Finally, keywords should be full -words, not abbreviations. Keywords and text are in the ISO 8859-1 -(Latin-1) character set (a superset of regular ASCII) and can not -contain NUL characters, and should not contain control or other -unprintable characters. To make the comments widely readable, stick -with basic ASCII, and avoid machine specific character set extensions -like the IBM-PC character set. The keyword must be present, but -you can leave off the text string on non-compressed pairs. -Compressed pairs must have a text string, as only the text string -is compressed anyway, so the compression would be meaningless. - -PNG supports modification time via the png_time structure. Two -conversion routines are provided, png_convert_from_time_t() for -time_t and png_convert_from_struct_tm() for struct tm. The -time_t routine uses gmtime(). You don't have to use either of -these, but if you wish to fill in the png_time structure directly, -you should provide the time in universal time (GMT) if possible -instead of your local time. Note that the year number is the full -year (e.g. 1998, rather than 98 - PNG is year 2000 compliant!), and -that months start with 1. - -If you want to store the time of the original image creation, you should -use a plain tEXt chunk with the "Creation Time" keyword. This is -necessary because the "creation time" of a PNG image is somewhat vague, -depending on whether you mean the PNG file, the time the image was -created in a non-PNG format, a still photo from which the image was -scanned, or possibly the subject matter itself. In order to facilitate -machine-readable dates, it is recommended that the "Creation Time" -tEXt chunk use RFC 1123 format dates (e.g. "22 May 1997 18:07:10 GMT"), -although this isn't a requirement. Unlike the tIME chunk, the -"Creation Time" tEXt chunk is not expected to be automatically changed -by the software. To facilitate the use of RFC 1123 dates, a function -png_convert_to_rfc1123(png_timep) is provided to convert from PNG -time to an RFC 1123 format string. - -Writing unknown chunks - -You can use the png_set_unknown_chunks function to queue up chunks -for writing. You give it a chunk name, raw data, and a size; that's -all there is to it. The chunks will be written by the next following -png_write_info_before_PLTE, png_write_info, or png_write_end function. -Any chunks previously read into the info structure's unknown-chunk -list will also be written out in a sequence that satisfies the PNG -specification's ordering rules. - -The high-level write interface - -At this point there are two ways to proceed; through the high-level -write interface, or through a sequence of low-level write operations. -You can use the high-level interface if your image data is present -in the info structure. All defined output -transformations are permitted, enabled by the following masks. - - PNG_TRANSFORM_IDENTITY No transformation - PNG_TRANSFORM_PACKING Pack 1, 2 and 4-bit samples - PNG_TRANSFORM_PACKSWAP Change order of packed - pixels to LSB first - PNG_TRANSFORM_INVERT_MONO Invert monochrome images - PNG_TRANSFORM_SHIFT Normalize pixels to the - sBIT depth - PNG_TRANSFORM_BGR Flip RGB to BGR, RGBA - to BGRA - PNG_TRANSFORM_SWAP_ALPHA Flip RGBA to ARGB or GA - to AG - PNG_TRANSFORM_INVERT_ALPHA Change alpha from opacity - to transparency - PNG_TRANSFORM_SWAP_ENDIAN Byte-swap 16-bit samples - PNG_TRANSFORM_STRIP_FILLER Strip out filler bytes. - -If you have valid image data in the info structure (you can use -png_set_rows() to put image data in the info structure), simply do this: - - png_write_png(png_ptr, info_ptr, png_transforms, NULL) - -where png_transforms is an integer containing the bitwise OR of some set of -transformation flags. This call is equivalent to png_write_info(), -followed the set of transformations indicated by the transform mask, -then png_write_image(), and finally png_write_end(). - -(The final parameter of this call is not yet used. Someday it might point -to transformation parameters required by some future output transform.) - -You must use png_transforms and not call any png_set_transform() functions -when you use png_write_png(). - -The low-level write interface - -If you are going the low-level route instead, you are now ready to -write all the file information up to the actual image data. You do -this with a call to png_write_info(). - - png_write_info(png_ptr, info_ptr); - -Note that there is one transformation you may need to do before -png_write_info(). In PNG files, the alpha channel in an image is the -level of opacity. If your data is supplied as a level of -transparency, you can invert the alpha channel before you write it, so -that 0 is fully transparent and 255 (in 8-bit or paletted images) or -65535 (in 16-bit images) is fully opaque, with - - png_set_invert_alpha(png_ptr); - -This must appear before png_write_info() instead of later with the -other transformations because in the case of paletted images the tRNS -chunk data has to be inverted before the tRNS chunk is written. If -your image is not a paletted image, the tRNS data (which in such cases -represents a single color to be rendered as transparent) won't need to -be changed, and you can safely do this transformation after your -png_write_info() call. - -If you need to write a private chunk that you want to appear before -the PLTE chunk when PLTE is present, you can write the PNG info in -two steps, and insert code to write your own chunk between them: - - png_write_info_before_PLTE(png_ptr, info_ptr); - png_set_unknown_chunks(png_ptr, info_ptr, ...); - png_write_info(png_ptr, info_ptr); - -After you've written the file information, you can set up the library -to handle any special transformations of the image data. The various -ways to transform the data will be described in the order that they -should occur. This is important, as some of these change the color -type and/or bit depth of the data, and some others only work on -certain color types and bit depths. Even though each transformation -checks to see if it has data that it can do something with, you should -make sure to only enable a transformation if it will be valid for the -data. For example, don't swap red and blue on grayscale data. - -PNG files store RGB pixels packed into 3 or 6 bytes. This code tells -the library to strip input data that has 4 or 8 bytes per pixel down -to 3 or 6 bytes (or strip 2 or 4-byte grayscale+filler data to 1 or 2 -bytes per pixel). - - png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); - -where the 0 is unused, and the location is either PNG_FILLER_BEFORE or -PNG_FILLER_AFTER, depending upon whether the filler byte in the pixel -is stored XRGB or RGBX. - -PNG files pack pixels of bit depths 1, 2, and 4 into bytes as small as -they can, resulting in, for example, 8 pixels per byte for 1 bit files. -If the data is supplied at 1 pixel per byte, use this code, which will -correctly pack the pixels into a single byte: - - png_set_packing(png_ptr); - -PNG files reduce possible bit depths to 1, 2, 4, 8, and 16. If your -data is of another bit depth, you can write an sBIT chunk into the -file so that decoders can recover the original data if desired. - - /* Set the true bit depth of the image data */ - if (color_type & PNG_COLOR_MASK_COLOR) - { - sig_bit.red = true_bit_depth; - sig_bit.green = true_bit_depth; - sig_bit.blue = true_bit_depth; - } - else - { - sig_bit.gray = true_bit_depth; - } - if (color_type & PNG_COLOR_MASK_ALPHA) - { - sig_bit.alpha = true_bit_depth; - } - - png_set_sBIT(png_ptr, info_ptr, &sig_bit); - -If the data is stored in the row buffer in a bit depth other than -one supported by PNG (e.g. 3 bit data in the range 0-7 for a 4-bit PNG), -this will scale the values to appear to be the correct bit depth as -is required by PNG. - - png_set_shift(png_ptr, &sig_bit); - -PNG files store 16 bit pixels in network byte order (big-endian, -ie. most significant bits first). This code would be used if they are -supplied the other way (little-endian, i.e. least significant bits -first, the way PCs store them): - - if (bit_depth > 8) - png_set_swap(png_ptr); - -If you are using packed-pixel images (1, 2, or 4 bits/pixel), and you -need to change the order the pixels are packed into bytes, you can use: - - if (bit_depth < 8) - png_set_packswap(png_ptr); - -PNG files store 3 color pixels in red, green, blue order. This code -would be used if they are supplied as blue, green, red: - - png_set_bgr(png_ptr); - -PNG files describe monochrome as black being zero and white being -one. This code would be used if the pixels are supplied with this reversed -(black being one and white being zero): - - png_set_invert_mono(png_ptr); - -Finally, you can write your own transformation function if none of -the existing ones meets your needs. This is done by setting a callback -with - - png_set_write_user_transform_fn(png_ptr, - write_transform_fn); - -You must supply the function - - void write_transform_fn(png_ptr ptr, row_info_ptr - row_info, png_bytep data) - -See pngtest.c for a working example. Your function will be called -before any of the other transformations are processed. - -You can also set up a pointer to a user structure for use by your -callback function. - - png_set_user_transform_info(png_ptr, user_ptr, 0, 0); - -The user_channels and user_depth parameters of this function are ignored -when writing; you can set them to zero as shown. - -You can retrieve the pointer via the function png_get_user_transform_ptr(). -For example: - - voidp write_user_transform_ptr = - png_get_user_transform_ptr(png_ptr); - -It is possible to have libpng flush any pending output, either manually, -or automatically after a certain number of lines have been written. To -flush the output stream a single time call: - - png_write_flush(png_ptr); - -and to have libpng flush the output stream periodically after a certain -number of scanlines have been written, call: - - png_set_flush(png_ptr, nrows); - -Note that the distance between rows is from the last time png_write_flush() -was called, or the first row of the image if it has never been called. -So if you write 50 lines, and then png_set_flush 25, it will flush the -output on the next scanline, and every 25 lines thereafter, unless -png_write_flush() is called before 25 more lines have been written. -If nrows is too small (less than about 10 lines for a 640 pixel wide -RGB image) the image compression may decrease noticeably (although this -may be acceptable for real-time applications). Infrequent flushing will -only degrade the compression performance by a few percent over images -that do not use flushing. - -Writing the image data - -That's it for the transformations. Now you can write the image data. -The simplest way to do this is in one function call. If you have the -whole image in memory, you can just call png_write_image() and libpng -will write the image. You will need to pass in an array of pointers to -each row. This function automatically handles interlacing, so you don't -need to call png_set_interlace_handling() or call this function multiple -times, or any of that other stuff necessary with png_write_rows(). - - png_write_image(png_ptr, row_pointers); - -where row_pointers is: - - png_byte *row_pointers[height]; - -You can point to void or char or whatever you use for pixels. - -If you don't want to write the whole image at once, you can -use png_write_rows() instead. If the file is not interlaced, -this is simple: - - png_write_rows(png_ptr, row_pointers, - number_of_rows); - -row_pointers is the same as in the png_write_image() call. - -If you are just writing one row at a time, you can do this with -a single row_pointer instead of an array of row_pointers: - - png_bytep row_pointer = row; - - png_write_row(png_ptr, row_pointer); - -When the file is interlaced, things can get a good deal more -complicated. The only currently (as of the PNG Specification -version 1.2, dated July 1999) defined interlacing scheme for PNG files -is the "Adam7" interlace scheme, that breaks down an -image into seven smaller images of varying size. libpng will build -these images for you, or you can do them yourself. If you want to -build them yourself, see the PNG specification for details of which -pixels to write when. - -If you don't want libpng to handle the interlacing details, just -use png_set_interlace_handling() and call png_write_rows() the -correct number of times to write all seven sub-images. - -If you want libpng to build the sub-images, call this before you start -writing any rows: - - number_of_passes = - png_set_interlace_handling(png_ptr); - -This will return the number of passes needed. Currently, this -is seven, but may change if another interlace type is added. - -Then write the complete image number_of_passes times. - - png_write_rows(png_ptr, row_pointers, - number_of_rows); - -As some of these rows are not used, and thus return immediately, -you may want to read about interlacing in the PNG specification, -and only update the rows that are actually used. - -Finishing a sequential write - -After you are finished writing the image, you should finish writing -the file. If you are interested in writing comments or time, you should -pass an appropriately filled png_info pointer. If you are not interested, -you can pass NULL. - - png_write_end(png_ptr, info_ptr); - -When you are done, you can free all memory used by libpng like this: - - png_destroy_write_struct(&png_ptr, &info_ptr); - -It is also possible to individually free the info_ptr members that -point to libpng-allocated storage with the following function: - - png_free_data(png_ptr, info_ptr, mask, seq) - mask - identifies data to be freed, a mask - containing the bitwise OR of one or - more of - PNG_FREE_PLTE, PNG_FREE_TRNS, - PNG_FREE_HIST, PNG_FREE_ICCP, - PNG_FREE_PCAL, PNG_FREE_ROWS, - PNG_FREE_SCAL, PNG_FREE_SPLT, - PNG_FREE_TEXT, PNG_FREE_UNKN, - or simply PNG_FREE_ALL - seq - sequence number of item to be freed - (-1 for all items) - -This function may be safely called when the relevant storage has -already been freed, or has not yet been allocated, or was allocated -by the user and not by libpng, and will in those -cases do nothing. The "seq" parameter is ignored if only one item -of the selected data type, such as PLTE, is allowed. If "seq" is not --1, and multiple items are allowed for the data type identified in -the mask, such as text or sPLT, only the n'th item in the structure -is freed, where n is "seq". - -If you allocated data such as a palette that you passed -in to libpng with png_set_*, you must not free it until just before the call to -png_destroy_write_struct(). - -The default behavior is only to free data that was allocated internally -by libpng. This can be changed, so that libpng will not free the data, -or so that it will free data that was allocated by the user with png_malloc() -or png_zalloc() and passed in via a png_set_*() function, with - - png_data_freer(png_ptr, info_ptr, freer, mask) - mask - which data elements are affected - same choices as in png_free_data() - freer - one of - PNG_DESTROY_WILL_FREE_DATA - PNG_SET_WILL_FREE_DATA - PNG_USER_WILL_FREE_DATA - -For example, to transfer responsibility for some data from a read structure -to a write structure, you could use - - png_data_freer(read_ptr, read_info_ptr, - PNG_USER_WILL_FREE_DATA, - PNG_FREE_PLTE|PNG_FREE_tRNS|PNG_FREE_hIST) - png_data_freer(write_ptr, write_info_ptr, - PNG_DESTROY_WILL_FREE_DATA, - PNG_FREE_PLTE|PNG_FREE_tRNS|PNG_FREE_hIST) - -thereby briefly reassigning responsibility for freeing to the user but -immediately afterwards reassigning it once more to the write_destroy -function. Having done this, it would then be safe to destroy the read -structure and continue to use the PLTE, tRNS, and hIST data in the write -structure. - -This function only affects data that has already been allocated. -You can call this function before calling after the png_set_*() functions -to control whether the user or png_destroy_*() is supposed to free the data. -When the user assumes responsibility for libpng-allocated data, the -application must use -png_free() to free it, and when the user transfers responsibility to libpng -for data that the user has allocated, the user must have used png_malloc() -or png_zalloc() to allocate it. - -If you allocated text_ptr.text, text_ptr.lang, and text_ptr.translated_keyword -separately, do not transfer responsibility for freeing text_ptr to libpng, -because when libpng fills a png_text structure it combines these members with -the key member, and png_free_data() will free only text_ptr.key. Similarly, -if you transfer responsibility for free'ing text_ptr from libpng to your -application, your application must not separately free those members. -For a more compact example of writing a PNG image, see the file example.c. - -V. Modifying/Customizing libpng: - -There are two issues here. The first is changing how libpng does -standard things like memory allocation, input/output, and error handling. -The second deals with more complicated things like adding new chunks, -adding new transformations, and generally changing how libpng works. -Both of those are compile-time issues; that is, they are generally -determined at the time the code is written, and there is rarely a need -to provide the user with a means of changing them. - -Memory allocation, input/output, and error handling - -All of the memory allocation, input/output, and error handling in libpng -goes through callbacks that are user-settable. The default routines are -in pngmem.c, pngrio.c, pngwio.c, and pngerror.c, respectively. To change -these functions, call the appropriate png_set_*_fn() function. - -Memory allocation is done through the functions png_malloc() -and png_free(). These currently just call the standard C functions. If -your pointers can't access more then 64K at a time, you will want to set -MAXSEG_64K in zlib.h. Since it is unlikely that the method of handling -memory allocation on a platform will change between applications, these -functions must be modified in the library at compile time. If you prefer -to use a different method of allocating and freeing data, you can use -png_create_read_struct_2() or png_create_write_struct_2() to register -your own functions as described above. -These functions also provide a void pointer that can be retrieved via - - mem_ptr=png_get_mem_ptr(png_ptr); - -Your replacement memory functions must have prototypes as follows: - - png_voidp malloc_fn(png_structp png_ptr, - png_size_t size); - void free_fn(png_structp png_ptr, png_voidp ptr); - -Your malloc_fn() must return NULL in case of failure. The png_malloc() -function will normally call png_error() if it receives a NULL from the -system memory allocator or from your replacement malloc_fn(). - -Input/Output in libpng is done through png_read() and png_write(), -which currently just call fread() and fwrite(). The FILE * is stored in -png_struct and is initialized via png_init_io(). If you wish to change -the method of I/O, the library supplies callbacks that you can set -through the function png_set_read_fn() and png_set_write_fn() at run -time, instead of calling the png_init_io() function. These functions -also provide a void pointer that can be retrieved via the function -png_get_io_ptr(). For example: - - png_set_read_fn(png_structp read_ptr, - voidp read_io_ptr, png_rw_ptr read_data_fn) - - png_set_write_fn(png_structp write_ptr, - voidp write_io_ptr, png_rw_ptr write_data_fn, - png_flush_ptr output_flush_fn); - - voidp read_io_ptr = png_get_io_ptr(read_ptr); - voidp write_io_ptr = png_get_io_ptr(write_ptr); - -The replacement I/O functions must have prototypes as follows: - - void user_read_data(png_structp png_ptr, - png_bytep data, png_size_t length); - void user_write_data(png_structp png_ptr, - png_bytep data, png_size_t length); - void user_flush_data(png_structp png_ptr); - -Supplying NULL for the read, write, or flush functions sets them back -to using the default C stream functions. It is an error to read from -a write stream, and vice versa. - -Error handling in libpng is done through png_error() and png_warning(). -Errors handled through png_error() are fatal, meaning that png_error() -should never return to its caller. Currently, this is handled via -setjmp() and longjmp() (unless you have compiled libpng with -PNG_SETJMP_NOT_SUPPORTED, in which case it is handled via PNG_ABORT()), -but you could change this to do things like exit() if you should wish. - -On non-fatal errors, png_warning() is called -to print a warning message, and then control returns to the calling code. -By default png_error() and png_warning() print a message on stderr via -fprintf() unless the library is compiled with PNG_NO_CONSOLE_IO defined -(because you don't want the messages) or PNG_NO_STDIO defined (because -fprintf() isn't available). If you wish to change the behavior of the error -functions, you will need to set up your own message callbacks. These -functions are normally supplied at the time that the png_struct is created. -It is also possible to redirect errors and warnings to your own replacement -functions after png_create_*_struct() has been called by calling: - - png_set_error_fn(png_structp png_ptr, - png_voidp error_ptr, png_error_ptr error_fn, - png_error_ptr warning_fn); - - png_voidp error_ptr = png_get_error_ptr(png_ptr); - -If NULL is supplied for either error_fn or warning_fn, then the libpng -default function will be used, calling fprintf() and/or longjmp() if a -problem is encountered. The replacement error functions should have -parameters as follows: - - void user_error_fn(png_structp png_ptr, - png_const_charp error_msg); - void user_warning_fn(png_structp png_ptr, - png_const_charp warning_msg); - -The motivation behind using setjmp() and longjmp() is the C++ throw and -catch exception handling methods. This makes the code much easier to write, -as there is no need to check every return code of every function call. -However, there are some uncertainties about the status of local variables -after a longjmp, so the user may want to be careful about doing anything after -setjmp returns non-zero besides returning itself. Consult your compiler -documentation for more details. For an alternative approach, you may wish -to use the "cexcept" facility (see http://cexcept.sourceforge.net). - -Custom chunks - -If you need to read or write custom chunks, you may need to get deeper -into the libpng code. The library now has mechanisms for storing -and writing chunks of unknown type; you can even declare callbacks -for custom chunks. However, this may not be good enough if the -library code itself needs to know about interactions between your -chunk and existing `intrinsic' chunks. - -If you need to write a new intrinsic chunk, first read the PNG -specification. Acquire a first level of -understanding of how it works. Pay particular attention to the -sections that describe chunk names, and look at how other chunks were -designed, so you can do things similarly. Second, check out the -sections of libpng that read and write chunks. Try to find a chunk -that is similar to yours and use it as a template. More details can -be found in the comments inside the code. It is best to handle unknown -chunks in a generic method, via callback functions, instead of by -modifying libpng functions. - -If you wish to write your own transformation for the data, look through -the part of the code that does the transformations, and check out some of -the simpler ones to get an idea of how they work. Try to find a similar -transformation to the one you want to add and copy off of it. More details -can be found in the comments inside the code itself. - -Configuring for 16 bit platforms - -You will want to look into zconf.h to tell zlib (and thus libpng) that -it cannot allocate more then 64K at a time. Even if you can, the memory -won't be accessible. So limit zlib and libpng to 64K by defining MAXSEG_64K. - -Configuring for DOS - -For DOS users who only have access to the lower 640K, you will -have to limit zlib's memory usage via a png_set_compression_mem_level() -call. See zlib.h or zconf.h in the zlib library for more information. - -Configuring for Medium Model - -Libpng's support for medium model has been tested on most of the popular -compilers. Make sure MAXSEG_64K gets defined, USE_FAR_KEYWORD gets -defined, and FAR gets defined to far in pngconf.h, and you should be -all set. Everything in the library (except for zlib's structure) is -expecting far data. You must use the typedefs with the p or pp on -the end for pointers (or at least look at them and be careful). Make -note that the rows of data are defined as png_bytepp, which is an -unsigned char far * far *. - -Configuring for gui/windowing platforms: - -You will need to write new error and warning functions that use the GUI -interface, as described previously, and set them to be the error and -warning functions at the time that png_create_*_struct() is called, -in order to have them available during the structure initialization. -They can be changed later via png_set_error_fn(). On some compilers, -you may also have to change the memory allocators (png_malloc, etc.). - -Configuring for compiler xxx: - -All includes for libpng are in pngconf.h. If you need to add/change/delete -an include, this is the place to do it. The includes that are not -needed outside libpng are protected by the PNG_INTERNAL definition, -which is only defined for those routines inside libpng itself. The -files in libpng proper only include png.h, which includes pngconf.h. - -Configuring zlib: - -There are special functions to configure the compression. Perhaps the -most useful one changes the compression level, which currently uses -input compression values in the range 0 - 9. The library normally -uses the default compression level (Z_DEFAULT_COMPRESSION = 6). Tests -have shown that for a large majority of images, compression values in -the range 3-6 compress nearly as well as higher levels, and do so much -faster. For online applications it may be desirable to have maximum speed -(Z_BEST_SPEED = 1). With versions of zlib after v0.99, you can also -specify no compression (Z_NO_COMPRESSION = 0), but this would create -files larger than just storing the raw bitmap. You can specify the -compression level by calling: - - png_set_compression_level(png_ptr, level); - -Another useful one is to reduce the memory level used by the library. -The memory level defaults to 8, but it can be lowered if you are -short on memory (running DOS, for example, where you only have 640K). -Note that the memory level does have an effect on compression; among -other things, lower levels will result in sections of incompressible -data being emitted in smaller stored blocks, with a correspondingly -larger relative overhead of up to 15% in the worst case. - - png_set_compression_mem_level(png_ptr, level); - -The other functions are for configuring zlib. They are not recommended -for normal use and may result in writing an invalid PNG file. See -zlib.h for more information on what these mean. - - png_set_compression_strategy(png_ptr, - strategy); - png_set_compression_window_bits(png_ptr, - window_bits); - png_set_compression_method(png_ptr, method); - png_set_compression_buffer_size(png_ptr, size); - -Controlling row filtering - -If you want to control whether libpng uses filtering or not, which -filters are used, and how it goes about picking row filters, you -can call one of these functions. The selection and configuration -of row filters can have a significant impact on the size and -encoding speed and a somewhat lesser impact on the decoding speed -of an image. Filtering is enabled by default for RGB and grayscale -images (with and without alpha), but not for paletted images nor -for any images with bit depths less than 8 bits/pixel. - -The 'method' parameter sets the main filtering method, which is -currently only '0' in the PNG 1.2 specification. The 'filters' -parameter sets which filter(s), if any, should be used for each -scanline. Possible values are PNG_ALL_FILTERS and PNG_NO_FILTERS -to turn filtering on and off, respectively. - -Individual filter types are PNG_FILTER_NONE, PNG_FILTER_SUB, -PNG_FILTER_UP, PNG_FILTER_AVG, PNG_FILTER_PAETH, which can be bitwise -ORed together with '|' to specify one or more filters to use. -These filters are described in more detail in the PNG specification. -If you intend to change the filter type during the course of writing -the image, you should start with flags set for all of the filters -you intend to use so that libpng can initialize its internal -structures appropriately for all of the filter types. (Note that this -means the first row must always be adaptively filtered, because libpng -currently does not allocate the filter buffers until png_write_row() -is called for the first time.) - - filters = PNG_FILTER_NONE | PNG_FILTER_SUB - PNG_FILTER_UP | PNG_FILTER_AVE | - PNG_FILTER_PAETH | PNG_ALL_FILTERS; - - png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, - filters); - The second parameter can also be - PNG_INTRAPIXEL_DIFFERENCING if you are - writing a PNG to be embedded in a MNG - datastream. This parameter must be the - same as the value of filter_method used - in png_set_IHDR(). - -It is also possible to influence how libpng chooses from among the -available filters. This is done in one or both of two ways - by -telling it how important it is to keep the same filter for successive -rows, and by telling it the relative computational costs of the filters. - - double weights[3] = {1.5, 1.3, 1.1}, - costs[PNG_FILTER_VALUE_LAST] = - {1.0, 1.3, 1.3, 1.5, 1.7}; - - png_set_filter_heuristics(png_ptr, - PNG_FILTER_HEURISTIC_WEIGHTED, 3, - weights, costs); - -The weights are multiplying factors that indicate to libpng that the -row filter should be the same for successive rows unless another row filter -is that many times better than the previous filter. In the above example, -if the previous 3 filters were SUB, SUB, NONE, the SUB filter could have a -"sum of absolute differences" 1.5 x 1.3 times higher than other filters -and still be chosen, while the NONE filter could have a sum 1.1 times -higher than other filters and still be chosen. Unspecified weights are -taken to be 1.0, and the specified weights should probably be declining -like those above in order to emphasize recent filters over older filters. - -The filter costs specify for each filter type a relative decoding cost -to be considered when selecting row filters. This means that filters -with higher costs are less likely to be chosen over filters with lower -costs, unless their "sum of absolute differences" is that much smaller. -The costs do not necessarily reflect the exact computational speeds of -the various filters, since this would unduly influence the final image -size. - -Note that the numbers above were invented purely for this example and -are given only to help explain the function usage. Little testing has -been done to find optimum values for either the costs or the weights. - -Removing unwanted object code - -There are a bunch of #define's in pngconf.h that control what parts of -libpng are compiled. All the defines end in _SUPPORTED. If you are -never going to use a capability, you can change the #define to #undef -before recompiling libpng and save yourself code and data space, or -you can turn off individual capabilities with defines that begin with -PNG_NO_. - -You can also turn all of the transforms and ancillary chunk capabilities -off en masse with compiler directives that define -PNG_NO_READ[or WRITE]_TRANSFORMS, or PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS, -or all four, -along with directives to turn on any of the capabilities that you do -want. The PNG_NO_READ[or WRITE]_TRANSFORMS directives disable -the extra transformations but still leave the library fully capable of reading -and writing PNG files with all known public chunks -Use of the PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS directive -produces a library that is incapable of reading or writing ancillary chunks. -If you are not using the progressive reading capability, you can -turn that off with PNG_NO_PROGRESSIVE_READ (don't confuse -this with the INTERLACING capability, which you'll still have). - -All the reading and writing specific code are in separate files, so the -linker should only grab the files it needs. However, if you want to -make sure, or if you are building a stand alone library, all the -reading files start with pngr and all the writing files start with -pngw. The files that don't match either (like png.c, pngtrans.c, etc.) -are used for both reading and writing, and always need to be included. -The progressive reader is in pngpread.c - -If you are creating or distributing a dynamically linked library (a .so -or DLL file), you should not remove or disable any parts of the library, -as this will cause applications linked with different versions of the -library to fail if they call functions not available in your library. -The size of the library itself should not be an issue, because only -those sections that are actually used will be loaded into memory. - -Requesting debug printout - -The macro definition PNG_DEBUG can be used to request debugging -printout. Set it to an integer value in the range 0 to 3. Higher -numbers result in increasing amounts of debugging information. The -information is printed to the "stderr" file, unless another file -name is specified in the PNG_DEBUG_FILE macro definition. - -When PNG_DEBUG > 0, the following functions (macros) become available: - - png_debug(level, message) - png_debug1(level, message, p1) - png_debug2(level, message, p1, p2) - -in which "level" is compared to PNG_DEBUG to decide whether to print -the message, "message" is the formatted string to be printed, -and p1 and p2 are parameters that are to be embedded in the string -according to printf-style formatting directives. For example, - - png_debug1(2, "foo=%d\n", foo); - -is expanded to - - if(PNG_DEBUG > 2) - fprintf(PNG_DEBUG_FILE, "foo=%d\n", foo); - -When PNG_DEBUG is defined but is zero, the macros aren't defined, but you -can still use PNG_DEBUG to control your own debugging: - - #ifdef PNG_DEBUG - fprintf(stderr, ... - #endif - -When PNG_DEBUG = 1, the macros are defined, but only png_debug statements -having level = 0 will be printed. There aren't any such statements in -this version of libpng, but if you insert some they will be printed. - -VII. MNG support - -The MNG specification (available at http://www.libpng.org/pub/mng) allows -certain extensions to PNG for PNG images that are embedded in MNG datastreams. -Libpng can support some of these extensions. To enable them, use the -png_permit_mng_features() function: - - feature_set = png_permit_mng_features(png_ptr, mask) - mask is a png_uint_32 containing the bitwise OR of the - features you want to enable. These include - PNG_FLAG_MNG_EMPTY_PLTE - PNG_FLAG_MNG_FILTER_64 - PNG_ALL_MNG_FEATURES - feature_set is a png_uint_32 that is the bitwise AND of - your mask with the set of MNG features that is - supported by the version of libpng that you are using. - -It is an error to use this function when reading or writing a standalone -PNG file with the PNG 8-byte signature. The PNG datastream must be wrapped -in a MNG datastream. As a minimum, it must have the MNG 8-byte signature -and the MHDR and MEND chunks. Libpng does not provide support for these -or any other MNG chunks; your application must provide its own support for -them. You may wish to consider using libmng (available at -http://www.libmng.com) instead. - -VIII. Changes to Libpng from version 0.88 - -It should be noted that versions of libpng later than 0.96 are not -distributed by the original libpng author, Guy Schalnat, nor by -Andreas Dilger, who had taken over from Guy during 1996 and 1997, and -distributed versions 0.89 through 0.96, but rather by another member -of the original PNG Group, Glenn Randers-Pehrson. Guy and Andreas are -still alive and well, but they have moved on to other things. - -The old libpng functions png_read_init(), png_write_init(), -png_info_init(), png_read_destroy(), and png_write_destroy() have been -moved to PNG_INTERNAL in version 0.95 to discourage their use. These -functions will be removed from libpng version 2.0.0. - -The preferred method of creating and initializing the libpng structures is -via the png_create_read_struct(), png_create_write_struct(), and -png_create_info_struct() because they isolate the size of the structures -from the application, allow version error checking, and also allow the -use of custom error handling routines during the initialization, which -the old functions do not. The functions png_read_destroy() and -png_write_destroy() do not actually free the memory that libpng -allocated for these structs, but just reset the data structures, so they -can be used instead of png_destroy_read_struct() and -png_destroy_write_struct() if you feel there is too much system overhead -allocating and freeing the png_struct for each image read. - -Setting the error callbacks via png_set_message_fn() before -png_read_init() as was suggested in libpng-0.88 is no longer supported -because this caused applications that do not use custom error functions -to fail if the png_ptr was not initialized to zero. It is still possible -to set the error callbacks AFTER png_read_init(), or to change them with -png_set_error_fn(), which is essentially the same function, but with a new -name to force compilation errors with applications that try to use the old -method. - -Starting with version 1.0.7, you can find out which version of the library -you are using at run-time: - - png_uint_32 libpng_vn = png_access_version_number(); - -The number libpng_vn is constructed from the major version, minor -version with leading zero, and release number with leading zero, -(e.g., libpng_vn for version 1.0.7 is 10007). - -You can also check which version of png.h you used when compiling your -application: - - png_uint_32 application_vn = PNG_LIBPNG_VER; - -IX. Y2K Compliance in libpng - -October 13, 2007 - -Since the PNG Development group is an ad-hoc body, we can't make -an official declaration. - -This is your unofficial assurance that libpng from version 0.71 and -upward through 1.2.22 are Y2K compliant. It is my belief that earlier -versions were also Y2K compliant. - -Libpng only has three year fields. One is a 2-byte unsigned integer that -will hold years up to 65535. The other two hold the date in text -format, and will hold years up to 9999. - -The integer is - "png_uint_16 year" in png_time_struct. - -The strings are - "png_charp time_buffer" in png_struct and - "near_time_buffer", which is a local character string in png.c. - -There are seven time-related functions: - - png_convert_to_rfc_1123() in png.c - (formerly png_convert_to_rfc_1152() in error) - png_convert_from_struct_tm() in pngwrite.c, called - in pngwrite.c - png_convert_from_time_t() in pngwrite.c - png_get_tIME() in pngget.c - png_handle_tIME() in pngrutil.c, called in pngread.c - png_set_tIME() in pngset.c - png_write_tIME() in pngwutil.c, called in pngwrite.c - -All appear to handle dates properly in a Y2K environment. The -png_convert_from_time_t() function calls gmtime() to convert from system -clock time, which returns (year - 1900), which we properly convert to -the full 4-digit year. There is a possibility that applications using -libpng are not passing 4-digit years into the png_convert_to_rfc_1123() -function, or that they are incorrectly passing only a 2-digit year -instead of "year - 1900" into the png_convert_from_struct_tm() function, -but this is not under our control. The libpng documentation has always -stated that it works with 4-digit years, and the APIs have been -documented as such. - -The tIME chunk itself is also Y2K compliant. It uses a 2-byte unsigned -integer to hold the year, and can hold years as large as 65535. - -zlib, upon which libpng depends, is also Y2K compliant. It contains -no date-related code. - - - Glenn Randers-Pehrson - libpng maintainer - PNG Development Group diff --git a/uppdev/plugin/png/lib/libpng.3 b/uppdev/plugin/png/lib/libpng.3 deleted file mode 100644 index 44b9334d0..000000000 --- a/uppdev/plugin/png/lib/libpng.3 +++ /dev/null @@ -1,3600 +0,0 @@ -.TH LIBPNG 3 "October 13, 2007" -.SH NAME -libpng \- Portable Network Graphics (PNG) Reference Library 1.2.22 -.SH SYNOPSIS -\fB -#include \fP - -\fBpng_uint_32 png_access_version_number \fI(void\fP\fB);\fP - -\fBint png_check_sig (png_bytep \fP\fIsig\fP\fB, int \fInum\fP\fB);\fP - -\fBvoid png_chunk_error (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fIerror\fP\fB);\fP - -\fBvoid png_chunk_warning (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fImessage\fP\fB);\fP - -\fBvoid png_convert_from_struct_tm (png_timep \fP\fIptime\fP\fB, struct tm FAR * \fIttime\fP\fB);\fP - -\fBvoid png_convert_from_time_t (png_timep \fP\fIptime\fP\fB, time_t \fIttime\fP\fB);\fP - -\fBpng_charp png_convert_to_rfc1123 (png_structp \fP\fIpng_ptr\fP\fB, png_timep \fIptime\fP\fB);\fP - -\fBpng_infop png_create_info_struct (png_structp \fIpng_ptr\fP\fB);\fP - -\fBpng_structp png_create_read_struct (png_const_charp \fP\fIuser_png_ver\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fIwarn_fn\fP\fB);\fP - -\fBpng_structp png_create_read_struct_2(png_const_charp \fP\fIuser_png_ver\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fP\fIwarn_fn\fP\fB, png_voidp \fP\fImem_ptr\fP\fB, png_malloc_ptr \fP\fImalloc_fn\fP\fB, png_free_ptr \fIfree_fn\fP\fB);\fP - -\fBpng_structp png_create_write_struct (png_const_charp \fP\fIuser_png_ver\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fIwarn_fn\fP\fB);\fP - -\fBpng_structp png_create_write_struct_2(png_const_charp \fP\fIuser_png_ver\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fP\fIwarn_fn\fP\fB, png_voidp \fP\fImem_ptr\fP\fB, png_malloc_ptr \fP\fImalloc_fn\fP\fB, png_free_ptr \fIfree_fn\fP\fB);\fP - -\fBint png_debug(int \fP\fIlevel\fP\fB, png_const_charp \fImessage\fP\fB);\fP - -\fBint png_debug1(int \fP\fIlevel\fP\fB, png_const_charp \fP\fImessage\fP\fB, \fIp1\fP\fB);\fP - -\fBint png_debug2(int \fP\fIlevel\fP\fB, png_const_charp \fP\fImessage\fP\fB, \fP\fIp1\fP\fB, \fIp2\fP\fB);\fP - -\fBvoid png_destroy_info_struct (png_structp \fP\fIpng_ptr\fP\fB, png_infopp \fIinfo_ptr_ptr\fP\fB);\fP - -\fBvoid png_destroy_read_struct (png_structpp \fP\fIpng_ptr_ptr\fP\fB, png_infopp \fP\fIinfo_ptr_ptr\fP\fB, png_infopp \fIend_info_ptr_ptr\fP\fB);\fP - -\fBvoid png_destroy_write_struct (png_structpp \fP\fIpng_ptr_ptr\fP\fB, png_infopp \fIinfo_ptr_ptr\fP\fB);\fP - -\fBvoid png_error (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fIerror\fP\fB);\fP - -\fBvoid png_free (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fIptr\fP\fB);\fP - -\fBvoid png_free_chunk_list (png_structp \fIpng_ptr\fP\fB);\fP - -\fBvoid png_free_default(png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fIptr\fP\fB);\fP - -\fBvoid png_free_data (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fInum\fP\fB);\fP - -\fBpng_byte png_get_bit_depth (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP - -\fBpng_uint_32 png_get_bKGD (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_color_16p \fI*background\fP\fB);\fP - -\fBpng_byte png_get_channels (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP - -\fBpng_uint_32 png_get_cHRM (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, double \fP\fI*white_x\fP\fB, double \fP\fI*white_y\fP\fB, double \fP\fI*red_x\fP\fB, double \fP\fI*red_y\fP\fB, double \fP\fI*green_x\fP\fB, double \fP\fI*green_y\fP\fB, double \fP\fI*blue_x\fP\fB, double \fI*blue_y\fP\fB);\fP - -\fBpng_uint_32 png_get_cHRM_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fI*white_x\fP\fB, png_uint_32 \fP\fI*white_y\fP\fB, png_uint_32 \fP\fI*red_x\fP\fB, png_uint_32 \fP\fI*red_y\fP\fB, png_uint_32 \fP\fI*green_x\fP\fB, png_uint_32 \fP\fI*green_y\fP\fB, png_uint_32 \fP\fI*blue_x\fP\fB, png_uint_32 \fI*blue_y\fP\fB);\fP - -\fBpng_byte png_get_color_type (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP - -\fBpng_byte png_get_compression_type (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP - -\fBpng_byte png_get_copyright (png_structp \fIpng_ptr\fP\fB);\fP - -\fBpng_voidp png_get_error_ptr (png_structp \fIpng_ptr\fP\fB);\fP - -\fBpng_byte png_get_filter_type (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP - -\fBpng_uint_32 png_get_gAMA (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, double \fI*file_gamma\fP\fB);\fP - -\fBpng_uint_32 png_get_gAMA_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fI*int_file_gamma\fP\fB);\fP - -\fBpng_byte png_get_header_ver (png_structp \fIpng_ptr\fP\fB);\fP - -\fBpng_byte png_get_header_version (png_structp \fIpng_ptr\fP\fB);\fP - -\fBpng_uint_32 png_get_hIST (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_16p \fI*hist\fP\fB);\fP - -\fBpng_uint_32 png_get_iCCP (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_charpp \fP\fIname\fP\fB, int \fP\fI*compression_type\fP\fB, png_charpp \fP\fIprofile\fP\fB, png_uint_32 \fI*proflen\fP\fB);\fP - -\fBpng_uint_32 png_get_IHDR (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fI*width\fP\fB, png_uint_32 \fP\fI*height\fP\fB, int \fP\fI*bit_depth\fP\fB, int \fP\fI*color_type\fP\fB, int \fP\fI*interlace_type\fP\fB, int \fP\fI*compression_type\fP\fB, int \fI*filter_type\fP\fB);\fP - -\fBpng_uint_32 png_get_image_height (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP - -\fBpng_uint_32 png_get_image_width (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP - -\fB#if !defined(PNG_1_0_X) png_int_32 png_get_int_32 (png_bytep buf); \fI#endif - -\fBpng_byte png_get_interlace_type (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP - -\fBpng_voidp png_get_io_ptr (png_structp \fIpng_ptr\fP\fB);\fP - -\fBpng_byte png_get_libpng_ver (png_structp \fIpng_ptr\fP\fB);\fP - -\fBpng_voidp png_get_mem_ptr(png_structp \fIpng_ptr\fP\fB);\fP - -\fBpng_uint_32 png_get_oFFs (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fI*offset_x\fP\fB, png_uint_32 \fP\fI*offset_y\fP\fB, int \fI*unit_type\fP\fB);\fP - -\fBpng_uint_32 png_get_pCAL (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_charp \fP\fI*purpose\fP\fB, png_int_32 \fP\fI*X0\fP\fB, png_int_32 \fP\fI*X1\fP\fB, int \fP\fI*type\fP\fB, int \fP\fI*nparams\fP\fB, png_charp \fP\fI*units\fP\fB, png_charpp \fI*params\fP\fB);\fP - -\fBpng_uint_32 png_get_pHYs (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fI*res_x\fP\fB, png_uint_32 \fP\fI*res_y\fP\fB, int \fI*unit_type\fP\fB);\fP - -\fBfloat png_get_pixel_aspect_ratio (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP - -\fBpng_uint_32 png_get_pixels_per_meter (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP - -\fBpng_voidp png_get_progressive_ptr (png_structp \fIpng_ptr\fP\fB);\fP - -\fBpng_uint_32 png_get_PLTE (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_colorp \fP\fI*palette\fP\fB, int \fI*num_palette\fP\fB);\fP - -\fBpng_byte png_get_rgb_to_gray_status (png_structp png_ptr) png_uint_32 png_get_rowbytes (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP - -\fBpng_bytepp png_get_rows (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP - -\fBpng_uint_32 png_get_sBIT (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_color_8p \fI*sig_bit\fP\fB);\fP - -\fBpng_bytep png_get_signature (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP - -\fBpng_uint_32 png_get_sPLT (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_spalette_p \fI*splt_ptr\fP\fB);\fP - -\fBpng_uint_32 png_get_sRGB (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fI*intent\fP\fB);\fP - -\fBpng_uint_32 png_get_text (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_textp \fP\fI*text_ptr\fP\fB, int \fI*num_text\fP\fB);\fP - -\fBpng_uint_32 png_get_tIME (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_timep \fI*mod_time\fP\fB);\fP - -\fBpng_uint_32 png_get_tRNS (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_bytep \fP\fI*trans\fP\fB, int \fP\fI*num_trans\fP\fB, png_color_16p \fI*trans_values\fP\fB);\fP - -\fB#if !defined(PNG_1_0_X) png_uint_16 png_get_uint_16 (png_bytep \fIbuf\fP\fB);\fP - -\fBpng_uint_32 png_get_uint_31 (png_bytep \fIbuf\fP\fB);\fP - -\fBpng_uint_32 png_get_uint_32 (png_bytep buf); \fI#endif - -\fBpng_uint_32 png_get_unknown_chunks (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_unknown_chunkpp \fIunknowns\fP\fB);\fP - -\fBpng_voidp png_get_user_chunk_ptr (png_structp \fIpng_ptr\fP\fB);\fP - -\fBpng_uint_32 png_get_user_height_max( png_structp \fIpng_ptr\fP\fB);\fP - -\fBpng_voidp png_get_user_transform_ptr (png_structp \fIpng_ptr\fP\fB);\fP - -\fBpng_uint_32 png_get_user_width_max (png_structp \fIpng_ptr\fP\fB);\fP - -\fBpng_uint_32 png_get_valid (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIflag\fP\fB);\fP - -\fBpng_int_32 png_get_x_offset_microns (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP - -\fBpng_int_32 png_get_x_offset_pixels (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP - -\fBpng_uint_32 png_get_x_pixels_per_meter (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP - -\fBpng_int_32 png_get_y_offset_microns (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP - -\fBpng_int_32 png_get_y_offset_pixels (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP - -\fBpng_uint_32 png_get_y_pixels_per_meter (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP - -\fBpng_uint_32 png_get_compression_buffer_size (png_structp \fIpng_ptr\fP\fB);\fP - -\fBint png_handle_as_unknown (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fIchunk_name\fP\fB);\fP - -\fBvoid png_init_io (png_structp \fP\fIpng_ptr\fP\fB, FILE \fI*fp\fP\fB);\fP - -\fBDEPRECATED: void png_info_init (png_infop \fIinfo_ptr\fP\fB);\fP - -\fBDEPRECATED: void png_info_init_2 (png_infopp \fP\fIptr_ptr\fP\fB, png_size_t \fIpng_info_struct_size\fP\fB);\fP - -\fBpng_voidp png_malloc (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIsize\fP\fB);\fP - -\fBpng_voidp png_malloc_default(png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIsize\fP\fB);\fP - -\fBvoidp png_memcpy (png_voidp \fP\fIs1\fP\fB, png_voidp \fP\fIs2\fP\fB, png_size_t \fIsize\fP\fB);\fP - -\fBpng_voidp png_memcpy_check (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIs1\fP\fB, png_voidp \fP\fIs2\fP\fB, png_uint_32 \fIsize\fP\fB);\fP - -\fBvoidp png_memset (png_voidp \fP\fIs1\fP\fB, int \fP\fIvalue\fP\fB, png_size_t \fIsize\fP\fB);\fP - -\fBpng_voidp png_memset_check (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIs1\fP\fB, int \fP\fIvalue\fP\fB, png_uint_32 \fIsize\fP\fB);\fP - -\fBDEPRECATED: void png_permit_empty_plte (png_structp \fP\fIpng_ptr\fP\fB, int \fIempty_plte_permitted\fP\fB);\fP - -\fBvoid png_process_data (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_bytep \fP\fIbuffer\fP\fB, png_size_t \fIbuffer_size\fP\fB);\fP - -\fBvoid png_progressive_combine_row (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIold_row\fP\fB, png_bytep \fInew_row\fP\fB);\fP - -\fBvoid png_read_destroy (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_infop \fIend_info_ptr\fP\fB);\fP - -\fBvoid png_read_end (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP - -\fBvoid png_read_image (png_structp \fP\fIpng_ptr\fP\fB, png_bytepp \fIimage\fP\fB);\fP - -\fBDEPRECATED: void png_read_init (png_structp \fIpng_ptr\fP\fB);\fP - -\fBDEPRECATED: void png_read_init_2 (png_structpp \fP\fIptr_ptr\fP\fB, png_const_charp \fP\fIuser_png_ver\fP\fB, png_size_t \fP\fIpng_struct_size\fP\fB, png_size_t \fIpng_info_size\fP\fB);\fP - -\fBvoid png_read_info (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP - -\fBvoid png_read_png (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fItransforms\fP\fB, png_voidp \fIparams\fP\fB);\fP - -\fBvoid png_read_row (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIrow\fP\fB, png_bytep \fIdisplay_row\fP\fB);\fP - -\fBvoid png_read_rows (png_structp \fP\fIpng_ptr\fP\fB, png_bytepp \fP\fIrow\fP\fB, png_bytepp \fP\fIdisplay_row\fP\fB, png_uint_32 \fInum_rows\fP\fB);\fP - -\fBvoid png_read_update_info (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP - -\fB#if !defined(PNG_1_0_X) png_save_int_32 (png_bytep \fP\fIbuf\fP\fB, png_int_32 \fIi\fP\fB);\fP - -\fBvoid png_save_uint_16 (png_bytep \fP\fIbuf\fP\fB, unsigned int \fIi\fP\fB);\fP - -\fBvoid png_save_uint_32 (png_bytep \fP\fIbuf\fP\fB, png_uint_32 \fIi\fP\fB);\fP - -\fBvoid png_set_add_alpha (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIfiller\fP\fB, int flags); \fI#endif - -\fBvoid png_set_background (png_structp \fP\fIpng_ptr\fP\fB, png_color_16p \fP\fIbackground_color\fP\fB, int \fP\fIbackground_gamma_code\fP\fB, int \fP\fIneed_expand\fP\fB, double \fIbackground_gamma\fP\fB);\fP - -\fBvoid png_set_bgr (png_structp \fIpng_ptr\fP\fB);\fP - -\fBvoid png_set_bKGD (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_color_16p \fIbackground\fP\fB);\fP - -\fBvoid png_set_cHRM (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, double \fP\fIwhite_x\fP\fB, double \fP\fIwhite_y\fP\fB, double \fP\fIred_x\fP\fB, double \fP\fIred_y\fP\fB, double \fP\fIgreen_x\fP\fB, double \fP\fIgreen_y\fP\fB, double \fP\fIblue_x\fP\fB, double \fIblue_y\fP\fB);\fP - -\fBvoid png_set_cHRM_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fIwhite_x\fP\fB, png_uint_32 \fP\fIwhite_y\fP\fB, png_uint_32 \fP\fIred_x\fP\fB, png_uint_32 \fP\fIred_y\fP\fB, png_uint_32 \fP\fIgreen_x\fP\fB, png_uint_32 \fP\fIgreen_y\fP\fB, png_uint_32 \fP\fIblue_x\fP\fB, png_uint_32 \fIblue_y\fP\fB);\fP - -\fBvoid png_set_compression_level (png_structp \fP\fIpng_ptr\fP\fB, int \fIlevel\fP\fB);\fP - -\fBvoid png_set_compression_mem_level (png_structp \fP\fIpng_ptr\fP\fB, int \fImem_level\fP\fB);\fP - -\fBvoid png_set_compression_method (png_structp \fP\fIpng_ptr\fP\fB, int \fImethod\fP\fB);\fP - -\fBvoid png_set_compression_strategy (png_structp \fP\fIpng_ptr\fP\fB, int \fIstrategy\fP\fB);\fP - -\fBvoid png_set_compression_window_bits (png_structp \fP\fIpng_ptr\fP\fB, int \fIwindow_bits\fP\fB);\fP - -\fBvoid png_set_crc_action (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIcrit_action\fP\fB, int \fIancil_action\fP\fB);\fP - -\fBvoid png_set_dither (png_structp \fP\fIpng_ptr\fP\fB, png_colorp \fP\fIpalette\fP\fB, int \fP\fInum_palette\fP\fB, int \fP\fImaximum_colors\fP\fB, png_uint_16p \fP\fIhistogram\fP\fB, int \fIfull_dither\fP\fB);\fP - -\fBvoid png_set_error_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fIwarning_fn\fP\fB);\fP - -\fBvoid png_set_expand (png_structp \fIpng_ptr\fP\fB);\fP - -\fBvoid png_set_expand_gray_1_2_4_to_8(png_structp \fIpng_ptr\fP\fB);\fP - -\fBvoid png_set_filler (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIfiller\fP\fB, int \fIflags\fP\fB);\fP - -\fBvoid png_set_filter (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fImethod\fP\fB, int \fIfilters\fP\fB);\fP - -\fBvoid png_set_filter_heuristics (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIheuristic_method\fP\fB, int \fP\fInum_weights\fP\fB, png_doublep \fP\fIfilter_weights\fP\fB, png_doublep \fIfilter_costs\fP\fB);\fP - -\fBvoid png_set_flush (png_structp \fP\fIpng_ptr\fP\fB, int \fInrows\fP\fB);\fP - -\fBvoid png_set_gamma (png_structp \fP\fIpng_ptr\fP\fB, double \fP\fIscreen_gamma\fP\fB, double \fIdefault_file_gamma\fP\fB);\fP - -\fBvoid png_set_gAMA (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, double \fIfile_gamma\fP\fB);\fP - -\fBvoid png_set_gAMA_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIfile_gamma\fP\fB);\fP - -\fBvoid png_set_gray_1_2_4_to_8(png_structp \fIpng_ptr\fP\fB);\fP - -\fBvoid png_set_gray_to_rgb (png_structp \fIpng_ptr\fP\fB);\fP - -\fBvoid png_set_hIST (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_16p \fIhist\fP\fB);\fP - -\fBvoid png_set_iCCP (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_charp \fP\fIname\fP\fB, int \fP\fIcompression_type\fP\fB, png_charp \fP\fIprofile\fP\fB, png_uint_32 \fIproflen\fP\fB);\fP - -\fBint png_set_interlace_handling (png_structp \fIpng_ptr\fP\fB);\fP - -\fBvoid png_set_invalid (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fImask\fP\fB);\fP - -\fBvoid png_set_invert_alpha (png_structp \fIpng_ptr\fP\fB);\fP - -\fBvoid png_set_invert_mono (png_structp \fIpng_ptr\fP\fB);\fP - -\fBvoid png_set_IHDR (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fIwidth\fP\fB, png_uint_32 \fP\fIheight\fP\fB, int \fP\fIbit_depth\fP\fB, int \fP\fIcolor_type\fP\fB, int \fP\fIinterlace_type\fP\fB, int \fP\fIcompression_type\fP\fB, int \fIfilter_type\fP\fB);\fP - -\fBvoid png_set_keep_unknown_chunks (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIkeep\fP\fB, png_bytep \fP\fIchunk_list\fP\fB, int \fInum_chunks\fP\fB);\fP - -\fBvoid png_set_mem_fn(png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fImem_ptr\fP\fB, png_malloc_ptr \fP\fImalloc_fn\fP\fB, png_free_ptr \fIfree_fn\fP\fB);\fP - -\fBvoid png_set_oFFs (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fIoffset_x\fP\fB, png_uint_32 \fP\fIoffset_y\fP\fB, int \fIunit_type\fP\fB);\fP - -\fBvoid png_set_packing (png_structp \fIpng_ptr\fP\fB);\fP - -\fBvoid png_set_packswap (png_structp \fIpng_ptr\fP\fB);\fP - -\fBvoid png_set_palette_to_rgb(png_structp \fIpng_ptr\fP\fB);\fP - -\fBvoid png_set_pCAL (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_charp \fP\fIpurpose\fP\fB, png_int_32 \fP\fIX0\fP\fB, png_int_32 \fP\fIX1\fP\fB, int \fP\fItype\fP\fB, int \fP\fInparams\fP\fB, png_charp \fP\fIunits\fP\fB, png_charpp \fIparams\fP\fB);\fP - -\fBvoid png_set_pHYs (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fIres_x\fP\fB, png_uint_32 \fP\fIres_y\fP\fB, int \fIunit_type\fP\fB);\fP - -\fBvoid png_set_progressive_read_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIprogressive_ptr\fP\fB, png_progressive_info_ptr \fP\fIinfo_fn\fP\fB, png_progressive_row_ptr \fP\fIrow_fn\fP\fB, png_progressive_end_ptr \fIend_fn\fP\fB);\fP - -\fBvoid png_set_PLTE (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_colorp \fP\fIpalette\fP\fB, int \fInum_palette\fP\fB);\fP - -\fBvoid png_set_read_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIio_ptr\fP\fB, png_rw_ptr \fIread_data_fn\fP\fB);\fP - -\fBvoid png_set_read_status_fn (png_structp \fP\fIpng_ptr\fP\fB, png_read_status_ptr \fIread_row_fn\fP\fB);\fP - -\fBvoid png_set_read_user_transform_fn (png_structp \fP\fIpng_ptr\fP\fB, png_user_transform_ptr \fIread_user_transform_fn\fP\fB);\fP - -\fBvoid png_set_rgb_to_gray (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIerror_action\fP\fB, double \fP\fIred\fP\fB, double \fIgreen\fP\fB);\fP - -\fBvoid png_set_rgb_to_gray_fixed (png_structp \fP\fIpng_ptr\fP\fB, int error_action png_fixed_point \fP\fIred\fP\fB, png_fixed_point \fIgreen\fP\fB);\fP - -\fBvoid png_set_rows (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_bytepp \fIrow_pointers\fP\fB);\fP - -\fBvoid png_set_sBIT (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_color_8p \fIsig_bit\fP\fB);\fP - -\fBvoid png_set_sCAL (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_charp \fP\fIunit\fP\fB, double \fP\fIwidth\fP\fB, double \fIheight\fP\fB);\fP - -\fBvoid png_set_shift (png_structp \fP\fIpng_ptr\fP\fB, png_color_8p \fItrue_bits\fP\fB);\fP - -\fBvoid png_set_sig_bytes (png_structp \fP\fIpng_ptr\fP\fB, int \fInum_bytes\fP\fB);\fP - -\fBvoid png_set_sPLT (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_spalette_p \fP\fIsplt_ptr\fP\fB, int \fInum_spalettes\fP\fB);\fP - -\fBvoid png_set_sRGB (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fIintent\fP\fB);\fP - -\fBvoid png_set_sRGB_gAMA_and_cHRM (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fIintent\fP\fB);\fP - -\fBvoid png_set_strip_16 (png_structp \fIpng_ptr\fP\fB);\fP - -\fBvoid png_set_strip_alpha (png_structp \fIpng_ptr\fP\fB);\fP - -\fBvoid png_set_swap (png_structp \fIpng_ptr\fP\fB);\fP - -\fBvoid png_set_swap_alpha (png_structp \fIpng_ptr\fP\fB);\fP - -\fBvoid png_set_text (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_textp \fP\fItext_ptr\fP\fB, int \fInum_text\fP\fB);\fP - -\fBvoid png_set_tIME (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_timep \fImod_time\fP\fB);\fP - -\fBvoid png_set_tRNS (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_bytep \fP\fItrans\fP\fB, int \fP\fInum_trans\fP\fB, png_color_16p \fItrans_values\fP\fB);\fP - -\fBvoid png_set_tRNS_to_alpha(png_structp \fIpng_ptr\fP\fB);\fP - -\fBpng_uint_32 png_set_unknown_chunks (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_unknown_chunkp \fP\fIunknowns\fP\fB, int \fP\fInum\fP\fB, int \fIlocation\fP\fB);\fP - -\fBvoid png_set_unknown_chunk_location(png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fIchunk\fP\fB, int \fIlocation\fP\fB);\fP - -\fBvoid png_set_read_user_chunk_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIuser_chunk_ptr\fP\fB, png_user_chunk_ptr \fIread_user_chunk_fn\fP\fB);\fP - -\fBvoid png_set_user_limits (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIuser_width_max\fP\fB, png_uint_32 \fIuser_height_max\fP\fB);\fP - -\fBvoid png_set_user_transform_info (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIuser_transform_ptr\fP\fB, int \fP\fIuser_transform_depth\fP\fB, int \fIuser_transform_channels\fP\fB);\fP - -\fBvoid png_set_write_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIio_ptr\fP\fB, png_rw_ptr \fP\fIwrite_data_fn\fP\fB, png_flush_ptr \fIoutput_flush_fn\fP\fB);\fP - -\fBvoid png_set_write_status_fn (png_structp \fP\fIpng_ptr\fP\fB, png_write_status_ptr \fIwrite_row_fn\fP\fB);\fP - -\fBvoid png_set_write_user_transform_fn (png_structp \fP\fIpng_ptr\fP\fB, png_user_transform_ptr \fIwrite_user_transform_fn\fP\fB);\fP - -\fBvoid png_set_compression_buffer_size(png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIsize\fP\fB);\fP - -\fBint png_sig_cmp (png_bytep \fP\fIsig\fP\fB, png_size_t \fP\fIstart\fP\fB, png_size_t \fInum_to_check\fP\fB);\fP - -\fBvoid png_start_read_image (png_structp \fIpng_ptr\fP\fB);\fP - -\fBvoid png_warning (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fImessage\fP\fB);\fP - -\fBvoid png_write_chunk (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIchunk_name\fP\fB, png_bytep \fP\fIdata\fP\fB, png_size_t \fIlength\fP\fB);\fP - -\fBvoid png_write_chunk_data (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIdata\fP\fB, png_size_t \fIlength\fP\fB);\fP - -\fBvoid png_write_chunk_end (png_structp \fIpng_ptr\fP\fB);\fP - -\fBvoid png_write_chunk_start (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIchunk_name\fP\fB, png_uint_32 \fIlength\fP\fB);\fP - -\fBvoid png_write_destroy (png_structp \fIpng_ptr\fP\fB);\fP - -\fBvoid png_write_end (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP - -\fBvoid png_write_flush (png_structp \fIpng_ptr\fP\fB);\fP - -\fBvoid png_write_image (png_structp \fP\fIpng_ptr\fP\fB, png_bytepp \fIimage\fP\fB);\fP - -\fBDEPRECATED: void png_write_init (png_structp \fIpng_ptr\fP\fB);\fP - -\fBDEPRECATED: void png_write_init_2 (png_structpp \fP\fIptr_ptr\fP\fB, png_const_charp \fP\fIuser_png_ver\fP\fB, png_size_t \fP\fIpng_struct_size\fP\fB, png_size_t \fIpng_info_size\fP\fB);\fP - -\fBvoid png_write_info (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP - -\fBvoid png_write_info_before_PLTE (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP - -\fBvoid png_write_png (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fItransforms\fP\fB, png_voidp \fIparams\fP\fB);\fP - -\fBvoid png_write_row (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fIrow\fP\fB);\fP - -\fBvoid png_write_rows (png_structp \fP\fIpng_ptr\fP\fB, png_bytepp \fP\fIrow\fP\fB, png_uint_32 \fInum_rows\fP\fB);\fP - -\fBvoidpf png_zalloc (voidpf \fP\fIpng_ptr\fP\fB, uInt \fP\fIitems\fP\fB, uInt \fIsize\fP\fB);\fP - -\fBvoid png_zfree (voidpf \fP\fIpng_ptr\fP\fB, voidpf \fIptr\fP\fB);\fP - -.SH DESCRIPTION -The -.I libpng -library supports encoding, decoding, and various manipulations of -the Portable Network Graphics (PNG) format image files. It uses the -.IR zlib(3) -compression library. -Following is a copy of the libpng.txt file that accompanies libpng. -.SH LIBPNG.TXT -libpng.txt - A description on how to use and modify libpng - - libpng version 1.2.22 - October 13, 2007 - Updated and distributed by Glenn Randers-Pehrson - - Copyright (c) 1998-2007 Glenn Randers-Pehrson - For conditions of distribution and use, see copyright - notice in png.h. - - based on: - - libpng 1.0 beta 6 version 0.96 May 28, 1997 - Updated and distributed by Andreas Dilger - Copyright (c) 1996, 1997 Andreas Dilger - - libpng 1.0 beta 2 - version 0.88 January 26, 1996 - For conditions of distribution and use, see copyright - notice in png.h. Copyright (c) 1995, 1996 Guy Eric - Schalnat, Group 42, Inc. - - Updated/rewritten per request in the libpng FAQ - Copyright (c) 1995, 1996 Frank J. T. Wojcik - December 18, 1995 & January 20, 1996 - -.SH I. Introduction - -This file describes how to use and modify the PNG reference library -(known as libpng) for your own use. There are five sections to this -file: introduction, structures, reading, writing, and modification and -configuration notes for various special platforms. In addition to this -file, example.c is a good starting point for using the library, as -it is heavily commented and should include everything most people -will need. We assume that libpng is already installed; see the -INSTALL file for instructions on how to install libpng. - -For examples of libpng usage, see the files "example.c", "pngtest.c", -and the files in the "contrib" directory, all of which are included in the -libpng distribution. - -Libpng was written as a companion to the PNG specification, as a way -of reducing the amount of time and effort it takes to support the PNG -file format in application programs. - -The PNG specification (second edition), November 2003, is available as -a W3C Recommendation and as an ISO Standard (ISO/IEC 15948:2003 (E)) at - - -The PNG-1.0 specification is available -as RFC 2083 and as a -W3C Recommendation . Some -additional chunks are described in the special-purpose public chunks -documents at . - -Other information -about PNG, and the latest version of libpng, can be found at the PNG home -page, . - -Most users will not have to modify the library significantly; advanced -users may want to modify it more. All attempts were made to make it as -complete as possible, while keeping the code easy to understand. -Currently, this library only supports C. Support for other languages -is being considered. - -Libpng has been designed to handle multiple sessions at one time, -to be easily modifiable, to be portable to the vast majority of -machines (ANSI, K&R, 16-, 32-, and 64-bit) available, and to be easy -to use. The ultimate goal of libpng is to promote the acceptance of -the PNG file format in whatever way possible. While there is still -work to be done (see the TODO file), libpng should cover the -majority of the needs of its users. - -Libpng uses zlib for its compression and decompression of PNG files. -Further information about zlib, and the latest version of zlib, can -be found at the zlib home page, . -The zlib compression utility is a general purpose utility that is -useful for more than PNG files, and can be used without libpng. -See the documentation delivered with zlib for more details. -You can usually find the source files for the zlib utility wherever you -find the libpng source files. - -Libpng is thread safe, provided the threads are using different -instances of the structures. Each thread should have its own -png_struct and png_info instances, and thus its own image. -Libpng does not protect itself against two threads using the -same instance of a structure. - -.SH II. Structures - -There are two main structures that are important to libpng, png_struct -and png_info. The first, png_struct, is an internal structure that -will not, for the most part, be used by a user except as the first -variable passed to every libpng function call. - -The png_info structure is designed to provide information about the -PNG file. At one time, the fields of png_info were intended to be -directly accessible to the user. However, this tended to cause problems -with applications using dynamically loaded libraries, and as a result -a set of interface functions for png_info (the png_get_*() and png_set_*() -functions) was developed. The fields of png_info are still available for -older applications, but it is suggested that applications use the new -interfaces if at all possible. - -Applications that do make direct access to the members of png_struct (except -for png_ptr->jmpbuf) must be recompiled whenever the library is updated, -and applications that make direct access to the members of png_info must -be recompiled if they were compiled or loaded with libpng version 1.0.6, -in which the members were in a different order. In version 1.0.7, the -members of the png_info structure reverted to the old order, as they were -in versions 0.97c through 1.0.5. Starting with version 2.0.0, both -structures are going to be hidden, and the contents of the structures will -only be accessible through the png_get/png_set functions. - -The png.h header file is an invaluable reference for programming with libpng. -And while I'm on the topic, make sure you include the libpng header file: - -#include - -.SH III. Reading - -We'll now walk you through the possible functions to call when reading -in a PNG file sequentially, briefly explaining the syntax and purpose -of each one. See example.c and png.h for more detail. While -progressive reading is covered in the next section, you will still -need some of the functions discussed in this section to read a PNG -file. - -.SS Setup - -You will want to do the I/O initialization(*) before you get into libpng, -so if it doesn't work, you don't have much to undo. Of course, you -will also want to insure that you are, in fact, dealing with a PNG -file. Libpng provides a simple check to see if a file is a PNG file. -To use it, pass in the first 1 to 8 bytes of the file to the function -png_sig_cmp(), and it will return 0 if the bytes match the corresponding -bytes of the PNG signature, or nonzero otherwise. Of course, the more bytes -you pass in, the greater the accuracy of the prediction. - -If you are intending to keep the file pointer open for use in libpng, -you must ensure you don't read more than 8 bytes from the beginning -of the file, and you also have to make a call to png_set_sig_bytes_read() -with the number of bytes you read from the beginning. Libpng will -then only check the bytes (if any) that your program didn't read. - -(*): If you are not using the standard I/O functions, you will need -to replace them with custom functions. See the discussion under -Customizing libpng. - - - FILE *fp = fopen(file_name, "rb"); - if (!fp) - { - return (ERROR); - } - fread(header, 1, number, fp); - is_png = !png_sig_cmp(header, 0, number); - if (!is_png) - { - return (NOT_PNG); - } - - -Next, png_struct and png_info need to be allocated and initialized. In -order to ensure that the size of these structures is correct even with a -dynamically linked libpng, there are functions to initialize and -allocate the structures. We also pass the library version, optional -pointers to error handling functions, and a pointer to a data struct for -use by the error functions, if necessary (the pointer and functions can -be NULL if the default error handlers are to be used). See the section -on Changes to Libpng below regarding the old initialization functions. -The structure allocation functions quietly return NULL if they fail to -create the structure, so your application should check for that. - - png_structp png_ptr = png_create_read_struct - (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, - user_error_fn, user_warning_fn); - if (!png_ptr) - return (ERROR); - - png_infop info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) - { - png_destroy_read_struct(&png_ptr, - (png_infopp)NULL, (png_infopp)NULL); - return (ERROR); - } - - png_infop end_info = png_create_info_struct(png_ptr); - if (!end_info) - { - png_destroy_read_struct(&png_ptr, &info_ptr, - (png_infopp)NULL); - return (ERROR); - } - -If you want to use your own memory allocation routines, -define PNG_USER_MEM_SUPPORTED and use -png_create_read_struct_2() instead of png_create_read_struct(): - - png_structp png_ptr = png_create_read_struct_2 - (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, - user_error_fn, user_warning_fn, (png_voidp) - user_mem_ptr, user_malloc_fn, user_free_fn); - -The error handling routines passed to png_create_read_struct() -and the memory alloc/free routines passed to png_create_struct_2() -are only necessary if you are not using the libpng supplied error -handling and memory alloc/free functions. - -When libpng encounters an error, it expects to longjmp back -to your routine. Therefore, you will need to call setjmp and pass -your png_jmpbuf(png_ptr). If you read the file from different -routines, you will need to update the jmpbuf field every time you enter -a new routine that will call a png_*() function. - -See your documentation of setjmp/longjmp for your compiler for more -information on setjmp/longjmp. See the discussion on libpng error -handling in the Customizing Libpng section below for more information -on the libpng error handling. If an error occurs, and libpng longjmp's -back to your setjmp, you will want to call png_destroy_read_struct() to -free any memory. - - if (setjmp(png_jmpbuf(png_ptr))) - { - png_destroy_read_struct(&png_ptr, &info_ptr, - &end_info); - fclose(fp); - return (ERROR); - } - -If you would rather avoid the complexity of setjmp/longjmp issues, -you can compile libpng with PNG_SETJMP_NOT_SUPPORTED, in which case -errors will result in a call to PNG_ABORT() which defaults to abort(). - -Now you need to set up the input code. The default for libpng is to -use the C function fread(). If you use this, you will need to pass a -valid FILE * in the function png_init_io(). Be sure that the file is -opened in binary mode. If you wish to handle reading data in another -way, you need not call the png_init_io() function, but you must then -implement the libpng I/O methods discussed in the Customizing Libpng -section below. - - png_init_io(png_ptr, fp); - -If you had previously opened the file and read any of the signature from -the beginning in order to see if this was a PNG file, you need to let -libpng know that there are some bytes missing from the start of the file. - - png_set_sig_bytes(png_ptr, number); - -.SS Setting up callback code - -You can set up a callback function to handle any unknown chunks in the -input stream. You must supply the function - - read_chunk_callback(png_ptr ptr, - png_unknown_chunkp chunk); - { - /* The unknown chunk structure contains your - chunk data: */ - png_byte name[5]; - png_byte *data; - png_size_t size; - /* Note that libpng has already taken care of - the CRC handling */ - - /* put your code here. Return one of the - following: */ - - return (-n); /* chunk had an error */ - return (0); /* did not recognize */ - return (n); /* success */ - } - -(You can give your function another name that you like instead of -"read_chunk_callback") - -To inform libpng about your function, use - - png_set_read_user_chunk_fn(png_ptr, user_chunk_ptr, - read_chunk_callback); - -This names not only the callback function, but also a user pointer that -you can retrieve with - - png_get_user_chunk_ptr(png_ptr); - -At this point, you can set up a callback function that will be -called after each row has been read, which you can use to control -a progress meter or the like. It's demonstrated in pngtest.c. -You must supply a function - - void read_row_callback(png_ptr ptr, png_uint_32 row, - int pass); - { - /* put your code here */ - } - -(You can give it another name that you like instead of "read_row_callback") - -To inform libpng about your function, use - - png_set_read_status_fn(png_ptr, read_row_callback); - -.SS Width and height limits - -The PNG specification allows the width and height of an image to be as -large as 2^31-1 (0x7fffffff), or about 2.147 billion rows and columns. -Since very few applications really need to process such large images, -we have imposed an arbitrary 1-million limit on rows and columns. -Larger images will be rejected immediately with a png_error() call. If -you wish to override this limit, you can use - - png_set_user_limits(png_ptr, width_max, height_max); - -to set your own limits, or use width_max = height_max = 0x7fffffffL -to allow all valid dimensions (libpng may reject some very large images -anyway because of potential buffer overflow conditions). - -You should put this statement after you create the PNG structure and -before calling png_read_info(), png_read_png(), or png_process_data(). -If you need to retrieve the limits that are being applied, use - - width_max = png_get_user_width_max(png_ptr); - height_max = png_get_user_height_max(png_ptr); - -.SS Unknown-chunk handling - -Now you get to set the way the library processes unknown chunks in the -input PNG stream. Both known and unknown chunks will be read. Normal -behavior is that known chunks will be parsed into information in -various info_ptr members; unknown chunks will be discarded. To change -this, you can call: - - png_set_keep_unknown_chunks(png_ptr, keep, - chunk_list, num_chunks); - keep - 0: do not handle as unknown - 1: do not keep - 2: keep only if safe-to-copy - 3: keep even if unsafe-to-copy - You can use these definitions: - PNG_HANDLE_CHUNK_AS_DEFAULT 0 - PNG_HANDLE_CHUNK_NEVER 1 - PNG_HANDLE_CHUNK_IF_SAFE 2 - PNG_HANDLE_CHUNK_ALWAYS 3 - chunk_list - list of chunks affected (a byte string, - five bytes per chunk, NULL or '\0' if - num_chunks is 0) - num_chunks - number of chunks affected; if 0, all - unknown chunks are affected. If nonzero, - only the chunks in the list are affected - -Unknown chunks declared in this way will be saved as raw data onto a -list of png_unknown_chunk structures. If a chunk that is normally -known to libpng is named in the list, it will be handled as unknown, -according to the "keep" directive. If a chunk is named in successive -instances of png_set_keep_unknown_chunks(), the final instance will -take precedence. The IHDR and IEND chunks should not be named in -chunk_list; if they are, libpng will process them normally anyway. - -.SS The high-level read interface - -At this point there are two ways to proceed; through the high-level -read interface, or through a sequence of low-level read operations. -You can use the high-level interface if (a) you are willing to read -the entire image into memory, and (b) the input transformations -you want to do are limited to the following set: - - PNG_TRANSFORM_IDENTITY No transformation - PNG_TRANSFORM_STRIP_16 Strip 16-bit samples to - 8 bits - PNG_TRANSFORM_STRIP_ALPHA Discard the alpha channel - PNG_TRANSFORM_PACKING Expand 1, 2 and 4-bit - samples to bytes - PNG_TRANSFORM_PACKSWAP Change order of packed - pixels to LSB first - PNG_TRANSFORM_EXPAND Perform set_expand() - PNG_TRANSFORM_INVERT_MONO Invert monochrome images - PNG_TRANSFORM_SHIFT Normalize pixels to the - sBIT depth - PNG_TRANSFORM_BGR Flip RGB to BGR, RGBA - to BGRA - PNG_TRANSFORM_SWAP_ALPHA Flip RGBA to ARGB or GA - to AG - PNG_TRANSFORM_INVERT_ALPHA Change alpha from opacity - to transparency - PNG_TRANSFORM_SWAP_ENDIAN Byte-swap 16-bit samples - -(This excludes setting a background color, doing gamma transformation, -dithering, and setting filler.) If this is the case, simply do this: - - png_read_png(png_ptr, info_ptr, png_transforms, NULL) - -where png_transforms is an integer containing the bitwise OR of -some set of transformation flags. This call is equivalent to png_read_info(), -followed the set of transformations indicated by the transform mask, -then png_read_image(), and finally png_read_end(). - -(The final parameter of this call is not yet used. Someday it might point -to transformation parameters required by some future input transform.) - -You must use png_transforms and not call any png_set_transform() functions -when you use png_read_png(). - -After you have called png_read_png(), you can retrieve the image data -with - - row_pointers = png_get_rows(png_ptr, info_ptr); - -where row_pointers is an array of pointers to the pixel data for each row: - - png_bytep row_pointers[height]; - -If you know your image size and pixel size ahead of time, you can allocate -row_pointers prior to calling png_read_png() with - - if (height > PNG_UINT_32_MAX/png_sizeof(png_byte)) - png_error (png_ptr, - "Image is too tall to process in memory"); - if (width > PNG_UINT_32_MAX/pixel_size) - png_error (png_ptr, - "Image is too wide to process in memory"); - row_pointers = png_malloc(png_ptr, - height*png_sizeof(png_bytep)); - for (int i=0; i) and -png_get_(png_ptr, info_ptr, ...) functions return non-zero if the -data has been read, or zero if it is missing. The parameters to the -png_get_ are set directly if they are simple data types, or a pointer -into the info_ptr is returned for any complex types. - - png_get_PLTE(png_ptr, info_ptr, &palette, - &num_palette); - palette - the palette for the file - (array of png_color) - num_palette - number of entries in the palette - - png_get_gAMA(png_ptr, info_ptr, &gamma); - gamma - the gamma the file is written - at (PNG_INFO_gAMA) - - png_get_sRGB(png_ptr, info_ptr, &srgb_intent); - srgb_intent - the rendering intent (PNG_INFO_sRGB) - The presence of the sRGB chunk - means that the pixel data is in the - sRGB color space. This chunk also - implies specific values of gAMA and - cHRM. - - png_get_iCCP(png_ptr, info_ptr, &name, - &compression_type, &profile, &proflen); - name - The profile name. - compression - The compression type; always - PNG_COMPRESSION_TYPE_BASE for PNG 1.0. - You may give NULL to this argument to - ignore it. - profile - International Color Consortium color - profile data. May contain NULs. - proflen - length of profile data in bytes. - - png_get_sBIT(png_ptr, info_ptr, &sig_bit); - sig_bit - the number of significant bits for - (PNG_INFO_sBIT) each of the gray, - red, green, and blue channels, - whichever are appropriate for the - given color type (png_color_16) - - png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, - &trans_values); - trans - array of transparent entries for - palette (PNG_INFO_tRNS) - trans_values - graylevel or color sample values of - the single transparent color for - non-paletted images (PNG_INFO_tRNS) - num_trans - number of transparent entries - (PNG_INFO_tRNS) - - png_get_hIST(png_ptr, info_ptr, &hist); - (PNG_INFO_hIST) - hist - histogram of palette (array of - png_uint_16) - - png_get_tIME(png_ptr, info_ptr, &mod_time); - mod_time - time image was last modified - (PNG_VALID_tIME) - - png_get_bKGD(png_ptr, info_ptr, &background); - background - background color (PNG_VALID_bKGD) - valid 16-bit red, green and blue - values, regardless of color_type - - num_comments = png_get_text(png_ptr, info_ptr, - &text_ptr, &num_text); - num_comments - number of comments - text_ptr - array of png_text holding image - comments - text_ptr[i].compression - type of compression used - on "text" PNG_TEXT_COMPRESSION_NONE - PNG_TEXT_COMPRESSION_zTXt - PNG_ITXT_COMPRESSION_NONE - PNG_ITXT_COMPRESSION_zTXt - text_ptr[i].key - keyword for comment. Must contain - 1-79 characters. - text_ptr[i].text - text comments for current - keyword. Can be empty. - text_ptr[i].text_length - length of text string, - after decompression, 0 for iTXt - text_ptr[i].itxt_length - length of itxt string, - after decompression, 0 for tEXt/zTXt - text_ptr[i].lang - language of comment (empty - string for unknown). - text_ptr[i].lang_key - keyword in UTF-8 - (empty string for unknown). - num_text - number of comments (same as - num_comments; you can put NULL here - to avoid the duplication) - Note while png_set_text() will accept text, language, - and translated keywords that can be NULL pointers, the - structure returned by png_get_text will always contain - regular zero-terminated C strings. They might be - empty strings but they will never be NULL pointers. - - num_spalettes = png_get_sPLT(png_ptr, info_ptr, - &palette_ptr); - palette_ptr - array of palette structures holding - contents of one or more sPLT chunks - read. - num_spalettes - number of sPLT chunks read. - - png_get_oFFs(png_ptr, info_ptr, &offset_x, &offset_y, - &unit_type); - offset_x - positive offset from the left edge - of the screen - offset_y - positive offset from the top edge - of the screen - unit_type - PNG_OFFSET_PIXEL, PNG_OFFSET_MICROMETER - - png_get_pHYs(png_ptr, info_ptr, &res_x, &res_y, - &unit_type); - res_x - pixels/unit physical resolution in - x direction - res_y - pixels/unit physical resolution in - x direction - unit_type - PNG_RESOLUTION_UNKNOWN, - PNG_RESOLUTION_METER - - png_get_sCAL(png_ptr, info_ptr, &unit, &width, - &height) - unit - physical scale units (an integer) - width - width of a pixel in physical scale units - height - height of a pixel in physical scale units - (width and height are doubles) - - png_get_sCAL_s(png_ptr, info_ptr, &unit, &width, - &height) - unit - physical scale units (an integer) - width - width of a pixel in physical scale units - height - height of a pixel in physical scale units - (width and height are strings like "2.54") - - num_unknown_chunks = png_get_unknown_chunks(png_ptr, - info_ptr, &unknowns) - unknowns - array of png_unknown_chunk - structures holding unknown chunks - unknowns[i].name - name of unknown chunk - unknowns[i].data - data of unknown chunk - unknowns[i].size - size of unknown chunk's data - unknowns[i].location - position of chunk in file - - The value of "i" corresponds to the order in which the - chunks were read from the PNG file or inserted with the - png_set_unknown_chunks() function. - -The data from the pHYs chunk can be retrieved in several convenient -forms: - - res_x = png_get_x_pixels_per_meter(png_ptr, - info_ptr) - res_y = png_get_y_pixels_per_meter(png_ptr, - info_ptr) - res_x_and_y = png_get_pixels_per_meter(png_ptr, - info_ptr) - res_x = png_get_x_pixels_per_inch(png_ptr, - info_ptr) - res_y = png_get_y_pixels_per_inch(png_ptr, - info_ptr) - res_x_and_y = png_get_pixels_per_inch(png_ptr, - info_ptr) - aspect_ratio = png_get_pixel_aspect_ratio(png_ptr, - info_ptr) - - (Each of these returns 0 [signifying "unknown"] if - the data is not present or if res_x is 0; - res_x_and_y is 0 if res_x != res_y) - -The data from the oFFs chunk can be retrieved in several convenient -forms: - - x_offset = png_get_x_offset_microns(png_ptr, info_ptr); - y_offset = png_get_y_offset_microns(png_ptr, info_ptr); - x_offset = png_get_x_offset_inches(png_ptr, info_ptr); - y_offset = png_get_y_offset_inches(png_ptr, info_ptr); - - (Each of these returns 0 [signifying "unknown" if both - x and y are 0] if the data is not present or if the - chunk is present but the unit is the pixel) - -For more information, see the png_info definition in png.h and the -PNG specification for chunk contents. Be careful with trusting -rowbytes, as some of the transformations could increase the space -needed to hold a row (expand, filler, gray_to_rgb, etc.). -See png_read_update_info(), below. - -A quick word about text_ptr and num_text. PNG stores comments in -keyword/text pairs, one pair per chunk, with no limit on the number -of text chunks, and a 2^31 byte limit on their size. While there are -suggested keywords, there is no requirement to restrict the use to these -strings. It is strongly suggested that keywords and text be sensible -to humans (that's the point), so don't use abbreviations. Non-printing -symbols are not allowed. See the PNG specification for more details. -There is also no requirement to have text after the keyword. - -Keywords should be limited to 79 Latin-1 characters without leading or -trailing spaces, but non-consecutive spaces are allowed within the -keyword. It is possible to have the same keyword any number of times. -The text_ptr is an array of png_text structures, each holding a -pointer to a language string, a pointer to a keyword and a pointer to -a text string. The text string, language code, and translated -keyword may be empty or NULL pointers. The keyword/text -pairs are put into the array in the order that they are received. -However, some or all of the text chunks may be after the image, so, to -make sure you have read all the text chunks, don't mess with these -until after you read the stuff after the image. This will be -mentioned again below in the discussion that goes with png_read_end(). - -.SS Input transformations - -After you've read the header information, you can set up the library -to handle any special transformations of the image data. The various -ways to transform the data will be described in the order that they -should occur. This is important, as some of these change the color -type and/or bit depth of the data, and some others only work on -certain color types and bit depths. Even though each transformation -checks to see if it has data that it can do something with, you should -make sure to only enable a transformation if it will be valid for the -data. For example, don't swap red and blue on grayscale data. - -The colors used for the background and transparency values should be -supplied in the same format/depth as the current image data. They -are stored in the same format/depth as the image data in a bKGD or tRNS -chunk, so this is what libpng expects for this data. The colors are -transformed to keep in sync with the image data when an application -calls the png_read_update_info() routine (see below). - -Data will be decoded into the supplied row buffers packed into bytes -unless the library has been told to transform it into another format. -For example, 4 bit/pixel paletted or grayscale data will be returned -2 pixels/byte with the leftmost pixel in the high-order bits of the -byte, unless png_set_packing() is called. 8-bit RGB data will be stored -in RGB RGB RGB format unless png_set_filler() or png_set_add_alpha() -is called to insert filler bytes, either before or after each RGB triplet. -16-bit RGB data will be returned RRGGBB RRGGBB, with the most significant -byte of the color value first, unless png_set_strip_16() is called to -transform it to regular RGB RGB triplets, or png_set_filler() or -png_set_add alpha() is called to insert filler bytes, either before or -after each RRGGBB triplet. Similarly, 8-bit or 16-bit grayscale data can -be modified with -png_set_filler(), png_set_add_alpha(), or png_set_strip_16(). - -The following code transforms grayscale images of less than 8 to 8 bits, -changes paletted images to RGB, and adds a full alpha channel if there is -transparency information in a tRNS chunk. This is most useful on -grayscale images with bit depths of 2 or 4 or if there is a multiple-image -viewing application that wishes to treat all images in the same way. - - if (color_type == PNG_COLOR_TYPE_PALETTE) - png_set_palette_to_rgb(png_ptr); - - if (color_type == PNG_COLOR_TYPE_GRAY && - bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr); - - if (png_get_valid(png_ptr, info_ptr, - PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); - -These three functions are actually aliases for png_set_expand(), added -in libpng version 1.0.4, with the function names expanded to improve code -readability. In some future version they may actually do different -things. - -As of libpng version 1.2.9, png_set_expand_gray_1_2_4_to_8() was -added. It expands the sample depth without changing tRNS to alpha. -At the same time, png_set_gray_1_2_4_to_8() was deprecated, and it -will be removed from a future version. - -PNG can have files with 16 bits per channel. If you only can handle -8 bits per channel, this will strip the pixels down to 8 bit. - - if (bit_depth == 16) - png_set_strip_16(png_ptr); - -If, for some reason, you don't need the alpha channel on an image, -and you want to remove it rather than combining it with the background -(but the image author certainly had in mind that you *would* combine -it with the background, so that's what you should probably do): - - if (color_type & PNG_COLOR_MASK_ALPHA) - png_set_strip_alpha(png_ptr); - -In PNG files, the alpha channel in an image -is the level of opacity. If you need the alpha channel in an image to -be the level of transparency instead of opacity, you can invert the -alpha channel (or the tRNS chunk data) after it's read, so that 0 is -fully opaque and 255 (in 8-bit or paletted images) or 65535 (in 16-bit -images) is fully transparent, with - - png_set_invert_alpha(png_ptr); - -PNG files pack pixels of bit depths 1, 2, and 4 into bytes as small as -they can, resulting in, for example, 8 pixels per byte for 1 bit -files. This code expands to 1 pixel per byte without changing the -values of the pixels: - - if (bit_depth < 8) - png_set_packing(png_ptr); - -PNG files have possible bit depths of 1, 2, 4, 8, and 16. All pixels -stored in a PNG image have been "scaled" or "shifted" up to the next -higher possible bit depth (e.g. from 5 bits/sample in the range [0,31] to -8 bits/sample in the range [0, 255]). However, it is also possible to -convert the PNG pixel data back to the original bit depth of the image. -This call reduces the pixels back down to the original bit depth: - - png_color_8p sig_bit; - - if (png_get_sBIT(png_ptr, info_ptr, &sig_bit)) - png_set_shift(png_ptr, sig_bit); - -PNG files store 3-color pixels in red, green, blue order. This code -changes the storage of the pixels to blue, green, red: - - if (color_type == PNG_COLOR_TYPE_RGB || - color_type == PNG_COLOR_TYPE_RGB_ALPHA) - png_set_bgr(png_ptr); - -PNG files store RGB pixels packed into 3 or 6 bytes. This code expands them -into 4 or 8 bytes for windowing systems that need them in this format: - - if (color_type == PNG_COLOR_TYPE_RGB) - png_set_filler(png_ptr, filler, PNG_FILLER_BEFORE); - -where "filler" is the 8 or 16-bit number to fill with, and the location is -either PNG_FILLER_BEFORE or PNG_FILLER_AFTER, depending upon whether -you want the filler before the RGB or after. This transformation -does not affect images that already have full alpha channels. To add an -opaque alpha channel, use filler=0xff or 0xffff and PNG_FILLER_AFTER which -will generate RGBA pixels. - -Note that png_set_filler() does not change the color type. If you want -to do that, you can add a true alpha channel with - - if (color_type == PNG_COLOR_TYPE_RGB || - color_type == PNG_COLOR_TYPE_GRAY) - png_set_add_alpha(png_ptr, filler, PNG_FILLER_AFTER); - -where "filler" contains the alpha value to assign to each pixel. -This function was added in libpng-1.2.7. - -If you are reading an image with an alpha channel, and you need the -data as ARGB instead of the normal PNG format RGBA: - - if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) - png_set_swap_alpha(png_ptr); - -For some uses, you may want a grayscale image to be represented as -RGB. This code will do that conversion: - - if (color_type == PNG_COLOR_TYPE_GRAY || - color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - png_set_gray_to_rgb(png_ptr); - -Conversely, you can convert an RGB or RGBA image to grayscale or grayscale -with alpha. - - if (color_type == PNG_COLOR_TYPE_RGB || - color_type == PNG_COLOR_TYPE_RGB_ALPHA) - png_set_rgb_to_gray_fixed(png_ptr, error_action, - int red_weight, int green_weight); - - error_action = 1: silently do the conversion - error_action = 2: issue a warning if the original - image has any pixel where - red != green or red != blue - error_action = 3: issue an error and abort the - conversion if the original - image has any pixel where - red != green or red != blue - - red_weight: weight of red component times 100000 - green_weight: weight of green component times 100000 - If either weight is negative, default - weights (21268, 71514) are used. - -If you have set error_action = 1 or 2, you can -later check whether the image really was gray, after processing -the image rows, with the png_get_rgb_to_gray_status(png_ptr) function. -It will return a png_byte that is zero if the image was gray or -1 if there were any non-gray pixels. bKGD and sBIT data -will be silently converted to grayscale, using the green channel -data, regardless of the error_action setting. - -With red_weight+green_weight<=100000, -the normalized graylevel is computed: - - int rw = red_weight * 65536; - int gw = green_weight * 65536; - int bw = 65536 - (rw + gw); - gray = (rw*red + gw*green + bw*blue)/65536; - -The default values approximate those recommended in the Charles -Poynton's Color FAQ, -Copyright (c) 1998-01-04 Charles Poynton - - Y = 0.212671 * R + 0.715160 * G + 0.072169 * B - -Libpng approximates this with - - Y = 0.21268 * R + 0.7151 * G + 0.07217 * B - -which can be expressed with integers as - - Y = (6969 * R + 23434 * G + 2365 * B)/32768 - -The calculation is done in a linear colorspace, if the image gamma -is known. - -If you have a grayscale and you are using png_set_expand_depth(), -png_set_expand(), or png_set_gray_to_rgb to change to truecolor or to -a higher bit-depth, you must either supply the background color as a gray -value at the original file bit-depth (need_expand = 1) or else supply the -background color as an RGB triplet at the final, expanded bit depth -(need_expand = 0). Similarly, if you are reading a paletted image, you -must either supply the background color as a palette index (need_expand = 1) -or as an RGB triplet that may or may not be in the palette (need_expand = 0). - - png_color_16 my_background; - png_color_16p image_background; - - if (png_get_bKGD(png_ptr, info_ptr, &image_background)) - png_set_background(png_ptr, image_background, - PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); - else - png_set_background(png_ptr, &my_background, - PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); - -The png_set_background() function tells libpng to composite images -with alpha or simple transparency against the supplied background -color. If the PNG file contains a bKGD chunk (PNG_INFO_bKGD valid), -you may use this color, or supply another color more suitable for -the current display (e.g., the background color from a web page). You -need to tell libpng whether the color is in the gamma space of the -display (PNG_BACKGROUND_GAMMA_SCREEN for colors you supply), the file -(PNG_BACKGROUND_GAMMA_FILE for colors from the bKGD chunk), or one -that is neither of these gammas (PNG_BACKGROUND_GAMMA_UNIQUE - I don't -know why anyone would use this, but it's here). - -To properly display PNG images on any kind of system, the application needs -to know what the display gamma is. Ideally, the user will know this, and -the application will allow them to set it. One method of allowing the user -to set the display gamma separately for each system is to check for a -SCREEN_GAMMA or DISPLAY_GAMMA environment variable, which will hopefully be -correctly set. - -Note that display_gamma is the overall gamma correction required to produce -pleasing results, which depends on the lighting conditions in the surrounding -environment. In a dim or brightly lit room, no compensation other than -the physical gamma exponent of the monitor is needed, while in a dark room -a slightly smaller exponent is better. - - double gamma, screen_gamma; - - if (/* We have a user-defined screen - gamma value */) - { - screen_gamma = user_defined_screen_gamma; - } - /* One way that applications can share the same - screen gamma value */ - else if ((gamma_str = getenv("SCREEN_GAMMA")) - != NULL) - { - screen_gamma = (double)atof(gamma_str); - } - /* If we don't have another value */ - else - { - screen_gamma = 2.2; /* A good guess for a - PC monitor in a bright office or a dim room */ - screen_gamma = 2.0; /* A good guess for a - PC monitor in a dark room */ - screen_gamma = 1.7 or 1.0; /* A good - guess for Mac systems */ - } - -The png_set_gamma() function handles gamma transformations of the data. -Pass both the file gamma and the current screen_gamma. If the file does -not have a gamma value, you can pass one anyway if you have an idea what -it is (usually 0.45455 is a good guess for GIF images on PCs). Note -that file gammas are inverted from screen gammas. See the discussions -on gamma in the PNG specification for an excellent description of what -gamma is, and why all applications should support it. It is strongly -recommended that PNG viewers support gamma correction. - - if (png_get_gAMA(png_ptr, info_ptr, &gamma)) - png_set_gamma(png_ptr, screen_gamma, gamma); - else - png_set_gamma(png_ptr, screen_gamma, 0.45455); - -If you need to reduce an RGB file to a paletted file, or if a paletted -file has more entries then will fit on your screen, png_set_dither() -will do that. Note that this is a simple match dither that merely -finds the closest color available. This should work fairly well with -optimized palettes, and fairly badly with linear color cubes. If you -pass a palette that is larger then maximum_colors, the file will -reduce the number of colors in the palette so it will fit into -maximum_colors. If there is a histogram, it will use it to make -more intelligent choices when reducing the palette. If there is no -histogram, it may not do as good a job. - - if (color_type & PNG_COLOR_MASK_COLOR) - { - if (png_get_valid(png_ptr, info_ptr, - PNG_INFO_PLTE)) - { - png_uint_16p histogram = NULL; - - png_get_hIST(png_ptr, info_ptr, - &histogram); - png_set_dither(png_ptr, palette, num_palette, - max_screen_colors, histogram, 1); - } - else - { - png_color std_color_cube[MAX_SCREEN_COLORS] = - { ... colors ... }; - - png_set_dither(png_ptr, std_color_cube, - MAX_SCREEN_COLORS, MAX_SCREEN_COLORS, - NULL,0); - } - } - -PNG files describe monochrome as black being zero and white being one. -The following code will reverse this (make black be one and white be -zero): - - if (bit_depth == 1 && color_type == PNG_COLOR_TYPE_GRAY) - png_set_invert_mono(png_ptr); - -This function can also be used to invert grayscale and gray-alpha images: - - if (color_type == PNG_COLOR_TYPE_GRAY || - color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - png_set_invert_mono(png_ptr); - -PNG files store 16 bit pixels in network byte order (big-endian, -ie. most significant bits first). This code changes the storage to the -other way (little-endian, i.e. least significant bits first, the -way PCs store them): - - if (bit_depth == 16) - png_set_swap(png_ptr); - -If you are using packed-pixel images (1, 2, or 4 bits/pixel), and you -need to change the order the pixels are packed into bytes, you can use: - - if (bit_depth < 8) - png_set_packswap(png_ptr); - -Finally, you can write your own transformation function if none of -the existing ones meets your needs. This is done by setting a callback -with - - png_set_read_user_transform_fn(png_ptr, - read_transform_fn); - -You must supply the function - - void read_transform_fn(png_ptr ptr, row_info_ptr - row_info, png_bytep data) - -See pngtest.c for a working example. Your function will be called -after all of the other transformations have been processed. - -You can also set up a pointer to a user structure for use by your -callback function, and you can inform libpng that your transform -function will change the number of channels or bit depth with the -function - - png_set_user_transform_info(png_ptr, user_ptr, - user_depth, user_channels); - -The user's application, not libpng, is responsible for allocating and -freeing any memory required for the user structure. - -You can retrieve the pointer via the function -png_get_user_transform_ptr(). For example: - - voidp read_user_transform_ptr = - png_get_user_transform_ptr(png_ptr); - -The last thing to handle is interlacing; this is covered in detail below, -but you must call the function here if you want libpng to handle expansion -of the interlaced image. - - number_of_passes = png_set_interlace_handling(png_ptr); - -After setting the transformations, libpng can update your png_info -structure to reflect any transformations you've requested with this -call. This is most useful to update the info structure's rowbytes -field so you can use it to allocate your image memory. This function -will also update your palette with the correct screen_gamma and -background if these have been given with the calls above. - - png_read_update_info(png_ptr, info_ptr); - -After you call png_read_update_info(), you can allocate any -memory you need to hold the image. The row data is simply -raw byte data for all forms of images. As the actual allocation -varies among applications, no example will be given. If you -are allocating one large chunk, you will need to build an -array of pointers to each row, as it will be needed for some -of the functions below. - -.SS Reading image data - -After you've allocated memory, you can read the image data. -The simplest way to do this is in one function call. If you are -allocating enough memory to hold the whole image, you can just -call png_read_image() and libpng will read in all the image data -and put it in the memory area supplied. You will need to pass in -an array of pointers to each row. - -This function automatically handles interlacing, so you don't need -to call png_set_interlace_handling() or call this function multiple -times, or any of that other stuff necessary with png_read_rows(). - - png_read_image(png_ptr, row_pointers); - -where row_pointers is: - - png_bytep row_pointers[height]; - -You can point to void or char or whatever you use for pixels. - -If you don't want to read in the whole image at once, you can -use png_read_rows() instead. If there is no interlacing (check -interlace_type == PNG_INTERLACE_NONE), this is simple: - - png_read_rows(png_ptr, row_pointers, NULL, - number_of_rows); - -where row_pointers is the same as in the png_read_image() call. - -If you are doing this just one row at a time, you can do this with -a single row_pointer instead of an array of row_pointers: - - png_bytep row_pointer = row; - png_read_row(png_ptr, row_pointer, NULL); - -If the file is interlaced (interlace_type != 0 in the IHDR chunk), things -get somewhat harder. The only current (PNG Specification version 1.2) -interlacing type for PNG is (interlace_type == PNG_INTERLACE_ADAM7) -is a somewhat complicated 2D interlace scheme, known as Adam7, that -breaks down an image into seven smaller images of varying size, based -on an 8x8 grid. - -libpng can fill out those images or it can give them to you "as is". -If you want them filled out, there are two ways to do that. The one -mentioned in the PNG specification is to expand each pixel to cover -those pixels that have not been read yet (the "rectangle" method). -This results in a blocky image for the first pass, which gradually -smooths out as more pixels are read. The other method is the "sparkle" -method, where pixels are drawn only in their final locations, with the -rest of the image remaining whatever colors they were initialized to -before the start of the read. The first method usually looks better, -but tends to be slower, as there are more pixels to put in the rows. - -If you don't want libpng to handle the interlacing details, just call -png_read_rows() seven times to read in all seven images. Each of the -images is a valid image by itself, or they can all be combined on an -8x8 grid to form a single image (although if you intend to combine them -you would be far better off using the libpng interlace handling). - -The first pass will return an image 1/8 as wide as the entire image -(every 8th column starting in column 0) and 1/8 as high as the original -(every 8th row starting in row 0), the second will be 1/8 as wide -(starting in column 4) and 1/8 as high (also starting in row 0). The -third pass will be 1/4 as wide (every 4th pixel starting in column 0) and -1/8 as high (every 8th row starting in row 4), and the fourth pass will -be 1/4 as wide and 1/4 as high (every 4th column starting in column 2, -and every 4th row starting in row 0). The fifth pass will return an -image 1/2 as wide, and 1/4 as high (starting at column 0 and row 2), -while the sixth pass will be 1/2 as wide and 1/2 as high as the original -(starting in column 1 and row 0). The seventh and final pass will be as -wide as the original, and 1/2 as high, containing all of the odd -numbered scanlines. Phew! - -If you want libpng to expand the images, call this before calling -png_start_read_image() or png_read_update_info(): - - if (interlace_type == PNG_INTERLACE_ADAM7) - number_of_passes - = png_set_interlace_handling(png_ptr); - -This will return the number of passes needed. Currently, this -is seven, but may change if another interlace type is added. -This function can be called even if the file is not interlaced, -where it will return one pass. - -If you are not going to display the image after each pass, but are -going to wait until the entire image is read in, use the sparkle -effect. This effect is faster and the end result of either method -is exactly the same. If you are planning on displaying the image -after each pass, the "rectangle" effect is generally considered the -better looking one. - -If you only want the "sparkle" effect, just call png_read_rows() as -normal, with the third parameter NULL. Make sure you make pass over -the image number_of_passes times, and you don't change the data in the -rows between calls. You can change the locations of the data, just -not the data. Each pass only writes the pixels appropriate for that -pass, and assumes the data from previous passes is still valid. - - png_read_rows(png_ptr, row_pointers, NULL, - number_of_rows); - -If you only want the first effect (the rectangles), do the same as -before except pass the row buffer in the third parameter, and leave -the second parameter NULL. - - png_read_rows(png_ptr, NULL, row_pointers, - number_of_rows); - -.SS Finishing a sequential read - -After you are finished reading the image through the -low-level interface, you can finish reading the file. If you are -interested in comments or time, which may be stored either before or -after the image data, you should pass the separate png_info struct if -you want to keep the comments from before and after the image -separate. If you are not interested, you can pass NULL. - - png_read_end(png_ptr, end_info); - -When you are done, you can free all memory allocated by libpng like this: - - png_destroy_read_struct(&png_ptr, &info_ptr, - &end_info); - -It is also possible to individually free the info_ptr members that -point to libpng-allocated storage with the following function: - - png_free_data(png_ptr, info_ptr, mask, seq) - mask - identifies data to be freed, a mask - containing the bitwise OR of one or - more of - PNG_FREE_PLTE, PNG_FREE_TRNS, - PNG_FREE_HIST, PNG_FREE_ICCP, - PNG_FREE_PCAL, PNG_FREE_ROWS, - PNG_FREE_SCAL, PNG_FREE_SPLT, - PNG_FREE_TEXT, PNG_FREE_UNKN, - or simply PNG_FREE_ALL - seq - sequence number of item to be freed - (-1 for all items) - -This function may be safely called when the relevant storage has -already been freed, or has not yet been allocated, or was allocated -by the user and not by libpng, and will in those -cases do nothing. The "seq" parameter is ignored if only one item -of the selected data type, such as PLTE, is allowed. If "seq" is not --1, and multiple items are allowed for the data type identified in -the mask, such as text or sPLT, only the n'th item in the structure -is freed, where n is "seq". - -The default behavior is only to free data that was allocated internally -by libpng. This can be changed, so that libpng will not free the data, -or so that it will free data that was allocated by the user with png_malloc() -or png_zalloc() and passed in via a png_set_*() function, with - - png_data_freer(png_ptr, info_ptr, freer, mask) - mask - which data elements are affected - same choices as in png_free_data() - freer - one of - PNG_DESTROY_WILL_FREE_DATA - PNG_SET_WILL_FREE_DATA - PNG_USER_WILL_FREE_DATA - -This function only affects data that has already been allocated. -You can call this function after reading the PNG data but before calling -any png_set_*() functions, to control whether the user or the png_set_*() -function is responsible for freeing any existing data that might be present, -and again after the png_set_*() functions to control whether the user -or png_destroy_*() is supposed to free the data. When the user assumes -responsibility for libpng-allocated data, the application must use -png_free() to free it, and when the user transfers responsibility to libpng -for data that the user has allocated, the user must have used png_malloc() -or png_zalloc() to allocate it. - -If you allocated your row_pointers in a single block, as suggested above in -the description of the high level read interface, you must not transfer -responsibility for freeing it to the png_set_rows or png_read_destroy function, -because they would also try to free the individual row_pointers[i]. - -If you allocated text_ptr.text, text_ptr.lang, and text_ptr.translated_keyword -separately, do not transfer responsibility for freeing text_ptr to libpng, -because when libpng fills a png_text structure it combines these members with -the key member, and png_free_data() will free only text_ptr.key. Similarly, -if you transfer responsibility for free'ing text_ptr from libpng to your -application, your application must not separately free those members. - -The png_free_data() function will turn off the "valid" flag for anything -it frees. If you need to turn the flag off for a chunk that was freed by your -application instead of by libpng, you can use - - png_set_invalid(png_ptr, info_ptr, mask); - mask - identifies the chunks to be made invalid, - containing the bitwise OR of one or - more of - PNG_INFO_gAMA, PNG_INFO_sBIT, - PNG_INFO_cHRM, PNG_INFO_PLTE, - PNG_INFO_tRNS, PNG_INFO_bKGD, - PNG_INFO_hIST, PNG_INFO_pHYs, - PNG_INFO_oFFs, PNG_INFO_tIME, - PNG_INFO_pCAL, PNG_INFO_sRGB, - PNG_INFO_iCCP, PNG_INFO_sPLT, - PNG_INFO_sCAL, PNG_INFO_IDAT - -For a more compact example of reading a PNG image, see the file example.c. - -.SS Reading PNG files progressively - -The progressive reader is slightly different then the non-progressive -reader. Instead of calling png_read_info(), png_read_rows(), and -png_read_end(), you make one call to png_process_data(), which calls -callbacks when it has the info, a row, or the end of the image. You -set up these callbacks with png_set_progressive_read_fn(). You don't -have to worry about the input/output functions of libpng, as you are -giving the library the data directly in png_process_data(). I will -assume that you have read the section on reading PNG files above, -so I will only highlight the differences (although I will show -all of the code). - -png_structp png_ptr; -png_infop info_ptr; - - /* An example code fragment of how you would - initialize the progressive reader in your - application. */ - int - initialize_png_reader() - { - png_ptr = png_create_read_struct - (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, - user_error_fn, user_warning_fn); - if (!png_ptr) - return (ERROR); - info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) - { - png_destroy_read_struct(&png_ptr, (png_infopp)NULL, - (png_infopp)NULL); - return (ERROR); - } - - if (setjmp(png_jmpbuf(png_ptr))) - { - png_destroy_read_struct(&png_ptr, &info_ptr, - (png_infopp)NULL); - return (ERROR); - } - - /* This one's new. You can provide functions - to be called when the header info is valid, - when each row is completed, and when the image - is finished. If you aren't using all functions, - you can specify NULL parameters. Even when all - three functions are NULL, you need to call - png_set_progressive_read_fn(). You can use - any struct as the user_ptr (cast to a void pointer - for the function call), and retrieve the pointer - from inside the callbacks using the function - - png_get_progressive_ptr(png_ptr); - - which will return a void pointer, which you have - to cast appropriately. - */ - png_set_progressive_read_fn(png_ptr, (void *)user_ptr, - info_callback, row_callback, end_callback); - - return 0; - } - - /* A code fragment that you call as you receive blocks - of data */ - int - process_data(png_bytep buffer, png_uint_32 length) - { - if (setjmp(png_jmpbuf(png_ptr))) - { - png_destroy_read_struct(&png_ptr, &info_ptr, - (png_infopp)NULL); - return (ERROR); - } - - /* This one's new also. Simply give it a chunk - of data from the file stream (in order, of - course). On machines with segmented memory - models machines, don't give it any more than - 64K. The library seems to run fine with sizes - of 4K. Although you can give it much less if - necessary (I assume you can give it chunks of - 1 byte, I haven't tried less then 256 bytes - yet). When this function returns, you may - want to display any rows that were generated - in the row callback if you don't already do - so there. - */ - png_process_data(png_ptr, info_ptr, buffer, length); - return 0; - } - - /* This function is called (as set by - png_set_progressive_read_fn() above) when enough data - has been supplied so all of the header has been - read. - */ - void - info_callback(png_structp png_ptr, png_infop info) - { - /* Do any setup here, including setting any of - the transformations mentioned in the Reading - PNG files section. For now, you _must_ call - either png_start_read_image() or - png_read_update_info() after all the - transformations are set (even if you don't set - any). You may start getting rows before - png_process_data() returns, so this is your - last chance to prepare for that. - */ - } - - /* This function is called when each row of image - data is complete */ - void - row_callback(png_structp png_ptr, png_bytep new_row, - png_uint_32 row_num, int pass) - { - /* If the image is interlaced, and you turned - on the interlace handler, this function will - be called for every row in every pass. Some - of these rows will not be changed from the - previous pass. When the row is not changed, - the new_row variable will be NULL. The rows - and passes are called in order, so you don't - really need the row_num and pass, but I'm - supplying them because it may make your life - easier. - - For the non-NULL rows of interlaced images, - you must call png_progressive_combine_row() - passing in the row and the old row. You can - call this function for NULL rows (it will just - return) and for non-interlaced images (it just - does the memcpy for you) if it will make the - code easier. Thus, you can just do this for - all cases: - */ - - png_progressive_combine_row(png_ptr, old_row, - new_row); - - /* where old_row is what was displayed for - previously for the row. Note that the first - pass (pass == 0, really) will completely cover - the old row, so the rows do not have to be - initialized. After the first pass (and only - for interlaced images), you will have to pass - the current row, and the function will combine - the old row and the new row. - */ - } - - void - end_callback(png_structp png_ptr, png_infop info) - { - /* This function is called after the whole image - has been read, including any chunks after the - image (up to and including the IEND). You - will usually have the same info chunk as you - had in the header, although some data may have - been added to the comments and time fields. - - Most people won't do much here, perhaps setting - a flag that marks the image as finished. - */ - } - - - -.SH IV. Writing - -Much of this is very similar to reading. However, everything of -importance is repeated here, so you won't have to constantly look -back up in the reading section to understand writing. - -.SS Setup - -You will want to do the I/O initialization before you get into libpng, -so if it doesn't work, you don't have anything to undo. If you are not -using the standard I/O functions, you will need to replace them with -custom writing functions. See the discussion under Customizing libpng. - - FILE *fp = fopen(file_name, "wb"); - if (!fp) - { - return (ERROR); - } - -Next, png_struct and png_info need to be allocated and initialized. -As these can be both relatively large, you may not want to store these -on the stack, unless you have stack space to spare. Of course, you -will want to check if they return NULL. If you are also reading, -you won't want to name your read structure and your write structure -both "png_ptr"; you can call them anything you like, such as -"read_ptr" and "write_ptr". Look at pngtest.c, for example. - - png_structp png_ptr = png_create_write_struct - (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, - user_error_fn, user_warning_fn); - if (!png_ptr) - return (ERROR); - - png_infop info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) - { - png_destroy_write_struct(&png_ptr, - (png_infopp)NULL); - return (ERROR); - } - -If you want to use your own memory allocation routines, -define PNG_USER_MEM_SUPPORTED and use -png_create_write_struct_2() instead of png_create_write_struct(): - - png_structp png_ptr = png_create_write_struct_2 - (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, - user_error_fn, user_warning_fn, (png_voidp) - user_mem_ptr, user_malloc_fn, user_free_fn); - -After you have these structures, you will need to set up the -error handling. When libpng encounters an error, it expects to -longjmp() back to your routine. Therefore, you will need to call -setjmp() and pass the png_jmpbuf(png_ptr). If you -write the file from different routines, you will need to update -the png_jmpbuf(png_ptr) every time you enter a new routine that will -call a png_*() function. See your documentation of setjmp/longjmp -for your compiler for more information on setjmp/longjmp. See -the discussion on libpng error handling in the Customizing Libpng -section below for more information on the libpng error handling. - - if (setjmp(png_jmpbuf(png_ptr))) - { - png_destroy_write_struct(&png_ptr, &info_ptr); - fclose(fp); - return (ERROR); - } - ... - return; - -If you would rather avoid the complexity of setjmp/longjmp issues, -you can compile libpng with PNG_SETJMP_NOT_SUPPORTED, in which case -errors will result in a call to PNG_ABORT() which defaults to abort(). - -Now you need to set up the output code. The default for libpng is to -use the C function fwrite(). If you use this, you will need to pass a -valid FILE * in the function png_init_io(). Be sure that the file is -opened in binary mode. Again, if you wish to handle writing data in -another way, see the discussion on libpng I/O handling in the Customizing -Libpng section below. - - png_init_io(png_ptr, fp); - -If you are embedding your PNG into a datastream such as MNG, and don't -want libpng to write the 8-byte signature, or if you have already -written the signature in your application, use - - png_set_sig_bytes(png_ptr, 8); - -to inform libpng that it should not write a signature. - -.SS Write callbacks - -At this point, you can set up a callback function that will be -called after each row has been written, which you can use to control -a progress meter or the like. It's demonstrated in pngtest.c. -You must supply a function - - void write_row_callback(png_ptr, png_uint_32 row, - int pass); - { - /* put your code here */ - } - -(You can give it another name that you like instead of "write_row_callback") - -To inform libpng about your function, use - - png_set_write_status_fn(png_ptr, write_row_callback); - -You now have the option of modifying how the compression library will -run. The following functions are mainly for testing, but may be useful -in some cases, like if you need to write PNG files extremely fast and -are willing to give up some compression, or if you want to get the -maximum possible compression at the expense of slower writing. If you -have no special needs in this area, let the library do what it wants by -not calling this function at all, as it has been tuned to deliver a good -speed/compression ratio. The second parameter to png_set_filter() is -the filter method, for which the only valid values are 0 (as of the -July 1999 PNG specification, version 1.2) or 64 (if you are writing -a PNG datastream that is to be embedded in a MNG datastream). The third -parameter is a flag that indicates which filter type(s) are to be tested -for each scanline. See the PNG specification for details on the specific filter -types. - - - /* turn on or off filtering, and/or choose - specific filters. You can use either a single - PNG_FILTER_VALUE_NAME or the bitwise OR of one - or more PNG_FILTER_NAME masks. */ - png_set_filter(png_ptr, 0, - PNG_FILTER_NONE | PNG_FILTER_VALUE_NONE | - PNG_FILTER_SUB | PNG_FILTER_VALUE_SUB | - PNG_FILTER_UP | PNG_FILTER_VALUE_UP | - PNG_FILTER_AVE | PNG_FILTER_VALUE_AVE | - PNG_FILTER_PAETH | PNG_FILTER_VALUE_PAETH| - PNG_ALL_FILTERS); - -If an application -wants to start and stop using particular filters during compression, -it should start out with all of the filters (to ensure that the previous -row of pixels will be stored in case it's needed later), and then add -and remove them after the start of compression. - -If you are writing a PNG datastream that is to be embedded in a MNG -datastream, the second parameter can be either 0 or 64. - -The png_set_compression_*() functions interface to the zlib compression -library, and should mostly be ignored unless you really know what you are -doing. The only generally useful call is png_set_compression_level() -which changes how much time zlib spends on trying to compress the image -data. See the Compression Library (zlib.h and algorithm.txt, distributed -with zlib) for details on the compression levels. - - /* set the zlib compression level */ - png_set_compression_level(png_ptr, - Z_BEST_COMPRESSION); - - /* set other zlib parameters */ - png_set_compression_mem_level(png_ptr, 8); - png_set_compression_strategy(png_ptr, - Z_DEFAULT_STRATEGY); - png_set_compression_window_bits(png_ptr, 15); - png_set_compression_method(png_ptr, 8); - png_set_compression_buffer_size(png_ptr, 8192) - -extern PNG_EXPORT(void,png_set_zbuf_size) - -.SS Setting the contents of info for output - -You now need to fill in the png_info structure with all the data you -wish to write before the actual image. Note that the only thing you -are allowed to write after the image is the text chunks and the time -chunk (as of PNG Specification 1.2, anyway). See png_write_end() and -the latest PNG specification for more information on that. If you -wish to write them before the image, fill them in now, and flag that -data as being valid. If you want to wait until after the data, don't -fill them until png_write_end(). For all the fields in png_info and -their data types, see png.h. For explanations of what the fields -contain, see the PNG specification. - -Some of the more important parts of the png_info are: - - png_set_IHDR(png_ptr, info_ptr, width, height, - bit_depth, color_type, interlace_type, - compression_type, filter_method) - width - holds the width of the image - in pixels (up to 2^31). - height - holds the height of the image - in pixels (up to 2^31). - bit_depth - holds the bit depth of one of the - image channels. - (valid values are 1, 2, 4, 8, 16 - and depend also on the - color_type. See also significant - bits (sBIT) below). - color_type - describes which color/alpha - channels are present. - PNG_COLOR_TYPE_GRAY - (bit depths 1, 2, 4, 8, 16) - PNG_COLOR_TYPE_GRAY_ALPHA - (bit depths 8, 16) - PNG_COLOR_TYPE_PALETTE - (bit depths 1, 2, 4, 8) - PNG_COLOR_TYPE_RGB - (bit_depths 8, 16) - PNG_COLOR_TYPE_RGB_ALPHA - (bit_depths 8, 16) - - PNG_COLOR_MASK_PALETTE - PNG_COLOR_MASK_COLOR - PNG_COLOR_MASK_ALPHA - - interlace_type - PNG_INTERLACE_NONE or - PNG_INTERLACE_ADAM7 - compression_type - (must be - PNG_COMPRESSION_TYPE_DEFAULT) - filter_method - (must be PNG_FILTER_TYPE_DEFAULT - or, if you are writing a PNG to - be embedded in a MNG datastream, - can also be - PNG_INTRAPIXEL_DIFFERENCING) - - png_set_PLTE(png_ptr, info_ptr, palette, - num_palette); - palette - the palette for the file - (array of png_color) - num_palette - number of entries in the palette - - png_set_gAMA(png_ptr, info_ptr, gamma); - gamma - the gamma the image was created - at (PNG_INFO_gAMA) - - png_set_sRGB(png_ptr, info_ptr, srgb_intent); - srgb_intent - the rendering intent - (PNG_INFO_sRGB) The presence of - the sRGB chunk means that the pixel - data is in the sRGB color space. - This chunk also implies specific - values of gAMA and cHRM. Rendering - intent is the CSS-1 property that - has been defined by the International - Color Consortium - (http://www.color.org). - It can be one of - PNG_sRGB_INTENT_SATURATION, - PNG_sRGB_INTENT_PERCEPTUAL, - PNG_sRGB_INTENT_ABSOLUTE, or - PNG_sRGB_INTENT_RELATIVE. - - - png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, - srgb_intent); - srgb_intent - the rendering intent - (PNG_INFO_sRGB) The presence of the - sRGB chunk means that the pixel - data is in the sRGB color space. - This function also causes gAMA and - cHRM chunks with the specific values - that are consistent with sRGB to be - written. - - png_set_iCCP(png_ptr, info_ptr, name, compression_type, - profile, proflen); - name - The profile name. - compression - The compression type; always - PNG_COMPRESSION_TYPE_BASE for PNG 1.0. - You may give NULL to this argument to - ignore it. - profile - International Color Consortium color - profile data. May contain NULs. - proflen - length of profile data in bytes. - - png_set_sBIT(png_ptr, info_ptr, sig_bit); - sig_bit - the number of significant bits for - (PNG_INFO_sBIT) each of the gray, red, - green, and blue channels, whichever are - appropriate for the given color type - (png_color_16) - - png_set_tRNS(png_ptr, info_ptr, trans, num_trans, - trans_values); - trans - array of transparent entries for - palette (PNG_INFO_tRNS) - trans_values - graylevel or color sample values of - the single transparent color for - non-paletted images (PNG_INFO_tRNS) - num_trans - number of transparent entries - (PNG_INFO_tRNS) - - png_set_hIST(png_ptr, info_ptr, hist); - (PNG_INFO_hIST) - hist - histogram of palette (array of - png_uint_16) - - png_set_tIME(png_ptr, info_ptr, mod_time); - mod_time - time image was last modified - (PNG_VALID_tIME) - - png_set_bKGD(png_ptr, info_ptr, background); - background - background color (PNG_VALID_bKGD) - - png_set_text(png_ptr, info_ptr, text_ptr, num_text); - text_ptr - array of png_text holding image - comments - text_ptr[i].compression - type of compression used - on "text" PNG_TEXT_COMPRESSION_NONE - PNG_TEXT_COMPRESSION_zTXt - PNG_ITXT_COMPRESSION_NONE - PNG_ITXT_COMPRESSION_zTXt - text_ptr[i].key - keyword for comment. Must contain - 1-79 characters. - text_ptr[i].text - text comments for current - keyword. Can be NULL or empty. - text_ptr[i].text_length - length of text string, - after decompression, 0 for iTXt - text_ptr[i].itxt_length - length of itxt string, - after decompression, 0 for tEXt/zTXt - text_ptr[i].lang - language of comment (NULL or - empty for unknown). - text_ptr[i].translated_keyword - keyword in UTF-8 (NULL - or empty for unknown). - num_text - number of comments - - png_set_sPLT(png_ptr, info_ptr, &palette_ptr, - num_spalettes); - palette_ptr - array of png_sPLT_struct structures - to be added to the list of palettes - in the info structure. - num_spalettes - number of palette structures to be - added. - - png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, - unit_type); - offset_x - positive offset from the left - edge of the screen - offset_y - positive offset from the top - edge of the screen - unit_type - PNG_OFFSET_PIXEL, PNG_OFFSET_MICROMETER - - png_set_pHYs(png_ptr, info_ptr, res_x, res_y, - unit_type); - res_x - pixels/unit physical resolution - in x direction - res_y - pixels/unit physical resolution - in y direction - unit_type - PNG_RESOLUTION_UNKNOWN, - PNG_RESOLUTION_METER - - png_set_sCAL(png_ptr, info_ptr, unit, width, height) - unit - physical scale units (an integer) - width - width of a pixel in physical scale units - height - height of a pixel in physical scale units - (width and height are doubles) - - png_set_sCAL_s(png_ptr, info_ptr, unit, width, height) - unit - physical scale units (an integer) - width - width of a pixel in physical scale units - height - height of a pixel in physical scale units - (width and height are strings like "2.54") - - png_set_unknown_chunks(png_ptr, info_ptr, &unknowns, - num_unknowns) - unknowns - array of png_unknown_chunk - structures holding unknown chunks - unknowns[i].name - name of unknown chunk - unknowns[i].data - data of unknown chunk - unknowns[i].size - size of unknown chunk's data - unknowns[i].location - position to write chunk in file - 0: do not write chunk - PNG_HAVE_IHDR: before PLTE - PNG_HAVE_PLTE: before IDAT - PNG_AFTER_IDAT: after IDAT - -The "location" member is set automatically according to -what part of the output file has already been written. -You can change its value after calling png_set_unknown_chunks() -as demonstrated in pngtest.c. Within each of the "locations", -the chunks are sequenced according to their position in the -structure (that is, the value of "i", which is the order in which -the chunk was either read from the input file or defined with -png_set_unknown_chunks). - -A quick word about text and num_text. text is an array of png_text -structures. num_text is the number of valid structures in the array. -Each png_text structure holds a language code, a keyword, a text value, -and a compression type. - -The compression types have the same valid numbers as the compression -types of the image data. Currently, the only valid number is zero. -However, you can store text either compressed or uncompressed, unlike -images, which always have to be compressed. So if you don't want the -text compressed, set the compression type to PNG_TEXT_COMPRESSION_NONE. -Because tEXt and zTXt chunks don't have a language field, if you -specify PNG_TEXT_COMPRESSION_NONE or PNG_TEXT_COMPRESSION_zTXt -any language code or translated keyword will not be written out. - -Until text gets around 1000 bytes, it is not worth compressing it. -After the text has been written out to the file, the compression type -is set to PNG_TEXT_COMPRESSION_NONE_WR or PNG_TEXT_COMPRESSION_zTXt_WR, -so that it isn't written out again at the end (in case you are calling -png_write_end() with the same struct. - -The keywords that are given in the PNG Specification are: - - Title Short (one line) title or - caption for image - Author Name of image's creator - Description Description of image (possibly long) - Copyright Copyright notice - Creation Time Time of original image creation - (usually RFC 1123 format, see below) - Software Software used to create the image - Disclaimer Legal disclaimer - Warning Warning of nature of content - Source Device used to create the image - Comment Miscellaneous comment; conversion - from other image format - -The keyword-text pairs work like this. Keywords should be short -simple descriptions of what the comment is about. Some typical -keywords are found in the PNG specification, as is some recommendations -on keywords. You can repeat keywords in a file. You can even write -some text before the image and some after. For example, you may want -to put a description of the image before the image, but leave the -disclaimer until after, so viewers working over modem connections -don't have to wait for the disclaimer to go over the modem before -they start seeing the image. Finally, keywords should be full -words, not abbreviations. Keywords and text are in the ISO 8859-1 -(Latin-1) character set (a superset of regular ASCII) and can not -contain NUL characters, and should not contain control or other -unprintable characters. To make the comments widely readable, stick -with basic ASCII, and avoid machine specific character set extensions -like the IBM-PC character set. The keyword must be present, but -you can leave off the text string on non-compressed pairs. -Compressed pairs must have a text string, as only the text string -is compressed anyway, so the compression would be meaningless. - -PNG supports modification time via the png_time structure. Two -conversion routines are provided, png_convert_from_time_t() for -time_t and png_convert_from_struct_tm() for struct tm. The -time_t routine uses gmtime(). You don't have to use either of -these, but if you wish to fill in the png_time structure directly, -you should provide the time in universal time (GMT) if possible -instead of your local time. Note that the year number is the full -year (e.g. 1998, rather than 98 - PNG is year 2000 compliant!), and -that months start with 1. - -If you want to store the time of the original image creation, you should -use a plain tEXt chunk with the "Creation Time" keyword. This is -necessary because the "creation time" of a PNG image is somewhat vague, -depending on whether you mean the PNG file, the time the image was -created in a non-PNG format, a still photo from which the image was -scanned, or possibly the subject matter itself. In order to facilitate -machine-readable dates, it is recommended that the "Creation Time" -tEXt chunk use RFC 1123 format dates (e.g. "22 May 1997 18:07:10 GMT"), -although this isn't a requirement. Unlike the tIME chunk, the -"Creation Time" tEXt chunk is not expected to be automatically changed -by the software. To facilitate the use of RFC 1123 dates, a function -png_convert_to_rfc1123(png_timep) is provided to convert from PNG -time to an RFC 1123 format string. - -.SS Writing unknown chunks - -You can use the png_set_unknown_chunks function to queue up chunks -for writing. You give it a chunk name, raw data, and a size; that's -all there is to it. The chunks will be written by the next following -png_write_info_before_PLTE, png_write_info, or png_write_end function. -Any chunks previously read into the info structure's unknown-chunk -list will also be written out in a sequence that satisfies the PNG -specification's ordering rules. - -.SS The high-level write interface - -At this point there are two ways to proceed; through the high-level -write interface, or through a sequence of low-level write operations. -You can use the high-level interface if your image data is present -in the info structure. All defined output -transformations are permitted, enabled by the following masks. - - PNG_TRANSFORM_IDENTITY No transformation - PNG_TRANSFORM_PACKING Pack 1, 2 and 4-bit samples - PNG_TRANSFORM_PACKSWAP Change order of packed - pixels to LSB first - PNG_TRANSFORM_INVERT_MONO Invert monochrome images - PNG_TRANSFORM_SHIFT Normalize pixels to the - sBIT depth - PNG_TRANSFORM_BGR Flip RGB to BGR, RGBA - to BGRA - PNG_TRANSFORM_SWAP_ALPHA Flip RGBA to ARGB or GA - to AG - PNG_TRANSFORM_INVERT_ALPHA Change alpha from opacity - to transparency - PNG_TRANSFORM_SWAP_ENDIAN Byte-swap 16-bit samples - PNG_TRANSFORM_STRIP_FILLER Strip out filler bytes. - -If you have valid image data in the info structure (you can use -png_set_rows() to put image data in the info structure), simply do this: - - png_write_png(png_ptr, info_ptr, png_transforms, NULL) - -where png_transforms is an integer containing the bitwise OR of some set of -transformation flags. This call is equivalent to png_write_info(), -followed the set of transformations indicated by the transform mask, -then png_write_image(), and finally png_write_end(). - -(The final parameter of this call is not yet used. Someday it might point -to transformation parameters required by some future output transform.) - -You must use png_transforms and not call any png_set_transform() functions -when you use png_write_png(). - -.SS The low-level write interface - -If you are going the low-level route instead, you are now ready to -write all the file information up to the actual image data. You do -this with a call to png_write_info(). - - png_write_info(png_ptr, info_ptr); - -Note that there is one transformation you may need to do before -png_write_info(). In PNG files, the alpha channel in an image is the -level of opacity. If your data is supplied as a level of -transparency, you can invert the alpha channel before you write it, so -that 0 is fully transparent and 255 (in 8-bit or paletted images) or -65535 (in 16-bit images) is fully opaque, with - - png_set_invert_alpha(png_ptr); - -This must appear before png_write_info() instead of later with the -other transformations because in the case of paletted images the tRNS -chunk data has to be inverted before the tRNS chunk is written. If -your image is not a paletted image, the tRNS data (which in such cases -represents a single color to be rendered as transparent) won't need to -be changed, and you can safely do this transformation after your -png_write_info() call. - -If you need to write a private chunk that you want to appear before -the PLTE chunk when PLTE is present, you can write the PNG info in -two steps, and insert code to write your own chunk between them: - - png_write_info_before_PLTE(png_ptr, info_ptr); - png_set_unknown_chunks(png_ptr, info_ptr, ...); - png_write_info(png_ptr, info_ptr); - -After you've written the file information, you can set up the library -to handle any special transformations of the image data. The various -ways to transform the data will be described in the order that they -should occur. This is important, as some of these change the color -type and/or bit depth of the data, and some others only work on -certain color types and bit depths. Even though each transformation -checks to see if it has data that it can do something with, you should -make sure to only enable a transformation if it will be valid for the -data. For example, don't swap red and blue on grayscale data. - -PNG files store RGB pixels packed into 3 or 6 bytes. This code tells -the library to strip input data that has 4 or 8 bytes per pixel down -to 3 or 6 bytes (or strip 2 or 4-byte grayscale+filler data to 1 or 2 -bytes per pixel). - - png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); - -where the 0 is unused, and the location is either PNG_FILLER_BEFORE or -PNG_FILLER_AFTER, depending upon whether the filler byte in the pixel -is stored XRGB or RGBX. - -PNG files pack pixels of bit depths 1, 2, and 4 into bytes as small as -they can, resulting in, for example, 8 pixels per byte for 1 bit files. -If the data is supplied at 1 pixel per byte, use this code, which will -correctly pack the pixels into a single byte: - - png_set_packing(png_ptr); - -PNG files reduce possible bit depths to 1, 2, 4, 8, and 16. If your -data is of another bit depth, you can write an sBIT chunk into the -file so that decoders can recover the original data if desired. - - /* Set the true bit depth of the image data */ - if (color_type & PNG_COLOR_MASK_COLOR) - { - sig_bit.red = true_bit_depth; - sig_bit.green = true_bit_depth; - sig_bit.blue = true_bit_depth; - } - else - { - sig_bit.gray = true_bit_depth; - } - if (color_type & PNG_COLOR_MASK_ALPHA) - { - sig_bit.alpha = true_bit_depth; - } - - png_set_sBIT(png_ptr, info_ptr, &sig_bit); - -If the data is stored in the row buffer in a bit depth other than -one supported by PNG (e.g. 3 bit data in the range 0-7 for a 4-bit PNG), -this will scale the values to appear to be the correct bit depth as -is required by PNG. - - png_set_shift(png_ptr, &sig_bit); - -PNG files store 16 bit pixels in network byte order (big-endian, -ie. most significant bits first). This code would be used if they are -supplied the other way (little-endian, i.e. least significant bits -first, the way PCs store them): - - if (bit_depth > 8) - png_set_swap(png_ptr); - -If you are using packed-pixel images (1, 2, or 4 bits/pixel), and you -need to change the order the pixels are packed into bytes, you can use: - - if (bit_depth < 8) - png_set_packswap(png_ptr); - -PNG files store 3 color pixels in red, green, blue order. This code -would be used if they are supplied as blue, green, red: - - png_set_bgr(png_ptr); - -PNG files describe monochrome as black being zero and white being -one. This code would be used if the pixels are supplied with this reversed -(black being one and white being zero): - - png_set_invert_mono(png_ptr); - -Finally, you can write your own transformation function if none of -the existing ones meets your needs. This is done by setting a callback -with - - png_set_write_user_transform_fn(png_ptr, - write_transform_fn); - -You must supply the function - - void write_transform_fn(png_ptr ptr, row_info_ptr - row_info, png_bytep data) - -See pngtest.c for a working example. Your function will be called -before any of the other transformations are processed. - -You can also set up a pointer to a user structure for use by your -callback function. - - png_set_user_transform_info(png_ptr, user_ptr, 0, 0); - -The user_channels and user_depth parameters of this function are ignored -when writing; you can set them to zero as shown. - -You can retrieve the pointer via the function png_get_user_transform_ptr(). -For example: - - voidp write_user_transform_ptr = - png_get_user_transform_ptr(png_ptr); - -It is possible to have libpng flush any pending output, either manually, -or automatically after a certain number of lines have been written. To -flush the output stream a single time call: - - png_write_flush(png_ptr); - -and to have libpng flush the output stream periodically after a certain -number of scanlines have been written, call: - - png_set_flush(png_ptr, nrows); - -Note that the distance between rows is from the last time png_write_flush() -was called, or the first row of the image if it has never been called. -So if you write 50 lines, and then png_set_flush 25, it will flush the -output on the next scanline, and every 25 lines thereafter, unless -png_write_flush() is called before 25 more lines have been written. -If nrows is too small (less than about 10 lines for a 640 pixel wide -RGB image) the image compression may decrease noticeably (although this -may be acceptable for real-time applications). Infrequent flushing will -only degrade the compression performance by a few percent over images -that do not use flushing. - -.SS Writing the image data - -That's it for the transformations. Now you can write the image data. -The simplest way to do this is in one function call. If you have the -whole image in memory, you can just call png_write_image() and libpng -will write the image. You will need to pass in an array of pointers to -each row. This function automatically handles interlacing, so you don't -need to call png_set_interlace_handling() or call this function multiple -times, or any of that other stuff necessary with png_write_rows(). - - png_write_image(png_ptr, row_pointers); - -where row_pointers is: - - png_byte *row_pointers[height]; - -You can point to void or char or whatever you use for pixels. - -If you don't want to write the whole image at once, you can -use png_write_rows() instead. If the file is not interlaced, -this is simple: - - png_write_rows(png_ptr, row_pointers, - number_of_rows); - -row_pointers is the same as in the png_write_image() call. - -If you are just writing one row at a time, you can do this with -a single row_pointer instead of an array of row_pointers: - - png_bytep row_pointer = row; - - png_write_row(png_ptr, row_pointer); - -When the file is interlaced, things can get a good deal more -complicated. The only currently (as of the PNG Specification -version 1.2, dated July 1999) defined interlacing scheme for PNG files -is the "Adam7" interlace scheme, that breaks down an -image into seven smaller images of varying size. libpng will build -these images for you, or you can do them yourself. If you want to -build them yourself, see the PNG specification for details of which -pixels to write when. - -If you don't want libpng to handle the interlacing details, just -use png_set_interlace_handling() and call png_write_rows() the -correct number of times to write all seven sub-images. - -If you want libpng to build the sub-images, call this before you start -writing any rows: - - number_of_passes = - png_set_interlace_handling(png_ptr); - -This will return the number of passes needed. Currently, this -is seven, but may change if another interlace type is added. - -Then write the complete image number_of_passes times. - - png_write_rows(png_ptr, row_pointers, - number_of_rows); - -As some of these rows are not used, and thus return immediately, -you may want to read about interlacing in the PNG specification, -and only update the rows that are actually used. - -.SS Finishing a sequential write - -After you are finished writing the image, you should finish writing -the file. If you are interested in writing comments or time, you should -pass an appropriately filled png_info pointer. If you are not interested, -you can pass NULL. - - png_write_end(png_ptr, info_ptr); - -When you are done, you can free all memory used by libpng like this: - - png_destroy_write_struct(&png_ptr, &info_ptr); - -It is also possible to individually free the info_ptr members that -point to libpng-allocated storage with the following function: - - png_free_data(png_ptr, info_ptr, mask, seq) - mask - identifies data to be freed, a mask - containing the bitwise OR of one or - more of - PNG_FREE_PLTE, PNG_FREE_TRNS, - PNG_FREE_HIST, PNG_FREE_ICCP, - PNG_FREE_PCAL, PNG_FREE_ROWS, - PNG_FREE_SCAL, PNG_FREE_SPLT, - PNG_FREE_TEXT, PNG_FREE_UNKN, - or simply PNG_FREE_ALL - seq - sequence number of item to be freed - (-1 for all items) - -This function may be safely called when the relevant storage has -already been freed, or has not yet been allocated, or was allocated -by the user and not by libpng, and will in those -cases do nothing. The "seq" parameter is ignored if only one item -of the selected data type, such as PLTE, is allowed. If "seq" is not --1, and multiple items are allowed for the data type identified in -the mask, such as text or sPLT, only the n'th item in the structure -is freed, where n is "seq". - -If you allocated data such as a palette that you passed -in to libpng with png_set_*, you must not free it until just before the call to -png_destroy_write_struct(). - -The default behavior is only to free data that was allocated internally -by libpng. This can be changed, so that libpng will not free the data, -or so that it will free data that was allocated by the user with png_malloc() -or png_zalloc() and passed in via a png_set_*() function, with - - png_data_freer(png_ptr, info_ptr, freer, mask) - mask - which data elements are affected - same choices as in png_free_data() - freer - one of - PNG_DESTROY_WILL_FREE_DATA - PNG_SET_WILL_FREE_DATA - PNG_USER_WILL_FREE_DATA - -For example, to transfer responsibility for some data from a read structure -to a write structure, you could use - - png_data_freer(read_ptr, read_info_ptr, - PNG_USER_WILL_FREE_DATA, - PNG_FREE_PLTE|PNG_FREE_tRNS|PNG_FREE_hIST) - png_data_freer(write_ptr, write_info_ptr, - PNG_DESTROY_WILL_FREE_DATA, - PNG_FREE_PLTE|PNG_FREE_tRNS|PNG_FREE_hIST) - -thereby briefly reassigning responsibility for freeing to the user but -immediately afterwards reassigning it once more to the write_destroy -function. Having done this, it would then be safe to destroy the read -structure and continue to use the PLTE, tRNS, and hIST data in the write -structure. - -This function only affects data that has already been allocated. -You can call this function before calling after the png_set_*() functions -to control whether the user or png_destroy_*() is supposed to free the data. -When the user assumes responsibility for libpng-allocated data, the -application must use -png_free() to free it, and when the user transfers responsibility to libpng -for data that the user has allocated, the user must have used png_malloc() -or png_zalloc() to allocate it. - -If you allocated text_ptr.text, text_ptr.lang, and text_ptr.translated_keyword -separately, do not transfer responsibility for freeing text_ptr to libpng, -because when libpng fills a png_text structure it combines these members with -the key member, and png_free_data() will free only text_ptr.key. Similarly, -if you transfer responsibility for free'ing text_ptr from libpng to your -application, your application must not separately free those members. -For a more compact example of writing a PNG image, see the file example.c. - -.SH V. Modifying/Customizing libpng: - -There are two issues here. The first is changing how libpng does -standard things like memory allocation, input/output, and error handling. -The second deals with more complicated things like adding new chunks, -adding new transformations, and generally changing how libpng works. -Both of those are compile-time issues; that is, they are generally -determined at the time the code is written, and there is rarely a need -to provide the user with a means of changing them. - -Memory allocation, input/output, and error handling - -All of the memory allocation, input/output, and error handling in libpng -goes through callbacks that are user-settable. The default routines are -in pngmem.c, pngrio.c, pngwio.c, and pngerror.c, respectively. To change -these functions, call the appropriate png_set_*_fn() function. - -Memory allocation is done through the functions png_malloc() -and png_free(). These currently just call the standard C functions. If -your pointers can't access more then 64K at a time, you will want to set -MAXSEG_64K in zlib.h. Since it is unlikely that the method of handling -memory allocation on a platform will change between applications, these -functions must be modified in the library at compile time. If you prefer -to use a different method of allocating and freeing data, you can use -png_create_read_struct_2() or png_create_write_struct_2() to register -your own functions as described above. -These functions also provide a void pointer that can be retrieved via - - mem_ptr=png_get_mem_ptr(png_ptr); - -Your replacement memory functions must have prototypes as follows: - - png_voidp malloc_fn(png_structp png_ptr, - png_size_t size); - void free_fn(png_structp png_ptr, png_voidp ptr); - -Your malloc_fn() must return NULL in case of failure. The png_malloc() -function will normally call png_error() if it receives a NULL from the -system memory allocator or from your replacement malloc_fn(). - -Input/Output in libpng is done through png_read() and png_write(), -which currently just call fread() and fwrite(). The FILE * is stored in -png_struct and is initialized via png_init_io(). If you wish to change -the method of I/O, the library supplies callbacks that you can set -through the function png_set_read_fn() and png_set_write_fn() at run -time, instead of calling the png_init_io() function. These functions -also provide a void pointer that can be retrieved via the function -png_get_io_ptr(). For example: - - png_set_read_fn(png_structp read_ptr, - voidp read_io_ptr, png_rw_ptr read_data_fn) - - png_set_write_fn(png_structp write_ptr, - voidp write_io_ptr, png_rw_ptr write_data_fn, - png_flush_ptr output_flush_fn); - - voidp read_io_ptr = png_get_io_ptr(read_ptr); - voidp write_io_ptr = png_get_io_ptr(write_ptr); - -The replacement I/O functions must have prototypes as follows: - - void user_read_data(png_structp png_ptr, - png_bytep data, png_size_t length); - void user_write_data(png_structp png_ptr, - png_bytep data, png_size_t length); - void user_flush_data(png_structp png_ptr); - -Supplying NULL for the read, write, or flush functions sets them back -to using the default C stream functions. It is an error to read from -a write stream, and vice versa. - -Error handling in libpng is done through png_error() and png_warning(). -Errors handled through png_error() are fatal, meaning that png_error() -should never return to its caller. Currently, this is handled via -setjmp() and longjmp() (unless you have compiled libpng with -PNG_SETJMP_NOT_SUPPORTED, in which case it is handled via PNG_ABORT()), -but you could change this to do things like exit() if you should wish. - -On non-fatal errors, png_warning() is called -to print a warning message, and then control returns to the calling code. -By default png_error() and png_warning() print a message on stderr via -fprintf() unless the library is compiled with PNG_NO_CONSOLE_IO defined -(because you don't want the messages) or PNG_NO_STDIO defined (because -fprintf() isn't available). If you wish to change the behavior of the error -functions, you will need to set up your own message callbacks. These -functions are normally supplied at the time that the png_struct is created. -It is also possible to redirect errors and warnings to your own replacement -functions after png_create_*_struct() has been called by calling: - - png_set_error_fn(png_structp png_ptr, - png_voidp error_ptr, png_error_ptr error_fn, - png_error_ptr warning_fn); - - png_voidp error_ptr = png_get_error_ptr(png_ptr); - -If NULL is supplied for either error_fn or warning_fn, then the libpng -default function will be used, calling fprintf() and/or longjmp() if a -problem is encountered. The replacement error functions should have -parameters as follows: - - void user_error_fn(png_structp png_ptr, - png_const_charp error_msg); - void user_warning_fn(png_structp png_ptr, - png_const_charp warning_msg); - -The motivation behind using setjmp() and longjmp() is the C++ throw and -catch exception handling methods. This makes the code much easier to write, -as there is no need to check every return code of every function call. -However, there are some uncertainties about the status of local variables -after a longjmp, so the user may want to be careful about doing anything after -setjmp returns non-zero besides returning itself. Consult your compiler -documentation for more details. For an alternative approach, you may wish -to use the "cexcept" facility (see http://cexcept.sourceforge.net). - -.SS Custom chunks - -If you need to read or write custom chunks, you may need to get deeper -into the libpng code. The library now has mechanisms for storing -and writing chunks of unknown type; you can even declare callbacks -for custom chunks. However, this may not be good enough if the -library code itself needs to know about interactions between your -chunk and existing `intrinsic' chunks. - -If you need to write a new intrinsic chunk, first read the PNG -specification. Acquire a first level of -understanding of how it works. Pay particular attention to the -sections that describe chunk names, and look at how other chunks were -designed, so you can do things similarly. Second, check out the -sections of libpng that read and write chunks. Try to find a chunk -that is similar to yours and use it as a template. More details can -be found in the comments inside the code. It is best to handle unknown -chunks in a generic method, via callback functions, instead of by -modifying libpng functions. - -If you wish to write your own transformation for the data, look through -the part of the code that does the transformations, and check out some of -the simpler ones to get an idea of how they work. Try to find a similar -transformation to the one you want to add and copy off of it. More details -can be found in the comments inside the code itself. - -.SS Configuring for 16 bit platforms - -You will want to look into zconf.h to tell zlib (and thus libpng) that -it cannot allocate more then 64K at a time. Even if you can, the memory -won't be accessible. So limit zlib and libpng to 64K by defining MAXSEG_64K. - -.SS Configuring for DOS - -For DOS users who only have access to the lower 640K, you will -have to limit zlib's memory usage via a png_set_compression_mem_level() -call. See zlib.h or zconf.h in the zlib library for more information. - -.SS Configuring for Medium Model - -Libpng's support for medium model has been tested on most of the popular -compilers. Make sure MAXSEG_64K gets defined, USE_FAR_KEYWORD gets -defined, and FAR gets defined to far in pngconf.h, and you should be -all set. Everything in the library (except for zlib's structure) is -expecting far data. You must use the typedefs with the p or pp on -the end for pointers (or at least look at them and be careful). Make -note that the rows of data are defined as png_bytepp, which is an -unsigned char far * far *. - -.SS Configuring for gui/windowing platforms: - -You will need to write new error and warning functions that use the GUI -interface, as described previously, and set them to be the error and -warning functions at the time that png_create_*_struct() is called, -in order to have them available during the structure initialization. -They can be changed later via png_set_error_fn(). On some compilers, -you may also have to change the memory allocators (png_malloc, etc.). - -.SS Configuring for compiler xxx: - -All includes for libpng are in pngconf.h. If you need to add/change/delete -an include, this is the place to do it. The includes that are not -needed outside libpng are protected by the PNG_INTERNAL definition, -which is only defined for those routines inside libpng itself. The -files in libpng proper only include png.h, which includes pngconf.h. - -.SS Configuring zlib: - -There are special functions to configure the compression. Perhaps the -most useful one changes the compression level, which currently uses -input compression values in the range 0 - 9. The library normally -uses the default compression level (Z_DEFAULT_COMPRESSION = 6). Tests -have shown that for a large majority of images, compression values in -the range 3-6 compress nearly as well as higher levels, and do so much -faster. For online applications it may be desirable to have maximum speed -(Z_BEST_SPEED = 1). With versions of zlib after v0.99, you can also -specify no compression (Z_NO_COMPRESSION = 0), but this would create -files larger than just storing the raw bitmap. You can specify the -compression level by calling: - - png_set_compression_level(png_ptr, level); - -Another useful one is to reduce the memory level used by the library. -The memory level defaults to 8, but it can be lowered if you are -short on memory (running DOS, for example, where you only have 640K). -Note that the memory level does have an effect on compression; among -other things, lower levels will result in sections of incompressible -data being emitted in smaller stored blocks, with a correspondingly -larger relative overhead of up to 15% in the worst case. - - png_set_compression_mem_level(png_ptr, level); - -The other functions are for configuring zlib. They are not recommended -for normal use and may result in writing an invalid PNG file. See -zlib.h for more information on what these mean. - - png_set_compression_strategy(png_ptr, - strategy); - png_set_compression_window_bits(png_ptr, - window_bits); - png_set_compression_method(png_ptr, method); - png_set_compression_buffer_size(png_ptr, size); - -.SS Controlling row filtering - -If you want to control whether libpng uses filtering or not, which -filters are used, and how it goes about picking row filters, you -can call one of these functions. The selection and configuration -of row filters can have a significant impact on the size and -encoding speed and a somewhat lesser impact on the decoding speed -of an image. Filtering is enabled by default for RGB and grayscale -images (with and without alpha), but not for paletted images nor -for any images with bit depths less than 8 bits/pixel. - -The 'method' parameter sets the main filtering method, which is -currently only '0' in the PNG 1.2 specification. The 'filters' -parameter sets which filter(s), if any, should be used for each -scanline. Possible values are PNG_ALL_FILTERS and PNG_NO_FILTERS -to turn filtering on and off, respectively. - -Individual filter types are PNG_FILTER_NONE, PNG_FILTER_SUB, -PNG_FILTER_UP, PNG_FILTER_AVG, PNG_FILTER_PAETH, which can be bitwise -ORed together with '|' to specify one or more filters to use. -These filters are described in more detail in the PNG specification. -If you intend to change the filter type during the course of writing -the image, you should start with flags set for all of the filters -you intend to use so that libpng can initialize its internal -structures appropriately for all of the filter types. (Note that this -means the first row must always be adaptively filtered, because libpng -currently does not allocate the filter buffers until png_write_row() -is called for the first time.) - - filters = PNG_FILTER_NONE | PNG_FILTER_SUB - PNG_FILTER_UP | PNG_FILTER_AVE | - PNG_FILTER_PAETH | PNG_ALL_FILTERS; - - png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, - filters); - The second parameter can also be - PNG_INTRAPIXEL_DIFFERENCING if you are - writing a PNG to be embedded in a MNG - datastream. This parameter must be the - same as the value of filter_method used - in png_set_IHDR(). - -It is also possible to influence how libpng chooses from among the -available filters. This is done in one or both of two ways - by -telling it how important it is to keep the same filter for successive -rows, and by telling it the relative computational costs of the filters. - - double weights[3] = {1.5, 1.3, 1.1}, - costs[PNG_FILTER_VALUE_LAST] = - {1.0, 1.3, 1.3, 1.5, 1.7}; - - png_set_filter_heuristics(png_ptr, - PNG_FILTER_HEURISTIC_WEIGHTED, 3, - weights, costs); - -The weights are multiplying factors that indicate to libpng that the -row filter should be the same for successive rows unless another row filter -is that many times better than the previous filter. In the above example, -if the previous 3 filters were SUB, SUB, NONE, the SUB filter could have a -"sum of absolute differences" 1.5 x 1.3 times higher than other filters -and still be chosen, while the NONE filter could have a sum 1.1 times -higher than other filters and still be chosen. Unspecified weights are -taken to be 1.0, and the specified weights should probably be declining -like those above in order to emphasize recent filters over older filters. - -The filter costs specify for each filter type a relative decoding cost -to be considered when selecting row filters. This means that filters -with higher costs are less likely to be chosen over filters with lower -costs, unless their "sum of absolute differences" is that much smaller. -The costs do not necessarily reflect the exact computational speeds of -the various filters, since this would unduly influence the final image -size. - -Note that the numbers above were invented purely for this example and -are given only to help explain the function usage. Little testing has -been done to find optimum values for either the costs or the weights. - -.SS Removing unwanted object code - -There are a bunch of #define's in pngconf.h that control what parts of -libpng are compiled. All the defines end in _SUPPORTED. If you are -never going to use a capability, you can change the #define to #undef -before recompiling libpng and save yourself code and data space, or -you can turn off individual capabilities with defines that begin with -PNG_NO_. - -You can also turn all of the transforms and ancillary chunk capabilities -off en masse with compiler directives that define -PNG_NO_READ[or WRITE]_TRANSFORMS, or PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS, -or all four, -along with directives to turn on any of the capabilities that you do -want. The PNG_NO_READ[or WRITE]_TRANSFORMS directives disable -the extra transformations but still leave the library fully capable of reading -and writing PNG files with all known public chunks -Use of the PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS directive -produces a library that is incapable of reading or writing ancillary chunks. -If you are not using the progressive reading capability, you can -turn that off with PNG_NO_PROGRESSIVE_READ (don't confuse -this with the INTERLACING capability, which you'll still have). - -All the reading and writing specific code are in separate files, so the -linker should only grab the files it needs. However, if you want to -make sure, or if you are building a stand alone library, all the -reading files start with pngr and all the writing files start with -pngw. The files that don't match either (like png.c, pngtrans.c, etc.) -are used for both reading and writing, and always need to be included. -The progressive reader is in pngpread.c - -If you are creating or distributing a dynamically linked library (a .so -or DLL file), you should not remove or disable any parts of the library, -as this will cause applications linked with different versions of the -library to fail if they call functions not available in your library. -The size of the library itself should not be an issue, because only -those sections that are actually used will be loaded into memory. - -.SS Requesting debug printout - -The macro definition PNG_DEBUG can be used to request debugging -printout. Set it to an integer value in the range 0 to 3. Higher -numbers result in increasing amounts of debugging information. The -information is printed to the "stderr" file, unless another file -name is specified in the PNG_DEBUG_FILE macro definition. - -When PNG_DEBUG > 0, the following functions (macros) become available: - - png_debug(level, message) - png_debug1(level, message, p1) - png_debug2(level, message, p1, p2) - -in which "level" is compared to PNG_DEBUG to decide whether to print -the message, "message" is the formatted string to be printed, -and p1 and p2 are parameters that are to be embedded in the string -according to printf-style formatting directives. For example, - - png_debug1(2, "foo=%d\n", foo); - -is expanded to - - if(PNG_DEBUG > 2) - fprintf(PNG_DEBUG_FILE, "foo=%d\n", foo); - -When PNG_DEBUG is defined but is zero, the macros aren't defined, but you -can still use PNG_DEBUG to control your own debugging: - - #ifdef PNG_DEBUG - fprintf(stderr, ... - #endif - -When PNG_DEBUG = 1, the macros are defined, but only png_debug statements -having level = 0 will be printed. There aren't any such statements in -this version of libpng, but if you insert some they will be printed. - -.SH VII. MNG support - -The MNG specification (available at http://www.libpng.org/pub/mng) allows -certain extensions to PNG for PNG images that are embedded in MNG datastreams. -Libpng can support some of these extensions. To enable them, use the -png_permit_mng_features() function: - - feature_set = png_permit_mng_features(png_ptr, mask) - mask is a png_uint_32 containing the bitwise OR of the - features you want to enable. These include - PNG_FLAG_MNG_EMPTY_PLTE - PNG_FLAG_MNG_FILTER_64 - PNG_ALL_MNG_FEATURES - feature_set is a png_uint_32 that is the bitwise AND of - your mask with the set of MNG features that is - supported by the version of libpng that you are using. - -It is an error to use this function when reading or writing a standalone -PNG file with the PNG 8-byte signature. The PNG datastream must be wrapped -in a MNG datastream. As a minimum, it must have the MNG 8-byte signature -and the MHDR and MEND chunks. Libpng does not provide support for these -or any other MNG chunks; your application must provide its own support for -them. You may wish to consider using libmng (available at -http://www.libmng.com) instead. - -.SH VIII. Changes to Libpng from version 0.88 - -It should be noted that versions of libpng later than 0.96 are not -distributed by the original libpng author, Guy Schalnat, nor by -Andreas Dilger, who had taken over from Guy during 1996 and 1997, and -distributed versions 0.89 through 0.96, but rather by another member -of the original PNG Group, Glenn Randers-Pehrson. Guy and Andreas are -still alive and well, but they have moved on to other things. - -The old libpng functions png_read_init(), png_write_init(), -png_info_init(), png_read_destroy(), and png_write_destroy() have been -moved to PNG_INTERNAL in version 0.95 to discourage their use. These -functions will be removed from libpng version 2.0.0. - -The preferred method of creating and initializing the libpng structures is -via the png_create_read_struct(), png_create_write_struct(), and -png_create_info_struct() because they isolate the size of the structures -from the application, allow version error checking, and also allow the -use of custom error handling routines during the initialization, which -the old functions do not. The functions png_read_destroy() and -png_write_destroy() do not actually free the memory that libpng -allocated for these structs, but just reset the data structures, so they -can be used instead of png_destroy_read_struct() and -png_destroy_write_struct() if you feel there is too much system overhead -allocating and freeing the png_struct for each image read. - -Setting the error callbacks via png_set_message_fn() before -png_read_init() as was suggested in libpng-0.88 is no longer supported -because this caused applications that do not use custom error functions -to fail if the png_ptr was not initialized to zero. It is still possible -to set the error callbacks AFTER png_read_init(), or to change them with -png_set_error_fn(), which is essentially the same function, but with a new -name to force compilation errors with applications that try to use the old -method. - -Starting with version 1.0.7, you can find out which version of the library -you are using at run-time: - - png_uint_32 libpng_vn = png_access_version_number(); - -The number libpng_vn is constructed from the major version, minor -version with leading zero, and release number with leading zero, -(e.g., libpng_vn for version 1.0.7 is 10007). - -You can also check which version of png.h you used when compiling your -application: - - png_uint_32 application_vn = PNG_LIBPNG_VER; - -.SH IX. Y2K Compliance in libpng - -October 13, 2007 - -Since the PNG Development group is an ad-hoc body, we can't make -an official declaration. - -This is your unofficial assurance that libpng from version 0.71 and -upward through 1.2.22 are Y2K compliant. It is my belief that earlier -versions were also Y2K compliant. - -Libpng only has three year fields. One is a 2-byte unsigned integer that -will hold years up to 65535. The other two hold the date in text -format, and will hold years up to 9999. - -The integer is - "png_uint_16 year" in png_time_struct. - -The strings are - "png_charp time_buffer" in png_struct and - "near_time_buffer", which is a local character string in png.c. - -There are seven time-related functions: - - png_convert_to_rfc_1123() in png.c - (formerly png_convert_to_rfc_1152() in error) - png_convert_from_struct_tm() in pngwrite.c, called - in pngwrite.c - png_convert_from_time_t() in pngwrite.c - png_get_tIME() in pngget.c - png_handle_tIME() in pngrutil.c, called in pngread.c - png_set_tIME() in pngset.c - png_write_tIME() in pngwutil.c, called in pngwrite.c - -All appear to handle dates properly in a Y2K environment. The -png_convert_from_time_t() function calls gmtime() to convert from system -clock time, which returns (year - 1900), which we properly convert to -the full 4-digit year. There is a possibility that applications using -libpng are not passing 4-digit years into the png_convert_to_rfc_1123() -function, or that they are incorrectly passing only a 2-digit year -instead of "year - 1900" into the png_convert_from_struct_tm() function, -but this is not under our control. The libpng documentation has always -stated that it works with 4-digit years, and the APIs have been -documented as such. - -The tIME chunk itself is also Y2K compliant. It uses a 2-byte unsigned -integer to hold the year, and can hold years as large as 65535. - -zlib, upon which libpng depends, is also Y2K compliant. It contains -no date-related code. - - - Glenn Randers-Pehrson - libpng maintainer - PNG Development Group - -.SH NOTE - -Note about libpng version numbers: - -Due to various miscommunications, unforeseen code incompatibilities -and occasional factors outside the authors' control, version numbering -on the library has not always been consistent and straightforward. -The following table summarizes matters since version 0.89c, which was -the first widely used release: - - source png.h png.h shared-lib - version string int version - ------- ------ ----- ---------- - 0.89c ("beta 3") 0.89 89 1.0.89 - 0.90 ("beta 4") 0.90 90 0.90 - 0.95 ("beta 5") 0.95 95 0.95 - 0.96 ("beta 6") 0.96 96 0.96 - 0.97b ("beta 7") 1.00.97 97 1.0.1 - 0.97c 0.97 97 2.0.97 - 0.98 0.98 98 2.0.98 - 0.99 0.99 98 2.0.99 - 0.99a-m 0.99 99 2.0.99 - 1.00 1.00 100 2.1.0 - 1.0.0 1.0.0 100 2.1.0 - 1.0.0 (from here on, the 100 2.1.0 - 1.0.1 png.h string is 10001 2.1.0 - 1.0.1a-e identical to the 10002 from here on, the - 1.0.2 source version) 10002 shared library is 2.V - 1.0.2a-b 10003 where V is the source - 1.0.1 10001 code version except as - 1.0.1a-e 10002 2.1.0.1a-e noted. - 1.0.2 10002 2.1.0.2 - 1.0.2a-b 10003 2.1.0.2a-b - 1.0.3 10003 2.1.0.3 - 1.0.3a-d 10004 2.1.0.3a-d - 1.0.4 10004 2.1.0.4 - 1.0.4a-f 10005 2.1.0.4a-f - 1.0.5 (+ 2 patches) 10005 2.1.0.5 - 1.0.5a-d 10006 2.1.0.5a-d - 1.0.5e-r 10100 2.1.0.5e-r - 1.0.5s-v 10006 2.1.0.5s-v - 1.0.6 (+ 3 patches) 10006 2.1.0.6 - 1.0.6d-g 10007 2.1.0.6d-g - 1.0.6h 10007 10.6h - 1.0.6i 10007 10.6i - 1.0.6j 10007 2.1.0.6j - 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 - 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 - 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 - 1.0.7 1 10007 2.1.0.7 - 1.0.8beta1-4 1 10008 2.1.0.8beta1-4 - 1.0.8rc1 1 10008 2.1.0.8rc1 - 1.0.8 1 10008 2.1.0.8 - 1.0.9beta1-6 1 10009 2.1.0.9beta1-6 - 1.0.9rc1 1 10009 2.1.0.9rc1 - 1.0.9beta7-10 1 10009 2.1.0.9beta7-10 - 1.0.9rc2 1 10009 2.1.0.9rc2 - 1.0.9 1 10009 2.1.0.9 - 1.0.10beta1 1 10010 2.1.0.10beta1 - 1.0.10rc1 1 10010 2.1.0.10rc1 - 1.0.10 1 10010 2.1.0.10 - 1.0.11beta1-3 1 10011 2.1.0.11beta1-3 - 1.0.11rc1 1 10011 2.1.0.11rc1 - 1.0.11 1 10011 2.1.0.11 - 1.0.12beta1-2 2 10012 2.1.0.12beta1-2 - 1.0.12rc1 2 10012 2.1.0.12rc1 - 1.0.12 2 10012 2.1.0.12 - 1.1.0a-f - 10100 2.1.1.0a-f abandoned - 1.2.0beta1-2 2 10200 2.1.2.0beta1-2 - 1.2.0beta3-5 3 10200 3.1.2.0beta3-5 - 1.2.0rc1 3 10200 3.1.2.0rc1 - 1.2.0 3 10200 3.1.2.0 - 1.2.1beta-4 3 10201 3.1.2.1beta1-4 - 1.2.1rc1-2 3 10201 3.1.2.1rc1-2 - 1.2.1 3 10201 3.1.2.1 - 1.2.2beta1-6 12 10202 12.so.0.1.2.2beta1-6 - 1.0.13beta1 10 10013 10.so.0.1.0.13beta1 - 1.0.13rc1 10 10013 10.so.0.1.0.13rc1 - 1.2.2rc1 12 10202 12.so.0.1.2.2rc1 - 1.0.13 10 10013 10.so.0.1.0.13 - 1.2.2 12 10202 12.so.0.1.2.2 - 1.2.3rc1-6 12 10203 12.so.0.1.2.3rc1-6 - 1.2.3 12 10203 12.so.0.1.2.3 - 1.2.4beta1-3 13 10204 12.so.0.1.2.4beta1-3 - 1.2.4rc1 13 10204 12.so.0.1.2.4rc1 - 1.0.14 10 10014 10.so.0.1.0.14 - 1.2.4 13 10204 12.so.0.1.2.4 - 1.2.5beta1-2 13 10205 12.so.0.1.2.5beta1-2 - 1.0.15rc1 10 10015 10.so.0.1.0.15rc1 - 1.0.15 10 10015 10.so.0.1.0.15 - 1.2.5 13 10205 12.so.0.1.2.5 - 1.2.6beta1-4 13 10206 12.so.0.1.2.6beta1-4 - 1.2.6rc1-5 13 10206 12.so.0.1.2.6rc1-5 - 1.0.16 10 10016 10.so.0.1.0.16 - 1.2.6 13 10206 12.so.0.1.2.6 - 1.2.7beta1-2 13 10207 12.so.0.1.2.7beta1-2 - 1.0.17rc1 10 10017 10.so.0.1.0.17rc1 - 1.2.7rc1 13 10207 12.so.0.1.2.7rc1 - 1.0.17 10 10017 10.so.0.1.0.17 - 1.2.7 13 10207 12.so.0.1.2.7 - 1.2.8beta1-5 13 10208 12.so.0.1.2.8beta1-5 - 1.0.18rc1-5 10 10018 10.so.0.1.0.18rc1-5 - 1.2.8rc1-5 13 10208 12.so.0.1.2.8rc1-5 - 1.0.18 10 10018 10.so.0.1.0.18 - 1.2.8 13 10208 12.so.0.1.2.8 - 1.2.9beta1-3 13 10209 12.so.0.1.2.9beta1-3 - 1.2.9beta4-11 13 10209 12.so.0.9[.0] - 1.2.9rc1 13 10209 12.so.0.9[.0] - 1.2.9 13 10209 12.so.0.9[.0] - 1.2.10beta1-8 13 10210 12.so.0.10[.0] - 1.2.10rc1-3 13 10210 12.so.0.10[.0] - 1.2.10 13 10210 12.so.0.10[.0] - 1.2.11beta1-4 13 10211 12.so.0.11[.0] - 1.0.19rc1-5 10 10019 10.so.0.19[.0] - 1.2.11rc1-5 13 10211 12.so.0.11[.0] - 1.0.19 10 10019 10.so.0.19[.0] - 1.2.11 13 10211 12.so.0.11[.0] - 1.0.20 10 10020 10.so.0.20[.0] - 1.2.12 13 10212 12.so.0.12[.0] - 1.2.13beta1 13 10213 12.so.0.13[.0] - 1.0.21 10 10021 10.so.0.21[.0] - 1.2.13 13 10213 12.so.0.13[.0] - 1.2.14beta1-2 13 10214 12.so.0.14[.0] - 1.0.22rc1 10 10022 10.so.0.22[.0] - 1.2.14rc1 13 10214 12.so.0.14[.0] - 1.2.15beta1-6 13 10215 12.so.0.15[.0] - 1.0.23rc1-5 10 10023 10.so.0.23[.0] - 1.2.15rc1-5 13 10215 12.so.0.15[.0] - 1.0.23 10 10023 10.so.0.23[.0] - 1.2.15 13 10215 12.so.0.15[.0] - 1.2.16beta1-2 13 10216 12.so.0.16[.0] - 1.2.16rc1 13 10216 12.so.0.16[.0] - 1.0.24 10 10024 10.so.0.24[.0] - 1.2.16 13 10216 12.so.0.16[.0] - 1.2.17beta1-2 13 10217 12.so.0.17[.0] - 1.0.25rc1 10 10025 10.so.0.25[.0] - 1.2.17rc1-3 13 10217 12.so.0.17[.0] - 1.0.25 10 10025 10.so.0.25[.0] - 1.2.17 13 10217 12.so.0.17[.0] - 1.0.26 10 10026 10.so.0.26[.0] - 1.2.18 13 10218 12.so.0.18[.0] - 1.2.19beta1-31 13 10219 12.so.0.19[.0] - 1.0.27rc1-6 10 10027 10.so.0.27[.0] - 1.2.19rc1-6 13 10219 12.so.0.19[.0] - 1.0.27 10 10027 10.so.0.27[.0] - 1.2.19 13 10219 12.so.0.19[.0] - 1.2.20beta01-04 13 10220 12.so.0.20[.0] - 1.0.28rc1-6 10 10028 10.so.0.28[.0] - 1.2.20rc1-6 13 10220 12.so.0.20[.0] - 1.0.28 10 10028 10.so.0.28[.0] - 1.2.20 13 10220 12.so.0.20[.0] - 1.2.21beta1-2 13 10221 12.so.0.21[.0] - 1.2.21rc1-3 13 10221 12.so.0.21[.0] - 1.0.29 10 10029 10.so.0.29[.0] - 1.2.21 13 10221 12.so.0.21[.0] - 1.2.22beta1-4 13 10222 12.so.0.22[.0] - 1.0.30rc1 13 10030 10.so.0.30[.0] - 1.2.22rc1 13 10222 12.so.0.22[.0] - 1.0.30 10 10030 10.so.0.30[.0] - 1.2.22 13 10222 12.so.0.22[.0] - -Henceforth the source version will match the shared-library minor -and patch numbers; the shared-library major version number will be -used for changes in backward compatibility, as it is intended. The -PNG_PNGLIB_VER macro, which is not used within libpng but is available -for applications, is an unsigned integer of the form xyyzz corresponding -to the source version x.y.z (leading zeros in y and z). Beta versions -were given the previous public release number plus a letter, until -version 1.0.6j; from then on they were given the upcoming public -release number plus "betaNN" or "rcN". - -.SH "SEE ALSO" -.IR libpngpf(3) ", " png(5) -.LP -.IR libpng : -.IP -http://libpng.sourceforge.net (follow the [DOWNLOAD] link) -http://www.libpng.org/pub/png - -.LP -.IR zlib : -.IP -(generally) at the same location as -.I libpng -or at -.br -ftp://ftp.info-zip.org/pub/infozip/zlib - -.LP -.IR PNG specification: RFC 2083 -.IP -(generally) at the same location as -.I libpng -or at -.br -ftp://ds.internic.net/rfc/rfc2083.txt -.br -or (as a W3C Recommendation) at -.br -http://www.w3.org/TR/REC-png.html - -.LP -In the case of any inconsistency between the PNG specification -and this library, the specification takes precedence. - -.SH AUTHORS -This man page: Glenn Randers-Pehrson - - -The contributing authors would like to thank all those who helped -with testing, bug fixes, and patience. This wouldn't have been -possible without all of you. - -Thanks to Frank J. T. Wojcik for helping with the documentation. - -Libpng version 1.2.22 - October 13, 2007: -Initially created in 1995 by Guy Eric Schalnat, then of Group 42, Inc. -Currently maintained by Glenn Randers-Pehrson (glennrp at users.sourceforge.net). - -Supported by the PNG development group -.br -png-mng-implement at lists.sf.net -(subscription required; visit -png-mng-implement at lists.sourceforge.net (subscription required; visit -https://lists.sourceforge.net/lists/listinfo/png-mng-implement -to subscribe). - -.SH COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: - -(This copy of the libpng notices is provided for your convenience. In case of -any discrepancy between this copy and the notices in the file png.h that is -included in the libpng distribution, the latter shall prevail.) - -If you modify libpng you may insert additional notices immediately following -this sentence. - -libpng versions 1.2.6, August 15, 2004, through 1.2.22, October 13, 2007, are -Copyright (c) 2004,2006-2007 Glenn Randers-Pehrson, and are -distributed according to the same disclaimer and license as libpng-1.2.5 -with the following individual added to the list of Contributing Authors - - Cosmin Truta - -libpng versions 1.0.7, July 1, 2000, through 1.2.5 - October 3, 2002, are -Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are -distributed according to the same disclaimer and license as libpng-1.0.6 -with the following individuals added to the list of Contributing Authors - - Simon-Pierre Cadieux - Eric S. Raymond - Gilles Vollant - -and with the following additions to the disclaimer: - - There is no warranty against interference with your - enjoyment of the library or against infringement. - There is no warranty that our efforts or the library - will fulfill any of your particular purposes or needs. - This library is provided with all faults, and the entire - risk of satisfactory quality, performance, accuracy, and - effort is with the user. - -libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are -Copyright (c) 1998, 1999 Glenn Randers-Pehrson -Distributed according to the same disclaimer and license as libpng-0.96, -with the following individuals added to the list of Contributing Authors: - - Tom Lane - Glenn Randers-Pehrson - Willem van Schaik - -libpng versions 0.89, June 1996, through 0.96, May 1997, are -Copyright (c) 1996, 1997 Andreas Dilger -Distributed according to the same disclaimer and license as libpng-0.88, -with the following individuals added to the list of Contributing Authors: - - John Bowler - Kevin Bracey - Sam Bushell - Magnus Holmgren - Greg Roelofs - Tom Tanner - -libpng versions 0.5, May 1995, through 0.88, January 1996, are -Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. - -For the purposes of this copyright and license, "Contributing Authors" -is defined as the following set of individuals: - - Andreas Dilger - Dave Martindale - Guy Eric Schalnat - Paul Schmidt - Tim Wegner - -The PNG Reference Library is supplied "AS IS". The Contributing Authors -and Group 42, Inc. disclaim all warranties, expressed or implied, -including, without limitation, the warranties of merchantability and of -fitness for any purpose. The Contributing Authors and Group 42, Inc. -assume no liability for direct, indirect, incidental, special, exemplary, -or consequential damages, which may result from the use of the PNG -Reference Library, even if advised of the possibility of such damage. - -Permission is hereby granted to use, copy, modify, and distribute this -source code, or portions hereof, for any purpose, without fee, subject -to the following restrictions: - -1. The origin of this source code must not be misrepresented. - -2. Altered versions must be plainly marked as such and - must not be misrepresented as being the original source. - -3. This Copyright notice may not be removed or altered from - any source or altered source distribution. - -The Contributing Authors and Group 42, Inc. specifically permit, without -fee, and encourage the use of this source code as a component to -supporting the PNG file format in commercial products. If you use this -source code in a product, acknowledgment is not required but would be -appreciated. - - -A "png_get_copyright" function is available, for convenient use in "about" -boxes and the like: - - printf("%s",png_get_copyright(NULL)); - -Also, the PNG logo (in PNG format, of course) is supplied in the -files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31). - -Libpng is OSI Certified Open Source Software. OSI Certified Open Source is a -certification mark of the Open Source Initiative. - -Glenn Randers-Pehrson -glennrp at users.sourceforge.net -October 13, 2007 - -.\" end of man page diff --git a/uppdev/plugin/png/lib/libpngpf.3 b/uppdev/plugin/png/lib/libpngpf.3 deleted file mode 100644 index 8704f232a..000000000 --- a/uppdev/plugin/png/lib/libpngpf.3 +++ /dev/null @@ -1,274 +0,0 @@ -.TH LIBPNGPF 3 "October 13, 2007" -.SH NAME -libpng \- Portable Network Graphics (PNG) Reference Library 1.2.22 -(private functions) -.SH SYNOPSIS -\fB#include \fP - -\fBvoid png_build_gamma_table (png_structp \fIpng_ptr\fP\fB);\fP - -\fBvoid png_build_grayscale_palette (int \fP\fIbit_depth\fP\fB, png_colorp \fIpalette\fP\fB);\fP - -\fBvoid png_calculate_crc (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIptr\fP\fB, png_size_t \fIlength\fP\fB);\fP - -\fBvoid png_check_chunk_name (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fIchunk_name\fP\fB);\fP - -\fBpng_size_t png_check_keyword (png_structp \fP\fIpng_ptr\fP\fB, png_charp \fP\fIkey\fP\fB, png_charpp \fInew_key\fP\fB);\fP - -\fBvoid png_combine_row (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIrow\fP\fB, int \fImask\fP\fB);\fP - -\fBvoid png_correct_palette (png_structp \fP\fIpng_ptr\fP\fB, png_colorp \fP\fIpalette\fP\fB, int \fInum_palette\fP\fB);\fP - -\fBint png_crc_error (png_structp \fIpng_ptr\fP\fB);\fP - -\fBint png_crc_finish (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIskip\fP\fB);\fP - -\fBvoid png_crc_read (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIbuf\fP\fB, png_size_t \fIlength\fP\fB);\fP - -\fBpng_voidp png_create_struct (int \fItype\fP\fB);\fP - -\fBpng_voidp png_create_struct_2 (int \fP\fItype\fP\fB, png_malloc_ptr \fP\fImalloc_fn\fP\fB, png_voidp \fImem_ptr\fP\fB);\fP - -\fBpng_charp png_decompress_chunk (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIcomp_type\fP\fB, png_charp \fP\fIchunkdata\fP\fB, png_size_t \fP\fIchunklength\fP\fB, png_size_t \fP\fIprefix_length\fP\fB, png_size_t \fI*data_length\fP\fB);\fP - -\fBvoid png_destroy_struct (png_voidp \fIstruct_ptr\fP\fB);\fP - -\fBvoid png_destroy_struct_2 (png_voidp \fP\fIstruct_ptr\fP\fB, png_free_ptr \fP\fIfree_fn\fP\fB, png_voidp \fImem_ptr\fP\fB);\fP - -\fBvoid png_do_background (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_color_16p \fP\fItrans_values\fP\fB, png_color_16p \fP\fIbackground\fP\fB, png_color_16p \fP\fIbackground_1\fP\fB, png_bytep \fP\fIgamma_table\fP\fB, png_bytep \fP\fIgamma_from_1\fP\fB, png_bytep \fP\fIgamma_to_1\fP\fB, png_uint_16pp \fP\fIgamma_16\fP\fB, png_uint_16pp \fP\fIgamma_16_from_1\fP\fB, png_uint_16pp \fP\fIgamma_16_to_1\fP\fB, int \fIgamma_shift\fP\fB);\fP - -\fBvoid png_do_bgr (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP - -\fBvoid png_do_chop (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP - -\fBvoid png_do_dither (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_bytep \fP\fIpalette_lookup\fP\fB, png_bytep \fIdither_lookup\fP\fB);\fP - -\fBvoid png_do_expand (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_color_16p \fItrans_value\fP\fB);\fP - -\fBvoid png_do_expand_palette (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_colorp \fP\fIpalette\fP\fB, png_bytep \fP\fItrans\fP\fB, int \fInum_trans\fP\fB);\fP - -\fBvoid png_do_gamma (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_bytep \fP\fIgamma_table\fP\fB, png_uint_16pp \fP\fIgamma_16_table\fP\fB, int \fIgamma_shift\fP\fB);\fP - -\fBvoid png_do_gray_to_rgb (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP - -\fBvoid png_do_invert (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP - -\fBvoid png_do_pack (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_uint_32 \fIbit_depth\fP\fB);\fP - -\fBvoid png_do_packswap (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP - -\fBvoid png_do_read_filler (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_uint_32 \fP\fIfiller\fP\fB, png_uint_32 \fIflags\fP\fB);\fP - -\fBvoid png_do_read_interlace (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, int \fP\fIpass\fP\fB, png_uint_32 \fItransformations\fP\fB);\fP - -\fBvoid png_do_read_invert_alpha (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP - -\fBvoid png_do_read_swap_alpha (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP - -\fBvoid png_do_read_transformations (png_structp \fIpng_ptr\fP\fB);\fP - -\fBint png_do_rgb_to_gray (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP - -\fBvoid png_do_shift (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_color_8p \fIbit_depth\fP\fB);\fP - -\fBvoid png_do_strip_filler (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_uint_32 \fIflags\fP\fB);\fP - -\fBvoid png_do_swap (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP - -\fBvoid png_do_unpack (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP - -\fBvoid png_do_unshift (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_color_8p \fIsig_bits\fP\fB);\fP - -\fBvoid png_do_write_interlace (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, int \fIpass\fP\fB);\fP - -\fBvoid png_do_write_invert_alpha (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP - -\fBvoid png_do_write_swap_alpha (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP - -\fBvoid png_do_write_transformations (png_structp \fIpng_ptr\fP\fB);\fP - -\fBvoid *png_far_to_near (png_structp png_ptr,png_voidp \fP\fIptr\fP\fB, int \fIcheck\fP\fB);\fP - -\fBvoid png_flush (png_structp \fIpng_ptr\fP\fB);\fP - -\fBvoid png_handle_bKGD (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP - -\fBvoid png_handle_cHRM (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP - -\fBvoid png_handle_gAMA (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP - -\fBvoid png_handle_hIST (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP - -\fBvoid png_handle_IEND (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP - -\fBvoid png_handle_IHDR (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP - -\fBvoid png_handle_iCCP (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP - -\fBvoid png_handle_iTXt (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP - -\fBvoid png_handle_oFFs (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP - -\fBvoid png_handle_pCAL (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP - -\fBvoid png_handle_pHYs (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP - -\fBvoid png_handle_PLTE (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP - -\fBvoid png_handle_sBIT (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP - -\fBvoid png_handle_sCAL (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP - -\fBvoid png_handle_sPLT (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP - -\fBvoid png_handle_sRGB (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP - -\fBvoid png_handle_tEXt (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP - -\fBvoid png_handle_tIME (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP - -\fBvoid png_handle_tRNS (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP - -\fBvoid png_handle_unknown (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP - -\fBvoid png_handle_zTXt (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP - -\fBvoid png_info_destroy (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP - -\fBvoid png_init_mmx_flags (png_structp \fIpng_ptr\fP\fB);\fP - -\fBvoid png_init_read_transformations (png_structp \fIpng_ptr\fP\fB);\fP - -\fBvoid png_process_IDAT_data (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIbuffer\fP\fB, png_size_t \fIbuffer_length\fP\fB);\fP - -\fBvoid png_process_some_data (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP - -\fBvoid png_push_check_crc (png_structp \fIpng_ptr\fP\fB);\fP - -\fBvoid png_push_crc_finish (png_structp \fIpng_ptr\fP\fB);\fP - -\fBvoid png_push_crc_skip (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP - -\fBvoid png_push_fill_buffer (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIbuffer\fP\fB, png_size_t \fIlength\fP\fB);\fP - -\fBvoid png_push_handle_tEXt (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP - -\fBvoid png_push_handle_unknown (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP - -\fBvoid png_push_handle_zTXt (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP - -\fBvoid png_push_have_end (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP - -\fBvoid png_push_have_info (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP - -\fBvoid png_push_have_row (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fIrow\fP\fB);\fP - -\fBvoid png_push_process_row (png_structp \fIpng_ptr\fP\fB);\fP - -\fBvoid png_push_read_chunk (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP - -\fBvoid png_push_read_end (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP - -\fBvoid png_push_read_IDAT (png_structp \fIpng_ptr\fP\fB);\fP - -\fBvoid png_push_read_sig (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP - -\fBvoid png_push_read_tEXt (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP - -\fBvoid png_push_read_zTXt (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP - -\fBvoid png_push_restore_buffer (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIbuffer\fP\fB, png_size_t \fIbuffer_length\fP\fB);\fP - -\fBvoid png_push_save_buffer (png_structp \fIpng_ptr\fP\fB);\fP - -\fBvoid png_read_data (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIdata\fP\fB, png_size_t \fIlength\fP\fB);\fP - -\fBvoid png_read_filter_row (png_structp \fP\fIpng_ptr\fP\fB, png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_bytep \fP\fIprev_row\fP\fB, int \fIfilter\fP\fB);\fP - -\fBvoid png_read_finish_row (png_structp \fIpng_ptr\fP\fB);\fP - -\fBvoid png_read_push_finish_row (png_structp \fIpng_ptr\fP\fB);\fP - -\fBvoid png_read_start_row (png_structp \fIpng_ptr\fP\fB);\fP - -\fBvoid png_read_transform_info (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP - -\fBvoid png_reset_crc (png_structp \fIpng_ptr\fP\fB);\fP - -\fBint png_set_text_2 (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_textp \fP\fItext_ptr\fP\fB, int \fInum_text\fP\fB);\fP - -\fBvoid png_write_cHRM (png_structp \fP\fIpng_ptr\fP\fB, double \fP\fIwhite_x\fP\fB, double \fP\fIwhite_y\fP\fB, double \fP\fIred_x\fP\fB, double \fP\fIred_y\fP\fB, double \fP\fIgreen_x\fP\fB, double \fP\fIgreen_y\fP\fB, double \fP\fIblue_x\fP\fB, double \fIblue_y\fP\fB);\fP - -\fBvoid png_write_cHRM_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIwhite_x\fP\fB, png_uint_32 \fP\fIwhite_y\fP\fB, png_uint_32 \fP\fIred_x\fP\fB, png_uint_32 \fP\fIred_y\fP\fB, png_uint_32 \fP\fIgreen_x\fP\fB, png_uint_32 \fP\fIgreen_y\fP\fB, png_uint_32 \fP\fIblue_x\fP\fB, png_uint_32 \fIblue_y\fP\fB);\fP - -\fBvoid png_write_data (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIdata\fP\fB, png_size_t \fIlength\fP\fB);\fP - -\fBvoid png_write_filtered_row (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fIfiltered_row\fP\fB);\fP - -\fBvoid png_write_find_filter (png_structp \fP\fIpng_ptr\fP\fB, png_row_infop \fIrow_info\fP\fB);\fP - -\fBvoid png_write_finish_row (png_structp \fIpng_ptr\fP\fB);\fP - -\fBvoid png_write_gAMA (png_structp \fP\fIpng_ptr\fP\fB, double \fIfile_gamma\fP\fB);\fP - -\fBvoid png_write_gAMA_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIint_file_gamma\fP\fB);\fP - -\fBvoid png_write_hIST (png_structp \fP\fIpng_ptr\fP\fB, png_uint_16p \fP\fIhist\fP\fB, int \fInum_hist\fP\fB);\fP - -\fBvoid png_write_iCCP (png_structp \fP\fIpng_ptr\fP\fB, png_charp \fP\fIname\fP\fB, int \fP\fIcompression_type\fP\fB, png_charp \fP\fIprofile\fP\fB, int \fIproflen\fP\fB);\fP - -\fBvoid png_write_IDAT (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIdata\fP\fB, png_size_t \fIlength\fP\fB);\fP - -\fBvoid png_write_IEND (png_structp \fIpng_ptr\fP\fB);\fP - -\fBvoid png_write_IHDR (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIwidth\fP\fB, png_uint_32 \fP\fIheight\fP\fB, int \fP\fIbit_depth\fP\fB, int \fP\fIcolor_type\fP\fB, int \fP\fIcompression_type\fP\fB, int \fP\fIfilter_type\fP\fB, int \fIinterlace_type\fP\fB);\fP - -\fBvoid png_write_iTXt (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIcompression\fP\fB, png_charp \fP\fIkey\fP\fB, png_charp \fP\fIlang\fP\fB, png_charp \fP\fItranslated_key\fP\fB, png_charp \fItext\fP\fB);\fP - -\fBvoid png_write_oFFs (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIx_offset\fP\fB, png_uint_32 \fP\fIy_offset\fP\fB, int \fIunit_type\fP\fB);\fP - -\fBvoid png_write_pCAL (png_structp \fP\fIpng_ptr\fP\fB, png_charp \fP\fIpurpose\fP\fB, png_int_32 \fP\fIX0\fP\fB, png_int_32 \fP\fIX1\fP\fB, int \fP\fItype\fP\fB, int \fP\fInparams\fP\fB, png_charp \fP\fIunits\fP\fB, png_charpp \fIparams\fP\fB);\fP - -\fBvoid png_write_pHYs (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIx_pixels_per_unit\fP\fB, png_uint_32 \fP\fIy_pixels_per_unit\fP\fB, int \fIunit_type\fP\fB);\fP - -\fBvoid png_write_PLTE (png_structp \fP\fIpng_ptr\fP\fB, png_colorp \fP\fIpalette\fP\fB, png_uint_32 \fInum_pal\fP\fB);\fP - -\fBvoid png_write_sBIT (png_structp \fP\fIpng_ptr\fP\fB, png_color_8p \fP\fIsbit\fP\fB, int \fIcolor_type\fP\fB);\fP - -\fBvoid png_write_sCAL (png_structp \fP\fIpng_ptr\fP\fB, png_charp \fP\fIunit\fP\fB, double \fP\fIwidth\fP\fB, double \fIheight\fP\fB);\fP - -\fBvoid png_write_sCAL_s (png_structp \fP\fIpng_ptr\fP\fB, png_charp \fP\fIunit\fP\fB, png_charp \fP\fIwidth\fP\fB, png_charp \fIheight\fP\fB);\fP - -\fBvoid png_write_sig (png_structp \fIpng_ptr\fP\fB);\fP - -\fBvoid png_write_sRGB (png_structp \fP\fIpng_ptr\fP\fB, int \fIintent\fP\fB);\fP - -\fBvoid png_write_sPLT (png_structp \fP\fIpng_ptr\fP\fB, png_spalette_p \fIpalette\fP\fB);\fP - -\fBvoid png_write_start_row (png_structp \fIpng_ptr\fP\fB);\fP - -\fBvoid png_write_tEXt (png_structp \fP\fIpng_ptr\fP\fB, png_charp \fP\fIkey\fP\fB, png_charp \fP\fItext\fP\fB, png_size_t \fItext_len\fP\fB);\fP - -\fBvoid png_write_tIME (png_structp \fP\fIpng_ptr\fP\fB, png_timep \fImod_time\fP\fB);\fP - -\fBvoid png_write_tRNS (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fItrans\fP\fB, png_color_16p \fP\fIvalues\fP\fB, int \fP\fInumber\fP\fB, int \fIcolor_type\fP\fB);\fP - -\fBvoid png_write_zTXt (png_structp \fP\fIpng_ptr\fP\fB, png_charp \fP\fIkey\fP\fB, png_charp \fP\fItext\fP\fB, png_size_t \fP\fItext_len\fP\fB, int \fIcompression\fP\fB);\fP - -\fBvoidpf png_zalloc (voidpf \fP\fIpng_ptr\fP\fB, uInt \fP\fIitems\fP\fB, uInt \fIsize\fP\fB);\fP - -\fBvoid png_zfree (voidpf \fP\fIpng_ptr\fP\fB, voidpf \fIptr\fP\fB);\fP - -\fI\fB - -.SH DESCRIPTION -The functions listed above are used privately by libpng -and are not recommended for use by applications. They are -not "exported" to applications using shared libraries. They -are listed alphabetically here as an aid to libpng maintainers. -See png.h for more information on these functions. - -.SH SEE ALSO -.IR libpng(3) ", " png(5) -.SH AUTHOR -Glenn Randers-Pehrson diff --git a/uppdev/plugin/png/lib/png.5 b/uppdev/plugin/png/lib/png.5 deleted file mode 100644 index e0294bc45..000000000 --- a/uppdev/plugin/png/lib/png.5 +++ /dev/null @@ -1,73 +0,0 @@ -.TH PNG 5 "October 13, 2007" -.SH NAME -png \- Portable Network Graphics (PNG) format -.SH DESCRIPTION -PNG (Portable Network Graphics) is an extensible file format for the -lossless, portable, well-compressed storage of raster images. PNG provides -a patent-free replacement for GIF and can also replace many -common uses of TIFF. Indexed-color, grayscale, and truecolor images are -supported, plus an optional alpha channel. Sample depths range from -1 to 16 bits. -.br - -PNG is designed to work well in online viewing applications, such as the -World Wide Web, so it is fully streamable with a progressive display -option. PNG is robust, providing both full file integrity checking and -fast, simple detection of common transmission errors. Also, PNG can store -gamma and chromaticity data for improved color matching on heterogeneous -platforms. - -.SH "SEE ALSO" -.IR libpng(3) ", " zlib(3) ", " deflate(5) ", and " zlib(5) -.LP -PNG specification (second edition), November 2003: -.IP -.br - 8) - png_error(png_ptr, "Too many bytes for PNG signature."); - - png_ptr->sig_bytes = (png_byte)(num_bytes < 0 ? 0 : num_bytes); -} - -/* Checks whether the supplied bytes match the PNG signature. We allow - * checking less than the full 8-byte signature so that those apps that - * already read the first few bytes of a file to determine the file type - * can simply check the remaining bytes for extra assurance. Returns - * an integer less than, equal to, or greater than zero if sig is found, - * respectively, to be less than, to match, or be greater than the correct - * PNG signature (this is the same behaviour as strcmp, memcmp, etc). - */ -int PNGAPI -png_sig_cmp(png_bytep sig, png_size_t start, png_size_t num_to_check) -{ - png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; - if (num_to_check > 8) - num_to_check = 8; - else if (num_to_check < 1) - return (-1); - - if (start > 7) - return (-1); - - if (start + num_to_check > 8) - num_to_check = 8 - start; - - return ((int)(png_memcmp(&sig[start], &png_signature[start], num_to_check))); -} - -#if defined(PNG_1_0_X) || defined(PNG_1_2_X) -/* (Obsolete) function to check signature bytes. It does not allow one - * to check a partial signature. This function might be removed in the - * future - use png_sig_cmp(). Returns true (nonzero) if the file is PNG. - */ -int PNGAPI -png_check_sig(png_bytep sig, int num) -{ - return ((int)!png_sig_cmp(sig, (png_size_t)0, (png_size_t)num)); -} -#endif -#endif /* PNG_READ_SUPPORTED */ - -#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) -/* Function to allocate memory for zlib and clear it to 0. */ -#ifdef PNG_1_0_X -voidpf PNGAPI -#else -voidpf /* private */ -#endif -png_zalloc(voidpf png_ptr, uInt items, uInt size) -{ - png_voidp ptr; - png_structp p=(png_structp)png_ptr; - png_uint_32 save_flags=p->flags; - png_uint_32 num_bytes; - - if(png_ptr == NULL) return (NULL); - if (items > PNG_UINT_32_MAX/size) - { - png_warning (p, "Potential overflow in png_zalloc()"); - return (NULL); - } - num_bytes = (png_uint_32)items * size; - - p->flags|=PNG_FLAG_MALLOC_NULL_MEM_OK; - ptr = (png_voidp)png_malloc((png_structp)png_ptr, num_bytes); - p->flags=save_flags; - -#if defined(PNG_1_0_X) && !defined(PNG_NO_ZALLOC_ZERO) - if (ptr == NULL) - return ((voidpf)ptr); - - if (num_bytes > (png_uint_32)0x8000L) - { - png_memset(ptr, 0, (png_size_t)0x8000L); - png_memset((png_bytep)ptr + (png_size_t)0x8000L, 0, - (png_size_t)(num_bytes - (png_uint_32)0x8000L)); - } - else - { - png_memset(ptr, 0, (png_size_t)num_bytes); - } -#endif - return ((voidpf)ptr); -} - -/* function to free memory for zlib */ -#ifdef PNG_1_0_X -void PNGAPI -#else -void /* private */ -#endif -png_zfree(voidpf png_ptr, voidpf ptr) -{ - png_free((png_structp)png_ptr, (png_voidp)ptr); -} - -/* Reset the CRC variable to 32 bits of 1's. Care must be taken - * in case CRC is > 32 bits to leave the top bits 0. - */ -void /* PRIVATE */ -png_reset_crc(png_structp png_ptr) -{ - png_ptr->crc = crc32(0, Z_NULL, 0); -} - -/* Calculate the CRC over a section of data. We can only pass as - * much data to this routine as the largest single buffer size. We - * also check that this data will actually be used before going to the - * trouble of calculating it. - */ -void /* PRIVATE */ -png_calculate_crc(png_structp png_ptr, png_bytep ptr, png_size_t length) -{ - int need_crc = 1; - - if (png_ptr->chunk_name[0] & 0x20) /* ancillary */ - { - if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) == - (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) - need_crc = 0; - } - else /* critical */ - { - if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) - need_crc = 0; - } - - if (need_crc) - png_ptr->crc = crc32(png_ptr->crc, ptr, (uInt)length); -} - -/* Allocate the memory for an info_struct for the application. We don't - * really need the png_ptr, but it could potentially be useful in the - * future. This should be used in favour of malloc(png_sizeof(png_info)) - * and png_info_init() so that applications that want to use a shared - * libpng don't have to be recompiled if png_info changes size. - */ -png_infop PNGAPI -png_create_info_struct(png_structp png_ptr) -{ - png_infop info_ptr; - - png_debug(1, "in png_create_info_struct\n"); - if(png_ptr == NULL) return (NULL); -#ifdef PNG_USER_MEM_SUPPORTED - info_ptr = (png_infop)png_create_struct_2(PNG_STRUCT_INFO, - png_ptr->malloc_fn, png_ptr->mem_ptr); -#else - info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO); -#endif - if (info_ptr != NULL) - png_info_init_3(&info_ptr, png_sizeof(png_info)); - - return (info_ptr); -} - -/* This function frees the memory associated with a single info struct. - * Normally, one would use either png_destroy_read_struct() or - * png_destroy_write_struct() to free an info struct, but this may be - * useful for some applications. - */ -void PNGAPI -png_destroy_info_struct(png_structp png_ptr, png_infopp info_ptr_ptr) -{ - png_infop info_ptr = NULL; - if(png_ptr == NULL) return; - - png_debug(1, "in png_destroy_info_struct\n"); - if (info_ptr_ptr != NULL) - info_ptr = *info_ptr_ptr; - - if (info_ptr != NULL) - { - png_info_destroy(png_ptr, info_ptr); - -#ifdef PNG_USER_MEM_SUPPORTED - png_destroy_struct_2((png_voidp)info_ptr, png_ptr->free_fn, - png_ptr->mem_ptr); -#else - png_destroy_struct((png_voidp)info_ptr); -#endif - *info_ptr_ptr = NULL; - } -} - -/* Initialize the info structure. This is now an internal function (0.89) - * and applications using it are urged to use png_create_info_struct() - * instead. - */ -#if defined(PNG_1_0_X) || defined(PNG_1_2_X) -#undef png_info_init -void PNGAPI -png_info_init(png_infop info_ptr) -{ - /* We only come here via pre-1.0.12-compiled applications */ - png_info_init_3(&info_ptr, 0); -} -#endif - -void PNGAPI -png_info_init_3(png_infopp ptr_ptr, png_size_t png_info_struct_size) -{ - png_infop info_ptr = *ptr_ptr; - - if(info_ptr == NULL) return; - - png_debug(1, "in png_info_init_3\n"); - - if(png_sizeof(png_info) > png_info_struct_size) - { - png_destroy_struct(info_ptr); - info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO); - *ptr_ptr = info_ptr; - } - - /* set everything to 0 */ - png_memset(info_ptr, 0, png_sizeof (png_info)); -} - -#ifdef PNG_FREE_ME_SUPPORTED -void PNGAPI -png_data_freer(png_structp png_ptr, png_infop info_ptr, - int freer, png_uint_32 mask) -{ - png_debug(1, "in png_data_freer\n"); - if (png_ptr == NULL || info_ptr == NULL) - return; - if(freer == PNG_DESTROY_WILL_FREE_DATA) - info_ptr->free_me |= mask; - else if(freer == PNG_USER_WILL_FREE_DATA) - info_ptr->free_me &= ~mask; - else - png_warning(png_ptr, - "Unknown freer parameter in png_data_freer."); -} -#endif - -void PNGAPI -png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask, - int num) -{ - png_debug(1, "in png_free_data\n"); - if (png_ptr == NULL || info_ptr == NULL) - return; - -#if defined(PNG_TEXT_SUPPORTED) -/* free text item num or (if num == -1) all text items */ -#ifdef PNG_FREE_ME_SUPPORTED -if ((mask & PNG_FREE_TEXT) & info_ptr->free_me) -#else -if (mask & PNG_FREE_TEXT) -#endif -{ - if (num != -1) - { - if (info_ptr->text && info_ptr->text[num].key) - { - png_free(png_ptr, info_ptr->text[num].key); - info_ptr->text[num].key = NULL; - } - } - else - { - int i; - for (i = 0; i < info_ptr->num_text; i++) - png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, i); - png_free(png_ptr, info_ptr->text); - info_ptr->text = NULL; - info_ptr->num_text=0; - } -} -#endif - -#if defined(PNG_tRNS_SUPPORTED) -/* free any tRNS entry */ -#ifdef PNG_FREE_ME_SUPPORTED -if ((mask & PNG_FREE_TRNS) & info_ptr->free_me) -#else -if ((mask & PNG_FREE_TRNS) && (png_ptr->flags & PNG_FLAG_FREE_TRNS)) -#endif -{ - png_free(png_ptr, info_ptr->trans); - info_ptr->valid &= ~PNG_INFO_tRNS; -#ifndef PNG_FREE_ME_SUPPORTED - png_ptr->flags &= ~PNG_FLAG_FREE_TRNS; -#endif - info_ptr->trans = NULL; -} -#endif - -#if defined(PNG_sCAL_SUPPORTED) -/* free any sCAL entry */ -#ifdef PNG_FREE_ME_SUPPORTED -if ((mask & PNG_FREE_SCAL) & info_ptr->free_me) -#else -if (mask & PNG_FREE_SCAL) -#endif -{ -#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED) - png_free(png_ptr, info_ptr->scal_s_width); - png_free(png_ptr, info_ptr->scal_s_height); - info_ptr->scal_s_width = NULL; - info_ptr->scal_s_height = NULL; -#endif - info_ptr->valid &= ~PNG_INFO_sCAL; -} -#endif - -#if defined(PNG_pCAL_SUPPORTED) -/* free any pCAL entry */ -#ifdef PNG_FREE_ME_SUPPORTED -if ((mask & PNG_FREE_PCAL) & info_ptr->free_me) -#else -if (mask & PNG_FREE_PCAL) -#endif -{ - png_free(png_ptr, info_ptr->pcal_purpose); - png_free(png_ptr, info_ptr->pcal_units); - info_ptr->pcal_purpose = NULL; - info_ptr->pcal_units = NULL; - if (info_ptr->pcal_params != NULL) - { - int i; - for (i = 0; i < (int)info_ptr->pcal_nparams; i++) - { - png_free(png_ptr, info_ptr->pcal_params[i]); - info_ptr->pcal_params[i]=NULL; - } - png_free(png_ptr, info_ptr->pcal_params); - info_ptr->pcal_params = NULL; - } - info_ptr->valid &= ~PNG_INFO_pCAL; -} -#endif - -#if defined(PNG_iCCP_SUPPORTED) -/* free any iCCP entry */ -#ifdef PNG_FREE_ME_SUPPORTED -if ((mask & PNG_FREE_ICCP) & info_ptr->free_me) -#else -if (mask & PNG_FREE_ICCP) -#endif -{ - png_free(png_ptr, info_ptr->iccp_name); - png_free(png_ptr, info_ptr->iccp_profile); - info_ptr->iccp_name = NULL; - info_ptr->iccp_profile = NULL; - info_ptr->valid &= ~PNG_INFO_iCCP; -} -#endif - -#if defined(PNG_sPLT_SUPPORTED) -/* free a given sPLT entry, or (if num == -1) all sPLT entries */ -#ifdef PNG_FREE_ME_SUPPORTED -if ((mask & PNG_FREE_SPLT) & info_ptr->free_me) -#else -if (mask & PNG_FREE_SPLT) -#endif -{ - if (num != -1) - { - if(info_ptr->splt_palettes) - { - png_free(png_ptr, info_ptr->splt_palettes[num].name); - png_free(png_ptr, info_ptr->splt_palettes[num].entries); - info_ptr->splt_palettes[num].name = NULL; - info_ptr->splt_palettes[num].entries = NULL; - } - } - else - { - if(info_ptr->splt_palettes_num) - { - int i; - for (i = 0; i < (int)info_ptr->splt_palettes_num; i++) - png_free_data(png_ptr, info_ptr, PNG_FREE_SPLT, i); - - png_free(png_ptr, info_ptr->splt_palettes); - info_ptr->splt_palettes = NULL; - info_ptr->splt_palettes_num = 0; - } - info_ptr->valid &= ~PNG_INFO_sPLT; - } -} -#endif - -#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) - if(png_ptr->unknown_chunk.data) - { - png_free(png_ptr, png_ptr->unknown_chunk.data); - png_ptr->unknown_chunk.data = NULL; - } -#ifdef PNG_FREE_ME_SUPPORTED -if ((mask & PNG_FREE_UNKN) & info_ptr->free_me) -#else -if (mask & PNG_FREE_UNKN) -#endif -{ - if (num != -1) - { - if(info_ptr->unknown_chunks) - { - png_free(png_ptr, info_ptr->unknown_chunks[num].data); - info_ptr->unknown_chunks[num].data = NULL; - } - } - else - { - int i; - - if(info_ptr->unknown_chunks_num) - { - for (i = 0; i < (int)info_ptr->unknown_chunks_num; i++) - png_free_data(png_ptr, info_ptr, PNG_FREE_UNKN, i); - - png_free(png_ptr, info_ptr->unknown_chunks); - info_ptr->unknown_chunks = NULL; - info_ptr->unknown_chunks_num = 0; - } - } -} -#endif - -#if defined(PNG_hIST_SUPPORTED) -/* free any hIST entry */ -#ifdef PNG_FREE_ME_SUPPORTED -if ((mask & PNG_FREE_HIST) & info_ptr->free_me) -#else -if ((mask & PNG_FREE_HIST) && (png_ptr->flags & PNG_FLAG_FREE_HIST)) -#endif -{ - png_free(png_ptr, info_ptr->hist); - info_ptr->hist = NULL; - info_ptr->valid &= ~PNG_INFO_hIST; -#ifndef PNG_FREE_ME_SUPPORTED - png_ptr->flags &= ~PNG_FLAG_FREE_HIST; -#endif -} -#endif - -/* free any PLTE entry that was internally allocated */ -#ifdef PNG_FREE_ME_SUPPORTED -if ((mask & PNG_FREE_PLTE) & info_ptr->free_me) -#else -if ((mask & PNG_FREE_PLTE) && (png_ptr->flags & PNG_FLAG_FREE_PLTE)) -#endif -{ - png_zfree(png_ptr, info_ptr->palette); - info_ptr->palette = NULL; - info_ptr->valid &= ~PNG_INFO_PLTE; -#ifndef PNG_FREE_ME_SUPPORTED - png_ptr->flags &= ~PNG_FLAG_FREE_PLTE; -#endif - info_ptr->num_palette = 0; -} - -#if defined(PNG_INFO_IMAGE_SUPPORTED) -/* free any image bits attached to the info structure */ -#ifdef PNG_FREE_ME_SUPPORTED -if ((mask & PNG_FREE_ROWS) & info_ptr->free_me) -#else -if (mask & PNG_FREE_ROWS) -#endif -{ - if(info_ptr->row_pointers) - { - int row; - for (row = 0; row < (int)info_ptr->height; row++) - { - png_free(png_ptr, info_ptr->row_pointers[row]); - info_ptr->row_pointers[row]=NULL; - } - png_free(png_ptr, info_ptr->row_pointers); - info_ptr->row_pointers=NULL; - } - info_ptr->valid &= ~PNG_INFO_IDAT; -} -#endif - -#ifdef PNG_FREE_ME_SUPPORTED - if(num == -1) - info_ptr->free_me &= ~mask; - else - info_ptr->free_me &= ~(mask & ~PNG_FREE_MUL); -#endif -} - -/* This is an internal routine to free any memory that the info struct is - * pointing to before re-using it or freeing the struct itself. Recall - * that png_free() checks for NULL pointers for us. - */ -void /* PRIVATE */ -png_info_destroy(png_structp png_ptr, png_infop info_ptr) -{ - png_debug(1, "in png_info_destroy\n"); - - png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); - -#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) - if (png_ptr->num_chunk_list) - { - png_free(png_ptr, png_ptr->chunk_list); - png_ptr->chunk_list=NULL; - png_ptr->num_chunk_list=0; - } -#endif - - png_info_init_3(&info_ptr, png_sizeof(png_info)); -} -#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ - -/* This function returns a pointer to the io_ptr associated with the user - * functions. The application should free any memory associated with this - * pointer before png_write_destroy() or png_read_destroy() are called. - */ -png_voidp PNGAPI -png_get_io_ptr(png_structp png_ptr) -{ - if(png_ptr == NULL) return (NULL); - return (png_ptr->io_ptr); -} - -#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) -#if !defined(PNG_NO_STDIO) -/* Initialize the default input/output functions for the PNG file. If you - * use your own read or write routines, you can call either png_set_read_fn() - * or png_set_write_fn() instead of png_init_io(). If you have defined - * PNG_NO_STDIO, you must use a function of your own because "FILE *" isn't - * necessarily available. - */ -void PNGAPI -png_init_io(png_structp png_ptr, png_FILE_p fp) -{ - png_debug(1, "in png_init_io\n"); - if(png_ptr == NULL) return; - png_ptr->io_ptr = (png_voidp)fp; -} -#endif - -#if defined(PNG_TIME_RFC1123_SUPPORTED) -/* Convert the supplied time into an RFC 1123 string suitable for use in - * a "Creation Time" or other text-based time string. - */ -png_charp PNGAPI -png_convert_to_rfc1123(png_structp png_ptr, png_timep ptime) -{ - static PNG_CONST char short_months[12][4] = - {"Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; - - if(png_ptr == NULL) return (NULL); - if (png_ptr->time_buffer == NULL) - { - png_ptr->time_buffer = (png_charp)png_malloc(png_ptr, (png_uint_32)(29* - png_sizeof(char))); - } - -#if defined(_WIN32_WCE) - { - wchar_t time_buf[29]; - wsprintf(time_buf, TEXT("%d %S %d %02d:%02d:%02d +0000"), - ptime->day % 32, short_months[(ptime->month - 1) % 12], - ptime->year, ptime->hour % 24, ptime->minute % 60, - ptime->second % 61); - WideCharToMultiByte(CP_ACP, 0, time_buf, -1, png_ptr->time_buffer, 29, - NULL, NULL); - } -#else -#ifdef USE_FAR_KEYWORD - { - char near_time_buf[29]; - png_snprintf6(near_time_buf,29,"%d %s %d %02d:%02d:%02d +0000", - ptime->day % 32, short_months[(ptime->month - 1) % 12], - ptime->year, ptime->hour % 24, ptime->minute % 60, - ptime->second % 61); - png_memcpy(png_ptr->time_buffer, near_time_buf, - 29*png_sizeof(char)); - } -#else - png_snprintf6(png_ptr->time_buffer,29,"%d %s %d %02d:%02d:%02d +0000", - ptime->day % 32, short_months[(ptime->month - 1) % 12], - ptime->year, ptime->hour % 24, ptime->minute % 60, - ptime->second % 61); -#endif -#endif /* _WIN32_WCE */ - return ((png_charp)png_ptr->time_buffer); -} -#endif /* PNG_TIME_RFC1123_SUPPORTED */ - -#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ - -png_charp PNGAPI -png_get_copyright(png_structp png_ptr) -{ - png_ptr = png_ptr; /* silence compiler warning about unused png_ptr */ - return ((png_charp) "\n libpng version 1.2.22 - October 13, 2007\n\ - Copyright (c) 1998-2007 Glenn Randers-Pehrson\n\ - Copyright (c) 1996-1997 Andreas Dilger\n\ - Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.\n"); -} - -/* The following return the library version as a short string in the - * format 1.0.0 through 99.99.99zz. To get the version of *.h files - * used with your application, print out PNG_LIBPNG_VER_STRING, which - * is defined in png.h. - * Note: now there is no difference between png_get_libpng_ver() and - * png_get_header_ver(). Due to the version_nn_nn_nn typedef guard, - * it is guaranteed that png.c uses the correct version of png.h. - */ -png_charp PNGAPI -png_get_libpng_ver(png_structp png_ptr) -{ - /* Version of *.c files used when building libpng */ - png_ptr = png_ptr; /* silence compiler warning about unused png_ptr */ - return ((png_charp) PNG_LIBPNG_VER_STRING); -} - -png_charp PNGAPI -png_get_header_ver(png_structp png_ptr) -{ - /* Version of *.h files used when building libpng */ - png_ptr = png_ptr; /* silence compiler warning about unused png_ptr */ - return ((png_charp) PNG_LIBPNG_VER_STRING); -} - -png_charp PNGAPI -png_get_header_version(png_structp png_ptr) -{ - /* Returns longer string containing both version and date */ - png_ptr = png_ptr; /* silence compiler warning about unused png_ptr */ - return ((png_charp) PNG_HEADER_VERSION_STRING -#ifndef PNG_READ_SUPPORTED - " (NO READ SUPPORT)" -#endif - "\n"); -} - -#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) -#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED -int PNGAPI -png_handle_as_unknown(png_structp png_ptr, png_bytep chunk_name) -{ - /* check chunk_name and return "keep" value if it's on the list, else 0 */ - int i; - png_bytep p; - if(png_ptr == NULL || chunk_name == NULL || png_ptr->num_chunk_list<=0) - return 0; - p=png_ptr->chunk_list+png_ptr->num_chunk_list*5-5; - for (i = png_ptr->num_chunk_list; i; i--, p-=5) - if (!png_memcmp(chunk_name, p, 4)) - return ((int)*(p+4)); - return 0; -} -#endif - -/* This function, added to libpng-1.0.6g, is untested. */ -int PNGAPI -png_reset_zstream(png_structp png_ptr) -{ - if (png_ptr == NULL) return Z_STREAM_ERROR; - return (inflateReset(&png_ptr->zstream)); -} -#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ - -/* This function was added to libpng-1.0.7 */ -png_uint_32 PNGAPI -png_access_version_number(void) -{ - /* Version of *.c files used when building libpng */ - return((png_uint_32) PNG_LIBPNG_VER); -} - - -#if defined(PNG_READ_SUPPORTED) && defined(PNG_ASSEMBLER_CODE_SUPPORTED) -#if !defined(PNG_1_0_X) -/* this function was added to libpng 1.2.0 */ -int PNGAPI -png_mmx_support(void) -{ - /* obsolete, to be removed from libpng-1.4.0 */ - return -1; -} -#endif /* PNG_1_0_X */ -#endif /* PNG_READ_SUPPORTED && PNG_ASSEMBLER_CODE_SUPPORTED */ - -#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) -#ifdef PNG_SIZE_T -/* Added at libpng version 1.2.6 */ - PNG_EXTERN png_size_t PNGAPI png_convert_size PNGARG((size_t size)); -png_size_t PNGAPI -png_convert_size(size_t size) -{ - if (size > (png_size_t)-1) - PNG_ABORT(); /* We haven't got access to png_ptr, so no png_error() */ - return ((png_size_t)size); -} -#endif /* PNG_SIZE_T */ -#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ diff --git a/uppdev/plugin/png/lib/png.h b/uppdev/plugin/png/lib/png.h deleted file mode 100644 index c63818124..000000000 --- a/uppdev/plugin/png/lib/png.h +++ /dev/null @@ -1,3540 +0,0 @@ - -/* png.h - header file for PNG reference library - * - * libpng version 1.2.22 - October 13, 2007 - * Copyright (c) 1998-2007 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * Authors and maintainers: - * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat - * libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger - * libpng versions 0.97, January 1998, through 1.2.22 - October 13, 2007: Glenn - * See also "Contributing Authors", below. - * - * Note about libpng version numbers: - * - * Due to various miscommunications, unforeseen code incompatibilities - * and occasional factors outside the authors' control, version numbering - * on the library has not always been consistent and straightforward. - * The following table summarizes matters since version 0.89c, which was - * the first widely used release: - * - * source png.h png.h shared-lib - * version string int version - * ------- ------ ----- ---------- - * 0.89c "1.0 beta 3" 0.89 89 1.0.89 - * 0.90 "1.0 beta 4" 0.90 90 0.90 [should have been 2.0.90] - * 0.95 "1.0 beta 5" 0.95 95 0.95 [should have been 2.0.95] - * 0.96 "1.0 beta 6" 0.96 96 0.96 [should have been 2.0.96] - * 0.97b "1.00.97 beta 7" 1.00.97 97 1.0.1 [should have been 2.0.97] - * 0.97c 0.97 97 2.0.97 - * 0.98 0.98 98 2.0.98 - * 0.99 0.99 98 2.0.99 - * 0.99a-m 0.99 99 2.0.99 - * 1.00 1.00 100 2.1.0 [100 should be 10000] - * 1.0.0 (from here on, the 100 2.1.0 [100 should be 10000] - * 1.0.1 png.h string is 10001 2.1.0 - * 1.0.1a-e identical to the 10002 from here on, the shared library - * 1.0.2 source version) 10002 is 2.V where V is the source code - * 1.0.2a-b 10003 version, except as noted. - * 1.0.3 10003 - * 1.0.3a-d 10004 - * 1.0.4 10004 - * 1.0.4a-f 10005 - * 1.0.5 (+ 2 patches) 10005 - * 1.0.5a-d 10006 - * 1.0.5e-r 10100 (not source compatible) - * 1.0.5s-v 10006 (not binary compatible) - * 1.0.6 (+ 3 patches) 10006 (still binary incompatible) - * 1.0.6d-f 10007 (still binary incompatible) - * 1.0.6g 10007 - * 1.0.6h 10007 10.6h (testing xy.z so-numbering) - * 1.0.6i 10007 10.6i - * 1.0.6j 10007 2.1.0.6j (incompatible with 1.0.0) - * 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 (binary compatible) - * 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 (binary compatible) - * 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible) - * 1.0.7 1 10007 (still compatible) - * 1.0.8beta1-4 1 10008 2.1.0.8beta1-4 - * 1.0.8rc1 1 10008 2.1.0.8rc1 - * 1.0.8 1 10008 2.1.0.8 - * 1.0.9beta1-6 1 10009 2.1.0.9beta1-6 - * 1.0.9rc1 1 10009 2.1.0.9rc1 - * 1.0.9beta7-10 1 10009 2.1.0.9beta7-10 - * 1.0.9rc2 1 10009 2.1.0.9rc2 - * 1.0.9 1 10009 2.1.0.9 - * 1.0.10beta1 1 10010 2.1.0.10beta1 - * 1.0.10rc1 1 10010 2.1.0.10rc1 - * 1.0.10 1 10010 2.1.0.10 - * 1.0.11beta1-3 1 10011 2.1.0.11beta1-3 - * 1.0.11rc1 1 10011 2.1.0.11rc1 - * 1.0.11 1 10011 2.1.0.11 - * 1.0.12beta1-2 2 10012 2.1.0.12beta1-2 - * 1.0.12rc1 2 10012 2.1.0.12rc1 - * 1.0.12 2 10012 2.1.0.12 - * 1.1.0a-f - 10100 2.1.1.0a-f (branch abandoned) - * 1.2.0beta1-2 2 10200 2.1.2.0beta1-2 - * 1.2.0beta3-5 3 10200 3.1.2.0beta3-5 - * 1.2.0rc1 3 10200 3.1.2.0rc1 - * 1.2.0 3 10200 3.1.2.0 - * 1.2.1beta1-4 3 10201 3.1.2.1beta1-4 - * 1.2.1rc1-2 3 10201 3.1.2.1rc1-2 - * 1.2.1 3 10201 3.1.2.1 - * 1.2.2beta1-6 12 10202 12.so.0.1.2.2beta1-6 - * 1.0.13beta1 10 10013 10.so.0.1.0.13beta1 - * 1.0.13rc1 10 10013 10.so.0.1.0.13rc1 - * 1.2.2rc1 12 10202 12.so.0.1.2.2rc1 - * 1.0.13 10 10013 10.so.0.1.0.13 - * 1.2.2 12 10202 12.so.0.1.2.2 - * 1.2.3rc1-6 12 10203 12.so.0.1.2.3rc1-6 - * 1.2.3 12 10203 12.so.0.1.2.3 - * 1.2.4beta1-3 13 10204 12.so.0.1.2.4beta1-3 - * 1.0.14rc1 13 10014 10.so.0.1.0.14rc1 - * 1.2.4rc1 13 10204 12.so.0.1.2.4rc1 - * 1.0.14 10 10014 10.so.0.1.0.14 - * 1.2.4 13 10204 12.so.0.1.2.4 - * 1.2.5beta1-2 13 10205 12.so.0.1.2.5beta1-2 - * 1.0.15rc1-3 10 10015 10.so.0.1.0.15rc1-3 - * 1.2.5rc1-3 13 10205 12.so.0.1.2.5rc1-3 - * 1.0.15 10 10015 10.so.0.1.0.15 - * 1.2.5 13 10205 12.so.0.1.2.5 - * 1.2.6beta1-4 13 10206 12.so.0.1.2.6beta1-4 - * 1.0.16 10 10016 10.so.0.1.0.16 - * 1.2.6 13 10206 12.so.0.1.2.6 - * 1.2.7beta1-2 13 10207 12.so.0.1.2.7beta1-2 - * 1.0.17rc1 10 10017 10.so.0.1.0.17rc1 - * 1.2.7rc1 13 10207 12.so.0.1.2.7rc1 - * 1.0.17 10 10017 10.so.0.1.0.17 - * 1.2.7 13 10207 12.so.0.1.2.7 - * 1.2.8beta1-5 13 10208 12.so.0.1.2.8beta1-5 - * 1.0.18rc1-5 10 10018 10.so.0.1.0.18rc1-5 - * 1.2.8rc1-5 13 10208 12.so.0.1.2.8rc1-5 - * 1.0.18 10 10018 10.so.0.1.0.18 - * 1.2.8 13 10208 12.so.0.1.2.8 - * 1.2.9beta1-3 13 10209 12.so.0.1.2.9beta1-3 - * 1.2.9beta4-11 13 10209 12.so.0.9[.0] - * 1.2.9rc1 13 10209 12.so.0.9[.0] - * 1.2.9 13 10209 12.so.0.9[.0] - * 1.2.10beta1-8 13 10210 12.so.0.10[.0] - * 1.2.10rc1-3 13 10210 12.so.0.10[.0] - * 1.2.10 13 10210 12.so.0.10[.0] - * 1.2.11beta1-4 13 10211 12.so.0.11[.0] - * 1.0.19rc1-5 10 10019 10.so.0.19[.0] - * 1.2.11rc1-5 13 10211 12.so.0.11[.0] - * 1.0.19 10 10019 10.so.0.19[.0] - * 1.2.11 13 10211 12.so.0.11[.0] - * 1.0.20 10 10020 10.so.0.20[.0] - * 1.2.12 13 10212 12.so.0.12[.0] - * 1.2.13beta1 13 10213 12.so.0.13[.0] - * 1.0.21 10 10021 10.so.0.21[.0] - * 1.2.13 13 10213 12.so.0.13[.0] - * 1.2.14beta1-2 13 10214 12.so.0.14[.0] - * 1.0.22rc1 10 10022 10.so.0.22[.0] - * 1.2.14rc1 13 10214 12.so.0.14[.0] - * 1.0.22 10 10022 10.so.0.22[.0] - * 1.2.14 13 10214 12.so.0.14[.0] - * 1.2.15beta1-6 13 10215 12.so.0.15[.0] - * 1.0.23rc1-5 10 10023 10.so.0.23[.0] - * 1.2.15rc1-5 13 10215 12.so.0.15[.0] - * 1.0.23 10 10023 10.so.0.23[.0] - * 1.2.15 13 10215 12.so.0.15[.0] - * 1.2.16beta1-2 13 10216 12.so.0.16[.0] - * 1.2.16rc1 13 10216 12.so.0.16[.0] - * 1.0.24 10 10024 10.so.0.24[.0] - * 1.2.16 13 10216 12.so.0.16[.0] - * 1.2.17beta1-2 13 10217 12.so.0.17[.0] - * 1.0.25rc1 10 10025 10.so.0.25[.0] - * 1.2.17rc1-3 13 10217 12.so.0.17[.0] - * 1.0.25 10 10025 10.so.0.25[.0] - * 1.2.17 13 10217 12.so.0.17[.0] - * 1.0.26 10 10026 10.so.0.26[.0] - * 1.2.18 13 10218 12.so.0.18[.0] - * 1.2.19beta1-31 13 10219 12.so.0.19[.0] - * 1.0.27rc1-6 10 10027 10.so.0.27[.0] - * 1.2.19rc1-6 13 10219 12.so.0.19[.0] - * 1.0.27 10 10027 10.so.0.27[.0] - * 1.2.19 13 10219 12.so.0.19[.0] - * 1.2.20beta01-04 13 10220 12.so.0.20[.0] - * 1.0.28rc1-6 10 10028 10.so.0.28[.0] - * 1.2.20rc1-6 13 10220 12.so.0.20[.0] - * 1.0.28 10 10028 10.so.0.28[.0] - * 1.2.20 13 10220 12.so.0.20[.0] - * 1.2.21beta1-2 13 10221 12.so.0.21[.0] - * 1.2.21rc1-3 13 10221 12.so.0.21[.0] - * 1.0.29 10 10029 10.so.0.29[.0] - * 1.2.21 13 10221 12.so.0.21[.0] - * 1.2.22beta1-4 13 10222 12.so.0.22[.0] - * 1.0.30rc1 10 10030 10.so.0.30[.0] - * 1.2.22rc1 13 10222 12.so.0.22[.0] - * 1.0.30 10 10030 10.so.0.30[.0] - * 1.2.22 13 10222 12.so.0.22[.0] - * - * Henceforth the source version will match the shared-library major - * and minor numbers; the shared-library major version number will be - * used for changes in backward compatibility, as it is intended. The - * PNG_LIBPNG_VER macro, which is not used within libpng but is available - * for applications, is an unsigned integer of the form xyyzz corresponding - * to the source version x.y.z (leading zeros in y and z). Beta versions - * were given the previous public release number plus a letter, until - * version 1.0.6j; from then on they were given the upcoming public - * release number plus "betaNN" or "rcN". - * - * Binary incompatibility exists only when applications make direct access - * to the info_ptr or png_ptr members through png.h, and the compiled - * application is loaded with a different version of the library. - * - * DLLNUM will change each time there are forward or backward changes - * in binary compatibility (e.g., when a new feature is added). - * - * See libpng.txt or libpng.3 for more information. The PNG specification - * is available as a W3C Recommendation and as an ISO Specification, - * -#endif - -/* include all user configurable info, including optional assembler routines */ -#include "pngconf.h" - -/* - * Added at libpng-1.2.8 */ -/* Ref MSDN: Private as priority over Special - * VS_FF_PRIVATEBUILD File *was not* built using standard release - * procedures. If this value is given, the StringFileInfo block must - * contain a PrivateBuild string. - * - * VS_FF_SPECIALBUILD File *was* built by the original company using - * standard release procedures but is a variation of the standard - * file of the same version number. If this value is given, the - * StringFileInfo block must contain a SpecialBuild string. - */ - -#if defined(PNG_USER_PRIVATEBUILD) -# define PNG_LIBPNG_BUILD_TYPE \ - (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_PRIVATE) -#else -# if defined(PNG_LIBPNG_SPECIALBUILD) -# define PNG_LIBPNG_BUILD_TYPE \ - (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_SPECIAL) -# else -# define PNG_LIBPNG_BUILD_TYPE (PNG_LIBPNG_BUILD_BASE_TYPE) -# endif -#endif - -#ifndef PNG_VERSION_INFO_ONLY - -/* Inhibit C++ name-mangling for libpng functions but not for system calls. */ -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/* This file is arranged in several sections. The first section contains - * structure and type definitions. The second section contains the external - * library functions, while the third has the internal library functions, - * which applications aren't expected to use directly. - */ - -#ifndef PNG_NO_TYPECAST_NULL -#define int_p_NULL (int *)NULL -#define png_bytep_NULL (png_bytep)NULL -#define png_bytepp_NULL (png_bytepp)NULL -#define png_doublep_NULL (png_doublep)NULL -#define png_error_ptr_NULL (png_error_ptr)NULL -#define png_flush_ptr_NULL (png_flush_ptr)NULL -#define png_free_ptr_NULL (png_free_ptr)NULL -#define png_infopp_NULL (png_infopp)NULL -#define png_malloc_ptr_NULL (png_malloc_ptr)NULL -#define png_read_status_ptr_NULL (png_read_status_ptr)NULL -#define png_rw_ptr_NULL (png_rw_ptr)NULL -#define png_structp_NULL (png_structp)NULL -#define png_uint_16p_NULL (png_uint_16p)NULL -#define png_voidp_NULL (png_voidp)NULL -#define png_write_status_ptr_NULL (png_write_status_ptr)NULL -#else -#define int_p_NULL NULL -#define png_bytep_NULL NULL -#define png_bytepp_NULL NULL -#define png_doublep_NULL NULL -#define png_error_ptr_NULL NULL -#define png_flush_ptr_NULL NULL -#define png_free_ptr_NULL NULL -#define png_infopp_NULL NULL -#define png_malloc_ptr_NULL NULL -#define png_read_status_ptr_NULL NULL -#define png_rw_ptr_NULL NULL -#define png_structp_NULL NULL -#define png_uint_16p_NULL NULL -#define png_voidp_NULL NULL -#define png_write_status_ptr_NULL NULL -#endif - -/* variables declared in png.c - only it needs to define PNG_NO_EXTERN */ -#if !defined(PNG_NO_EXTERN) || defined(PNG_ALWAYS_EXTERN) -/* Version information for C files, stored in png.c. This had better match - * the version above. - */ -#ifdef PNG_USE_GLOBAL_ARRAYS -PNG_EXPORT_VAR (PNG_CONST char) png_libpng_ver[18]; - /* need room for 99.99.99beta99z */ -#else -#define png_libpng_ver png_get_header_ver(NULL) -#endif - -#ifdef PNG_USE_GLOBAL_ARRAYS -/* This was removed in version 1.0.5c */ -/* Structures to facilitate easy interlacing. See png.c for more details */ -PNG_EXPORT_VAR (PNG_CONST int FARDATA) png_pass_start[7]; -PNG_EXPORT_VAR (PNG_CONST int FARDATA) png_pass_inc[7]; -PNG_EXPORT_VAR (PNG_CONST int FARDATA) png_pass_ystart[7]; -PNG_EXPORT_VAR (PNG_CONST int FARDATA) png_pass_yinc[7]; -PNG_EXPORT_VAR (PNG_CONST int FARDATA) png_pass_mask[7]; -PNG_EXPORT_VAR (PNG_CONST int FARDATA) png_pass_dsp_mask[7]; -/* This isn't currently used. If you need it, see png.c for more details. -PNG_EXPORT_VAR (PNG_CONST int FARDATA) png_pass_height[7]; -*/ -#endif - -#endif /* PNG_NO_EXTERN */ - -/* Three color definitions. The order of the red, green, and blue, (and the - * exact size) is not important, although the size of the fields need to - * be png_byte or png_uint_16 (as defined below). - */ -typedef struct png_color_struct -{ - png_byte red; - png_byte green; - png_byte blue; -} png_color; -typedef png_color FAR * png_colorp; -typedef png_color FAR * FAR * png_colorpp; - -typedef struct png_color_16_struct -{ - png_byte index; /* used for palette files */ - png_uint_16 red; /* for use in red green blue files */ - png_uint_16 green; - png_uint_16 blue; - png_uint_16 gray; /* for use in grayscale files */ -} png_color_16; -typedef png_color_16 FAR * png_color_16p; -typedef png_color_16 FAR * FAR * png_color_16pp; - -typedef struct png_color_8_struct -{ - png_byte red; /* for use in red green blue files */ - png_byte green; - png_byte blue; - png_byte gray; /* for use in grayscale files */ - png_byte alpha; /* for alpha channel files */ -} png_color_8; -typedef png_color_8 FAR * png_color_8p; -typedef png_color_8 FAR * FAR * png_color_8pp; - -/* - * The following two structures are used for the in-core representation - * of sPLT chunks. - */ -typedef struct png_sPLT_entry_struct -{ - png_uint_16 red; - png_uint_16 green; - png_uint_16 blue; - png_uint_16 alpha; - png_uint_16 frequency; -} png_sPLT_entry; -typedef png_sPLT_entry FAR * png_sPLT_entryp; -typedef png_sPLT_entry FAR * FAR * png_sPLT_entrypp; - -/* When the depth of the sPLT palette is 8 bits, the color and alpha samples - * occupy the LSB of their respective members, and the MSB of each member - * is zero-filled. The frequency member always occupies the full 16 bits. - */ - -typedef struct png_sPLT_struct -{ - png_charp name; /* palette name */ - png_byte depth; /* depth of palette samples */ - png_sPLT_entryp entries; /* palette entries */ - png_int_32 nentries; /* number of palette entries */ -} png_sPLT_t; -typedef png_sPLT_t FAR * png_sPLT_tp; -typedef png_sPLT_t FAR * FAR * png_sPLT_tpp; - -#ifdef PNG_TEXT_SUPPORTED -/* png_text holds the contents of a text/ztxt/itxt chunk in a PNG file, - * and whether that contents is compressed or not. The "key" field - * points to a regular zero-terminated C string. The "text", "lang", and - * "lang_key" fields can be regular C strings, empty strings, or NULL pointers. - * However, the * structure returned by png_get_text() will always contain - * regular zero-terminated C strings (possibly empty), never NULL pointers, - * so they can be safely used in printf() and other string-handling functions. - */ -typedef struct png_text_struct -{ - int compression; /* compression value: - -1: tEXt, none - 0: zTXt, deflate - 1: iTXt, none - 2: iTXt, deflate */ - png_charp key; /* keyword, 1-79 character description of "text" */ - png_charp text; /* comment, may be an empty string (ie "") - or a NULL pointer */ - png_size_t text_length; /* length of the text string */ -#ifdef PNG_iTXt_SUPPORTED - png_size_t itxt_length; /* length of the itxt string */ - png_charp lang; /* language code, 0-79 characters - or a NULL pointer */ - png_charp lang_key; /* keyword translated UTF-8 string, 0 or more - chars or a NULL pointer */ -#endif -} png_text; -typedef png_text FAR * png_textp; -typedef png_text FAR * FAR * png_textpp; -#endif - -/* Supported compression types for text in PNG files (tEXt, and zTXt). - * The values of the PNG_TEXT_COMPRESSION_ defines should NOT be changed. */ -#define PNG_TEXT_COMPRESSION_NONE_WR -3 -#define PNG_TEXT_COMPRESSION_zTXt_WR -2 -#define PNG_TEXT_COMPRESSION_NONE -1 -#define PNG_TEXT_COMPRESSION_zTXt 0 -#define PNG_ITXT_COMPRESSION_NONE 1 -#define PNG_ITXT_COMPRESSION_zTXt 2 -#define PNG_TEXT_COMPRESSION_LAST 3 /* Not a valid value */ - -/* png_time is a way to hold the time in an machine independent way. - * Two conversions are provided, both from time_t and struct tm. There - * is no portable way to convert to either of these structures, as far - * as I know. If you know of a portable way, send it to me. As a side - * note - PNG has always been Year 2000 compliant! - */ -typedef struct png_time_struct -{ - png_uint_16 year; /* full year, as in, 1995 */ - png_byte month; /* month of year, 1 - 12 */ - png_byte day; /* day of month, 1 - 31 */ - png_byte hour; /* hour of day, 0 - 23 */ - png_byte minute; /* minute of hour, 0 - 59 */ - png_byte second; /* second of minute, 0 - 60 (for leap seconds) */ -} png_time; -typedef png_time FAR * png_timep; -typedef png_time FAR * FAR * png_timepp; - -#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) -/* png_unknown_chunk is a structure to hold queued chunks for which there is - * no specific support. The idea is that we can use this to queue - * up private chunks for output even though the library doesn't actually - * know about their semantics. - */ -typedef struct png_unknown_chunk_t -{ - png_byte name[5]; - png_byte *data; - png_size_t size; - - /* libpng-using applications should NOT directly modify this byte. */ - png_byte location; /* mode of operation at read time */ -} -png_unknown_chunk; -typedef png_unknown_chunk FAR * png_unknown_chunkp; -typedef png_unknown_chunk FAR * FAR * png_unknown_chunkpp; -#endif - -/* png_info is a structure that holds the information in a PNG file so - * that the application can find out the characteristics of the image. - * If you are reading the file, this structure will tell you what is - * in the PNG file. If you are writing the file, fill in the information - * you want to put into the PNG file, then call png_write_info(). - * The names chosen should be very close to the PNG specification, so - * consult that document for information about the meaning of each field. - * - * With libpng < 0.95, it was only possible to directly set and read the - * the values in the png_info_struct, which meant that the contents and - * order of the values had to remain fixed. With libpng 0.95 and later, - * however, there are now functions that abstract the contents of - * png_info_struct from the application, so this makes it easier to use - * libpng with dynamic libraries, and even makes it possible to use - * libraries that don't have all of the libpng ancillary chunk-handing - * functionality. - * - * In any case, the order of the parameters in png_info_struct should NOT - * be changed for as long as possible to keep compatibility with applications - * that use the old direct-access method with png_info_struct. - * - * The following members may have allocated storage attached that should be - * cleaned up before the structure is discarded: palette, trans, text, - * pcal_purpose, pcal_units, pcal_params, hist, iccp_name, iccp_profile, - * splt_palettes, scal_unit, row_pointers, and unknowns. By default, these - * are automatically freed when the info structure is deallocated, if they were - * allocated internally by libpng. This behavior can be changed by means - * of the png_data_freer() function. - * - * More allocation details: all the chunk-reading functions that - * change these members go through the corresponding png_set_* - * functions. A function to clear these members is available: see - * png_free_data(). The png_set_* functions do not depend on being - * able to point info structure members to any of the storage they are - * passed (they make their own copies), EXCEPT that the png_set_text - * functions use the same storage passed to them in the text_ptr or - * itxt_ptr structure argument, and the png_set_rows and png_set_unknowns - * functions do not make their own copies. - */ -typedef struct png_info_struct -{ - /* the following are necessary for every PNG file */ - png_uint_32 width; /* width of image in pixels (from IHDR) */ - png_uint_32 height; /* height of image in pixels (from IHDR) */ - png_uint_32 valid; /* valid chunk data (see PNG_INFO_ below) */ - png_uint_32 rowbytes; /* bytes needed to hold an untransformed row */ - png_colorp palette; /* array of color values (valid & PNG_INFO_PLTE) */ - png_uint_16 num_palette; /* number of color entries in "palette" (PLTE) */ - png_uint_16 num_trans; /* number of transparent palette color (tRNS) */ - png_byte bit_depth; /* 1, 2, 4, 8, or 16 bits/channel (from IHDR) */ - png_byte color_type; /* see PNG_COLOR_TYPE_ below (from IHDR) */ - /* The following three should have been named *_method not *_type */ - png_byte compression_type; /* must be PNG_COMPRESSION_TYPE_BASE (IHDR) */ - png_byte filter_type; /* must be PNG_FILTER_TYPE_BASE (from IHDR) */ - png_byte interlace_type; /* One of PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ - - /* The following is informational only on read, and not used on writes. */ - png_byte channels; /* number of data channels per pixel (1, 2, 3, 4) */ - png_byte pixel_depth; /* number of bits per pixel */ - png_byte spare_byte; /* to align the data, and for future use */ - png_byte signature[8]; /* magic bytes read by libpng from start of file */ - - /* The rest of the data is optional. If you are reading, check the - * valid field to see if the information in these are valid. If you - * are writing, set the valid field to those chunks you want written, - * and initialize the appropriate fields below. - */ - -#if defined(PNG_gAMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) - /* The gAMA chunk describes the gamma characteristics of the system - * on which the image was created, normally in the range [1.0, 2.5]. - * Data is valid if (valid & PNG_INFO_gAMA) is non-zero. - */ - float gamma; /* gamma value of image, if (valid & PNG_INFO_gAMA) */ -#endif - -#if defined(PNG_sRGB_SUPPORTED) - /* GR-P, 0.96a */ - /* Data valid if (valid & PNG_INFO_sRGB) non-zero. */ - png_byte srgb_intent; /* sRGB rendering intent [0, 1, 2, or 3] */ -#endif - -#if defined(PNG_TEXT_SUPPORTED) - /* The tEXt, and zTXt chunks contain human-readable textual data in - * uncompressed, compressed, and optionally compressed forms, respectively. - * The data in "text" is an array of pointers to uncompressed, - * null-terminated C strings. Each chunk has a keyword that describes the - * textual data contained in that chunk. Keywords are not required to be - * unique, and the text string may be empty. Any number of text chunks may - * be in an image. - */ - int num_text; /* number of comments read/to write */ - int max_text; /* current size of text array */ - png_textp text; /* array of comments read/to write */ -#endif /* PNG_TEXT_SUPPORTED */ - -#if defined(PNG_tIME_SUPPORTED) - /* The tIME chunk holds the last time the displayed image data was - * modified. See the png_time struct for the contents of this struct. - */ - png_time mod_time; -#endif - -#if defined(PNG_sBIT_SUPPORTED) - /* The sBIT chunk specifies the number of significant high-order bits - * in the pixel data. Values are in the range [1, bit_depth], and are - * only specified for the channels in the pixel data. The contents of - * the low-order bits is not specified. Data is valid if - * (valid & PNG_INFO_sBIT) is non-zero. - */ - png_color_8 sig_bit; /* significant bits in color channels */ -#endif - -#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_EXPAND_SUPPORTED) || \ -defined(PNG_READ_BACKGROUND_SUPPORTED) - /* The tRNS chunk supplies transparency data for paletted images and - * other image types that don't need a full alpha channel. There are - * "num_trans" transparency values for a paletted image, stored in the - * same order as the palette colors, starting from index 0. Values - * for the data are in the range [0, 255], ranging from fully transparent - * to fully opaque, respectively. For non-paletted images, there is a - * single color specified that should be treated as fully transparent. - * Data is valid if (valid & PNG_INFO_tRNS) is non-zero. - */ - png_bytep trans; /* transparent values for paletted image */ - png_color_16 trans_values; /* transparent color for non-palette image */ -#endif - -#if defined(PNG_bKGD_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - /* The bKGD chunk gives the suggested image background color if the - * display program does not have its own background color and the image - * is needs to composited onto a background before display. The colors - * in "background" are normally in the same color space/depth as the - * pixel data. Data is valid if (valid & PNG_INFO_bKGD) is non-zero. - */ - png_color_16 background; -#endif - -#if defined(PNG_oFFs_SUPPORTED) - /* The oFFs chunk gives the offset in "offset_unit_type" units rightwards - * and downwards from the top-left corner of the display, page, or other - * application-specific co-ordinate space. See the PNG_OFFSET_ defines - * below for the unit types. Valid if (valid & PNG_INFO_oFFs) non-zero. - */ - png_int_32 x_offset; /* x offset on page */ - png_int_32 y_offset; /* y offset on page */ - png_byte offset_unit_type; /* offset units type */ -#endif - -#if defined(PNG_pHYs_SUPPORTED) - /* The pHYs chunk gives the physical pixel density of the image for - * display or printing in "phys_unit_type" units (see PNG_RESOLUTION_ - * defines below). Data is valid if (valid & PNG_INFO_pHYs) is non-zero. - */ - png_uint_32 x_pixels_per_unit; /* horizontal pixel density */ - png_uint_32 y_pixels_per_unit; /* vertical pixel density */ - png_byte phys_unit_type; /* resolution type (see PNG_RESOLUTION_ below) */ -#endif - -#if defined(PNG_hIST_SUPPORTED) - /* The hIST chunk contains the relative frequency or importance of the - * various palette entries, so that a viewer can intelligently select a - * reduced-color palette, if required. Data is an array of "num_palette" - * values in the range [0,65535]. Data valid if (valid & PNG_INFO_hIST) - * is non-zero. - */ - png_uint_16p hist; -#endif - -#ifdef PNG_cHRM_SUPPORTED - /* The cHRM chunk describes the CIE color characteristics of the monitor - * on which the PNG was created. This data allows the viewer to do gamut - * mapping of the input image to ensure that the viewer sees the same - * colors in the image as the creator. Values are in the range - * [0.0, 0.8]. Data valid if (valid & PNG_INFO_cHRM) non-zero. - */ -#ifdef PNG_FLOATING_POINT_SUPPORTED - float x_white; - float y_white; - float x_red; - float y_red; - float x_green; - float y_green; - float x_blue; - float y_blue; -#endif -#endif - -#if defined(PNG_pCAL_SUPPORTED) - /* The pCAL chunk describes a transformation between the stored pixel - * values and original physical data values used to create the image. - * The integer range [0, 2^bit_depth - 1] maps to the floating-point - * range given by [pcal_X0, pcal_X1], and are further transformed by a - * (possibly non-linear) transformation function given by "pcal_type" - * and "pcal_params" into "pcal_units". Please see the PNG_EQUATION_ - * defines below, and the PNG-Group's PNG extensions document for a - * complete description of the transformations and how they should be - * implemented, and for a description of the ASCII parameter strings. - * Data values are valid if (valid & PNG_INFO_pCAL) non-zero. - */ - png_charp pcal_purpose; /* pCAL chunk description string */ - png_int_32 pcal_X0; /* minimum value */ - png_int_32 pcal_X1; /* maximum value */ - png_charp pcal_units; /* Latin-1 string giving physical units */ - png_charpp pcal_params; /* ASCII strings containing parameter values */ - png_byte pcal_type; /* equation type (see PNG_EQUATION_ below) */ - png_byte pcal_nparams; /* number of parameters given in pcal_params */ -#endif - -/* New members added in libpng-1.0.6 */ -#ifdef PNG_FREE_ME_SUPPORTED - png_uint_32 free_me; /* flags items libpng is responsible for freeing */ -#endif - -#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) - /* storage for unknown chunks that the library doesn't recognize. */ - png_unknown_chunkp unknown_chunks; - png_size_t unknown_chunks_num; -#endif - -#if defined(PNG_iCCP_SUPPORTED) - /* iCCP chunk data. */ - png_charp iccp_name; /* profile name */ - png_charp iccp_profile; /* International Color Consortium profile data */ - /* Note to maintainer: should be png_bytep */ - png_uint_32 iccp_proflen; /* ICC profile data length */ - png_byte iccp_compression; /* Always zero */ -#endif - -#if defined(PNG_sPLT_SUPPORTED) - /* data on sPLT chunks (there may be more than one). */ - png_sPLT_tp splt_palettes; - png_uint_32 splt_palettes_num; -#endif - -#if defined(PNG_sCAL_SUPPORTED) - /* The sCAL chunk describes the actual physical dimensions of the - * subject matter of the graphic. The chunk contains a unit specification - * a byte value, and two ASCII strings representing floating-point - * values. The values are width and height corresponsing to one pixel - * in the image. This external representation is converted to double - * here. Data values are valid if (valid & PNG_INFO_sCAL) is non-zero. - */ - png_byte scal_unit; /* unit of physical scale */ -#ifdef PNG_FLOATING_POINT_SUPPORTED - double scal_pixel_width; /* width of one pixel */ - double scal_pixel_height; /* height of one pixel */ -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED - png_charp scal_s_width; /* string containing height */ - png_charp scal_s_height; /* string containing width */ -#endif -#endif - -#if defined(PNG_INFO_IMAGE_SUPPORTED) - /* Memory has been allocated if (valid & PNG_ALLOCATED_INFO_ROWS) non-zero */ - /* Data valid if (valid & PNG_INFO_IDAT) non-zero */ - png_bytepp row_pointers; /* the image bits */ -#endif - -#if defined(PNG_FIXED_POINT_SUPPORTED) && defined(PNG_gAMA_SUPPORTED) - png_fixed_point int_gamma; /* gamma of image, if (valid & PNG_INFO_gAMA) */ -#endif - -#if defined(PNG_cHRM_SUPPORTED) && defined(PNG_FIXED_POINT_SUPPORTED) - png_fixed_point int_x_white; - png_fixed_point int_y_white; - png_fixed_point int_x_red; - png_fixed_point int_y_red; - png_fixed_point int_x_green; - png_fixed_point int_y_green; - png_fixed_point int_x_blue; - png_fixed_point int_y_blue; -#endif - -} png_info; - -typedef png_info FAR * png_infop; -typedef png_info FAR * FAR * png_infopp; - -/* Maximum positive integer used in PNG is (2^31)-1 */ -#define PNG_UINT_31_MAX ((png_uint_32)0x7fffffffL) -#define PNG_UINT_32_MAX ((png_uint_32)(-1)) -#define PNG_SIZE_MAX ((png_size_t)(-1)) -#if defined(PNG_1_0_X) || defined (PNG_1_2_X) -/* PNG_MAX_UINT is deprecated; use PNG_UINT_31_MAX instead. */ -#define PNG_MAX_UINT PNG_UINT_31_MAX -#endif - -/* These describe the color_type field in png_info. */ -/* color type masks */ -#define PNG_COLOR_MASK_PALETTE 1 -#define PNG_COLOR_MASK_COLOR 2 -#define PNG_COLOR_MASK_ALPHA 4 - -/* color types. Note that not all combinations are legal */ -#define PNG_COLOR_TYPE_GRAY 0 -#define PNG_COLOR_TYPE_PALETTE (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE) -#define PNG_COLOR_TYPE_RGB (PNG_COLOR_MASK_COLOR) -#define PNG_COLOR_TYPE_RGB_ALPHA (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA) -#define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA) -/* aliases */ -#define PNG_COLOR_TYPE_RGBA PNG_COLOR_TYPE_RGB_ALPHA -#define PNG_COLOR_TYPE_GA PNG_COLOR_TYPE_GRAY_ALPHA - -/* This is for compression type. PNG 1.0-1.2 only define the single type. */ -#define PNG_COMPRESSION_TYPE_BASE 0 /* Deflate method 8, 32K window */ -#define PNG_COMPRESSION_TYPE_DEFAULT PNG_COMPRESSION_TYPE_BASE - -/* This is for filter type. PNG 1.0-1.2 only define the single type. */ -#define PNG_FILTER_TYPE_BASE 0 /* Single row per-byte filtering */ -#define PNG_INTRAPIXEL_DIFFERENCING 64 /* Used only in MNG datastreams */ -#define PNG_FILTER_TYPE_DEFAULT PNG_FILTER_TYPE_BASE - -/* These are for the interlacing type. These values should NOT be changed. */ -#define PNG_INTERLACE_NONE 0 /* Non-interlaced image */ -#define PNG_INTERLACE_ADAM7 1 /* Adam7 interlacing */ -#define PNG_INTERLACE_LAST 2 /* Not a valid value */ - -/* These are for the oFFs chunk. These values should NOT be changed. */ -#define PNG_OFFSET_PIXEL 0 /* Offset in pixels */ -#define PNG_OFFSET_MICROMETER 1 /* Offset in micrometers (1/10^6 meter) */ -#define PNG_OFFSET_LAST 2 /* Not a valid value */ - -/* These are for the pCAL chunk. These values should NOT be changed. */ -#define PNG_EQUATION_LINEAR 0 /* Linear transformation */ -#define PNG_EQUATION_BASE_E 1 /* Exponential base e transform */ -#define PNG_EQUATION_ARBITRARY 2 /* Arbitrary base exponential transform */ -#define PNG_EQUATION_HYPERBOLIC 3 /* Hyperbolic sine transformation */ -#define PNG_EQUATION_LAST 4 /* Not a valid value */ - -/* These are for the sCAL chunk. These values should NOT be changed. */ -#define PNG_SCALE_UNKNOWN 0 /* unknown unit (image scale) */ -#define PNG_SCALE_METER 1 /* meters per pixel */ -#define PNG_SCALE_RADIAN 2 /* radians per pixel */ -#define PNG_SCALE_LAST 3 /* Not a valid value */ - -/* These are for the pHYs chunk. These values should NOT be changed. */ -#define PNG_RESOLUTION_UNKNOWN 0 /* pixels/unknown unit (aspect ratio) */ -#define PNG_RESOLUTION_METER 1 /* pixels/meter */ -#define PNG_RESOLUTION_LAST 2 /* Not a valid value */ - -/* These are for the sRGB chunk. These values should NOT be changed. */ -#define PNG_sRGB_INTENT_PERCEPTUAL 0 -#define PNG_sRGB_INTENT_RELATIVE 1 -#define PNG_sRGB_INTENT_SATURATION 2 -#define PNG_sRGB_INTENT_ABSOLUTE 3 -#define PNG_sRGB_INTENT_LAST 4 /* Not a valid value */ - -/* This is for text chunks */ -#define PNG_KEYWORD_MAX_LENGTH 79 - -/* Maximum number of entries in PLTE/sPLT/tRNS arrays */ -#define PNG_MAX_PALETTE_LENGTH 256 - -/* These determine if an ancillary chunk's data has been successfully read - * from the PNG header, or if the application has filled in the corresponding - * data in the info_struct to be written into the output file. The values - * of the PNG_INFO_ defines should NOT be changed. - */ -#define PNG_INFO_gAMA 0x0001 -#define PNG_INFO_sBIT 0x0002 -#define PNG_INFO_cHRM 0x0004 -#define PNG_INFO_PLTE 0x0008 -#define PNG_INFO_tRNS 0x0010 -#define PNG_INFO_bKGD 0x0020 -#define PNG_INFO_hIST 0x0040 -#define PNG_INFO_pHYs 0x0080 -#define PNG_INFO_oFFs 0x0100 -#define PNG_INFO_tIME 0x0200 -#define PNG_INFO_pCAL 0x0400 -#define PNG_INFO_sRGB 0x0800 /* GR-P, 0.96a */ -#define PNG_INFO_iCCP 0x1000 /* ESR, 1.0.6 */ -#define PNG_INFO_sPLT 0x2000 /* ESR, 1.0.6 */ -#define PNG_INFO_sCAL 0x4000 /* ESR, 1.0.6 */ -#define PNG_INFO_IDAT 0x8000L /* ESR, 1.0.6 */ - -/* This is used for the transformation routines, as some of them - * change these values for the row. It also should enable using - * the routines for other purposes. - */ -typedef struct png_row_info_struct -{ - png_uint_32 width; /* width of row */ - png_uint_32 rowbytes; /* number of bytes in row */ - png_byte color_type; /* color type of row */ - png_byte bit_depth; /* bit depth of row */ - png_byte channels; /* number of channels (1, 2, 3, or 4) */ - png_byte pixel_depth; /* bits per pixel (depth * channels) */ -} png_row_info; - -typedef png_row_info FAR * png_row_infop; -typedef png_row_info FAR * FAR * png_row_infopp; - -/* These are the function types for the I/O functions and for the functions - * that allow the user to override the default I/O functions with his or her - * own. The png_error_ptr type should match that of user-supplied warning - * and error functions, while the png_rw_ptr type should match that of the - * user read/write data functions. - */ -typedef struct png_struct_def png_struct; -typedef png_struct FAR * png_structp; - -typedef void (PNGAPI *png_error_ptr) PNGARG((png_structp, png_const_charp)); -typedef void (PNGAPI *png_rw_ptr) PNGARG((png_structp, png_bytep, png_size_t)); -typedef void (PNGAPI *png_flush_ptr) PNGARG((png_structp)); -typedef void (PNGAPI *png_read_status_ptr) PNGARG((png_structp, png_uint_32, - int)); -typedef void (PNGAPI *png_write_status_ptr) PNGARG((png_structp, png_uint_32, - int)); - -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED -typedef void (PNGAPI *png_progressive_info_ptr) PNGARG((png_structp, png_infop)); -typedef void (PNGAPI *png_progressive_end_ptr) PNGARG((png_structp, png_infop)); -typedef void (PNGAPI *png_progressive_row_ptr) PNGARG((png_structp, png_bytep, - png_uint_32, int)); -#endif - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_LEGACY_SUPPORTED) -typedef void (PNGAPI *png_user_transform_ptr) PNGARG((png_structp, - png_row_infop, png_bytep)); -#endif - -#if defined(PNG_USER_CHUNKS_SUPPORTED) -typedef int (PNGAPI *png_user_chunk_ptr) PNGARG((png_structp, png_unknown_chunkp)); -#endif -#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) -typedef void (PNGAPI *png_unknown_chunk_ptr) PNGARG((png_structp)); -#endif - -/* Transform masks for the high-level interface */ -#define PNG_TRANSFORM_IDENTITY 0x0000 /* read and write */ -#define PNG_TRANSFORM_STRIP_16 0x0001 /* read only */ -#define PNG_TRANSFORM_STRIP_ALPHA 0x0002 /* read only */ -#define PNG_TRANSFORM_PACKING 0x0004 /* read and write */ -#define PNG_TRANSFORM_PACKSWAP 0x0008 /* read and write */ -#define PNG_TRANSFORM_EXPAND 0x0010 /* read only */ -#define PNG_TRANSFORM_INVERT_MONO 0x0020 /* read and write */ -#define PNG_TRANSFORM_SHIFT 0x0040 /* read and write */ -#define PNG_TRANSFORM_BGR 0x0080 /* read and write */ -#define PNG_TRANSFORM_SWAP_ALPHA 0x0100 /* read and write */ -#define PNG_TRANSFORM_SWAP_ENDIAN 0x0200 /* read and write */ -#define PNG_TRANSFORM_INVERT_ALPHA 0x0400 /* read and write */ -#define PNG_TRANSFORM_STRIP_FILLER 0x0800 /* WRITE only */ - -/* Flags for MNG supported features */ -#define PNG_FLAG_MNG_EMPTY_PLTE 0x01 -#define PNG_FLAG_MNG_FILTER_64 0x04 -#define PNG_ALL_MNG_FEATURES 0x05 - -typedef png_voidp (*png_malloc_ptr) PNGARG((png_structp, png_size_t)); -typedef void (*png_free_ptr) PNGARG((png_structp, png_voidp)); - -/* The structure that holds the information to read and write PNG files. - * The only people who need to care about what is inside of this are the - * people who will be modifying the library for their own special needs. - * It should NOT be accessed directly by an application, except to store - * the jmp_buf. - */ - -struct png_struct_def -{ -#ifdef PNG_SETJMP_SUPPORTED - jmp_buf jmpbuf; /* used in png_error */ -#endif - png_error_ptr error_fn; /* function for printing errors and aborting */ - png_error_ptr warning_fn; /* function for printing warnings */ - png_voidp error_ptr; /* user supplied struct for error functions */ - png_rw_ptr write_data_fn; /* function for writing output data */ - png_rw_ptr read_data_fn; /* function for reading input data */ - png_voidp io_ptr; /* ptr to application struct for I/O functions */ - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) - png_user_transform_ptr read_user_transform_fn; /* user read transform */ -#endif - -#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) - png_user_transform_ptr write_user_transform_fn; /* user write transform */ -#endif - -/* These were added in libpng-1.0.2 */ -#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) - png_voidp user_transform_ptr; /* user supplied struct for user transform */ - png_byte user_transform_depth; /* bit depth of user transformed pixels */ - png_byte user_transform_channels; /* channels in user transformed pixels */ -#endif -#endif - - png_uint_32 mode; /* tells us where we are in the PNG file */ - png_uint_32 flags; /* flags indicating various things to libpng */ - png_uint_32 transformations; /* which transformations to perform */ - - z_stream zstream; /* pointer to decompression structure (below) */ - png_bytep zbuf; /* buffer for zlib */ - png_size_t zbuf_size; /* size of zbuf */ - int zlib_level; /* holds zlib compression level */ - int zlib_method; /* holds zlib compression method */ - int zlib_window_bits; /* holds zlib compression window bits */ - int zlib_mem_level; /* holds zlib compression memory level */ - int zlib_strategy; /* holds zlib compression strategy */ - - png_uint_32 width; /* width of image in pixels */ - png_uint_32 height; /* height of image in pixels */ - png_uint_32 num_rows; /* number of rows in current pass */ - png_uint_32 usr_width; /* width of row at start of write */ - png_uint_32 rowbytes; /* size of row in bytes */ - png_uint_32 irowbytes; /* size of current interlaced row in bytes */ - png_uint_32 iwidth; /* width of current interlaced row in pixels */ - png_uint_32 row_number; /* current row in interlace pass */ - png_bytep prev_row; /* buffer to save previous (unfiltered) row */ - png_bytep row_buf; /* buffer to save current (unfiltered) row */ - png_bytep sub_row; /* buffer to save "sub" row when filtering */ - png_bytep up_row; /* buffer to save "up" row when filtering */ - png_bytep avg_row; /* buffer to save "avg" row when filtering */ - png_bytep paeth_row; /* buffer to save "Paeth" row when filtering */ - png_row_info row_info; /* used for transformation routines */ - - png_uint_32 idat_size; /* current IDAT size for read */ - png_uint_32 crc; /* current chunk CRC value */ - png_colorp palette; /* palette from the input file */ - png_uint_16 num_palette; /* number of color entries in palette */ - png_uint_16 num_trans; /* number of transparency values */ - png_byte chunk_name[5]; /* null-terminated name of current chunk */ - png_byte compression; /* file compression type (always 0) */ - png_byte filter; /* file filter type (always 0) */ - png_byte interlaced; /* PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ - png_byte pass; /* current interlace pass (0 - 6) */ - png_byte do_filter; /* row filter flags (see PNG_FILTER_ below ) */ - png_byte color_type; /* color type of file */ - png_byte bit_depth; /* bit depth of file */ - png_byte usr_bit_depth; /* bit depth of users row */ - png_byte pixel_depth; /* number of bits per pixel */ - png_byte channels; /* number of channels in file */ - png_byte usr_channels; /* channels at start of write */ - png_byte sig_bytes; /* magic bytes read/written from start of file */ - -#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) -#ifdef PNG_LEGACY_SUPPORTED - png_byte filler; /* filler byte for pixel expansion */ -#else - png_uint_16 filler; /* filler bytes for pixel expansion */ -#endif -#endif - -#if defined(PNG_bKGD_SUPPORTED) - png_byte background_gamma_type; -# ifdef PNG_FLOATING_POINT_SUPPORTED - float background_gamma; -# endif - png_color_16 background; /* background color in screen gamma space */ -#if defined(PNG_READ_GAMMA_SUPPORTED) - png_color_16 background_1; /* background normalized to gamma 1.0 */ -#endif -#endif /* PNG_bKGD_SUPPORTED */ - -#if defined(PNG_WRITE_FLUSH_SUPPORTED) - png_flush_ptr output_flush_fn;/* Function for flushing output */ - png_uint_32 flush_dist; /* how many rows apart to flush, 0 - no flush */ - png_uint_32 flush_rows; /* number of rows written since last flush */ -#endif - -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - int gamma_shift; /* number of "insignificant" bits 16-bit gamma */ -#ifdef PNG_FLOATING_POINT_SUPPORTED - float gamma; /* file gamma value */ - float screen_gamma; /* screen gamma value (display_exponent) */ -#endif -#endif - -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - png_bytep gamma_table; /* gamma table for 8-bit depth files */ - png_bytep gamma_from_1; /* converts from 1.0 to screen */ - png_bytep gamma_to_1; /* converts from file to 1.0 */ - png_uint_16pp gamma_16_table; /* gamma table for 16-bit depth files */ - png_uint_16pp gamma_16_from_1; /* converts from 1.0 to screen */ - png_uint_16pp gamma_16_to_1; /* converts from file to 1.0 */ -#endif - -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_sBIT_SUPPORTED) - png_color_8 sig_bit; /* significant bits in each available channel */ -#endif - -#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) - png_color_8 shift; /* shift for significant bit tranformation */ -#endif - -#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) \ - || defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - png_bytep trans; /* transparency values for paletted files */ - png_color_16 trans_values; /* transparency values for non-paletted files */ -#endif - - png_read_status_ptr read_row_fn; /* called after each row is decoded */ - png_write_status_ptr write_row_fn; /* called after each row is encoded */ -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED - png_progressive_info_ptr info_fn; /* called after header data fully read */ - png_progressive_row_ptr row_fn; /* called after each prog. row is decoded */ - png_progressive_end_ptr end_fn; /* called after image is complete */ - png_bytep save_buffer_ptr; /* current location in save_buffer */ - png_bytep save_buffer; /* buffer for previously read data */ - png_bytep current_buffer_ptr; /* current location in current_buffer */ - png_bytep current_buffer; /* buffer for recently used data */ - png_uint_32 push_length; /* size of current input chunk */ - png_uint_32 skip_length; /* bytes to skip in input data */ - png_size_t save_buffer_size; /* amount of data now in save_buffer */ - png_size_t save_buffer_max; /* total size of save_buffer */ - png_size_t buffer_size; /* total amount of available input data */ - png_size_t current_buffer_size; /* amount of data now in current_buffer */ - int process_mode; /* what push library is currently doing */ - int cur_palette; /* current push library palette index */ - -# if defined(PNG_TEXT_SUPPORTED) - png_size_t current_text_size; /* current size of text input data */ - png_size_t current_text_left; /* how much text left to read in input */ - png_charp current_text; /* current text chunk buffer */ - png_charp current_text_ptr; /* current location in current_text */ -# endif /* PNG_TEXT_SUPPORTED */ -#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ - -#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__) -/* for the Borland special 64K segment handler */ - png_bytepp offset_table_ptr; - png_bytep offset_table; - png_uint_16 offset_table_number; - png_uint_16 offset_table_count; - png_uint_16 offset_table_count_free; -#endif - -#if defined(PNG_READ_DITHER_SUPPORTED) - png_bytep palette_lookup; /* lookup table for dithering */ - png_bytep dither_index; /* index translation for palette files */ -#endif - -#if defined(PNG_READ_DITHER_SUPPORTED) || defined(PNG_hIST_SUPPORTED) - png_uint_16p hist; /* histogram */ -#endif - -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - png_byte heuristic_method; /* heuristic for row filter selection */ - png_byte num_prev_filters; /* number of weights for previous rows */ - png_bytep prev_filters; /* filter type(s) of previous row(s) */ - png_uint_16p filter_weights; /* weight(s) for previous line(s) */ - png_uint_16p inv_filter_weights; /* 1/weight(s) for previous line(s) */ - png_uint_16p filter_costs; /* relative filter calculation cost */ - png_uint_16p inv_filter_costs; /* 1/relative filter calculation cost */ -#endif - -#if defined(PNG_TIME_RFC1123_SUPPORTED) - png_charp time_buffer; /* String to hold RFC 1123 time text */ -#endif - -/* New members added in libpng-1.0.6 */ - -#ifdef PNG_FREE_ME_SUPPORTED - png_uint_32 free_me; /* flags items libpng is responsible for freeing */ -#endif - -#if defined(PNG_USER_CHUNKS_SUPPORTED) - png_voidp user_chunk_ptr; - png_user_chunk_ptr read_user_chunk_fn; /* user read chunk handler */ -#endif - -#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) - int num_chunk_list; - png_bytep chunk_list; -#endif - -/* New members added in libpng-1.0.3 */ -#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) - png_byte rgb_to_gray_status; - /* These were changed from png_byte in libpng-1.0.6 */ - png_uint_16 rgb_to_gray_red_coeff; - png_uint_16 rgb_to_gray_green_coeff; - png_uint_16 rgb_to_gray_blue_coeff; -#endif - -/* New member added in libpng-1.0.4 (renamed in 1.0.9) */ -#if defined(PNG_MNG_FEATURES_SUPPORTED) || \ - defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \ - defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) -/* changed from png_byte to png_uint_32 at version 1.2.0 */ -#ifdef PNG_1_0_X - png_byte mng_features_permitted; -#else - png_uint_32 mng_features_permitted; -#endif /* PNG_1_0_X */ -#endif - -/* New member added in libpng-1.0.7 */ -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - png_fixed_point int_gamma; -#endif - -/* New member added in libpng-1.0.9, ifdef'ed out in 1.0.12, enabled in 1.2.0 */ -#if defined(PNG_MNG_FEATURES_SUPPORTED) - png_byte filter_type; -#endif - -#if defined(PNG_1_0_X) -/* New member added in libpng-1.0.10, ifdef'ed out in 1.2.0 */ - png_uint_32 row_buf_size; -#endif - -/* New members added in libpng-1.2.0 */ -#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) -# if !defined(PNG_1_0_X) -# if defined(PNG_MMX_CODE_SUPPORTED) - png_byte mmx_bitdepth_threshold; - png_uint_32 mmx_rowbytes_threshold; -# endif - png_uint_32 asm_flags; -# endif -#endif - -/* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */ -#ifdef PNG_USER_MEM_SUPPORTED - png_voidp mem_ptr; /* user supplied struct for mem functions */ - png_malloc_ptr malloc_fn; /* function for allocating memory */ - png_free_ptr free_fn; /* function for freeing memory */ -#endif - -/* New member added in libpng-1.0.13 and 1.2.0 */ - png_bytep big_row_buf; /* buffer to save current (unfiltered) row */ - -#if defined(PNG_READ_DITHER_SUPPORTED) -/* The following three members were added at version 1.0.14 and 1.2.4 */ - png_bytep dither_sort; /* working sort array */ - png_bytep index_to_palette; /* where the original index currently is */ - /* in the palette */ - png_bytep palette_to_index; /* which original index points to this */ - /* palette color */ -#endif - -/* New members added in libpng-1.0.16 and 1.2.6 */ - png_byte compression_type; - -#ifdef PNG_SET_USER_LIMITS_SUPPORTED - png_uint_32 user_width_max; - png_uint_32 user_height_max; -#endif - -/* New member added in libpng-1.0.25 and 1.2.17 */ -#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) - /* storage for unknown chunk that the library doesn't recognize. */ - png_unknown_chunk unknown_chunk; -#endif -}; - - -/* This triggers a compiler error in png.c, if png.c and png.h - * do not agree upon the version number. - */ -typedef png_structp version_1_2_22; - -typedef png_struct FAR * FAR * png_structpp; - -/* Here are the function definitions most commonly used. This is not - * the place to find out how to use libpng. See libpng.txt for the - * full explanation, see example.c for the summary. This just provides - * a simple one line description of the use of each function. - */ - -/* Returns the version number of the library */ -extern PNG_EXPORT(png_uint_32,png_access_version_number) PNGARG((void)); - -/* Tell lib we have already handled the first magic bytes. - * Handling more than 8 bytes from the beginning of the file is an error. - */ -extern PNG_EXPORT(void,png_set_sig_bytes) PNGARG((png_structp png_ptr, - int num_bytes)); - -/* Check sig[start] through sig[start + num_to_check - 1] to see if it's a - * PNG file. Returns zero if the supplied bytes match the 8-byte PNG - * signature, and non-zero otherwise. Having num_to_check == 0 or - * start > 7 will always fail (ie return non-zero). - */ -extern PNG_EXPORT(int,png_sig_cmp) PNGARG((png_bytep sig, png_size_t start, - png_size_t num_to_check)); - -/* Simple signature checking function. This is the same as calling - * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). - */ -extern PNG_EXPORT(int,png_check_sig) PNGARG((png_bytep sig, int num)); - -/* Allocate and initialize png_ptr struct for reading, and any other memory. */ -extern PNG_EXPORT(png_structp,png_create_read_struct) - PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn)); - -/* Allocate and initialize png_ptr struct for writing, and any other memory */ -extern PNG_EXPORT(png_structp,png_create_write_struct) - PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn)); - -#ifdef PNG_WRITE_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_compression_buffer_size) - PNGARG((png_structp png_ptr)); -#endif - -#ifdef PNG_WRITE_SUPPORTED -extern PNG_EXPORT(void,png_set_compression_buffer_size) - PNGARG((png_structp png_ptr, png_uint_32 size)); -#endif - -/* Reset the compression stream */ -extern PNG_EXPORT(int,png_reset_zstream) PNGARG((png_structp png_ptr)); - -/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */ -#ifdef PNG_USER_MEM_SUPPORTED -extern PNG_EXPORT(png_structp,png_create_read_struct_2) - PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, - png_malloc_ptr malloc_fn, png_free_ptr free_fn)); -extern PNG_EXPORT(png_structp,png_create_write_struct_2) - PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, - png_malloc_ptr malloc_fn, png_free_ptr free_fn)); -#endif - -/* Write a PNG chunk - size, type, (optional) data, CRC. */ -extern PNG_EXPORT(void,png_write_chunk) PNGARG((png_structp png_ptr, - png_bytep chunk_name, png_bytep data, png_size_t length)); - -/* Write the start of a PNG chunk - length and chunk name. */ -extern PNG_EXPORT(void,png_write_chunk_start) PNGARG((png_structp png_ptr, - png_bytep chunk_name, png_uint_32 length)); - -/* Write the data of a PNG chunk started with png_write_chunk_start(). */ -extern PNG_EXPORT(void,png_write_chunk_data) PNGARG((png_structp png_ptr, - png_bytep data, png_size_t length)); - -/* Finish a chunk started with png_write_chunk_start() (includes CRC). */ -extern PNG_EXPORT(void,png_write_chunk_end) PNGARG((png_structp png_ptr)); - -/* Allocate and initialize the info structure */ -extern PNG_EXPORT(png_infop,png_create_info_struct) - PNGARG((png_structp png_ptr)); - -#if defined(PNG_1_0_X) || defined (PNG_1_2_X) -/* Initialize the info structure (old interface - DEPRECATED) */ -extern PNG_EXPORT(void,png_info_init) PNGARG((png_infop info_ptr)); -#undef png_info_init -#define png_info_init(info_ptr) png_info_init_3(&info_ptr,\ - png_sizeof(png_info)); -#endif - -extern PNG_EXPORT(void,png_info_init_3) PNGARG((png_infopp info_ptr, - png_size_t png_info_struct_size)); - -/* Writes all the PNG information before the image. */ -extern PNG_EXPORT(void,png_write_info_before_PLTE) PNGARG((png_structp png_ptr, - png_infop info_ptr)); -extern PNG_EXPORT(void,png_write_info) PNGARG((png_structp png_ptr, - png_infop info_ptr)); - -#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED -/* read the information before the actual image data. */ -extern PNG_EXPORT(void,png_read_info) PNGARG((png_structp png_ptr, - png_infop info_ptr)); -#endif - -#if defined(PNG_TIME_RFC1123_SUPPORTED) -extern PNG_EXPORT(png_charp,png_convert_to_rfc1123) - PNGARG((png_structp png_ptr, png_timep ptime)); -#endif - -#if !defined(_WIN32_WCE) -/* "time.h" functions are not supported on WindowsCE */ -#if defined(PNG_WRITE_tIME_SUPPORTED) -/* convert from a struct tm to png_time */ -extern PNG_EXPORT(void,png_convert_from_struct_tm) PNGARG((png_timep ptime, - struct tm FAR * ttime)); - -/* convert from time_t to png_time. Uses gmtime() */ -extern PNG_EXPORT(void,png_convert_from_time_t) PNGARG((png_timep ptime, - time_t ttime)); -#endif /* PNG_WRITE_tIME_SUPPORTED */ -#endif /* _WIN32_WCE */ - -#if defined(PNG_READ_EXPAND_SUPPORTED) -/* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */ -extern PNG_EXPORT(void,png_set_expand) PNGARG((png_structp png_ptr)); -#if !defined(PNG_1_0_X) -extern PNG_EXPORT(void,png_set_expand_gray_1_2_4_to_8) PNGARG((png_structp - png_ptr)); -#endif -extern PNG_EXPORT(void,png_set_palette_to_rgb) PNGARG((png_structp png_ptr)); -extern PNG_EXPORT(void,png_set_tRNS_to_alpha) PNGARG((png_structp png_ptr)); -#if defined(PNG_1_0_X) || defined (PNG_1_2_X) -/* Deprecated */ -extern PNG_EXPORT(void,png_set_gray_1_2_4_to_8) PNGARG((png_structp png_ptr)); -#endif -#endif - -#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) -/* Use blue, green, red order for pixels. */ -extern PNG_EXPORT(void,png_set_bgr) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) -/* Expand the grayscale to 24-bit RGB if necessary. */ -extern PNG_EXPORT(void,png_set_gray_to_rgb) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) -/* Reduce RGB to grayscale. */ -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_rgb_to_gray) PNGARG((png_structp png_ptr, - int error_action, double red, double green )); -#endif -extern PNG_EXPORT(void,png_set_rgb_to_gray_fixed) PNGARG((png_structp png_ptr, - int error_action, png_fixed_point red, png_fixed_point green )); -extern PNG_EXPORT(png_byte,png_get_rgb_to_gray_status) PNGARG((png_structp - png_ptr)); -#endif - -extern PNG_EXPORT(void,png_build_grayscale_palette) PNGARG((int bit_depth, - png_colorp palette)); - -#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) -extern PNG_EXPORT(void,png_set_strip_alpha) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ - defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) -extern PNG_EXPORT(void,png_set_swap_alpha) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ - defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) -extern PNG_EXPORT(void,png_set_invert_alpha) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) -/* Add a filler byte to 8-bit Gray or 24-bit RGB images. */ -extern PNG_EXPORT(void,png_set_filler) PNGARG((png_structp png_ptr, - png_uint_32 filler, int flags)); -/* The values of the PNG_FILLER_ defines should NOT be changed */ -#define PNG_FILLER_BEFORE 0 -#define PNG_FILLER_AFTER 1 -/* Add an alpha byte to 8-bit Gray or 24-bit RGB images. */ -#if !defined(PNG_1_0_X) -extern PNG_EXPORT(void,png_set_add_alpha) PNGARG((png_structp png_ptr, - png_uint_32 filler, int flags)); -#endif -#endif /* PNG_READ_FILLER_SUPPORTED || PNG_WRITE_FILLER_SUPPORTED */ - -#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) -/* Swap bytes in 16-bit depth files. */ -extern PNG_EXPORT(void,png_set_swap) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) -/* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */ -extern PNG_EXPORT(void,png_set_packing) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_PACKSWAP_SUPPORTED) || defined(PNG_WRITE_PACKSWAP_SUPPORTED) -/* Swap packing order of pixels in bytes. */ -extern PNG_EXPORT(void,png_set_packswap) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) -/* Converts files to legal bit depths. */ -extern PNG_EXPORT(void,png_set_shift) PNGARG((png_structp png_ptr, - png_color_8p true_bits)); -#endif - -#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ - defined(PNG_WRITE_INTERLACING_SUPPORTED) -/* Have the code handle the interlacing. Returns the number of passes. */ -extern PNG_EXPORT(int,png_set_interlace_handling) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) -/* Invert monochrome files */ -extern PNG_EXPORT(void,png_set_invert_mono) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_BACKGROUND_SUPPORTED) -/* Handle alpha and tRNS by replacing with a background color. */ -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_background) PNGARG((png_structp png_ptr, - png_color_16p background_color, int background_gamma_code, - int need_expand, double background_gamma)); -#endif -#define PNG_BACKGROUND_GAMMA_UNKNOWN 0 -#define PNG_BACKGROUND_GAMMA_SCREEN 1 -#define PNG_BACKGROUND_GAMMA_FILE 2 -#define PNG_BACKGROUND_GAMMA_UNIQUE 3 -#endif - -#if defined(PNG_READ_16_TO_8_SUPPORTED) -/* strip the second byte of information from a 16-bit depth file. */ -extern PNG_EXPORT(void,png_set_strip_16) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_DITHER_SUPPORTED) -/* Turn on dithering, and reduce the palette to the number of colors available. */ -extern PNG_EXPORT(void,png_set_dither) PNGARG((png_structp png_ptr, - png_colorp palette, int num_palette, int maximum_colors, - png_uint_16p histogram, int full_dither)); -#endif - -#if defined(PNG_READ_GAMMA_SUPPORTED) -/* Handle gamma correction. Screen_gamma=(display_exponent) */ -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_gamma) PNGARG((png_structp png_ptr, - double screen_gamma, double default_file_gamma)); -#endif -#endif - -#if defined(PNG_1_0_X) || defined (PNG_1_2_X) -#if defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \ - defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) -/* Permit or disallow empty PLTE (0: not permitted, 1: permitted) */ -/* Deprecated and will be removed. Use png_permit_mng_features() instead. */ -extern PNG_EXPORT(void,png_permit_empty_plte) PNGARG((png_structp png_ptr, - int empty_plte_permitted)); -#endif -#endif - -#if defined(PNG_WRITE_FLUSH_SUPPORTED) -/* Set how many lines between output flushes - 0 for no flushing */ -extern PNG_EXPORT(void,png_set_flush) PNGARG((png_structp png_ptr, int nrows)); -/* Flush the current PNG output buffer */ -extern PNG_EXPORT(void,png_write_flush) PNGARG((png_structp png_ptr)); -#endif - -/* optional update palette with requested transformations */ -extern PNG_EXPORT(void,png_start_read_image) PNGARG((png_structp png_ptr)); - -/* optional call to update the users info structure */ -extern PNG_EXPORT(void,png_read_update_info) PNGARG((png_structp png_ptr, - png_infop info_ptr)); - -#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED -/* read one or more rows of image data. */ -extern PNG_EXPORT(void,png_read_rows) PNGARG((png_structp png_ptr, - png_bytepp row, png_bytepp display_row, png_uint_32 num_rows)); -#endif - -#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED -/* read a row of data. */ -extern PNG_EXPORT(void,png_read_row) PNGARG((png_structp png_ptr, - png_bytep row, - png_bytep display_row)); -#endif - -#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED -/* read the whole image into memory at once. */ -extern PNG_EXPORT(void,png_read_image) PNGARG((png_structp png_ptr, - png_bytepp image)); -#endif - -/* write a row of image data */ -extern PNG_EXPORT(void,png_write_row) PNGARG((png_structp png_ptr, - png_bytep row)); - -/* write a few rows of image data */ -extern PNG_EXPORT(void,png_write_rows) PNGARG((png_structp png_ptr, - png_bytepp row, png_uint_32 num_rows)); - -/* write the image data */ -extern PNG_EXPORT(void,png_write_image) PNGARG((png_structp png_ptr, - png_bytepp image)); - -/* writes the end of the PNG file. */ -extern PNG_EXPORT(void,png_write_end) PNGARG((png_structp png_ptr, - png_infop info_ptr)); - -#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED -/* read the end of the PNG file. */ -extern PNG_EXPORT(void,png_read_end) PNGARG((png_structp png_ptr, - png_infop info_ptr)); -#endif - -/* free any memory associated with the png_info_struct */ -extern PNG_EXPORT(void,png_destroy_info_struct) PNGARG((png_structp png_ptr, - png_infopp info_ptr_ptr)); - -/* free any memory associated with the png_struct and the png_info_structs */ -extern PNG_EXPORT(void,png_destroy_read_struct) PNGARG((png_structpp - png_ptr_ptr, png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr)); - -/* free all memory used by the read (old method - NOT DLL EXPORTED) */ -extern void png_read_destroy PNGARG((png_structp png_ptr, png_infop info_ptr, - png_infop end_info_ptr)); - -/* free any memory associated with the png_struct and the png_info_structs */ -extern PNG_EXPORT(void,png_destroy_write_struct) - PNGARG((png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)); - -/* free any memory used in png_ptr struct (old method - NOT DLL EXPORTED) */ -extern void png_write_destroy PNGARG((png_structp png_ptr)); - -/* set the libpng method of handling chunk CRC errors */ -extern PNG_EXPORT(void,png_set_crc_action) PNGARG((png_structp png_ptr, - int crit_action, int ancil_action)); - -/* Values for png_set_crc_action() to say how to handle CRC errors in - * ancillary and critical chunks, and whether to use the data contained - * therein. Note that it is impossible to "discard" data in a critical - * chunk. For versions prior to 0.90, the action was always error/quit, - * whereas in version 0.90 and later, the action for CRC errors in ancillary - * chunks is warn/discard. These values should NOT be changed. - * - * value action:critical action:ancillary - */ -#define PNG_CRC_DEFAULT 0 /* error/quit warn/discard data */ -#define PNG_CRC_ERROR_QUIT 1 /* error/quit error/quit */ -#define PNG_CRC_WARN_DISCARD 2 /* (INVALID) warn/discard data */ -#define PNG_CRC_WARN_USE 3 /* warn/use data warn/use data */ -#define PNG_CRC_QUIET_USE 4 /* quiet/use data quiet/use data */ -#define PNG_CRC_NO_CHANGE 5 /* use current value use current value */ - -/* These functions give the user control over the scan-line filtering in - * libpng and the compression methods used by zlib. These functions are - * mainly useful for testing, as the defaults should work with most users. - * Those users who are tight on memory or want faster performance at the - * expense of compression can modify them. See the compression library - * header file (zlib.h) for an explination of the compression functions. - */ - -/* set the filtering method(s) used by libpng. Currently, the only valid - * value for "method" is 0. - */ -extern PNG_EXPORT(void,png_set_filter) PNGARG((png_structp png_ptr, int method, - int filters)); - -/* Flags for png_set_filter() to say which filters to use. The flags - * are chosen so that they don't conflict with real filter types - * below, in case they are supplied instead of the #defined constants. - * These values should NOT be changed. - */ -#define PNG_NO_FILTERS 0x00 -#define PNG_FILTER_NONE 0x08 -#define PNG_FILTER_SUB 0x10 -#define PNG_FILTER_UP 0x20 -#define PNG_FILTER_AVG 0x40 -#define PNG_FILTER_PAETH 0x80 -#define PNG_ALL_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP | \ - PNG_FILTER_AVG | PNG_FILTER_PAETH) - -/* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now. - * These defines should NOT be changed. - */ -#define PNG_FILTER_VALUE_NONE 0 -#define PNG_FILTER_VALUE_SUB 1 -#define PNG_FILTER_VALUE_UP 2 -#define PNG_FILTER_VALUE_AVG 3 -#define PNG_FILTER_VALUE_PAETH 4 -#define PNG_FILTER_VALUE_LAST 5 - -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) /* EXPERIMENTAL */ -/* The "heuristic_method" is given by one of the PNG_FILTER_HEURISTIC_ - * defines, either the default (minimum-sum-of-absolute-differences), or - * the experimental method (weighted-minimum-sum-of-absolute-differences). - * - * Weights are factors >= 1.0, indicating how important it is to keep the - * filter type consistent between rows. Larger numbers mean the current - * filter is that many times as likely to be the same as the "num_weights" - * previous filters. This is cumulative for each previous row with a weight. - * There needs to be "num_weights" values in "filter_weights", or it can be - * NULL if the weights aren't being specified. Weights have no influence on - * the selection of the first row filter. Well chosen weights can (in theory) - * improve the compression for a given image. - * - * Costs are factors >= 1.0 indicating the relative decoding costs of a - * filter type. Higher costs indicate more decoding expense, and are - * therefore less likely to be selected over a filter with lower computational - * costs. There needs to be a value in "filter_costs" for each valid filter - * type (given by PNG_FILTER_VALUE_LAST), or it can be NULL if you aren't - * setting the costs. Costs try to improve the speed of decompression without - * unduly increasing the compressed image size. - * - * A negative weight or cost indicates the default value is to be used, and - * values in the range [0.0, 1.0) indicate the value is to remain unchanged. - * The default values for both weights and costs are currently 1.0, but may - * change if good general weighting/cost heuristics can be found. If both - * the weights and costs are set to 1.0, this degenerates the WEIGHTED method - * to the UNWEIGHTED method, but with added encoding time/computation. - */ -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_filter_heuristics) PNGARG((png_structp png_ptr, - int heuristic_method, int num_weights, png_doublep filter_weights, - png_doublep filter_costs)); -#endif -#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ - -/* Heuristic used for row filter selection. These defines should NOT be - * changed. - */ -#define PNG_FILTER_HEURISTIC_DEFAULT 0 /* Currently "UNWEIGHTED" */ -#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1 /* Used by libpng < 0.95 */ -#define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */ -#define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */ - -/* Set the library compression level. Currently, valid values range from - * 0 - 9, corresponding directly to the zlib compression levels 0 - 9 - * (0 - no compression, 9 - "maximal" compression). Note that tests have - * shown that zlib compression levels 3-6 usually perform as well as level 9 - * for PNG images, and do considerably fewer caclulations. In the future, - * these values may not correspond directly to the zlib compression levels. - */ -extern PNG_EXPORT(void,png_set_compression_level) PNGARG((png_structp png_ptr, - int level)); - -extern PNG_EXPORT(void,png_set_compression_mem_level) - PNGARG((png_structp png_ptr, int mem_level)); - -extern PNG_EXPORT(void,png_set_compression_strategy) - PNGARG((png_structp png_ptr, int strategy)); - -extern PNG_EXPORT(void,png_set_compression_window_bits) - PNGARG((png_structp png_ptr, int window_bits)); - -extern PNG_EXPORT(void,png_set_compression_method) PNGARG((png_structp png_ptr, - int method)); - -/* These next functions are called for input/output, memory, and error - * handling. They are in the file pngrio.c, pngwio.c, and pngerror.c, - * and call standard C I/O routines such as fread(), fwrite(), and - * fprintf(). These functions can be made to use other I/O routines - * at run time for those applications that need to handle I/O in a - * different manner by calling png_set_???_fn(). See libpng.txt for - * more information. - */ - -#if !defined(PNG_NO_STDIO) -/* Initialize the input/output for the PNG file to the default functions. */ -extern PNG_EXPORT(void,png_init_io) PNGARG((png_structp png_ptr, png_FILE_p fp)); -#endif - -/* Replace the (error and abort), and warning functions with user - * supplied functions. If no messages are to be printed you must still - * write and use replacement functions. The replacement error_fn should - * still do a longjmp to the last setjmp location if you are using this - * method of error handling. If error_fn or warning_fn is NULL, the - * default function will be used. - */ - -extern PNG_EXPORT(void,png_set_error_fn) PNGARG((png_structp png_ptr, - png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn)); - -/* Return the user pointer associated with the error functions */ -extern PNG_EXPORT(png_voidp,png_get_error_ptr) PNGARG((png_structp png_ptr)); - -/* Replace the default data output functions with a user supplied one(s). - * If buffered output is not used, then output_flush_fn can be set to NULL. - * If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time - * output_flush_fn will be ignored (and thus can be NULL). - */ -extern PNG_EXPORT(void,png_set_write_fn) PNGARG((png_structp png_ptr, - png_voidp io_ptr, png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)); - -/* Replace the default data input function with a user supplied one. */ -extern PNG_EXPORT(void,png_set_read_fn) PNGARG((png_structp png_ptr, - png_voidp io_ptr, png_rw_ptr read_data_fn)); - -/* Return the user pointer associated with the I/O functions */ -extern PNG_EXPORT(png_voidp,png_get_io_ptr) PNGARG((png_structp png_ptr)); - -extern PNG_EXPORT(void,png_set_read_status_fn) PNGARG((png_structp png_ptr, - png_read_status_ptr read_row_fn)); - -extern PNG_EXPORT(void,png_set_write_status_fn) PNGARG((png_structp png_ptr, - png_write_status_ptr write_row_fn)); - -#ifdef PNG_USER_MEM_SUPPORTED -/* Replace the default memory allocation functions with user supplied one(s). */ -extern PNG_EXPORT(void,png_set_mem_fn) PNGARG((png_structp png_ptr, - png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn)); -/* Return the user pointer associated with the memory functions */ -extern PNG_EXPORT(png_voidp,png_get_mem_ptr) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_LEGACY_SUPPORTED) -extern PNG_EXPORT(void,png_set_read_user_transform_fn) PNGARG((png_structp - png_ptr, png_user_transform_ptr read_user_transform_fn)); -#endif - -#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_LEGACY_SUPPORTED) -extern PNG_EXPORT(void,png_set_write_user_transform_fn) PNGARG((png_structp - png_ptr, png_user_transform_ptr write_user_transform_fn)); -#endif - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_LEGACY_SUPPORTED) -extern PNG_EXPORT(void,png_set_user_transform_info) PNGARG((png_structp - png_ptr, png_voidp user_transform_ptr, int user_transform_depth, - int user_transform_channels)); -/* Return the user pointer associated with the user transform functions */ -extern PNG_EXPORT(png_voidp,png_get_user_transform_ptr) - PNGARG((png_structp png_ptr)); -#endif - -#ifdef PNG_USER_CHUNKS_SUPPORTED -extern PNG_EXPORT(void,png_set_read_user_chunk_fn) PNGARG((png_structp png_ptr, - png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)); -extern PNG_EXPORT(png_voidp,png_get_user_chunk_ptr) PNGARG((png_structp - png_ptr)); -#endif - -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED -/* Sets the function callbacks for the push reader, and a pointer to a - * user-defined structure available to the callback functions. - */ -extern PNG_EXPORT(void,png_set_progressive_read_fn) PNGARG((png_structp png_ptr, - png_voidp progressive_ptr, - png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn, - png_progressive_end_ptr end_fn)); - -/* returns the user pointer associated with the push read functions */ -extern PNG_EXPORT(png_voidp,png_get_progressive_ptr) - PNGARG((png_structp png_ptr)); - -/* function to be called when data becomes available */ -extern PNG_EXPORT(void,png_process_data) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_bytep buffer, png_size_t buffer_size)); - -/* function that combines rows. Not very much different than the - * png_combine_row() call. Is this even used????? - */ -extern PNG_EXPORT(void,png_progressive_combine_row) PNGARG((png_structp png_ptr, - png_bytep old_row, png_bytep new_row)); -#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ - -extern PNG_EXPORT(png_voidp,png_malloc) PNGARG((png_structp png_ptr, - png_uint_32 size)); - -#if defined(PNG_1_0_X) -# define png_malloc_warn png_malloc -#else -/* Added at libpng version 1.2.4 */ -extern PNG_EXPORT(png_voidp,png_malloc_warn) PNGARG((png_structp png_ptr, - png_uint_32 size)); -#endif - -/* frees a pointer allocated by png_malloc() */ -extern PNG_EXPORT(void,png_free) PNGARG((png_structp png_ptr, png_voidp ptr)); - -#if defined(PNG_1_0_X) -/* Function to allocate memory for zlib. */ -extern PNG_EXPORT(voidpf,png_zalloc) PNGARG((voidpf png_ptr, uInt items, - uInt size)); - -/* Function to free memory for zlib */ -extern PNG_EXPORT(void,png_zfree) PNGARG((voidpf png_ptr, voidpf ptr)); -#endif - -/* Free data that was allocated internally */ -extern PNG_EXPORT(void,png_free_data) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 free_me, int num)); -#ifdef PNG_FREE_ME_SUPPORTED -/* Reassign responsibility for freeing existing data, whether allocated - * by libpng or by the application */ -extern PNG_EXPORT(void,png_data_freer) PNGARG((png_structp png_ptr, - png_infop info_ptr, int freer, png_uint_32 mask)); -#endif -/* assignments for png_data_freer */ -#define PNG_DESTROY_WILL_FREE_DATA 1 -#define PNG_SET_WILL_FREE_DATA 1 -#define PNG_USER_WILL_FREE_DATA 2 -/* Flags for png_ptr->free_me and info_ptr->free_me */ -#define PNG_FREE_HIST 0x0008 -#define PNG_FREE_ICCP 0x0010 -#define PNG_FREE_SPLT 0x0020 -#define PNG_FREE_ROWS 0x0040 -#define PNG_FREE_PCAL 0x0080 -#define PNG_FREE_SCAL 0x0100 -#define PNG_FREE_UNKN 0x0200 -#define PNG_FREE_LIST 0x0400 -#define PNG_FREE_PLTE 0x1000 -#define PNG_FREE_TRNS 0x2000 -#define PNG_FREE_TEXT 0x4000 -#define PNG_FREE_ALL 0x7fff -#define PNG_FREE_MUL 0x4220 /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ - -#ifdef PNG_USER_MEM_SUPPORTED -extern PNG_EXPORT(png_voidp,png_malloc_default) PNGARG((png_structp png_ptr, - png_uint_32 size)); -extern PNG_EXPORT(void,png_free_default) PNGARG((png_structp png_ptr, - png_voidp ptr)); -#endif - -extern PNG_EXPORT(png_voidp,png_memcpy_check) PNGARG((png_structp png_ptr, - png_voidp s1, png_voidp s2, png_uint_32 size)); - -extern PNG_EXPORT(png_voidp,png_memset_check) PNGARG((png_structp png_ptr, - png_voidp s1, int value, png_uint_32 size)); - -#if defined(USE_FAR_KEYWORD) /* memory model conversion function */ -extern void *png_far_to_near PNGARG((png_structp png_ptr,png_voidp ptr, - int check)); -#endif /* USE_FAR_KEYWORD */ - -#ifndef PNG_NO_ERROR_TEXT -/* Fatal error in PNG image of libpng - can't continue */ -extern PNG_EXPORT(void,png_error) PNGARG((png_structp png_ptr, - png_const_charp error_message)); - -/* The same, but the chunk name is prepended to the error string. */ -extern PNG_EXPORT(void,png_chunk_error) PNGARG((png_structp png_ptr, - png_const_charp error_message)); -#else -/* Fatal error in PNG image of libpng - can't continue */ -extern PNG_EXPORT(void,png_err) PNGARG((png_structp png_ptr)); -#endif - -#ifndef PNG_NO_WARNINGS -/* Non-fatal error in libpng. Can continue, but may have a problem. */ -extern PNG_EXPORT(void,png_warning) PNGARG((png_structp png_ptr, - png_const_charp warning_message)); - -#ifdef PNG_READ_SUPPORTED -/* Non-fatal error in libpng, chunk name is prepended to message. */ -extern PNG_EXPORT(void,png_chunk_warning) PNGARG((png_structp png_ptr, - png_const_charp warning_message)); -#endif /* PNG_READ_SUPPORTED */ -#endif /* PNG_NO_WARNINGS */ - -/* The png_set_ functions are for storing values in the png_info_struct. - * Similarly, the png_get_ calls are used to read values from the - * png_info_struct, either storing the parameters in the passed variables, or - * setting pointers into the png_info_struct where the data is stored. The - * png_get_ functions return a non-zero value if the data was available - * in info_ptr, or return zero and do not change any of the parameters if the - * data was not available. - * - * These functions should be used instead of directly accessing png_info - * to avoid problems with future changes in the size and internal layout of - * png_info_struct. - */ -/* Returns "flag" if chunk data is valid in info_ptr. */ -extern PNG_EXPORT(png_uint_32,png_get_valid) PNGARG((png_structp png_ptr, -png_infop info_ptr, png_uint_32 flag)); - -/* Returns number of bytes needed to hold a transformed row. */ -extern PNG_EXPORT(png_uint_32,png_get_rowbytes) PNGARG((png_structp png_ptr, -png_infop info_ptr)); - -#if defined(PNG_INFO_IMAGE_SUPPORTED) -/* Returns row_pointers, which is an array of pointers to scanlines that was -returned from png_read_png(). */ -extern PNG_EXPORT(png_bytepp,png_get_rows) PNGARG((png_structp png_ptr, -png_infop info_ptr)); -/* Set row_pointers, which is an array of pointers to scanlines for use -by png_write_png(). */ -extern PNG_EXPORT(void,png_set_rows) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_bytepp row_pointers)); -#endif - -/* Returns number of color channels in image. */ -extern PNG_EXPORT(png_byte,png_get_channels) PNGARG((png_structp png_ptr, -png_infop info_ptr)); - -#ifdef PNG_EASY_ACCESS_SUPPORTED -/* Returns image width in pixels. */ -extern PNG_EXPORT(png_uint_32, png_get_image_width) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -/* Returns image height in pixels. */ -extern PNG_EXPORT(png_uint_32, png_get_image_height) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -/* Returns image bit_depth. */ -extern PNG_EXPORT(png_byte, png_get_bit_depth) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -/* Returns image color_type. */ -extern PNG_EXPORT(png_byte, png_get_color_type) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -/* Returns image filter_type. */ -extern PNG_EXPORT(png_byte, png_get_filter_type) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -/* Returns image interlace_type. */ -extern PNG_EXPORT(png_byte, png_get_interlace_type) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -/* Returns image compression_type. */ -extern PNG_EXPORT(png_byte, png_get_compression_type) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -/* Returns image resolution in pixels per meter, from pHYs chunk data. */ -extern PNG_EXPORT(png_uint_32, png_get_pixels_per_meter) PNGARG((png_structp -png_ptr, png_infop info_ptr)); -extern PNG_EXPORT(png_uint_32, png_get_x_pixels_per_meter) PNGARG((png_structp -png_ptr, png_infop info_ptr)); -extern PNG_EXPORT(png_uint_32, png_get_y_pixels_per_meter) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -/* Returns pixel aspect ratio, computed from pHYs chunk data. */ -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(float, png_get_pixel_aspect_ratio) PNGARG((png_structp -png_ptr, png_infop info_ptr)); -#endif - -/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */ -extern PNG_EXPORT(png_int_32, png_get_x_offset_pixels) PNGARG((png_structp -png_ptr, png_infop info_ptr)); -extern PNG_EXPORT(png_int_32, png_get_y_offset_pixels) PNGARG((png_structp -png_ptr, png_infop info_ptr)); -extern PNG_EXPORT(png_int_32, png_get_x_offset_microns) PNGARG((png_structp -png_ptr, png_infop info_ptr)); -extern PNG_EXPORT(png_int_32, png_get_y_offset_microns) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -#endif /* PNG_EASY_ACCESS_SUPPORTED */ - -/* Returns pointer to signature string read from PNG header */ -extern PNG_EXPORT(png_bytep,png_get_signature) PNGARG((png_structp png_ptr, -png_infop info_ptr)); - -#if defined(PNG_bKGD_SUPPORTED) -extern PNG_EXPORT(png_uint_32,png_get_bKGD) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_color_16p *background)); -#endif - -#if defined(PNG_bKGD_SUPPORTED) -extern PNG_EXPORT(void,png_set_bKGD) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_color_16p background)); -#endif - -#if defined(PNG_cHRM_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_cHRM) PNGARG((png_structp png_ptr, - png_infop info_ptr, double *white_x, double *white_y, double *red_x, - double *red_y, double *green_x, double *green_y, double *blue_x, - double *blue_y)); -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_cHRM_fixed) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_fixed_point *int_white_x, png_fixed_point - *int_white_y, png_fixed_point *int_red_x, png_fixed_point *int_red_y, - png_fixed_point *int_green_x, png_fixed_point *int_green_y, png_fixed_point - *int_blue_x, png_fixed_point *int_blue_y)); -#endif -#endif - -#if defined(PNG_cHRM_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_cHRM) PNGARG((png_structp png_ptr, - png_infop info_ptr, double white_x, double white_y, double red_x, - double red_y, double green_x, double green_y, double blue_x, double blue_y)); -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_cHRM_fixed) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_fixed_point int_white_x, png_fixed_point int_white_y, - png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point - int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x, - png_fixed_point int_blue_y)); -#endif -#endif - -#if defined(PNG_gAMA_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_gAMA) PNGARG((png_structp png_ptr, - png_infop info_ptr, double *file_gamma)); -#endif -extern PNG_EXPORT(png_uint_32,png_get_gAMA_fixed) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_fixed_point *int_file_gamma)); -#endif - -#if defined(PNG_gAMA_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_gAMA) PNGARG((png_structp png_ptr, - png_infop info_ptr, double file_gamma)); -#endif -extern PNG_EXPORT(void,png_set_gAMA_fixed) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_fixed_point int_file_gamma)); -#endif - -#if defined(PNG_hIST_SUPPORTED) -extern PNG_EXPORT(png_uint_32,png_get_hIST) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_16p *hist)); -#endif - -#if defined(PNG_hIST_SUPPORTED) -extern PNG_EXPORT(void,png_set_hIST) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_16p hist)); -#endif - -extern PNG_EXPORT(png_uint_32,png_get_IHDR) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 *width, png_uint_32 *height, - int *bit_depth, int *color_type, int *interlace_method, - int *compression_method, int *filter_method)); - -extern PNG_EXPORT(void,png_set_IHDR) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 width, png_uint_32 height, int bit_depth, - int color_type, int interlace_method, int compression_method, - int filter_method)); - -#if defined(PNG_oFFs_SUPPORTED) -extern PNG_EXPORT(png_uint_32,png_get_oFFs) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_int_32 *offset_x, png_int_32 *offset_y, - int *unit_type)); -#endif - -#if defined(PNG_oFFs_SUPPORTED) -extern PNG_EXPORT(void,png_set_oFFs) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_int_32 offset_x, png_int_32 offset_y, - int unit_type)); -#endif - -#if defined(PNG_pCAL_SUPPORTED) -extern PNG_EXPORT(png_uint_32,png_get_pCAL) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_charp *purpose, png_int_32 *X0, png_int_32 *X1, - int *type, int *nparams, png_charp *units, png_charpp *params)); -#endif - -#if defined(PNG_pCAL_SUPPORTED) -extern PNG_EXPORT(void,png_set_pCAL) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_charp purpose, png_int_32 X0, png_int_32 X1, - int type, int nparams, png_charp units, png_charpp params)); -#endif - -#if defined(PNG_pHYs_SUPPORTED) -extern PNG_EXPORT(png_uint_32,png_get_pHYs) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); -#endif - -#if defined(PNG_pHYs_SUPPORTED) -extern PNG_EXPORT(void,png_set_pHYs) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 res_x, png_uint_32 res_y, int unit_type)); -#endif - -extern PNG_EXPORT(png_uint_32,png_get_PLTE) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_colorp *palette, int *num_palette)); - -extern PNG_EXPORT(void,png_set_PLTE) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_colorp palette, int num_palette)); - -#if defined(PNG_sBIT_SUPPORTED) -extern PNG_EXPORT(png_uint_32,png_get_sBIT) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_color_8p *sig_bit)); -#endif - -#if defined(PNG_sBIT_SUPPORTED) -extern PNG_EXPORT(void,png_set_sBIT) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_color_8p sig_bit)); -#endif - -#if defined(PNG_sRGB_SUPPORTED) -extern PNG_EXPORT(png_uint_32,png_get_sRGB) PNGARG((png_structp png_ptr, - png_infop info_ptr, int *intent)); -#endif - -#if defined(PNG_sRGB_SUPPORTED) -extern PNG_EXPORT(void,png_set_sRGB) PNGARG((png_structp png_ptr, - png_infop info_ptr, int intent)); -extern PNG_EXPORT(void,png_set_sRGB_gAMA_and_cHRM) PNGARG((png_structp png_ptr, - png_infop info_ptr, int intent)); -#endif - -#if defined(PNG_iCCP_SUPPORTED) -extern PNG_EXPORT(png_uint_32,png_get_iCCP) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_charpp name, int *compression_type, - png_charpp profile, png_uint_32 *proflen)); - /* Note to maintainer: profile should be png_bytepp */ -#endif - -#if defined(PNG_iCCP_SUPPORTED) -extern PNG_EXPORT(void,png_set_iCCP) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_charp name, int compression_type, - png_charp profile, png_uint_32 proflen)); - /* Note to maintainer: profile should be png_bytep */ -#endif - -#if defined(PNG_sPLT_SUPPORTED) -extern PNG_EXPORT(png_uint_32,png_get_sPLT) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_sPLT_tpp entries)); -#endif - -#if defined(PNG_sPLT_SUPPORTED) -extern PNG_EXPORT(void,png_set_sPLT) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_sPLT_tp entries, int nentries)); -#endif - -#if defined(PNG_TEXT_SUPPORTED) -/* png_get_text also returns the number of text chunks in *num_text */ -extern PNG_EXPORT(png_uint_32,png_get_text) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_textp *text_ptr, int *num_text)); -#endif - -/* - * Note while png_set_text() will accept a structure whose text, - * language, and translated keywords are NULL pointers, the structure - * returned by png_get_text will always contain regular - * zero-terminated C strings. They might be empty strings but - * they will never be NULL pointers. - */ - -#if defined(PNG_TEXT_SUPPORTED) -extern PNG_EXPORT(void,png_set_text) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_textp text_ptr, int num_text)); -#endif - -#if defined(PNG_tIME_SUPPORTED) -extern PNG_EXPORT(png_uint_32,png_get_tIME) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_timep *mod_time)); -#endif - -#if defined(PNG_tIME_SUPPORTED) -extern PNG_EXPORT(void,png_set_tIME) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_timep mod_time)); -#endif - -#if defined(PNG_tRNS_SUPPORTED) -extern PNG_EXPORT(png_uint_32,png_get_tRNS) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_bytep *trans, int *num_trans, - png_color_16p *trans_values)); -#endif - -#if defined(PNG_tRNS_SUPPORTED) -extern PNG_EXPORT(void,png_set_tRNS) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_bytep trans, int num_trans, - png_color_16p trans_values)); -#endif - -#if defined(PNG_tRNS_SUPPORTED) -#endif - -#if defined(PNG_sCAL_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_sCAL) PNGARG((png_structp png_ptr, - png_infop info_ptr, int *unit, double *width, double *height)); -#else -#ifdef PNG_FIXED_POINT_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_sCAL_s) PNGARG((png_structp png_ptr, - png_infop info_ptr, int *unit, png_charpp swidth, png_charpp sheight)); -#endif -#endif -#endif /* PNG_sCAL_SUPPORTED */ - -#if defined(PNG_sCAL_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_sCAL) PNGARG((png_structp png_ptr, - png_infop info_ptr, int unit, double width, double height)); -#else -#ifdef PNG_FIXED_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_sCAL_s) PNGARG((png_structp png_ptr, - png_infop info_ptr, int unit, png_charp swidth, png_charp sheight)); -#endif -#endif -#endif /* PNG_sCAL_SUPPORTED || PNG_WRITE_sCAL_SUPPORTED */ - -#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) -/* provide a list of chunks and how they are to be handled, if the built-in - handling or default unknown chunk handling is not desired. Any chunks not - listed will be handled in the default manner. The IHDR and IEND chunks - must not be listed. - keep = 0: follow default behaviour - = 1: do not keep - = 2: keep only if safe-to-copy - = 3: keep even if unsafe-to-copy -*/ -extern PNG_EXPORT(void, png_set_keep_unknown_chunks) PNGARG((png_structp - png_ptr, int keep, png_bytep chunk_list, int num_chunks)); -extern PNG_EXPORT(void, png_set_unknown_chunks) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns)); -extern PNG_EXPORT(void, png_set_unknown_chunk_location) - PNGARG((png_structp png_ptr, png_infop info_ptr, int chunk, int location)); -extern PNG_EXPORT(png_uint_32,png_get_unknown_chunks) PNGARG((png_structp - png_ptr, png_infop info_ptr, png_unknown_chunkpp entries)); -#endif -#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED -PNG_EXPORT(int,png_handle_as_unknown) PNGARG((png_structp png_ptr, png_bytep - chunk_name)); -#endif - -/* Png_free_data() will turn off the "valid" flag for anything it frees. - If you need to turn it off for a chunk that your application has freed, - you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK); */ -extern PNG_EXPORT(void, png_set_invalid) PNGARG((png_structp png_ptr, - png_infop info_ptr, int mask)); - -#if defined(PNG_INFO_IMAGE_SUPPORTED) -/* The "params" pointer is currently not used and is for future expansion. */ -extern PNG_EXPORT(void, png_read_png) PNGARG((png_structp png_ptr, - png_infop info_ptr, - int transforms, - png_voidp params)); -extern PNG_EXPORT(void, png_write_png) PNGARG((png_structp png_ptr, - png_infop info_ptr, - int transforms, - png_voidp params)); -#endif - -/* Define PNG_DEBUG at compile time for debugging information. Higher - * numbers for PNG_DEBUG mean more debugging information. This has - * only been added since version 0.95 so it is not implemented throughout - * libpng yet, but more support will be added as needed. - */ -#ifdef PNG_DEBUG -#if (PNG_DEBUG > 0) -#if !defined(PNG_DEBUG_FILE) && defined(_MSC_VER) -#include -#if (PNG_DEBUG > 1) -#define png_debug(l,m) _RPT0(_CRT_WARN,m) -#define png_debug1(l,m,p1) _RPT1(_CRT_WARN,m,p1) -#define png_debug2(l,m,p1,p2) _RPT2(_CRT_WARN,m,p1,p2) -#endif -#else /* PNG_DEBUG_FILE || !_MSC_VER */ -#ifndef PNG_DEBUG_FILE -#define PNG_DEBUG_FILE stderr -#endif /* PNG_DEBUG_FILE */ -#if (PNG_DEBUG > 1) -#define png_debug(l,m) \ -{ \ - int num_tabs=l; \ - fprintf(PNG_DEBUG_FILE,"%s"m,(num_tabs==1 ? "\t" : \ - (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":"")))); \ -} -#define png_debug1(l,m,p1) \ -{ \ - int num_tabs=l; \ - fprintf(PNG_DEBUG_FILE,"%s"m,(num_tabs==1 ? "\t" : \ - (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1); \ -} -#define png_debug2(l,m,p1,p2) \ -{ \ - int num_tabs=l; \ - fprintf(PNG_DEBUG_FILE,"%s"m,(num_tabs==1 ? "\t" : \ - (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1,p2); \ -} -#endif /* (PNG_DEBUG > 1) */ -#endif /* _MSC_VER */ -#endif /* (PNG_DEBUG > 0) */ -#endif /* PNG_DEBUG */ -#ifndef png_debug -#define png_debug(l, m) -#endif -#ifndef png_debug1 -#define png_debug1(l, m, p1) -#endif -#ifndef png_debug2 -#define png_debug2(l, m, p1, p2) -#endif - -extern PNG_EXPORT(png_charp,png_get_copyright) PNGARG((png_structp png_ptr)); -extern PNG_EXPORT(png_charp,png_get_header_ver) PNGARG((png_structp png_ptr)); -extern PNG_EXPORT(png_charp,png_get_header_version) PNGARG((png_structp png_ptr)); -extern PNG_EXPORT(png_charp,png_get_libpng_ver) PNGARG((png_structp png_ptr)); - -#ifdef PNG_MNG_FEATURES_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_permit_mng_features) PNGARG((png_structp - png_ptr, png_uint_32 mng_features_permitted)); -#endif - -/* For use in png_set_keep_unknown, added to version 1.2.6 */ -#define PNG_HANDLE_CHUNK_AS_DEFAULT 0 -#define PNG_HANDLE_CHUNK_NEVER 1 -#define PNG_HANDLE_CHUNK_IF_SAFE 2 -#define PNG_HANDLE_CHUNK_ALWAYS 3 - -/* Added to version 1.2.0 */ -#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) -#if defined(PNG_MMX_CODE_SUPPORTED) -#define PNG_ASM_FLAG_MMX_SUPPORT_COMPILED 0x01 /* not user-settable */ -#define PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU 0x02 /* not user-settable */ -#define PNG_ASM_FLAG_MMX_READ_COMBINE_ROW 0x04 -#define PNG_ASM_FLAG_MMX_READ_INTERLACE 0x08 -#define PNG_ASM_FLAG_MMX_READ_FILTER_SUB 0x10 -#define PNG_ASM_FLAG_MMX_READ_FILTER_UP 0x20 -#define PNG_ASM_FLAG_MMX_READ_FILTER_AVG 0x40 -#define PNG_ASM_FLAG_MMX_READ_FILTER_PAETH 0x80 -#define PNG_ASM_FLAGS_INITIALIZED 0x80000000 /* not user-settable */ - -#define PNG_MMX_READ_FLAGS ( PNG_ASM_FLAG_MMX_READ_COMBINE_ROW \ - | PNG_ASM_FLAG_MMX_READ_INTERLACE \ - | PNG_ASM_FLAG_MMX_READ_FILTER_SUB \ - | PNG_ASM_FLAG_MMX_READ_FILTER_UP \ - | PNG_ASM_FLAG_MMX_READ_FILTER_AVG \ - | PNG_ASM_FLAG_MMX_READ_FILTER_PAETH ) -#define PNG_MMX_WRITE_FLAGS ( 0 ) - -#define PNG_MMX_FLAGS ( PNG_ASM_FLAG_MMX_SUPPORT_COMPILED \ - | PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU \ - | PNG_MMX_READ_FLAGS \ - | PNG_MMX_WRITE_FLAGS ) - -#define PNG_SELECT_READ 1 -#define PNG_SELECT_WRITE 2 -#endif /* PNG_MMX_CODE_SUPPORTED */ - -#if !defined(PNG_1_0_X) -/* pngget.c */ -extern PNG_EXPORT(png_uint_32,png_get_mmx_flagmask) - PNGARG((int flag_select, int *compilerID)); - -/* pngget.c */ -extern PNG_EXPORT(png_uint_32,png_get_asm_flagmask) - PNGARG((int flag_select)); - -/* pngget.c */ -extern PNG_EXPORT(png_uint_32,png_get_asm_flags) - PNGARG((png_structp png_ptr)); - -/* pngget.c */ -extern PNG_EXPORT(png_byte,png_get_mmx_bitdepth_threshold) - PNGARG((png_structp png_ptr)); - -/* pngget.c */ -extern PNG_EXPORT(png_uint_32,png_get_mmx_rowbytes_threshold) - PNGARG((png_structp png_ptr)); - -/* pngset.c */ -extern PNG_EXPORT(void,png_set_asm_flags) - PNGARG((png_structp png_ptr, png_uint_32 asm_flags)); - -/* pngset.c */ -extern PNG_EXPORT(void,png_set_mmx_thresholds) - PNGARG((png_structp png_ptr, png_byte mmx_bitdepth_threshold, - png_uint_32 mmx_rowbytes_threshold)); - -#endif /* PNG_1_0_X */ - -#if !defined(PNG_1_0_X) -/* png.c, pnggccrd.c, or pngvcrd.c */ -extern PNG_EXPORT(int,png_mmx_support) PNGARG((void)); -#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */ - -/* Strip the prepended error numbers ("#nnn ") from error and warning - * messages before passing them to the error or warning handler. */ -#ifdef PNG_ERROR_NUMBERS_SUPPORTED -extern PNG_EXPORT(void,png_set_strip_error_numbers) PNGARG((png_structp - png_ptr, png_uint_32 strip_mode)); -#endif - -#endif /* PNG_1_0_X */ - -/* Added at libpng-1.2.6 */ -#ifdef PNG_SET_USER_LIMITS_SUPPORTED -extern PNG_EXPORT(void,png_set_user_limits) PNGARG((png_structp - png_ptr, png_uint_32 user_width_max, png_uint_32 user_height_max)); -extern PNG_EXPORT(png_uint_32,png_get_user_width_max) PNGARG((png_structp - png_ptr)); -extern PNG_EXPORT(png_uint_32,png_get_user_height_max) PNGARG((png_structp - png_ptr)); -#endif - -/* Maintainer: Put new public prototypes here ^, in libpng.3, and project defs */ - -#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED -/* With these routines we avoid an integer divide, which will be slower on - * most machines. However, it does take more operations than the corresponding - * divide method, so it may be slower on a few RISC systems. There are two - * shifts (by 8 or 16 bits) and an addition, versus a single integer divide. - * - * Note that the rounding factors are NOT supposed to be the same! 128 and - * 32768 are correct for the NODIV code; 127 and 32767 are correct for the - * standard method. - * - * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ] - */ - - /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ - -# define png_composite(composite, fg, alpha, bg) \ - { png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) * (png_uint_16)(alpha) \ - + (png_uint_16)(bg)*(png_uint_16)(255 - \ - (png_uint_16)(alpha)) + (png_uint_16)128); \ - (composite) = (png_byte)((temp + (temp >> 8)) >> 8); } - -# define png_composite_16(composite, fg, alpha, bg) \ - { png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) * (png_uint_32)(alpha) \ - + (png_uint_32)(bg)*(png_uint_32)(65535L - \ - (png_uint_32)(alpha)) + (png_uint_32)32768L); \ - (composite) = (png_uint_16)((temp + (temp >> 16)) >> 16); } - -#else /* standard method using integer division */ - -# define png_composite(composite, fg, alpha, bg) \ - (composite) = (png_byte)(((png_uint_16)(fg) * (png_uint_16)(alpha) + \ - (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \ - (png_uint_16)127) / 255) - -# define png_composite_16(composite, fg, alpha, bg) \ - (composite) = (png_uint_16)(((png_uint_32)(fg) * (png_uint_32)(alpha) + \ - (png_uint_32)(bg)*(png_uint_32)(65535L - (png_uint_32)(alpha)) + \ - (png_uint_32)32767) / (png_uint_32)65535L) - -#endif /* PNG_READ_COMPOSITE_NODIV_SUPPORTED */ - -/* Inline macros to do direct reads of bytes from the input buffer. These - * require that you are using an architecture that uses PNG byte ordering - * (MSB first) and supports unaligned data storage. I think that PowerPC - * in big-endian mode and 680x0 are the only ones that will support this. - * The x86 line of processors definitely do not. The png_get_int_32() - * routine also assumes we are using two's complement format for negative - * values, which is almost certainly true. - */ -#if defined(PNG_READ_BIG_ENDIAN_SUPPORTED) -# define png_get_uint_32(buf) ( *((png_uint_32p) (buf))) -# define png_get_uint_16(buf) ( *((png_uint_16p) (buf))) -# define png_get_int_32(buf) ( *((png_int_32p) (buf))) -#else -extern PNG_EXPORT(png_uint_32,png_get_uint_32) PNGARG((png_bytep buf)); -extern PNG_EXPORT(png_uint_16,png_get_uint_16) PNGARG((png_bytep buf)); -extern PNG_EXPORT(png_int_32,png_get_int_32) PNGARG((png_bytep buf)); -#endif /* !PNG_READ_BIG_ENDIAN_SUPPORTED */ -extern PNG_EXPORT(png_uint_32,png_get_uint_31) - PNGARG((png_structp png_ptr, png_bytep buf)); -/* No png_get_int_16 -- may be added if there's a real need for it. */ - -/* Place a 32-bit number into a buffer in PNG byte order (big-endian). - */ -extern PNG_EXPORT(void,png_save_uint_32) - PNGARG((png_bytep buf, png_uint_32 i)); -extern PNG_EXPORT(void,png_save_int_32) - PNGARG((png_bytep buf, png_int_32 i)); - -/* Place a 16-bit number into a buffer in PNG byte order. - * The parameter is declared unsigned int, not png_uint_16, - * just to avoid potential problems on pre-ANSI C compilers. - */ -extern PNG_EXPORT(void,png_save_uint_16) - PNGARG((png_bytep buf, unsigned int i)); -/* No png_save_int_16 -- may be added if there's a real need for it. */ - -/* ************************************************************************* */ - -/* These next functions are used internally in the code. They generally - * shouldn't be used unless you are writing code to add or replace some - * functionality in libpng. More information about most functions can - * be found in the files where the functions are located. - */ - - -/* Various modes of operation, that are visible to applications because - * they are used for unknown chunk location. - */ -#define PNG_HAVE_IHDR 0x01 -#define PNG_HAVE_PLTE 0x02 -#define PNG_HAVE_IDAT 0x04 -#define PNG_AFTER_IDAT 0x08 /* Have complete zlib datastream */ -#define PNG_HAVE_IEND 0x10 - -#if defined(PNG_INTERNAL) - -/* More modes of operation. Note that after an init, mode is set to - * zero automatically when the structure is created. - */ -#define PNG_HAVE_gAMA 0x20 -#define PNG_HAVE_cHRM 0x40 -#define PNG_HAVE_sRGB 0x80 -#define PNG_HAVE_CHUNK_HEADER 0x100 -#define PNG_WROTE_tIME 0x200 -#define PNG_WROTE_INFO_BEFORE_PLTE 0x400 -#define PNG_BACKGROUND_IS_GRAY 0x800 -#define PNG_HAVE_PNG_SIGNATURE 0x1000 -#define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000 /* Have another chunk after IDAT */ - -/* flags for the transformations the PNG library does on the image data */ -#define PNG_BGR 0x0001 -#define PNG_INTERLACE 0x0002 -#define PNG_PACK 0x0004 -#define PNG_SHIFT 0x0008 -#define PNG_SWAP_BYTES 0x0010 -#define PNG_INVERT_MONO 0x0020 -#define PNG_DITHER 0x0040 -#define PNG_BACKGROUND 0x0080 -#define PNG_BACKGROUND_EXPAND 0x0100 - /* 0x0200 unused */ -#define PNG_16_TO_8 0x0400 -#define PNG_RGBA 0x0800 -#define PNG_EXPAND 0x1000 -#define PNG_GAMMA 0x2000 -#define PNG_GRAY_TO_RGB 0x4000 -#define PNG_FILLER 0x8000L -#define PNG_PACKSWAP 0x10000L -#define PNG_SWAP_ALPHA 0x20000L -#define PNG_STRIP_ALPHA 0x40000L -#define PNG_INVERT_ALPHA 0x80000L -#define PNG_USER_TRANSFORM 0x100000L -#define PNG_RGB_TO_GRAY_ERR 0x200000L -#define PNG_RGB_TO_GRAY_WARN 0x400000L -#define PNG_RGB_TO_GRAY 0x600000L /* two bits, RGB_TO_GRAY_ERR|WARN */ - /* 0x800000L Unused */ -#define PNG_ADD_ALPHA 0x1000000L /* Added to libpng-1.2.7 */ -#define PNG_EXPAND_tRNS 0x2000000L /* Added to libpng-1.2.9 */ - /* 0x4000000L unused */ - /* 0x8000000L unused */ - /* 0x10000000L unused */ - /* 0x20000000L unused */ - /* 0x40000000L unused */ - -/* flags for png_create_struct */ -#define PNG_STRUCT_PNG 0x0001 -#define PNG_STRUCT_INFO 0x0002 - -/* Scaling factor for filter heuristic weighting calculations */ -#define PNG_WEIGHT_SHIFT 8 -#define PNG_WEIGHT_FACTOR (1<<(PNG_WEIGHT_SHIFT)) -#define PNG_COST_SHIFT 3 -#define PNG_COST_FACTOR (1<<(PNG_COST_SHIFT)) - -/* flags for the png_ptr->flags rather than declaring a byte for each one */ -#define PNG_FLAG_ZLIB_CUSTOM_STRATEGY 0x0001 -#define PNG_FLAG_ZLIB_CUSTOM_LEVEL 0x0002 -#define PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL 0x0004 -#define PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS 0x0008 -#define PNG_FLAG_ZLIB_CUSTOM_METHOD 0x0010 -#define PNG_FLAG_ZLIB_FINISHED 0x0020 -#define PNG_FLAG_ROW_INIT 0x0040 -#define PNG_FLAG_FILLER_AFTER 0x0080 -#define PNG_FLAG_CRC_ANCILLARY_USE 0x0100 -#define PNG_FLAG_CRC_ANCILLARY_NOWARN 0x0200 -#define PNG_FLAG_CRC_CRITICAL_USE 0x0400 -#define PNG_FLAG_CRC_CRITICAL_IGNORE 0x0800 -#define PNG_FLAG_FREE_PLTE 0x1000 -#define PNG_FLAG_FREE_TRNS 0x2000 -#define PNG_FLAG_FREE_HIST 0x4000 -#define PNG_FLAG_KEEP_UNKNOWN_CHUNKS 0x8000L -#define PNG_FLAG_KEEP_UNSAFE_CHUNKS 0x10000L -#define PNG_FLAG_LIBRARY_MISMATCH 0x20000L -#define PNG_FLAG_STRIP_ERROR_NUMBERS 0x40000L -#define PNG_FLAG_STRIP_ERROR_TEXT 0x80000L -#define PNG_FLAG_MALLOC_NULL_MEM_OK 0x100000L -#define PNG_FLAG_ADD_ALPHA 0x200000L /* Added to libpng-1.2.8 */ -#define PNG_FLAG_STRIP_ALPHA 0x400000L /* Added to libpng-1.2.8 */ - /* 0x800000L unused */ - /* 0x1000000L unused */ - /* 0x2000000L unused */ - /* 0x4000000L unused */ - /* 0x8000000L unused */ - /* 0x10000000L unused */ - /* 0x20000000L unused */ - /* 0x40000000L unused */ - -#define PNG_FLAG_CRC_ANCILLARY_MASK (PNG_FLAG_CRC_ANCILLARY_USE | \ - PNG_FLAG_CRC_ANCILLARY_NOWARN) - -#define PNG_FLAG_CRC_CRITICAL_MASK (PNG_FLAG_CRC_CRITICAL_USE | \ - PNG_FLAG_CRC_CRITICAL_IGNORE) - -#define PNG_FLAG_CRC_MASK (PNG_FLAG_CRC_ANCILLARY_MASK | \ - PNG_FLAG_CRC_CRITICAL_MASK) - -/* save typing and make code easier to understand */ - -#define PNG_COLOR_DIST(c1, c2) (abs((int)((c1).red) - (int)((c2).red)) + \ - abs((int)((c1).green) - (int)((c2).green)) + \ - abs((int)((c1).blue) - (int)((c2).blue))) - -/* Added to libpng-1.2.6 JB */ -#define PNG_ROWBYTES(pixel_bits, width) \ - ((pixel_bits) >= 8 ? \ - ((width) * (((png_uint_32)(pixel_bits)) >> 3)) : \ - (( ((width) * ((png_uint_32)(pixel_bits))) + 7) >> 3) ) - -/* PNG_OUT_OF_RANGE returns true if value is outside the range - ideal-delta..ideal+delta. Each argument is evaluated twice. - "ideal" and "delta" should be constants, normally simple - integers, "value" a variable. Added to libpng-1.2.6 JB */ -#define PNG_OUT_OF_RANGE(value, ideal, delta) \ - ( (value) < (ideal)-(delta) || (value) > (ideal)+(delta) ) - -/* variables declared in png.c - only it needs to define PNG_NO_EXTERN */ -#if !defined(PNG_NO_EXTERN) || defined(PNG_ALWAYS_EXTERN) -/* place to hold the signature string for a PNG file. */ -#ifdef PNG_USE_GLOBAL_ARRAYS - PNG_EXPORT_VAR (PNG_CONST png_byte FARDATA) png_sig[8]; -#else -#endif -#endif /* PNG_NO_EXTERN */ - -/* Constant strings for known chunk types. If you need to add a chunk, - * define the name here, and add an invocation of the macro in png.c and - * wherever it's needed. - */ -#define PNG_IHDR png_byte png_IHDR[5] = { 73, 72, 68, 82, '\0'} -#define PNG_IDAT png_byte png_IDAT[5] = { 73, 68, 65, 84, '\0'} -#define PNG_IEND png_byte png_IEND[5] = { 73, 69, 78, 68, '\0'} -#define PNG_PLTE png_byte png_PLTE[5] = { 80, 76, 84, 69, '\0'} -#define PNG_bKGD png_byte png_bKGD[5] = { 98, 75, 71, 68, '\0'} -#define PNG_cHRM png_byte png_cHRM[5] = { 99, 72, 82, 77, '\0'} -#define PNG_gAMA png_byte png_gAMA[5] = {103, 65, 77, 65, '\0'} -#define PNG_hIST png_byte png_hIST[5] = {104, 73, 83, 84, '\0'} -#define PNG_iCCP png_byte png_iCCP[5] = {105, 67, 67, 80, '\0'} -#define PNG_iTXt png_byte png_iTXt[5] = {105, 84, 88, 116, '\0'} -#define PNG_oFFs png_byte png_oFFs[5] = {111, 70, 70, 115, '\0'} -#define PNG_pCAL png_byte png_pCAL[5] = {112, 67, 65, 76, '\0'} -#define PNG_sCAL png_byte png_sCAL[5] = {115, 67, 65, 76, '\0'} -#define PNG_pHYs png_byte png_pHYs[5] = {112, 72, 89, 115, '\0'} -#define PNG_sBIT png_byte png_sBIT[5] = {115, 66, 73, 84, '\0'} -#define PNG_sPLT png_byte png_sPLT[5] = {115, 80, 76, 84, '\0'} -#define PNG_sRGB png_byte png_sRGB[5] = {115, 82, 71, 66, '\0'} -#define PNG_tEXt png_byte png_tEXt[5] = {116, 69, 88, 116, '\0'} -#define PNG_tIME png_byte png_tIME[5] = {116, 73, 77, 69, '\0'} -#define PNG_tRNS png_byte png_tRNS[5] = {116, 82, 78, 83, '\0'} -#define PNG_zTXt png_byte png_zTXt[5] = {122, 84, 88, 116, '\0'} - -#ifdef PNG_USE_GLOBAL_ARRAYS -PNG_EXPORT_VAR (png_byte FARDATA) png_IHDR[5]; -PNG_EXPORT_VAR (png_byte FARDATA) png_IDAT[5]; -PNG_EXPORT_VAR (png_byte FARDATA) png_IEND[5]; -PNG_EXPORT_VAR (png_byte FARDATA) png_PLTE[5]; -PNG_EXPORT_VAR (png_byte FARDATA) png_bKGD[5]; -PNG_EXPORT_VAR (png_byte FARDATA) png_cHRM[5]; -PNG_EXPORT_VAR (png_byte FARDATA) png_gAMA[5]; -PNG_EXPORT_VAR (png_byte FARDATA) png_hIST[5]; -PNG_EXPORT_VAR (png_byte FARDATA) png_iCCP[5]; -PNG_EXPORT_VAR (png_byte FARDATA) png_iTXt[5]; -PNG_EXPORT_VAR (png_byte FARDATA) png_oFFs[5]; -PNG_EXPORT_VAR (png_byte FARDATA) png_pCAL[5]; -PNG_EXPORT_VAR (png_byte FARDATA) png_sCAL[5]; -PNG_EXPORT_VAR (png_byte FARDATA) png_pHYs[5]; -PNG_EXPORT_VAR (png_byte FARDATA) png_sBIT[5]; -PNG_EXPORT_VAR (png_byte FARDATA) png_sPLT[5]; -PNG_EXPORT_VAR (png_byte FARDATA) png_sRGB[5]; -PNG_EXPORT_VAR (png_byte FARDATA) png_tEXt[5]; -PNG_EXPORT_VAR (png_byte FARDATA) png_tIME[5]; -PNG_EXPORT_VAR (png_byte FARDATA) png_tRNS[5]; -PNG_EXPORT_VAR (png_byte FARDATA) png_zTXt[5]; -#endif /* PNG_USE_GLOBAL_ARRAYS */ - -#if defined(PNG_1_0_X) || defined (PNG_1_2_X) -/* Initialize png_ptr struct for reading, and allocate any other memory. - * (old interface - DEPRECATED - use png_create_read_struct instead). - */ -extern PNG_EXPORT(void,png_read_init) PNGARG((png_structp png_ptr)); -#undef png_read_init -#define png_read_init(png_ptr) png_read_init_3(&png_ptr, \ - PNG_LIBPNG_VER_STRING, png_sizeof(png_struct)); -#endif - -extern PNG_EXPORT(void,png_read_init_3) PNGARG((png_structpp ptr_ptr, - png_const_charp user_png_ver, png_size_t png_struct_size)); -#if defined(PNG_1_0_X) || defined (PNG_1_2_X) -extern PNG_EXPORT(void,png_read_init_2) PNGARG((png_structp png_ptr, - png_const_charp user_png_ver, png_size_t png_struct_size, png_size_t - png_info_size)); -#endif - -#if defined(PNG_1_0_X) || defined (PNG_1_2_X) -/* Initialize png_ptr struct for writing, and allocate any other memory. - * (old interface - DEPRECATED - use png_create_write_struct instead). - */ -extern PNG_EXPORT(void,png_write_init) PNGARG((png_structp png_ptr)); -#undef png_write_init -#define png_write_init(png_ptr) png_write_init_3(&png_ptr, \ - PNG_LIBPNG_VER_STRING, png_sizeof(png_struct)); -#endif - -extern PNG_EXPORT(void,png_write_init_3) PNGARG((png_structpp ptr_ptr, - png_const_charp user_png_ver, png_size_t png_struct_size)); -extern PNG_EXPORT(void,png_write_init_2) PNGARG((png_structp png_ptr, - png_const_charp user_png_ver, png_size_t png_struct_size, png_size_t - png_info_size)); - -/* Allocate memory for an internal libpng struct */ -PNG_EXTERN png_voidp png_create_struct PNGARG((int type)); - -/* Free memory from internal libpng struct */ -PNG_EXTERN void png_destroy_struct PNGARG((png_voidp struct_ptr)); - -PNG_EXTERN png_voidp png_create_struct_2 PNGARG((int type, png_malloc_ptr - malloc_fn, png_voidp mem_ptr)); -PNG_EXTERN void png_destroy_struct_2 PNGARG((png_voidp struct_ptr, - png_free_ptr free_fn, png_voidp mem_ptr)); - -/* Free any memory that info_ptr points to and reset struct. */ -PNG_EXTERN void png_info_destroy PNGARG((png_structp png_ptr, - png_infop info_ptr)); - -#ifndef PNG_1_0_X -/* Function to allocate memory for zlib. */ -PNG_EXTERN voidpf png_zalloc PNGARG((voidpf png_ptr, uInt items, uInt size)); - -/* Function to free memory for zlib */ -PNG_EXTERN void png_zfree PNGARG((voidpf png_ptr, voidpf ptr)); - -#ifdef PNG_SIZE_T -/* Function to convert a sizeof an item to png_sizeof item */ - PNG_EXTERN png_size_t PNGAPI png_convert_size PNGARG((size_t size)); -#endif - -/* Next four functions are used internally as callbacks. PNGAPI is required - * but not PNG_EXPORT. PNGAPI added at libpng version 1.2.3. */ - -PNG_EXTERN void PNGAPI png_default_read_data PNGARG((png_structp png_ptr, - png_bytep data, png_size_t length)); - -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED -PNG_EXTERN void PNGAPI png_push_fill_buffer PNGARG((png_structp png_ptr, - png_bytep buffer, png_size_t length)); -#endif - -PNG_EXTERN void PNGAPI png_default_write_data PNGARG((png_structp png_ptr, - png_bytep data, png_size_t length)); - -#if defined(PNG_WRITE_FLUSH_SUPPORTED) -#if !defined(PNG_NO_STDIO) -PNG_EXTERN void PNGAPI png_default_flush PNGARG((png_structp png_ptr)); -#endif -#endif -#else /* PNG_1_0_X */ -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED -PNG_EXTERN void png_push_fill_buffer PNGARG((png_structp png_ptr, - png_bytep buffer, png_size_t length)); -#endif -#endif /* PNG_1_0_X */ - -/* Reset the CRC variable */ -PNG_EXTERN void png_reset_crc PNGARG((png_structp png_ptr)); - -/* Write the "data" buffer to whatever output you are using. */ -PNG_EXTERN void png_write_data PNGARG((png_structp png_ptr, png_bytep data, - png_size_t length)); - -/* Read data from whatever input you are using into the "data" buffer */ -PNG_EXTERN void png_read_data PNGARG((png_structp png_ptr, png_bytep data, - png_size_t length)); - -/* Read bytes into buf, and update png_ptr->crc */ -PNG_EXTERN void png_crc_read PNGARG((png_structp png_ptr, png_bytep buf, - png_size_t length)); - -/* Decompress data in a chunk that uses compression */ -#if defined(PNG_zTXt_SUPPORTED) || defined(PNG_iTXt_SUPPORTED) || \ - defined(PNG_iCCP_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) -PNG_EXTERN png_charp png_decompress_chunk PNGARG((png_structp png_ptr, - int comp_type, png_charp chunkdata, png_size_t chunklength, - png_size_t prefix_length, png_size_t *data_length)); -#endif - -/* Read "skip" bytes, read the file crc, and (optionally) verify png_ptr->crc */ -PNG_EXTERN int png_crc_finish PNGARG((png_structp png_ptr, png_uint_32 skip)); - -/* Read the CRC from the file and compare it to the libpng calculated CRC */ -PNG_EXTERN int png_crc_error PNGARG((png_structp png_ptr)); - -/* Calculate the CRC over a section of data. Note that we are only - * passing a maximum of 64K on systems that have this as a memory limit, - * since this is the maximum buffer size we can specify. - */ -PNG_EXTERN void png_calculate_crc PNGARG((png_structp png_ptr, png_bytep ptr, - png_size_t length)); - -#if defined(PNG_WRITE_FLUSH_SUPPORTED) -PNG_EXTERN void png_flush PNGARG((png_structp png_ptr)); -#endif - -/* simple function to write the signature */ -PNG_EXTERN void png_write_sig PNGARG((png_structp png_ptr)); - -/* write various chunks */ - -/* Write the IHDR chunk, and update the png_struct with the necessary - * information. - */ -PNG_EXTERN void png_write_IHDR PNGARG((png_structp png_ptr, png_uint_32 width, - png_uint_32 height, - int bit_depth, int color_type, int compression_method, int filter_method, - int interlace_method)); - -PNG_EXTERN void png_write_PLTE PNGARG((png_structp png_ptr, png_colorp palette, - png_uint_32 num_pal)); - -PNG_EXTERN void png_write_IDAT PNGARG((png_structp png_ptr, png_bytep data, - png_size_t length)); - -PNG_EXTERN void png_write_IEND PNGARG((png_structp png_ptr)); - -#if defined(PNG_WRITE_gAMA_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED -PNG_EXTERN void png_write_gAMA PNGARG((png_structp png_ptr, double file_gamma)); -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED -PNG_EXTERN void png_write_gAMA_fixed PNGARG((png_structp png_ptr, png_fixed_point - file_gamma)); -#endif -#endif - -#if defined(PNG_WRITE_sBIT_SUPPORTED) -PNG_EXTERN void png_write_sBIT PNGARG((png_structp png_ptr, png_color_8p sbit, - int color_type)); -#endif - -#if defined(PNG_WRITE_cHRM_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED -PNG_EXTERN void png_write_cHRM PNGARG((png_structp png_ptr, - double white_x, double white_y, - double red_x, double red_y, double green_x, double green_y, - double blue_x, double blue_y)); -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED -PNG_EXTERN void png_write_cHRM_fixed PNGARG((png_structp png_ptr, - png_fixed_point int_white_x, png_fixed_point int_white_y, - png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point - int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x, - png_fixed_point int_blue_y)); -#endif -#endif - -#if defined(PNG_WRITE_sRGB_SUPPORTED) -PNG_EXTERN void png_write_sRGB PNGARG((png_structp png_ptr, - int intent)); -#endif - -#if defined(PNG_WRITE_iCCP_SUPPORTED) -PNG_EXTERN void png_write_iCCP PNGARG((png_structp png_ptr, - png_charp name, int compression_type, - png_charp profile, int proflen)); - /* Note to maintainer: profile should be png_bytep */ -#endif - -#if defined(PNG_WRITE_sPLT_SUPPORTED) -PNG_EXTERN void png_write_sPLT PNGARG((png_structp png_ptr, - png_sPLT_tp palette)); -#endif - -#if defined(PNG_WRITE_tRNS_SUPPORTED) -PNG_EXTERN void png_write_tRNS PNGARG((png_structp png_ptr, png_bytep trans, - png_color_16p values, int number, int color_type)); -#endif - -#if defined(PNG_WRITE_bKGD_SUPPORTED) -PNG_EXTERN void png_write_bKGD PNGARG((png_structp png_ptr, - png_color_16p values, int color_type)); -#endif - -#if defined(PNG_WRITE_hIST_SUPPORTED) -PNG_EXTERN void png_write_hIST PNGARG((png_structp png_ptr, png_uint_16p hist, - int num_hist)); -#endif - -#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \ - defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) -PNG_EXTERN png_size_t png_check_keyword PNGARG((png_structp png_ptr, - png_charp key, png_charpp new_key)); -#endif - -#if defined(PNG_WRITE_tEXt_SUPPORTED) -PNG_EXTERN void png_write_tEXt PNGARG((png_structp png_ptr, png_charp key, - png_charp text, png_size_t text_len)); -#endif - -#if defined(PNG_WRITE_zTXt_SUPPORTED) -PNG_EXTERN void png_write_zTXt PNGARG((png_structp png_ptr, png_charp key, - png_charp text, png_size_t text_len, int compression)); -#endif - -#if defined(PNG_WRITE_iTXt_SUPPORTED) -PNG_EXTERN void png_write_iTXt PNGARG((png_structp png_ptr, - int compression, png_charp key, png_charp lang, png_charp lang_key, - png_charp text)); -#endif - -#if defined(PNG_TEXT_SUPPORTED) /* Added at version 1.0.14 and 1.2.4 */ -PNG_EXTERN int png_set_text_2 PNGARG((png_structp png_ptr, - png_infop info_ptr, png_textp text_ptr, int num_text)); -#endif - -#if defined(PNG_WRITE_oFFs_SUPPORTED) -PNG_EXTERN void png_write_oFFs PNGARG((png_structp png_ptr, - png_int_32 x_offset, png_int_32 y_offset, int unit_type)); -#endif - -#if defined(PNG_WRITE_pCAL_SUPPORTED) -PNG_EXTERN void png_write_pCAL PNGARG((png_structp png_ptr, png_charp purpose, - png_int_32 X0, png_int_32 X1, int type, int nparams, - png_charp units, png_charpp params)); -#endif - -#if defined(PNG_WRITE_pHYs_SUPPORTED) -PNG_EXTERN void png_write_pHYs PNGARG((png_structp png_ptr, - png_uint_32 x_pixels_per_unit, png_uint_32 y_pixels_per_unit, - int unit_type)); -#endif - -#if defined(PNG_WRITE_tIME_SUPPORTED) -PNG_EXTERN void png_write_tIME PNGARG((png_structp png_ptr, - png_timep mod_time)); -#endif - -#if defined(PNG_WRITE_sCAL_SUPPORTED) -#if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO) -PNG_EXTERN void png_write_sCAL PNGARG((png_structp png_ptr, - int unit, double width, double height)); -#else -#ifdef PNG_FIXED_POINT_SUPPORTED -PNG_EXTERN void png_write_sCAL_s PNGARG((png_structp png_ptr, - int unit, png_charp width, png_charp height)); -#endif -#endif -#endif - -/* Called when finished processing a row of data */ -PNG_EXTERN void png_write_finish_row PNGARG((png_structp png_ptr)); - -/* Internal use only. Called before first row of data */ -PNG_EXTERN void png_write_start_row PNGARG((png_structp png_ptr)); - -#if defined(PNG_READ_GAMMA_SUPPORTED) -PNG_EXTERN void png_build_gamma_table PNGARG((png_structp png_ptr)); -#endif - -/* combine a row of data, dealing with alpha, etc. if requested */ -PNG_EXTERN void png_combine_row PNGARG((png_structp png_ptr, png_bytep row, - int mask)); - -#if defined(PNG_READ_INTERLACING_SUPPORTED) -/* expand an interlaced row */ -/* OLD pre-1.0.9 interface: -PNG_EXTERN void png_do_read_interlace PNGARG((png_row_infop row_info, - png_bytep row, int pass, png_uint_32 transformations)); - */ -PNG_EXTERN void png_do_read_interlace PNGARG((png_structp png_ptr)); -#endif - -/* GRR TO DO (2.0 or whenever): simplify other internal calling interfaces */ - -#if defined(PNG_WRITE_INTERLACING_SUPPORTED) -/* grab pixels out of a row for an interlaced pass */ -PNG_EXTERN void png_do_write_interlace PNGARG((png_row_infop row_info, - png_bytep row, int pass)); -#endif - -/* unfilter a row */ -PNG_EXTERN void png_read_filter_row PNGARG((png_structp png_ptr, - png_row_infop row_info, png_bytep row, png_bytep prev_row, int filter)); - -/* Choose the best filter to use and filter the row data */ -PNG_EXTERN void png_write_find_filter PNGARG((png_structp png_ptr, - png_row_infop row_info)); - -/* Write out the filtered row. */ -PNG_EXTERN void png_write_filtered_row PNGARG((png_structp png_ptr, - png_bytep filtered_row)); -/* finish a row while reading, dealing with interlacing passes, etc. */ -PNG_EXTERN void png_read_finish_row PNGARG((png_structp png_ptr)); - -/* initialize the row buffers, etc. */ -PNG_EXTERN void png_read_start_row PNGARG((png_structp png_ptr)); -/* optional call to update the users info structure */ -PNG_EXTERN void png_read_transform_info PNGARG((png_structp png_ptr, - png_infop info_ptr)); - -/* these are the functions that do the transformations */ -#if defined(PNG_READ_FILLER_SUPPORTED) -PNG_EXTERN void png_do_read_filler PNGARG((png_row_infop row_info, - png_bytep row, png_uint_32 filler, png_uint_32 flags)); -#endif - -#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) -PNG_EXTERN void png_do_read_swap_alpha PNGARG((png_row_infop row_info, - png_bytep row)); -#endif - -#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) -PNG_EXTERN void png_do_write_swap_alpha PNGARG((png_row_infop row_info, - png_bytep row)); -#endif - -#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) -PNG_EXTERN void png_do_read_invert_alpha PNGARG((png_row_infop row_info, - png_bytep row)); -#endif - -#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) -PNG_EXTERN void png_do_write_invert_alpha PNGARG((png_row_infop row_info, - png_bytep row)); -#endif - -#if defined(PNG_WRITE_FILLER_SUPPORTED) || \ - defined(PNG_READ_STRIP_ALPHA_SUPPORTED) -PNG_EXTERN void png_do_strip_filler PNGARG((png_row_infop row_info, - png_bytep row, png_uint_32 flags)); -#endif - -#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) -PNG_EXTERN void png_do_swap PNGARG((png_row_infop row_info, png_bytep row)); -#endif - -#if defined(PNG_READ_PACKSWAP_SUPPORTED) || defined(PNG_WRITE_PACKSWAP_SUPPORTED) -PNG_EXTERN void png_do_packswap PNGARG((png_row_infop row_info, png_bytep row)); -#endif - -#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) -PNG_EXTERN int png_do_rgb_to_gray PNGARG((png_structp png_ptr, png_row_infop - row_info, png_bytep row)); -#endif - -#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) -PNG_EXTERN void png_do_gray_to_rgb PNGARG((png_row_infop row_info, - png_bytep row)); -#endif - -#if defined(PNG_READ_PACK_SUPPORTED) -PNG_EXTERN void png_do_unpack PNGARG((png_row_infop row_info, png_bytep row)); -#endif - -#if defined(PNG_READ_SHIFT_SUPPORTED) -PNG_EXTERN void png_do_unshift PNGARG((png_row_infop row_info, png_bytep row, - png_color_8p sig_bits)); -#endif - -#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) -PNG_EXTERN void png_do_invert PNGARG((png_row_infop row_info, png_bytep row)); -#endif - -#if defined(PNG_READ_16_TO_8_SUPPORTED) -PNG_EXTERN void png_do_chop PNGARG((png_row_infop row_info, png_bytep row)); -#endif - -#if defined(PNG_READ_DITHER_SUPPORTED) -PNG_EXTERN void png_do_dither PNGARG((png_row_infop row_info, - png_bytep row, png_bytep palette_lookup, png_bytep dither_lookup)); - -# if defined(PNG_CORRECT_PALETTE_SUPPORTED) -PNG_EXTERN void png_correct_palette PNGARG((png_structp png_ptr, - png_colorp palette, int num_palette)); -# endif -#endif - -#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) -PNG_EXTERN void png_do_bgr PNGARG((png_row_infop row_info, png_bytep row)); -#endif - -#if defined(PNG_WRITE_PACK_SUPPORTED) -PNG_EXTERN void png_do_pack PNGARG((png_row_infop row_info, - png_bytep row, png_uint_32 bit_depth)); -#endif - -#if defined(PNG_WRITE_SHIFT_SUPPORTED) -PNG_EXTERN void png_do_shift PNGARG((png_row_infop row_info, png_bytep row, - png_color_8p bit_depth)); -#endif - -#if defined(PNG_READ_BACKGROUND_SUPPORTED) -#if defined(PNG_READ_GAMMA_SUPPORTED) -PNG_EXTERN void png_do_background PNGARG((png_row_infop row_info, png_bytep row, - png_color_16p trans_values, png_color_16p background, - png_color_16p background_1, - png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1, - png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1, - png_uint_16pp gamma_16_to_1, int gamma_shift)); -#else -PNG_EXTERN void png_do_background PNGARG((png_row_infop row_info, png_bytep row, - png_color_16p trans_values, png_color_16p background)); -#endif -#endif - -#if defined(PNG_READ_GAMMA_SUPPORTED) -PNG_EXTERN void png_do_gamma PNGARG((png_row_infop row_info, png_bytep row, - png_bytep gamma_table, png_uint_16pp gamma_16_table, - int gamma_shift)); -#endif - -#if defined(PNG_READ_EXPAND_SUPPORTED) -PNG_EXTERN void png_do_expand_palette PNGARG((png_row_infop row_info, - png_bytep row, png_colorp palette, png_bytep trans, int num_trans)); -PNG_EXTERN void png_do_expand PNGARG((png_row_infop row_info, - png_bytep row, png_color_16p trans_value)); -#endif - -/* The following decodes the appropriate chunks, and does error correction, - * then calls the appropriate callback for the chunk if it is valid. - */ - -/* decode the IHDR chunk */ -PNG_EXTERN void png_handle_IHDR PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -PNG_EXTERN void png_handle_PLTE PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -PNG_EXTERN void png_handle_IEND PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); - -#if defined(PNG_READ_bKGD_SUPPORTED) -PNG_EXTERN void png_handle_bKGD PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_cHRM_SUPPORTED) -PNG_EXTERN void png_handle_cHRM PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_gAMA_SUPPORTED) -PNG_EXTERN void png_handle_gAMA PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_hIST_SUPPORTED) -PNG_EXTERN void png_handle_hIST PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_iCCP_SUPPORTED) -extern void png_handle_iCCP PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif /* PNG_READ_iCCP_SUPPORTED */ - -#if defined(PNG_READ_iTXt_SUPPORTED) -PNG_EXTERN void png_handle_iTXt PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_oFFs_SUPPORTED) -PNG_EXTERN void png_handle_oFFs PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_pCAL_SUPPORTED) -PNG_EXTERN void png_handle_pCAL PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_pHYs_SUPPORTED) -PNG_EXTERN void png_handle_pHYs PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_sBIT_SUPPORTED) -PNG_EXTERN void png_handle_sBIT PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_sCAL_SUPPORTED) -PNG_EXTERN void png_handle_sCAL PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_sPLT_SUPPORTED) -extern void png_handle_sPLT PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif /* PNG_READ_sPLT_SUPPORTED */ - -#if defined(PNG_READ_sRGB_SUPPORTED) -PNG_EXTERN void png_handle_sRGB PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_tEXt_SUPPORTED) -PNG_EXTERN void png_handle_tEXt PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_tIME_SUPPORTED) -PNG_EXTERN void png_handle_tIME PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_tRNS_SUPPORTED) -PNG_EXTERN void png_handle_tRNS PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_zTXt_SUPPORTED) -PNG_EXTERN void png_handle_zTXt PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -PNG_EXTERN void png_handle_unknown PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 length)); - -PNG_EXTERN void png_check_chunk_name PNGARG((png_structp png_ptr, - png_bytep chunk_name)); - -/* handle the transformations for reading and writing */ -PNG_EXTERN void png_do_read_transformations PNGARG((png_structp png_ptr)); -PNG_EXTERN void png_do_write_transformations PNGARG((png_structp png_ptr)); - -PNG_EXTERN void png_init_read_transformations PNGARG((png_structp png_ptr)); - -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED -PNG_EXTERN void png_push_read_chunk PNGARG((png_structp png_ptr, - png_infop info_ptr)); -PNG_EXTERN void png_push_read_sig PNGARG((png_structp png_ptr, - png_infop info_ptr)); -PNG_EXTERN void png_push_check_crc PNGARG((png_structp png_ptr)); -PNG_EXTERN void png_push_crc_skip PNGARG((png_structp png_ptr, - png_uint_32 length)); -PNG_EXTERN void png_push_crc_finish PNGARG((png_structp png_ptr)); -PNG_EXTERN void png_push_save_buffer PNGARG((png_structp png_ptr)); -PNG_EXTERN void png_push_restore_buffer PNGARG((png_structp png_ptr, - png_bytep buffer, png_size_t buffer_length)); -PNG_EXTERN void png_push_read_IDAT PNGARG((png_structp png_ptr)); -PNG_EXTERN void png_process_IDAT_data PNGARG((png_structp png_ptr, - png_bytep buffer, png_size_t buffer_length)); -PNG_EXTERN void png_push_process_row PNGARG((png_structp png_ptr)); -PNG_EXTERN void png_push_handle_unknown PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 length)); -PNG_EXTERN void png_push_have_info PNGARG((png_structp png_ptr, - png_infop info_ptr)); -PNG_EXTERN void png_push_have_end PNGARG((png_structp png_ptr, - png_infop info_ptr)); -PNG_EXTERN void png_push_have_row PNGARG((png_structp png_ptr, png_bytep row)); -PNG_EXTERN void png_push_read_end PNGARG((png_structp png_ptr, - png_infop info_ptr)); -PNG_EXTERN void png_process_some_data PNGARG((png_structp png_ptr, - png_infop info_ptr)); -PNG_EXTERN void png_read_push_finish_row PNGARG((png_structp png_ptr)); -#if defined(PNG_READ_tEXt_SUPPORTED) -PNG_EXTERN void png_push_handle_tEXt PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 length)); -PNG_EXTERN void png_push_read_tEXt PNGARG((png_structp png_ptr, - png_infop info_ptr)); -#endif -#if defined(PNG_READ_zTXt_SUPPORTED) -PNG_EXTERN void png_push_handle_zTXt PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 length)); -PNG_EXTERN void png_push_read_zTXt PNGARG((png_structp png_ptr, - png_infop info_ptr)); -#endif -#if defined(PNG_READ_iTXt_SUPPORTED) -PNG_EXTERN void png_push_handle_iTXt PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 length)); -PNG_EXTERN void png_push_read_iTXt PNGARG((png_structp png_ptr, - png_infop info_ptr)); -#endif - -#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ - -#ifdef PNG_MNG_FEATURES_SUPPORTED -PNG_EXTERN void png_do_read_intrapixel PNGARG((png_row_infop row_info, - png_bytep row)); -PNG_EXTERN void png_do_write_intrapixel PNGARG((png_row_infop row_info, - png_bytep row)); -#endif - -#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) -#if defined(PNG_MMX_CODE_SUPPORTED) -/* png.c */ /* PRIVATE */ -PNG_EXTERN void png_init_mmx_flags PNGARG((png_structp png_ptr)); -#endif -#endif - -#if defined(PNG_INCH_CONVERSIONS) && defined(PNG_FLOATING_POINT_SUPPORTED) -PNG_EXTERN png_uint_32 png_get_pixels_per_inch PNGARG((png_structp png_ptr, -png_infop info_ptr)); - -PNG_EXTERN png_uint_32 png_get_x_pixels_per_inch PNGARG((png_structp png_ptr, -png_infop info_ptr)); - -PNG_EXTERN png_uint_32 png_get_y_pixels_per_inch PNGARG((png_structp png_ptr, -png_infop info_ptr)); - -PNG_EXTERN float png_get_x_offset_inches PNGARG((png_structp png_ptr, -png_infop info_ptr)); - -PNG_EXTERN float png_get_y_offset_inches PNGARG((png_structp png_ptr, -png_infop info_ptr)); - -#if defined(PNG_pHYs_SUPPORTED) -PNG_EXTERN png_uint_32 png_get_pHYs_dpi PNGARG((png_structp png_ptr, -png_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); -#endif /* PNG_pHYs_SUPPORTED */ -#endif /* PNG_INCH_CONVERSIONS && PNG_FLOATING_POINT_SUPPORTED */ - -/* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */ - -#endif /* PNG_INTERNAL */ - -#ifdef __cplusplus -} -#endif - -#endif /* PNG_VERSION_INFO_ONLY */ -/* do not put anything past this line */ -#endif /* PNG_H */ diff --git a/uppdev/plugin/png/lib/pngconf.h b/uppdev/plugin/png/lib/pngconf.h deleted file mode 100644 index 30e5851c0..000000000 --- a/uppdev/plugin/png/lib/pngconf.h +++ /dev/null @@ -1,1483 +0,0 @@ - -/* pngconf.h - machine configurable file for libpng - * - * libpng version 1.2.22 - October 13, 2007 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2007 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - */ - -/* Any machine specific code is near the front of this file, so if you - * are configuring libpng for a machine, you may want to read the section - * starting here down to where it starts to typedef png_color, png_text, - * and png_info. - */ - -#ifndef PNGCONF_H -#define PNGCONF_H - -#define PNG_1_2_X - -/* - * PNG_USER_CONFIG has to be defined on the compiler command line. This - * includes the resource compiler for Windows DLL configurations. - */ -#ifdef PNG_USER_CONFIG -# ifndef PNG_USER_PRIVATEBUILD -# define PNG_USER_PRIVATEBUILD -# endif -#include "pngusr.h" -#endif - -/* PNG_CONFIGURE_LIBPNG is set by the "configure" script. */ -#ifdef PNG_CONFIGURE_LIBPNG -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#endif - -/* - * Added at libpng-1.2.8 - * - * If you create a private DLL you need to define in "pngusr.h" the followings: - * #define PNG_USER_PRIVATEBUILD - * e.g. #define PNG_USER_PRIVATEBUILD "Build by MyCompany for xyz reasons." - * #define PNG_USER_DLLFNAME_POSTFIX - * e.g. // private DLL "libpng13gx.dll" - * #define PNG_USER_DLLFNAME_POSTFIX "gx" - * - * The following macros are also at your disposal if you want to complete the - * DLL VERSIONINFO structure. - * - PNG_USER_VERSIONINFO_COMMENTS - * - PNG_USER_VERSIONINFO_COMPANYNAME - * - PNG_USER_VERSIONINFO_LEGALTRADEMARKS - */ - -#ifdef __STDC__ -#ifdef SPECIALBUILD -# pragma message("PNG_LIBPNG_SPECIALBUILD (and deprecated SPECIALBUILD)\ - are now LIBPNG reserved macros. Use PNG_USER_PRIVATEBUILD instead.") -#endif - -#ifdef PRIVATEBUILD -# pragma message("PRIVATEBUILD is deprecated.\ - Use PNG_USER_PRIVATEBUILD instead.") -# define PNG_USER_PRIVATEBUILD PRIVATEBUILD -#endif -#endif /* __STDC__ */ - -#ifndef PNG_VERSION_INFO_ONLY - -/* End of material added to libpng-1.2.8 */ - -/* Added at libpng-1.2.19, removed at libpng-1.2.20 because it caused trouble - Restored at libpng-1.2.21 */ -#if !defined(PNG_NO_WARN_UNINITIALIZED_ROW) && \ - !defined(PNG_WARN_UNINITIALIZED_ROW) -# define PNG_WARN_UNINITIALIZED_ROW 1 -#endif -/* End of material added at libpng-1.2.19/1.2.21 */ - -/* This is the size of the compression buffer, and thus the size of - * an IDAT chunk. Make this whatever size you feel is best for your - * machine. One of these will be allocated per png_struct. When this - * is full, it writes the data to the disk, and does some other - * calculations. Making this an extremely small size will slow - * the library down, but you may want to experiment to determine - * where it becomes significant, if you are concerned with memory - * usage. Note that zlib allocates at least 32Kb also. For readers, - * this describes the size of the buffer available to read the data in. - * Unless this gets smaller than the size of a row (compressed), - * it should not make much difference how big this is. - */ - -#ifndef PNG_ZBUF_SIZE -# define PNG_ZBUF_SIZE 8192 -#endif - -/* Enable if you want a write-only libpng */ - -#ifndef PNG_NO_READ_SUPPORTED -# define PNG_READ_SUPPORTED -#endif - -/* Enable if you want a read-only libpng */ - -#ifndef PNG_NO_WRITE_SUPPORTED -# define PNG_WRITE_SUPPORTED -#endif - -/* Enabled by default in 1.2.0. You can disable this if you don't need to - support PNGs that are embedded in MNG datastreams */ -#if !defined(PNG_1_0_X) && !defined(PNG_NO_MNG_FEATURES) -# ifndef PNG_MNG_FEATURES_SUPPORTED -# define PNG_MNG_FEATURES_SUPPORTED -# endif -#endif - -#ifndef PNG_NO_FLOATING_POINT_SUPPORTED -# ifndef PNG_FLOATING_POINT_SUPPORTED -# define PNG_FLOATING_POINT_SUPPORTED -# endif -#endif - -/* If you are running on a machine where you cannot allocate more - * than 64K of memory at once, uncomment this. While libpng will not - * normally need that much memory in a chunk (unless you load up a very - * large file), zlib needs to know how big of a chunk it can use, and - * libpng thus makes sure to check any memory allocation to verify it - * will fit into memory. -#define PNG_MAX_MALLOC_64K - */ -#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K) -# define PNG_MAX_MALLOC_64K -#endif - -/* Special munging to support doing things the 'cygwin' way: - * 'Normal' png-on-win32 defines/defaults: - * PNG_BUILD_DLL -- building dll - * PNG_USE_DLL -- building an application, linking to dll - * (no define) -- building static library, or building an - * application and linking to the static lib - * 'Cygwin' defines/defaults: - * PNG_BUILD_DLL -- (ignored) building the dll - * (no define) -- (ignored) building an application, linking to the dll - * PNG_STATIC -- (ignored) building the static lib, or building an - * application that links to the static lib. - * ALL_STATIC -- (ignored) building various static libs, or building an - * application that links to the static libs. - * Thus, - * a cygwin user should define either PNG_BUILD_DLL or PNG_STATIC, and - * this bit of #ifdefs will define the 'correct' config variables based on - * that. If a cygwin user *wants* to define 'PNG_USE_DLL' that's okay, but - * unnecessary. - * - * Also, the precedence order is: - * ALL_STATIC (since we can't #undef something outside our namespace) - * PNG_BUILD_DLL - * PNG_STATIC - * (nothing) == PNG_USE_DLL - * - * CYGWIN (2002-01-20): The preceding is now obsolete. With the advent - * of auto-import in binutils, we no longer need to worry about - * __declspec(dllexport) / __declspec(dllimport) and friends. Therefore, - * we don't need to worry about PNG_STATIC or ALL_STATIC when it comes - * to __declspec() stuff. However, we DO need to worry about - * PNG_BUILD_DLL and PNG_STATIC because those change some defaults - * such as CONSOLE_IO and whether GLOBAL_ARRAYS are allowed. - */ -#if defined(__CYGWIN__) -# if defined(ALL_STATIC) -# if defined(PNG_BUILD_DLL) -# undef PNG_BUILD_DLL -# endif -# if defined(PNG_USE_DLL) -# undef PNG_USE_DLL -# endif -# if defined(PNG_DLL) -# undef PNG_DLL -# endif -# if !defined(PNG_STATIC) -# define PNG_STATIC -# endif -# else -# if defined (PNG_BUILD_DLL) -# if defined(PNG_STATIC) -# undef PNG_STATIC -# endif -# if defined(PNG_USE_DLL) -# undef PNG_USE_DLL -# endif -# if !defined(PNG_DLL) -# define PNG_DLL -# endif -# else -# if defined(PNG_STATIC) -# if defined(PNG_USE_DLL) -# undef PNG_USE_DLL -# endif -# if defined(PNG_DLL) -# undef PNG_DLL -# endif -# else -# if !defined(PNG_USE_DLL) -# define PNG_USE_DLL -# endif -# if !defined(PNG_DLL) -# define PNG_DLL -# endif -# endif -# endif -# endif -#endif - -/* This protects us against compilers that run on a windowing system - * and thus don't have or would rather us not use the stdio types: - * stdin, stdout, and stderr. The only one currently used is stderr - * in png_error() and png_warning(). #defining PNG_NO_CONSOLE_IO will - * prevent these from being compiled and used. #defining PNG_NO_STDIO - * will also prevent these, plus will prevent the entire set of stdio - * macros and functions (FILE *, printf, etc.) from being compiled and used, - * unless (PNG_DEBUG > 0) has been #defined. - * - * #define PNG_NO_CONSOLE_IO - * #define PNG_NO_STDIO - */ - -#if defined(_WIN32_WCE) -# include - /* Console I/O functions are not supported on WindowsCE */ -# define PNG_NO_CONSOLE_IO -# ifdef PNG_DEBUG -# undef PNG_DEBUG -# endif -#endif - -#ifdef PNG_BUILD_DLL -# ifndef PNG_CONSOLE_IO_SUPPORTED -# ifndef PNG_NO_CONSOLE_IO -# define PNG_NO_CONSOLE_IO -# endif -# endif -#endif - -# ifdef PNG_NO_STDIO -# ifndef PNG_NO_CONSOLE_IO -# define PNG_NO_CONSOLE_IO -# endif -# ifdef PNG_DEBUG -# if (PNG_DEBUG > 0) -# include -# endif -# endif -# else -# if !defined(_WIN32_WCE) -/* "stdio.h" functions are not supported on WindowsCE */ -# include -# endif -# endif - -/* This macro protects us against machines that don't have function - * prototypes (ie K&R style headers). If your compiler does not handle - * function prototypes, define this macro and use the included ansi2knr. - * I've always been able to use _NO_PROTO as the indicator, but you may - * need to drag the empty declaration out in front of here, or change the - * ifdef to suit your own needs. - */ -#ifndef PNGARG - -#ifdef OF /* zlib prototype munger */ -# define PNGARG(arglist) OF(arglist) -#else - -#ifdef _NO_PROTO -# define PNGARG(arglist) () -# ifndef PNG_TYPECAST_NULL -# define PNG_TYPECAST_NULL -# endif -#else -# define PNGARG(arglist) arglist -#endif /* _NO_PROTO */ - - -#endif /* OF */ - -#endif /* PNGARG */ - -/* Try to determine if we are compiling on a Mac. Note that testing for - * just __MWERKS__ is not good enough, because the Codewarrior is now used - * on non-Mac platforms. - */ -#ifndef MACOS -# if (defined(__MWERKS__) && defined(macintosh)) || defined(applec) || \ - defined(THINK_C) || defined(__SC__) || defined(TARGET_OS_MAC) -# define MACOS -# endif -#endif - -/* enough people need this for various reasons to include it here */ -#if !defined(MACOS) && !defined(RISCOS) && !defined(_WIN32_WCE) -# include -#endif - -#if !defined(PNG_SETJMP_NOT_SUPPORTED) && !defined(PNG_NO_SETJMP_SUPPORTED) -# define PNG_SETJMP_SUPPORTED -#endif - -#ifdef PNG_SETJMP_SUPPORTED -/* This is an attempt to force a single setjmp behaviour on Linux. If - * the X config stuff didn't define _BSD_SOURCE we wouldn't need this. - */ - -# ifdef __linux__ -# ifdef _BSD_SOURCE -# define PNG_SAVE_BSD_SOURCE -# undef _BSD_SOURCE -# endif -# ifdef _SETJMP_H - /* If you encounter a compiler error here, see the explanation - * near the end of INSTALL. - */ - __png.h__ already includes setjmp.h; - __dont__ include it again.; -# endif -# endif /* __linux__ */ - - /* include setjmp.h for error handling */ -# include - -# ifdef __linux__ -# ifdef PNG_SAVE_BSD_SOURCE -# define _BSD_SOURCE -# undef PNG_SAVE_BSD_SOURCE -# endif -# endif /* __linux__ */ -#endif /* PNG_SETJMP_SUPPORTED */ - -#ifdef BSD -# include -#else -# include -#endif - -/* Other defines for things like memory and the like can go here. */ -#ifdef PNG_INTERNAL - -#include - -/* The functions exported by PNG_EXTERN are PNG_INTERNAL functions, which - * aren't usually used outside the library (as far as I know), so it is - * debatable if they should be exported at all. In the future, when it is - * possible to have run-time registry of chunk-handling functions, some of - * these will be made available again. -#define PNG_EXTERN extern - */ -#define PNG_EXTERN - -/* Other defines specific to compilers can go here. Try to keep - * them inside an appropriate ifdef/endif pair for portability. - */ - -#if defined(PNG_FLOATING_POINT_SUPPORTED) -# if defined(MACOS) - /* We need to check that hasn't already been included earlier - * as it seems it doesn't agree with , yet we should really use - * if possible. - */ -# if !defined(__MATH_H__) && !defined(__MATH_H) && !defined(__cmath__) -# include -# endif -# else -# include -# endif -# if defined(_AMIGA) && defined(__SASC) && defined(_M68881) - /* Amiga SAS/C: We must include builtin FPU functions when compiling using - * MATH=68881 - */ -# include -# endif -#endif - -/* Codewarrior on NT has linking problems without this. */ -#if (defined(__MWERKS__) && defined(WIN32)) || defined(__STDC__) -# define PNG_ALWAYS_EXTERN -#endif - -/* This provides the non-ANSI (far) memory allocation routines. */ -#if defined(__TURBOC__) && defined(__MSDOS__) -# include -# include -#endif - -/* I have no idea why is this necessary... */ -#if defined(_MSC_VER) && (defined(WIN32) || defined(_Windows) || \ - defined(_WINDOWS) || defined(_WIN32) || defined(__WIN32__)) -# include -#endif - -/* This controls how fine the dithering gets. As this allocates - * a largish chunk of memory (32K), those who are not as concerned - * with dithering quality can decrease some or all of these. - */ -#ifndef PNG_DITHER_RED_BITS -# define PNG_DITHER_RED_BITS 5 -#endif -#ifndef PNG_DITHER_GREEN_BITS -# define PNG_DITHER_GREEN_BITS 5 -#endif -#ifndef PNG_DITHER_BLUE_BITS -# define PNG_DITHER_BLUE_BITS 5 -#endif - -/* This controls how fine the gamma correction becomes when you - * are only interested in 8 bits anyway. Increasing this value - * results in more memory being used, and more pow() functions - * being called to fill in the gamma tables. Don't set this value - * less then 8, and even that may not work (I haven't tested it). - */ - -#ifndef PNG_MAX_GAMMA_8 -# define PNG_MAX_GAMMA_8 11 -#endif - -/* This controls how much a difference in gamma we can tolerate before - * we actually start doing gamma conversion. - */ -#ifndef PNG_GAMMA_THRESHOLD -# define PNG_GAMMA_THRESHOLD 0.05 -#endif - -#endif /* PNG_INTERNAL */ - -/* The following uses const char * instead of char * for error - * and warning message functions, so some compilers won't complain. - * If you do not want to use const, define PNG_NO_CONST here. - */ - -#ifndef PNG_NO_CONST -# define PNG_CONST const -#else -# define PNG_CONST -#endif - -/* The following defines give you the ability to remove code from the - * library that you will not be using. I wish I could figure out how to - * automate this, but I can't do that without making it seriously hard - * on the users. So if you are not using an ability, change the #define - * to and #undef, and that part of the library will not be compiled. If - * your linker can't find a function, you may want to make sure the - * ability is defined here. Some of these depend upon some others being - * defined. I haven't figured out all the interactions here, so you may - * have to experiment awhile to get everything to compile. If you are - * creating or using a shared library, you probably shouldn't touch this, - * as it will affect the size of the structures, and this will cause bad - * things to happen if the library and/or application ever change. - */ - -/* Any features you will not be using can be undef'ed here */ - -/* GR-P, 0.96a: Set "*TRANSFORMS_SUPPORTED as default but allow user - * to turn it off with "*TRANSFORMS_NOT_SUPPORTED" or *PNG_NO_*_TRANSFORMS - * on the compile line, then pick and choose which ones to define without - * having to edit this file. It is safe to use the *TRANSFORMS_NOT_SUPPORTED - * if you only want to have a png-compliant reader/writer but don't need - * any of the extra transformations. This saves about 80 kbytes in a - * typical installation of the library. (PNG_NO_* form added in version - * 1.0.1c, for consistency) - */ - -/* The size of the png_text structure changed in libpng-1.0.6 when - * iTXt support was added. iTXt support was turned off by default through - * libpng-1.2.x, to support old apps that malloc the png_text structure - * instead of calling png_set_text() and letting libpng malloc it. It - * was turned on by default in libpng-1.3.0. - */ - -#if defined(PNG_1_0_X) || defined (PNG_1_2_X) -# ifndef PNG_NO_iTXt_SUPPORTED -# define PNG_NO_iTXt_SUPPORTED -# endif -# ifndef PNG_NO_READ_iTXt -# define PNG_NO_READ_iTXt -# endif -# ifndef PNG_NO_WRITE_iTXt -# define PNG_NO_WRITE_iTXt -# endif -#endif - -#if !defined(PNG_NO_iTXt_SUPPORTED) -# if !defined(PNG_READ_iTXt_SUPPORTED) && !defined(PNG_NO_READ_iTXt) -# define PNG_READ_iTXt -# endif -# if !defined(PNG_WRITE_iTXt_SUPPORTED) && !defined(PNG_NO_WRITE_iTXt) -# define PNG_WRITE_iTXt -# endif -#endif - -/* The following support, added after version 1.0.0, can be turned off here en - * masse by defining PNG_LEGACY_SUPPORTED in case you need binary compatibility - * with old applications that require the length of png_struct and png_info - * to remain unchanged. - */ - -#ifdef PNG_LEGACY_SUPPORTED -# define PNG_NO_FREE_ME -# define PNG_NO_READ_UNKNOWN_CHUNKS -# define PNG_NO_WRITE_UNKNOWN_CHUNKS -# define PNG_NO_READ_USER_CHUNKS -# define PNG_NO_READ_iCCP -# define PNG_NO_WRITE_iCCP -# define PNG_NO_READ_iTXt -# define PNG_NO_WRITE_iTXt -# define PNG_NO_READ_sCAL -# define PNG_NO_WRITE_sCAL -# define PNG_NO_READ_sPLT -# define PNG_NO_WRITE_sPLT -# define PNG_NO_INFO_IMAGE -# define PNG_NO_READ_RGB_TO_GRAY -# define PNG_NO_READ_USER_TRANSFORM -# define PNG_NO_WRITE_USER_TRANSFORM -# define PNG_NO_USER_MEM -# define PNG_NO_READ_EMPTY_PLTE -# define PNG_NO_MNG_FEATURES -# define PNG_NO_FIXED_POINT_SUPPORTED -#endif - -/* Ignore attempt to turn off both floating and fixed point support */ -#if !defined(PNG_FLOATING_POINT_SUPPORTED) || \ - !defined(PNG_NO_FIXED_POINT_SUPPORTED) -# define PNG_FIXED_POINT_SUPPORTED -#endif - -#ifndef PNG_NO_FREE_ME -# define PNG_FREE_ME_SUPPORTED -#endif - -#if defined(PNG_READ_SUPPORTED) - -#if !defined(PNG_READ_TRANSFORMS_NOT_SUPPORTED) && \ - !defined(PNG_NO_READ_TRANSFORMS) -# define PNG_READ_TRANSFORMS_SUPPORTED -#endif - -#ifdef PNG_READ_TRANSFORMS_SUPPORTED -# ifndef PNG_NO_READ_EXPAND -# define PNG_READ_EXPAND_SUPPORTED -# endif -# ifndef PNG_NO_READ_SHIFT -# define PNG_READ_SHIFT_SUPPORTED -# endif -# ifndef PNG_NO_READ_PACK -# define PNG_READ_PACK_SUPPORTED -# endif -# ifndef PNG_NO_READ_BGR -# define PNG_READ_BGR_SUPPORTED -# endif -# ifndef PNG_NO_READ_SWAP -# define PNG_READ_SWAP_SUPPORTED -# endif -# ifndef PNG_NO_READ_PACKSWAP -# define PNG_READ_PACKSWAP_SUPPORTED -# endif -# ifndef PNG_NO_READ_INVERT -# define PNG_READ_INVERT_SUPPORTED -# endif -# ifndef PNG_NO_READ_DITHER -# define PNG_READ_DITHER_SUPPORTED -# endif -# ifndef PNG_NO_READ_BACKGROUND -# define PNG_READ_BACKGROUND_SUPPORTED -# endif -# ifndef PNG_NO_READ_16_TO_8 -# define PNG_READ_16_TO_8_SUPPORTED -# endif -# ifndef PNG_NO_READ_FILLER -# define PNG_READ_FILLER_SUPPORTED -# endif -# ifndef PNG_NO_READ_GAMMA -# define PNG_READ_GAMMA_SUPPORTED -# endif -# ifndef PNG_NO_READ_GRAY_TO_RGB -# define PNG_READ_GRAY_TO_RGB_SUPPORTED -# endif -# ifndef PNG_NO_READ_SWAP_ALPHA -# define PNG_READ_SWAP_ALPHA_SUPPORTED -# endif -# ifndef PNG_NO_READ_INVERT_ALPHA -# define PNG_READ_INVERT_ALPHA_SUPPORTED -# endif -# ifndef PNG_NO_READ_STRIP_ALPHA -# define PNG_READ_STRIP_ALPHA_SUPPORTED -# endif -# ifndef PNG_NO_READ_USER_TRANSFORM -# define PNG_READ_USER_TRANSFORM_SUPPORTED -# endif -# ifndef PNG_NO_READ_RGB_TO_GRAY -# define PNG_READ_RGB_TO_GRAY_SUPPORTED -# endif -#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ - -#if !defined(PNG_NO_PROGRESSIVE_READ) && \ - !defined(PNG_PROGRESSIVE_READ_SUPPORTED) /* if you don't do progressive */ -# define PNG_PROGRESSIVE_READ_SUPPORTED /* reading. This is not talking */ -#endif /* about interlacing capability! You'll */ - /* still have interlacing unless you change the following line: */ - -#define PNG_READ_INTERLACING_SUPPORTED /* required in PNG-compliant decoders */ - -#ifndef PNG_NO_READ_COMPOSITE_NODIV -# ifndef PNG_NO_READ_COMPOSITED_NODIV /* libpng-1.0.x misspelling */ -# define PNG_READ_COMPOSITE_NODIV_SUPPORTED /* well tested on Intel, SGI */ -# endif -#endif - -#if defined(PNG_1_0_X) || defined (PNG_1_2_X) -/* Deprecated, will be removed from version 2.0.0. - Use PNG_MNG_FEATURES_SUPPORTED instead. */ -#ifndef PNG_NO_READ_EMPTY_PLTE -# define PNG_READ_EMPTY_PLTE_SUPPORTED -#endif -#endif - -#endif /* PNG_READ_SUPPORTED */ - -#if defined(PNG_WRITE_SUPPORTED) - -# if !defined(PNG_WRITE_TRANSFORMS_NOT_SUPPORTED) && \ - !defined(PNG_NO_WRITE_TRANSFORMS) -# define PNG_WRITE_TRANSFORMS_SUPPORTED -#endif - -#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED -# ifndef PNG_NO_WRITE_SHIFT -# define PNG_WRITE_SHIFT_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_PACK -# define PNG_WRITE_PACK_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_BGR -# define PNG_WRITE_BGR_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_SWAP -# define PNG_WRITE_SWAP_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_PACKSWAP -# define PNG_WRITE_PACKSWAP_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_INVERT -# define PNG_WRITE_INVERT_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_FILLER -# define PNG_WRITE_FILLER_SUPPORTED /* same as WRITE_STRIP_ALPHA */ -# endif -# ifndef PNG_NO_WRITE_SWAP_ALPHA -# define PNG_WRITE_SWAP_ALPHA_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_INVERT_ALPHA -# define PNG_WRITE_INVERT_ALPHA_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_USER_TRANSFORM -# define PNG_WRITE_USER_TRANSFORM_SUPPORTED -# endif -#endif /* PNG_WRITE_TRANSFORMS_SUPPORTED */ - -#if !defined(PNG_NO_WRITE_INTERLACING_SUPPORTED) && \ - !defined(PNG_WRITE_INTERLACING_SUPPORTED) -#define PNG_WRITE_INTERLACING_SUPPORTED /* not required for PNG-compliant - encoders, but can cause trouble - if left undefined */ -#endif - -#if !defined(PNG_NO_WRITE_WEIGHTED_FILTER) && \ - !defined(PNG_WRITE_WEIGHTED_FILTER) && \ - defined(PNG_FLOATING_POINT_SUPPORTED) -# define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED -#endif - -#ifndef PNG_NO_WRITE_FLUSH -# define PNG_WRITE_FLUSH_SUPPORTED -#endif - -#if defined(PNG_1_0_X) || defined (PNG_1_2_X) -/* Deprecated, see PNG_MNG_FEATURES_SUPPORTED, above */ -#ifndef PNG_NO_WRITE_EMPTY_PLTE -# define PNG_WRITE_EMPTY_PLTE_SUPPORTED -#endif -#endif - -#endif /* PNG_WRITE_SUPPORTED */ - -#ifndef PNG_1_0_X -# ifndef PNG_NO_ERROR_NUMBERS -# define PNG_ERROR_NUMBERS_SUPPORTED -# endif -#endif /* PNG_1_0_X */ - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) -# ifndef PNG_NO_USER_TRANSFORM_PTR -# define PNG_USER_TRANSFORM_PTR_SUPPORTED -# endif -#endif - -#ifndef PNG_NO_STDIO -# define PNG_TIME_RFC1123_SUPPORTED -#endif - -/* This adds extra functions in pngget.c for accessing data from the - * info pointer (added in version 0.99) - * png_get_image_width() - * png_get_image_height() - * png_get_bit_depth() - * png_get_color_type() - * png_get_compression_type() - * png_get_filter_type() - * png_get_interlace_type() - * png_get_pixel_aspect_ratio() - * png_get_pixels_per_meter() - * png_get_x_offset_pixels() - * png_get_y_offset_pixels() - * png_get_x_offset_microns() - * png_get_y_offset_microns() - */ -#if !defined(PNG_NO_EASY_ACCESS) && !defined(PNG_EASY_ACCESS_SUPPORTED) -# define PNG_EASY_ACCESS_SUPPORTED -#endif - -/* PNG_ASSEMBLER_CODE was enabled by default in version 1.2.0 - * and removed from version 1.2.20. The following will be removed - * from libpng-1.4.0 -*/ - -#if defined(PNG_READ_SUPPORTED) && !defined(PNG_NO_OPTIMIZED_CODE) -# ifndef PNG_OPTIMIZED_CODE_SUPPORTED -# define PNG_OPTIMIZED_CODE_SUPPORTED -# endif -#endif - -#if defined(PNG_READ_SUPPORTED) && !defined(PNG_NO_ASSEMBLER_CODE) -# ifndef PNG_ASSEMBLER_CODE_SUPPORTED -# define PNG_ASSEMBLER_CODE_SUPPORTED -# endif - -# if defined(__GNUC__) && defined(__x86_64__) && (__GNUC__ < 4) - /* work around 64-bit gcc compiler bugs in gcc-3.x */ -# if !defined(PNG_MMX_CODE_SUPPORTED) && !defined(PNG_NO_MMX_CODE) -# define PNG_NO_MMX_CODE -# endif -# endif - -# if defined(__APPLE__) -# if !defined(PNG_MMX_CODE_SUPPORTED) && !defined(PNG_NO_MMX_CODE) -# define PNG_NO_MMX_CODE -# endif -# endif - -# if (defined(__MWERKS__) && ((__MWERKS__ < 0x0900) || macintosh)) -# if !defined(PNG_MMX_CODE_SUPPORTED) && !defined(PNG_NO_MMX_CODE) -# define PNG_NO_MMX_CODE -# endif -# endif - -# if !defined(PNG_MMX_CODE_SUPPORTED) && !defined(PNG_NO_MMX_CODE) -# define PNG_MMX_CODE_SUPPORTED -# endif - -#endif -/* end of obsolete code to be removed from libpng-1.4.0 */ - -#if !defined(PNG_1_0_X) -#if !defined(PNG_NO_USER_MEM) && !defined(PNG_USER_MEM_SUPPORTED) -# define PNG_USER_MEM_SUPPORTED -#endif -#endif /* PNG_1_0_X */ - -/* Added at libpng-1.2.6 */ -#if !defined(PNG_1_0_X) -#ifndef PNG_SET_USER_LIMITS_SUPPORTED -#if !defined(PNG_NO_SET_USER_LIMITS) && !defined(PNG_SET_USER_LIMITS_SUPPORTED) -# define PNG_SET_USER_LIMITS_SUPPORTED -#endif -#endif -#endif /* PNG_1_0_X */ - -/* Added at libpng-1.0.16 and 1.2.6. To accept all valid PNGS no matter - * how large, set these limits to 0x7fffffffL - */ -#ifndef PNG_USER_WIDTH_MAX -# define PNG_USER_WIDTH_MAX 1000000L -#endif -#ifndef PNG_USER_HEIGHT_MAX -# define PNG_USER_HEIGHT_MAX 1000000L -#endif - -/* These are currently experimental features, define them if you want */ - -/* very little testing */ -/* -#ifdef PNG_READ_SUPPORTED -# ifndef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED -# define PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED -# endif -#endif -*/ - -/* This is only for PowerPC big-endian and 680x0 systems */ -/* some testing */ -/* -#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED -# define PNG_READ_BIG_ENDIAN_SUPPORTED -#endif -*/ - -/* Buggy compilers (e.g., gcc 2.7.2.2) need this */ -/* -#define PNG_NO_POINTER_INDEXING -*/ - -/* These functions are turned off by default, as they will be phased out. */ -/* -#define PNG_USELESS_TESTS_SUPPORTED -#define PNG_CORRECT_PALETTE_SUPPORTED -*/ - -/* Any chunks you are not interested in, you can undef here. The - * ones that allocate memory may be expecially important (hIST, - * tEXt, zTXt, tRNS, pCAL). Others will just save time and make png_info - * a bit smaller. - */ - -#if defined(PNG_READ_SUPPORTED) && \ - !defined(PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \ - !defined(PNG_NO_READ_ANCILLARY_CHUNKS) -# define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED -#endif - -#if defined(PNG_WRITE_SUPPORTED) && \ - !defined(PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \ - !defined(PNG_NO_WRITE_ANCILLARY_CHUNKS) -# define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED -#endif - -#ifdef PNG_READ_ANCILLARY_CHUNKS_SUPPORTED - -#ifdef PNG_NO_READ_TEXT -# define PNG_NO_READ_iTXt -# define PNG_NO_READ_tEXt -# define PNG_NO_READ_zTXt -#endif -#ifndef PNG_NO_READ_bKGD -# define PNG_READ_bKGD_SUPPORTED -# define PNG_bKGD_SUPPORTED -#endif -#ifndef PNG_NO_READ_cHRM -# define PNG_READ_cHRM_SUPPORTED -# define PNG_cHRM_SUPPORTED -#endif -#ifndef PNG_NO_READ_gAMA -# define PNG_READ_gAMA_SUPPORTED -# define PNG_gAMA_SUPPORTED -#endif -#ifndef PNG_NO_READ_hIST -# define PNG_READ_hIST_SUPPORTED -# define PNG_hIST_SUPPORTED -#endif -#ifndef PNG_NO_READ_iCCP -# define PNG_READ_iCCP_SUPPORTED -# define PNG_iCCP_SUPPORTED -#endif -#ifndef PNG_NO_READ_iTXt -# ifndef PNG_READ_iTXt_SUPPORTED -# define PNG_READ_iTXt_SUPPORTED -# endif -# ifndef PNG_iTXt_SUPPORTED -# define PNG_iTXt_SUPPORTED -# endif -#endif -#ifndef PNG_NO_READ_oFFs -# define PNG_READ_oFFs_SUPPORTED -# define PNG_oFFs_SUPPORTED -#endif -#ifndef PNG_NO_READ_pCAL -# define PNG_READ_pCAL_SUPPORTED -# define PNG_pCAL_SUPPORTED -#endif -#ifndef PNG_NO_READ_sCAL -# define PNG_READ_sCAL_SUPPORTED -# define PNG_sCAL_SUPPORTED -#endif -#ifndef PNG_NO_READ_pHYs -# define PNG_READ_pHYs_SUPPORTED -# define PNG_pHYs_SUPPORTED -#endif -#ifndef PNG_NO_READ_sBIT -# define PNG_READ_sBIT_SUPPORTED -# define PNG_sBIT_SUPPORTED -#endif -#ifndef PNG_NO_READ_sPLT -# define PNG_READ_sPLT_SUPPORTED -# define PNG_sPLT_SUPPORTED -#endif -#ifndef PNG_NO_READ_sRGB -# define PNG_READ_sRGB_SUPPORTED -# define PNG_sRGB_SUPPORTED -#endif -#ifndef PNG_NO_READ_tEXt -# define PNG_READ_tEXt_SUPPORTED -# define PNG_tEXt_SUPPORTED -#endif -#ifndef PNG_NO_READ_tIME -# define PNG_READ_tIME_SUPPORTED -# define PNG_tIME_SUPPORTED -#endif -#ifndef PNG_NO_READ_tRNS -# define PNG_READ_tRNS_SUPPORTED -# define PNG_tRNS_SUPPORTED -#endif -#ifndef PNG_NO_READ_zTXt -# define PNG_READ_zTXt_SUPPORTED -# define PNG_zTXt_SUPPORTED -#endif -#ifndef PNG_NO_READ_UNKNOWN_CHUNKS -# define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED -# ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED -# define PNG_UNKNOWN_CHUNKS_SUPPORTED -# endif -# ifndef PNG_NO_HANDLE_AS_UNKNOWN -# define PNG_HANDLE_AS_UNKNOWN_SUPPORTED -# endif -#endif -#if !defined(PNG_NO_READ_USER_CHUNKS) && \ - defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) -# define PNG_READ_USER_CHUNKS_SUPPORTED -# define PNG_USER_CHUNKS_SUPPORTED -# ifdef PNG_NO_READ_UNKNOWN_CHUNKS -# undef PNG_NO_READ_UNKNOWN_CHUNKS -# endif -# ifdef PNG_NO_HANDLE_AS_UNKNOWN -# undef PNG_NO_HANDLE_AS_UNKNOWN -# endif -#endif -#ifndef PNG_NO_READ_OPT_PLTE -# define PNG_READ_OPT_PLTE_SUPPORTED /* only affects support of the */ -#endif /* optional PLTE chunk in RGB and RGBA images */ -#if defined(PNG_READ_iTXt_SUPPORTED) || defined(PNG_READ_tEXt_SUPPORTED) || \ - defined(PNG_READ_zTXt_SUPPORTED) -# define PNG_READ_TEXT_SUPPORTED -# define PNG_TEXT_SUPPORTED -#endif - -#endif /* PNG_READ_ANCILLARY_CHUNKS_SUPPORTED */ - -#ifdef PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED - -#ifdef PNG_NO_WRITE_TEXT -# define PNG_NO_WRITE_iTXt -# define PNG_NO_WRITE_tEXt -# define PNG_NO_WRITE_zTXt -#endif -#ifndef PNG_NO_WRITE_bKGD -# define PNG_WRITE_bKGD_SUPPORTED -# ifndef PNG_bKGD_SUPPORTED -# define PNG_bKGD_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_cHRM -# define PNG_WRITE_cHRM_SUPPORTED -# ifndef PNG_cHRM_SUPPORTED -# define PNG_cHRM_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_gAMA -# define PNG_WRITE_gAMA_SUPPORTED -# ifndef PNG_gAMA_SUPPORTED -# define PNG_gAMA_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_hIST -# define PNG_WRITE_hIST_SUPPORTED -# ifndef PNG_hIST_SUPPORTED -# define PNG_hIST_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_iCCP -# define PNG_WRITE_iCCP_SUPPORTED -# ifndef PNG_iCCP_SUPPORTED -# define PNG_iCCP_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_iTXt -# ifndef PNG_WRITE_iTXt_SUPPORTED -# define PNG_WRITE_iTXt_SUPPORTED -# endif -# ifndef PNG_iTXt_SUPPORTED -# define PNG_iTXt_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_oFFs -# define PNG_WRITE_oFFs_SUPPORTED -# ifndef PNG_oFFs_SUPPORTED -# define PNG_oFFs_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_pCAL -# define PNG_WRITE_pCAL_SUPPORTED -# ifndef PNG_pCAL_SUPPORTED -# define PNG_pCAL_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_sCAL -# define PNG_WRITE_sCAL_SUPPORTED -# ifndef PNG_sCAL_SUPPORTED -# define PNG_sCAL_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_pHYs -# define PNG_WRITE_pHYs_SUPPORTED -# ifndef PNG_pHYs_SUPPORTED -# define PNG_pHYs_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_sBIT -# define PNG_WRITE_sBIT_SUPPORTED -# ifndef PNG_sBIT_SUPPORTED -# define PNG_sBIT_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_sPLT -# define PNG_WRITE_sPLT_SUPPORTED -# ifndef PNG_sPLT_SUPPORTED -# define PNG_sPLT_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_sRGB -# define PNG_WRITE_sRGB_SUPPORTED -# ifndef PNG_sRGB_SUPPORTED -# define PNG_sRGB_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_tEXt -# define PNG_WRITE_tEXt_SUPPORTED -# ifndef PNG_tEXt_SUPPORTED -# define PNG_tEXt_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_tIME -# define PNG_WRITE_tIME_SUPPORTED -# ifndef PNG_tIME_SUPPORTED -# define PNG_tIME_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_tRNS -# define PNG_WRITE_tRNS_SUPPORTED -# ifndef PNG_tRNS_SUPPORTED -# define PNG_tRNS_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_zTXt -# define PNG_WRITE_zTXt_SUPPORTED -# ifndef PNG_zTXt_SUPPORTED -# define PNG_zTXt_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_UNKNOWN_CHUNKS -# define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED -# ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED -# define PNG_UNKNOWN_CHUNKS_SUPPORTED -# endif -# ifndef PNG_NO_HANDLE_AS_UNKNOWN -# ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED -# define PNG_HANDLE_AS_UNKNOWN_SUPPORTED -# endif -# endif -#endif -#if defined(PNG_WRITE_iTXt_SUPPORTED) || defined(PNG_WRITE_tEXt_SUPPORTED) || \ - defined(PNG_WRITE_zTXt_SUPPORTED) -# define PNG_WRITE_TEXT_SUPPORTED -# ifndef PNG_TEXT_SUPPORTED -# define PNG_TEXT_SUPPORTED -# endif -#endif - -#endif /* PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED */ - -/* Turn this off to disable png_read_png() and - * png_write_png() and leave the row_pointers member - * out of the info structure. - */ -#ifndef PNG_NO_INFO_IMAGE -# define PNG_INFO_IMAGE_SUPPORTED -#endif - -/* need the time information for reading tIME chunks */ -#if defined(PNG_tIME_SUPPORTED) -# if !defined(_WIN32_WCE) - /* "time.h" functions are not supported on WindowsCE */ -# include -# endif -#endif - -/* Some typedefs to get us started. These should be safe on most of the - * common platforms. The typedefs should be at least as large as the - * numbers suggest (a png_uint_32 must be at least 32 bits long), but they - * don't have to be exactly that size. Some compilers dislike passing - * unsigned shorts as function parameters, so you may be better off using - * unsigned int for png_uint_16. Likewise, for 64-bit systems, you may - * want to have unsigned int for png_uint_32 instead of unsigned long. - */ - -typedef unsigned long png_uint_32; -typedef long png_int_32; -typedef unsigned short png_uint_16; -typedef short png_int_16; -typedef unsigned char png_byte; - -/* This is usually size_t. It is typedef'ed just in case you need it to - change (I'm not sure if you will or not, so I thought I'd be safe) */ -#ifdef PNG_SIZE_T - typedef PNG_SIZE_T png_size_t; -# define png_sizeof(x) png_convert_size(sizeof (x)) -#else - typedef size_t png_size_t; -# define png_sizeof(x) sizeof (x) -#endif - -/* The following is needed for medium model support. It cannot be in the - * PNG_INTERNAL section. Needs modification for other compilers besides - * MSC. Model independent support declares all arrays and pointers to be - * large using the far keyword. The zlib version used must also support - * model independent data. As of version zlib 1.0.4, the necessary changes - * have been made in zlib. The USE_FAR_KEYWORD define triggers other - * changes that are needed. (Tim Wegner) - */ - -/* Separate compiler dependencies (problem here is that zlib.h always - defines FAR. (SJT) */ -#ifdef __BORLANDC__ -# if defined(__LARGE__) || defined(__HUGE__) || defined(__COMPACT__) -# define LDATA 1 -# else -# define LDATA 0 -# endif - /* GRR: why is Cygwin in here? Cygwin is not Borland C... */ -# if !defined(__WIN32__) && !defined(__FLAT__) && !defined(__CYGWIN__) -# define PNG_MAX_MALLOC_64K -# if (LDATA != 1) -# ifndef FAR -# define FAR __far -# endif -# define USE_FAR_KEYWORD -# endif /* LDATA != 1 */ - /* Possibly useful for moving data out of default segment. - * Uncomment it if you want. Could also define FARDATA as - * const if your compiler supports it. (SJT) -# define FARDATA FAR - */ -# endif /* __WIN32__, __FLAT__, __CYGWIN__ */ -#endif /* __BORLANDC__ */ - - -/* Suggest testing for specific compiler first before testing for - * FAR. The Watcom compiler defines both __MEDIUM__ and M_I86MM, - * making reliance oncertain keywords suspect. (SJT) - */ - -/* MSC Medium model */ -#if defined(FAR) -# if defined(M_I86MM) -# define USE_FAR_KEYWORD -# define FARDATA FAR -# include -# endif -#endif - -/* SJT: default case */ -#ifndef FAR -# define FAR -#endif - -/* At this point FAR is always defined */ -#ifndef FARDATA -# define FARDATA -#endif - -/* Typedef for floating-point numbers that are converted - to fixed-point with a multiple of 100,000, e.g., int_gamma */ -typedef png_int_32 png_fixed_point; - -/* Add typedefs for pointers */ -typedef void FAR * png_voidp; -typedef png_byte FAR * png_bytep; -typedef png_uint_32 FAR * png_uint_32p; -typedef png_int_32 FAR * png_int_32p; -typedef png_uint_16 FAR * png_uint_16p; -typedef png_int_16 FAR * png_int_16p; -typedef PNG_CONST char FAR * png_const_charp; -typedef char FAR * png_charp; -typedef png_fixed_point FAR * png_fixed_point_p; - -#ifndef PNG_NO_STDIO -#if defined(_WIN32_WCE) -typedef HANDLE png_FILE_p; -#else -typedef FILE * png_FILE_p; -#endif -#endif - -#ifdef PNG_FLOATING_POINT_SUPPORTED -typedef double FAR * png_doublep; -#endif - -/* Pointers to pointers; i.e. arrays */ -typedef png_byte FAR * FAR * png_bytepp; -typedef png_uint_32 FAR * FAR * png_uint_32pp; -typedef png_int_32 FAR * FAR * png_int_32pp; -typedef png_uint_16 FAR * FAR * png_uint_16pp; -typedef png_int_16 FAR * FAR * png_int_16pp; -typedef PNG_CONST char FAR * FAR * png_const_charpp; -typedef char FAR * FAR * png_charpp; -typedef png_fixed_point FAR * FAR * png_fixed_point_pp; -#ifdef PNG_FLOATING_POINT_SUPPORTED -typedef double FAR * FAR * png_doublepp; -#endif - -/* Pointers to pointers to pointers; i.e., pointer to array */ -typedef char FAR * FAR * FAR * png_charppp; - -#if defined(PNG_1_0_X) || defined(PNG_1_2_X) -/* SPC - Is this stuff deprecated? */ -/* It'll be removed as of libpng-1.3.0 - GR-P */ -/* libpng typedefs for types in zlib. If zlib changes - * or another compression library is used, then change these. - * Eliminates need to change all the source files. - */ -typedef charf * png_zcharp; -typedef charf * FAR * png_zcharpp; -typedef z_stream FAR * png_zstreamp; -#endif /* (PNG_1_0_X) || defined(PNG_1_2_X) */ - -/* - * Define PNG_BUILD_DLL if the module being built is a Windows - * LIBPNG DLL. - * - * Define PNG_USE_DLL if you want to *link* to the Windows LIBPNG DLL. - * It is equivalent to Microsoft predefined macro _DLL that is - * automatically defined when you compile using the share - * version of the CRT (C Run-Time library) - * - * The cygwin mods make this behavior a little different: - * Define PNG_BUILD_DLL if you are building a dll for use with cygwin - * Define PNG_STATIC if you are building a static library for use with cygwin, - * -or- if you are building an application that you want to link to the - * static library. - * PNG_USE_DLL is defined by default (no user action needed) unless one of - * the other flags is defined. - */ - -#if !defined(PNG_DLL) && (defined(PNG_BUILD_DLL) || defined(PNG_USE_DLL)) -# define PNG_DLL -#endif -/* If CYGWIN, then disallow GLOBAL ARRAYS unless building a static lib. - * When building a static lib, default to no GLOBAL ARRAYS, but allow - * command-line override - */ -#if defined(__CYGWIN__) -# if !defined(PNG_STATIC) -# if defined(PNG_USE_GLOBAL_ARRAYS) -# undef PNG_USE_GLOBAL_ARRAYS -# endif -# if !defined(PNG_USE_LOCAL_ARRAYS) -# define PNG_USE_LOCAL_ARRAYS -# endif -# else -# if defined(PNG_USE_LOCAL_ARRAYS) || defined(PNG_NO_GLOBAL_ARRAYS) -# if defined(PNG_USE_GLOBAL_ARRAYS) -# undef PNG_USE_GLOBAL_ARRAYS -# endif -# endif -# endif -# if !defined(PNG_USE_LOCAL_ARRAYS) && !defined(PNG_USE_GLOBAL_ARRAYS) -# define PNG_USE_LOCAL_ARRAYS -# endif -#endif - -/* Do not use global arrays (helps with building DLL's) - * They are no longer used in libpng itself, since version 1.0.5c, - * but might be required for some pre-1.0.5c applications. - */ -#if !defined(PNG_USE_LOCAL_ARRAYS) && !defined(PNG_USE_GLOBAL_ARRAYS) -# if defined(PNG_NO_GLOBAL_ARRAYS) || \ - (defined(__GNUC__) && defined(PNG_DLL)) || defined(_MSC_VER) -# define PNG_USE_LOCAL_ARRAYS -# else -# define PNG_USE_GLOBAL_ARRAYS -# endif -#endif - -#if defined(__CYGWIN__) -# undef PNGAPI -# define PNGAPI __cdecl -# undef PNG_IMPEXP -# define PNG_IMPEXP -#endif - -/* If you define PNGAPI, e.g., with compiler option "-DPNGAPI=__stdcall", - * you may get warnings regarding the linkage of png_zalloc and png_zfree. - * Don't ignore those warnings; you must also reset the default calling - * convention in your compiler to match your PNGAPI, and you must build - * zlib and your applications the same way you build libpng. - */ - -#if defined(__MINGW32__) && !defined(PNG_MODULEDEF) -# ifndef PNG_NO_MODULEDEF -# define PNG_NO_MODULEDEF -# endif -#endif - -#if !defined(PNG_IMPEXP) && defined(PNG_BUILD_DLL) && !defined(PNG_NO_MODULEDEF) -# define PNG_IMPEXP -#endif - -#if defined(PNG_DLL) || defined(_DLL) || defined(__DLL__ ) || \ - (( defined(_Windows) || defined(_WINDOWS) || \ - defined(WIN32) || defined(_WIN32) || defined(__WIN32__) )) - -# ifndef PNGAPI -# if defined(__GNUC__) || (defined (_MSC_VER) && (_MSC_VER >= 800)) -# define PNGAPI __cdecl -# else -# define PNGAPI _cdecl -# endif -# endif - -# if !defined(PNG_IMPEXP) && (!defined(PNG_DLL) || \ - 0 /* WINCOMPILER_WITH_NO_SUPPORT_FOR_DECLIMPEXP */) -# define PNG_IMPEXP -# endif - -# if !defined(PNG_IMPEXP) - -# define PNG_EXPORT_TYPE1(type,symbol) PNG_IMPEXP type PNGAPI symbol -# define PNG_EXPORT_TYPE2(type,symbol) type PNG_IMPEXP PNGAPI symbol - - /* Borland/Microsoft */ -# if defined(_MSC_VER) || defined(__BORLANDC__) -# if (_MSC_VER >= 800) || (__BORLANDC__ >= 0x500) -# define PNG_EXPORT PNG_EXPORT_TYPE1 -# else -# define PNG_EXPORT PNG_EXPORT_TYPE2 -# if defined(PNG_BUILD_DLL) -# define PNG_IMPEXP __export -# else -# define PNG_IMPEXP /*__import */ /* doesn't exist AFAIK in - VC++ */ -# endif /* Exists in Borland C++ for - C++ classes (== huge) */ -# endif -# endif - -# if !defined(PNG_IMPEXP) -# if defined(PNG_BUILD_DLL) -# define PNG_IMPEXP __declspec(dllexport) -# else -# define PNG_IMPEXP __declspec(dllimport) -# endif -# endif -# endif /* PNG_IMPEXP */ -#else /* !(DLL || non-cygwin WINDOWS) */ -# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__) -# ifndef PNGAPI -# define PNGAPI _System -# endif -# else -# if 0 /* ... other platforms, with other meanings */ -# endif -# endif -#endif - -#ifndef PNGAPI -# define PNGAPI -#endif -#ifndef PNG_IMPEXP -# define PNG_IMPEXP -#endif - -#ifdef PNG_BUILDSYMS -# ifndef PNG_EXPORT -# define PNG_EXPORT(type,symbol) PNG_FUNCTION_EXPORT symbol END -# endif -# ifdef PNG_USE_GLOBAL_ARRAYS -# ifndef PNG_EXPORT_VAR -# define PNG_EXPORT_VAR(type) PNG_DATA_EXPORT -# endif -# endif -#endif - -#ifndef PNG_EXPORT -# define PNG_EXPORT(type,symbol) PNG_IMPEXP type PNGAPI symbol -#endif - -#ifdef PNG_USE_GLOBAL_ARRAYS -# ifndef PNG_EXPORT_VAR -# define PNG_EXPORT_VAR(type) extern PNG_IMPEXP type -# endif -#endif - -/* User may want to use these so they are not in PNG_INTERNAL. Any library - * functions that are passed far data must be model independent. - */ - -#ifndef PNG_ABORT -# define PNG_ABORT() abort() -#endif - -#ifdef PNG_SETJMP_SUPPORTED -# define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) -#else -# define png_jmpbuf(png_ptr) \ - (LIBPNG_WAS_COMPILED_WITH__PNG_SETJMP_NOT_SUPPORTED) -#endif - -#if defined(USE_FAR_KEYWORD) /* memory model independent fns */ -/* use this to make far-to-near assignments */ -# define CHECK 1 -# define NOCHECK 0 -# define CVT_PTR(ptr) (png_far_to_near(png_ptr,ptr,CHECK)) -# define CVT_PTR_NOCHECK(ptr) (png_far_to_near(png_ptr,ptr,NOCHECK)) -# define png_snprintf _fsnprintf /* Added to v 1.2.19 */ -# define png_strcpy _fstrcpy -# define png_strncpy _fstrncpy /* Added to v 1.2.6 */ -# define png_strlen _fstrlen -# define png_memcmp _fmemcmp /* SJT: added */ -# define png_memcpy _fmemcpy -# define png_memset _fmemset -#else /* use the usual functions */ -# define CVT_PTR(ptr) (ptr) -# define CVT_PTR_NOCHECK(ptr) (ptr) -# ifndef PNG_NO_SNPRINTF -# ifdef _MSC_VER -# define png_snprintf _snprintf /* Added to v 1.2.19 */ -# define png_snprintf2 _snprintf -# define png_snprintf6 _snprintf -# else -# define png_snprintf snprintf /* Added to v 1.2.19 */ -# define png_snprintf2 snprintf -# define png_snprintf6 snprintf -# endif -# else - /* You don't have or don't want to use snprintf(). Caution: Using - * sprintf instead of snprintf exposes your application to accidental - * or malevolent buffer overflows. If you don't have snprintf() - * as a general rule you should provide one (you can get one from - * Portable OpenSSH). */ -# define png_snprintf(s1,n,fmt,x1) sprintf(s1,fmt,x1) -# define png_snprintf2(s1,n,fmt,x1,x2) sprintf(s1,fmt,x1,x2) -# define png_snprintf6(s1,n,fmt,x1,x2,x3,x4,x5,x6) \ - sprintf(s1,fmt,x1,x2,x3,x4,x5,x6) -# endif -# define png_strcpy strcpy -# define png_strncpy strncpy /* Added to v 1.2.6 */ -# define png_strlen strlen -# define png_memcmp memcmp /* SJT: added */ -# define png_memcpy memcpy -# define png_memset memset -#endif -/* End of memory model independent support */ - -/* Just a little check that someone hasn't tried to define something - * contradictory. - */ -#if (PNG_ZBUF_SIZE > 65536L) && defined(PNG_MAX_MALLOC_64K) -# undef PNG_ZBUF_SIZE -# define PNG_ZBUF_SIZE 65536L -#endif - -/* Added at libpng-1.2.8 */ -#endif /* PNG_VERSION_INFO_ONLY */ - -#endif /* PNGCONF_H */ diff --git a/uppdev/plugin/png/lib/pngerror.c b/uppdev/plugin/png/lib/pngerror.c deleted file mode 100644 index 43820442c..000000000 --- a/uppdev/plugin/png/lib/pngerror.c +++ /dev/null @@ -1,341 +0,0 @@ - -/* pngerror.c - stub functions for i/o and memory allocation - * - * Last changed in libpng 1.2.22 [October 13, 2007] - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2007 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This file provides a location for all error handling. Users who - * need special error handling are expected to write replacement functions - * and use png_set_error_fn() to use those functions. See the instructions - * at each function. - */ - -#define PNG_INTERNAL -#include "png.h" - -#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) -static void /* PRIVATE */ -png_default_error PNGARG((png_structp png_ptr, - png_const_charp error_message)); -#ifndef PNG_NO_WARNINGS -static void /* PRIVATE */ -png_default_warning PNGARG((png_structp png_ptr, - png_const_charp warning_message)); -#endif /* PNG_NO_WARNINGS */ - -/* This function is called whenever there is a fatal error. This function - * should not be changed. If there is a need to handle errors differently, - * you should supply a replacement error function and use png_set_error_fn() - * to replace the error function at run-time. - */ -#ifndef PNG_NO_ERROR_TEXT -void PNGAPI -png_error(png_structp png_ptr, png_const_charp error_message) -{ -#ifdef PNG_ERROR_NUMBERS_SUPPORTED - char msg[16]; - if (png_ptr != NULL) - { - if (png_ptr->flags& - (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) - { - if (*error_message == '#') - { - int offset; - for (offset=1; offset<15; offset++) - if (*(error_message+offset) == ' ') - break; - if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT) - { - int i; - for (i=0; iflags&PNG_FLAG_STRIP_ERROR_TEXT) - { - msg[0]='0'; - msg[1]='\0'; - error_message=msg; - } - } - } - } -#endif - if (png_ptr != NULL && png_ptr->error_fn != NULL) - (*(png_ptr->error_fn))(png_ptr, error_message); - - /* If the custom handler doesn't exist, or if it returns, - use the default handler, which will not return. */ - png_default_error(png_ptr, error_message); -} -#else -void PNGAPI -png_err(png_structp png_ptr) -{ - if (png_ptr != NULL && png_ptr->error_fn != NULL) - (*(png_ptr->error_fn))(png_ptr, '\0'); - - /* If the custom handler doesn't exist, or if it returns, - use the default handler, which will not return. */ - png_default_error(png_ptr, '\0'); -} -#endif /* PNG_NO_ERROR_TEXT */ - -#ifndef PNG_NO_WARNINGS -/* This function is called whenever there is a non-fatal error. This function - * should not be changed. If there is a need to handle warnings differently, - * you should supply a replacement warning function and use - * png_set_error_fn() to replace the warning function at run-time. - */ -void PNGAPI -png_warning(png_structp png_ptr, png_const_charp warning_message) -{ - int offset = 0; - if (png_ptr != NULL) - { -#ifdef PNG_ERROR_NUMBERS_SUPPORTED - if (png_ptr->flags& - (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) -#endif - { - if (*warning_message == '#') - { - for (offset=1; offset<15; offset++) - if (*(warning_message+offset) == ' ') - break; - } - } - if (png_ptr != NULL && png_ptr->warning_fn != NULL) - (*(png_ptr->warning_fn))(png_ptr, warning_message+offset); - } - else - png_default_warning(png_ptr, warning_message+offset); -} -#endif /* PNG_NO_WARNINGS */ - - -/* These utilities are used internally to build an error message that relates - * to the current chunk. The chunk name comes from png_ptr->chunk_name, - * this is used to prefix the message. The message is limited in length - * to 63 bytes, the name characters are output as hex digits wrapped in [] - * if the character is invalid. - */ -#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) -static PNG_CONST char png_digit[16] = { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - 'A', 'B', 'C', 'D', 'E', 'F' -}; - -#if !defined(PNG_NO_WARNINGS) || !defined(PNG_NO_ERROR_TEXT) -static void /* PRIVATE */ -png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp - error_message) -{ - int iout = 0, iin = 0; - - while (iin < 4) - { - int c = png_ptr->chunk_name[iin++]; - if (isnonalpha(c)) - { - buffer[iout++] = '['; - buffer[iout++] = png_digit[(c & 0xf0) >> 4]; - buffer[iout++] = png_digit[c & 0x0f]; - buffer[iout++] = ']'; - } - else - { - buffer[iout++] = (png_byte)c; - } - } - - if (error_message == NULL) - buffer[iout] = '\0'; - else - { - buffer[iout++] = ':'; - buffer[iout++] = ' '; - png_strncpy(buffer+iout, error_message, 63); - buffer[iout+63] = '\0'; - } -} - -#ifdef PNG_READ_SUPPORTED -void PNGAPI -png_chunk_error(png_structp png_ptr, png_const_charp error_message) -{ - char msg[18+64]; - if (png_ptr == NULL) - png_error(png_ptr, error_message); - else - { - png_format_buffer(png_ptr, msg, error_message); - png_error(png_ptr, msg); - } -} -#endif /* PNG_READ_SUPPORTED */ -#endif /* !defined(PNG_NO_WARNINGS) || !defined(PNG_NO_ERROR_TEXT) */ - -#ifndef PNG_NO_WARNINGS -void PNGAPI -png_chunk_warning(png_structp png_ptr, png_const_charp warning_message) -{ - char msg[18+64]; - if (png_ptr == NULL) - png_warning(png_ptr, warning_message); - else - { - png_format_buffer(png_ptr, msg, warning_message); - png_warning(png_ptr, msg); - } -} -#endif /* PNG_NO_WARNINGS */ - - -/* This is the default error handling function. Note that replacements for - * this function MUST NOT RETURN, or the program will likely crash. This - * function is used by default, or if the program supplies NULL for the - * error function pointer in png_set_error_fn(). - */ -static void /* PRIVATE */ -png_default_error(png_structp png_ptr, png_const_charp error_message) -{ -#ifndef PNG_NO_CONSOLE_IO -#ifdef PNG_ERROR_NUMBERS_SUPPORTED - if (*error_message == '#') - { - int offset; - char error_number[16]; - for (offset=0; offset<15; offset++) - { - error_number[offset] = *(error_message+offset+1); - if (*(error_message+offset) == ' ') - break; - } - if((offset > 1) && (offset < 15)) - { - error_number[offset-1]='\0'; - fprintf(stderr, "libpng error no. %s: %s\n", error_number, - error_message+offset); - } - else - fprintf(stderr, "libpng error: %s, offset=%d\n", error_message,offset); - } - else -#endif - fprintf(stderr, "libpng error: %s\n", error_message); -#endif - -#ifdef PNG_SETJMP_SUPPORTED - if (png_ptr) - { -# ifdef USE_FAR_KEYWORD - { - jmp_buf jmpbuf; - png_memcpy(jmpbuf, png_ptr->jmpbuf, png_sizeof(jmp_buf)); - longjmp(jmpbuf, 1); - } -# else - longjmp(png_ptr->jmpbuf, 1); -# endif - } -#else - PNG_ABORT(); -#endif -#ifdef PNG_NO_CONSOLE_IO - error_message = error_message; /* make compiler happy */ -#endif -} - -#ifndef PNG_NO_WARNINGS -/* This function is called when there is a warning, but the library thinks - * it can continue anyway. Replacement functions don't have to do anything - * here if you don't want them to. In the default configuration, png_ptr is - * not used, but it is passed in case it may be useful. - */ -static void /* PRIVATE */ -png_default_warning(png_structp png_ptr, png_const_charp warning_message) -{ -#ifndef PNG_NO_CONSOLE_IO -# ifdef PNG_ERROR_NUMBERS_SUPPORTED - if (*warning_message == '#') - { - int offset; - char warning_number[16]; - for (offset=0; offset<15; offset++) - { - warning_number[offset]=*(warning_message+offset+1); - if (*(warning_message+offset) == ' ') - break; - } - if((offset > 1) && (offset < 15)) - { - warning_number[offset-1]='\0'; - fprintf(stderr, "libpng warning no. %s: %s\n", warning_number, - warning_message+offset); - } - else - fprintf(stderr, "libpng warning: %s\n", warning_message); - } - else -# endif - fprintf(stderr, "libpng warning: %s\n", warning_message); -#else - warning_message = warning_message; /* make compiler happy */ -#endif - png_ptr = png_ptr; /* make compiler happy */ -} -#endif /* PNG_NO_WARNINGS */ - -/* This function is called when the application wants to use another method - * of handling errors and warnings. Note that the error function MUST NOT - * return to the calling routine or serious problems will occur. The return - * method used in the default routine calls longjmp(png_ptr->jmpbuf, 1) - */ -void PNGAPI -png_set_error_fn(png_structp png_ptr, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warning_fn) -{ - if (png_ptr == NULL) - return; - png_ptr->error_ptr = error_ptr; - png_ptr->error_fn = error_fn; - png_ptr->warning_fn = warning_fn; -} - - -/* This function returns a pointer to the error_ptr associated with the user - * functions. The application should free any memory associated with this - * pointer before png_write_destroy and png_read_destroy are called. - */ -png_voidp PNGAPI -png_get_error_ptr(png_structp png_ptr) -{ - if (png_ptr == NULL) - return NULL; - return ((png_voidp)png_ptr->error_ptr); -} - - -#ifdef PNG_ERROR_NUMBERS_SUPPORTED -void PNGAPI -png_set_strip_error_numbers(png_structp png_ptr, png_uint_32 strip_mode) -{ - if(png_ptr != NULL) - { - png_ptr->flags &= - ((~(PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT))&strip_mode); - } -} -#endif -#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/uppdev/plugin/png/lib/pnggccrd.c b/uppdev/plugin/png/lib/pnggccrd.c deleted file mode 100644 index bb3f685cd..000000000 --- a/uppdev/plugin/png/lib/pnggccrd.c +++ /dev/null @@ -1,101 +0,0 @@ -/* pnggccrd.c was removed from libpng-1.2.20. */ - -/* This code snippet is for use by configure's compilation test. */ - -#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) && \ - defined(PNG_MMX_CODE_SUPPORTED) -int PNGAPI png_dummy_mmx_support(void); - -static int _mmx_supported = 2; // 0: no MMX; 1: MMX supported; 2: not tested - -int PNGAPI -png_dummy_mmx_support(void) __attribute__((noinline)); - -int PNGAPI -png_dummy_mmx_support(void) -{ - int result; -#if defined(PNG_MMX_CODE_SUPPORTED) // superfluous, but what the heck - __asm__ __volatile__ ( -#if defined(__x86_64__) - "pushq %%rbx \n\t" // rbx gets clobbered by CPUID instruction - "pushq %%rcx \n\t" // so does rcx... - "pushq %%rdx \n\t" // ...and rdx (but rcx & rdx safe on Linux) - "pushfq \n\t" // save Eflag to stack - "popq %%rax \n\t" // get Eflag from stack into rax - "movq %%rax, %%rcx \n\t" // make another copy of Eflag in rcx - "xorl $0x200000, %%eax \n\t" // toggle ID bit in Eflag (i.e., bit 21) - "pushq %%rax \n\t" // save modified Eflag back to stack - "popfq \n\t" // restore modified value to Eflag reg - "pushfq \n\t" // save Eflag to stack - "popq %%rax \n\t" // get Eflag from stack - "pushq %%rcx \n\t" // save original Eflag to stack - "popfq \n\t" // restore original Eflag -#else - "pushl %%ebx \n\t" // ebx gets clobbered by CPUID instruction - "pushl %%ecx \n\t" // so does ecx... - "pushl %%edx \n\t" // ...and edx (but ecx & edx safe on Linux) - "pushfl \n\t" // save Eflag to stack - "popl %%eax \n\t" // get Eflag from stack into eax - "movl %%eax, %%ecx \n\t" // make another copy of Eflag in ecx - "xorl $0x200000, %%eax \n\t" // toggle ID bit in Eflag (i.e., bit 21) - "pushl %%eax \n\t" // save modified Eflag back to stack - "popfl \n\t" // restore modified value to Eflag reg - "pushfl \n\t" // save Eflag to stack - "popl %%eax \n\t" // get Eflag from stack - "pushl %%ecx \n\t" // save original Eflag to stack - "popfl \n\t" // restore original Eflag -#endif - "xorl %%ecx, %%eax \n\t" // compare new Eflag with original Eflag - "jz 0f \n\t" // if same, CPUID instr. is not supported - - "xorl %%eax, %%eax \n\t" // set eax to zero -// ".byte 0x0f, 0xa2 \n\t" // CPUID instruction (two-byte opcode) - "cpuid \n\t" // get the CPU identification info - "cmpl $1, %%eax \n\t" // make sure eax return non-zero value - "jl 0f \n\t" // if eax is zero, MMX is not supported - - "xorl %%eax, %%eax \n\t" // set eax to zero and... - "incl %%eax \n\t" // ...increment eax to 1. This pair is - // faster than the instruction "mov eax, 1" - "cpuid \n\t" // get the CPU identification info again - "andl $0x800000, %%edx \n\t" // mask out all bits but MMX bit (23) - "cmpl $0, %%edx \n\t" // 0 = MMX not supported - "jz 0f \n\t" // non-zero = yes, MMX IS supported - - "movl $1, %%eax \n\t" // set return value to 1 - "jmp 1f \n\t" // DONE: have MMX support - - "0: \n\t" // .NOT_SUPPORTED: target label for jump instructions - "movl $0, %%eax \n\t" // set return value to 0 - "1: \n\t" // .RETURN: target label for jump instructions -#if defined(__x86_64__) - "popq %%rdx \n\t" // restore rdx - "popq %%rcx \n\t" // restore rcx - "popq %%rbx \n\t" // restore rbx -#else - "popl %%edx \n\t" // restore edx - "popl %%ecx \n\t" // restore ecx - "popl %%ebx \n\t" // restore ebx -#endif - -// "ret \n\t" // DONE: no MMX support - // (fall through to standard C "ret") - - : "=a" (result) // output list - - : // any variables used on input (none) - - // no clobber list -// , "%ebx", "%ecx", "%edx" // GRR: we handle these manually -// , "memory" // if write to a variable gcc thought was in a reg -// , "cc" // "condition codes" (flag bits) - ); - _mmx_supported = result; -#else - _mmx_supported = 0; -#endif /* PNG_MMX_CODE_SUPPORTED */ - - return _mmx_supported; -} -#endif diff --git a/uppdev/plugin/png/lib/pngget.c b/uppdev/plugin/png/lib/pngget.c deleted file mode 100644 index 36be6a6ce..000000000 --- a/uppdev/plugin/png/lib/pngget.c +++ /dev/null @@ -1,901 +0,0 @@ - -/* pngget.c - retrieval of values from info struct - * - * Last changed in libpng 1.2.15 January 5, 2007 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2007 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - */ - -#define PNG_INTERNAL -#include "png.h" - -#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) - -png_uint_32 PNGAPI -png_get_valid(png_structp png_ptr, png_infop info_ptr, png_uint_32 flag) -{ - if (png_ptr != NULL && info_ptr != NULL) - return(info_ptr->valid & flag); - else - return(0); -} - -png_uint_32 PNGAPI -png_get_rowbytes(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) - return(info_ptr->rowbytes); - else - return(0); -} - -#if defined(PNG_INFO_IMAGE_SUPPORTED) -png_bytepp PNGAPI -png_get_rows(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) - return(info_ptr->row_pointers); - else - return(0); -} -#endif - -#ifdef PNG_EASY_ACCESS_SUPPORTED -/* easy access to info, added in libpng-0.99 */ -png_uint_32 PNGAPI -png_get_image_width(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) - { - return info_ptr->width; - } - return (0); -} - -png_uint_32 PNGAPI -png_get_image_height(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) - { - return info_ptr->height; - } - return (0); -} - -png_byte PNGAPI -png_get_bit_depth(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) - { - return info_ptr->bit_depth; - } - return (0); -} - -png_byte PNGAPI -png_get_color_type(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) - { - return info_ptr->color_type; - } - return (0); -} - -png_byte PNGAPI -png_get_filter_type(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) - { - return info_ptr->filter_type; - } - return (0); -} - -png_byte PNGAPI -png_get_interlace_type(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) - { - return info_ptr->interlace_type; - } - return (0); -} - -png_byte PNGAPI -png_get_compression_type(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) - { - return info_ptr->compression_type; - } - return (0); -} - -png_uint_32 PNGAPI -png_get_x_pixels_per_meter(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) -#if defined(PNG_pHYs_SUPPORTED) - if (info_ptr->valid & PNG_INFO_pHYs) - { - png_debug1(1, "in %s retrieval function\n", "png_get_x_pixels_per_meter"); - if(info_ptr->phys_unit_type != PNG_RESOLUTION_METER) - return (0); - else return (info_ptr->x_pixels_per_unit); - } -#else - return (0); -#endif - return (0); -} - -png_uint_32 PNGAPI -png_get_y_pixels_per_meter(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) -#if defined(PNG_pHYs_SUPPORTED) - if (info_ptr->valid & PNG_INFO_pHYs) - { - png_debug1(1, "in %s retrieval function\n", "png_get_y_pixels_per_meter"); - if(info_ptr->phys_unit_type != PNG_RESOLUTION_METER) - return (0); - else return (info_ptr->y_pixels_per_unit); - } -#else - return (0); -#endif - return (0); -} - -png_uint_32 PNGAPI -png_get_pixels_per_meter(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) -#if defined(PNG_pHYs_SUPPORTED) - if (info_ptr->valid & PNG_INFO_pHYs) - { - png_debug1(1, "in %s retrieval function\n", "png_get_pixels_per_meter"); - if(info_ptr->phys_unit_type != PNG_RESOLUTION_METER || - info_ptr->x_pixels_per_unit != info_ptr->y_pixels_per_unit) - return (0); - else return (info_ptr->x_pixels_per_unit); - } -#else - return (0); -#endif - return (0); -} - -#ifdef PNG_FLOATING_POINT_SUPPORTED -float PNGAPI -png_get_pixel_aspect_ratio(png_structp png_ptr, png_infop info_ptr) - { - if (png_ptr != NULL && info_ptr != NULL) -#if defined(PNG_pHYs_SUPPORTED) - if (info_ptr->valid & PNG_INFO_pHYs) - { - png_debug1(1, "in %s retrieval function\n", "png_get_aspect_ratio"); - if (info_ptr->x_pixels_per_unit == 0) - return ((float)0.0); - else - return ((float)((float)info_ptr->y_pixels_per_unit - /(float)info_ptr->x_pixels_per_unit)); - } -#else - return (0.0); -#endif - return ((float)0.0); -} -#endif - -png_int_32 PNGAPI -png_get_x_offset_microns(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) -#if defined(PNG_oFFs_SUPPORTED) - if (info_ptr->valid & PNG_INFO_oFFs) - { - png_debug1(1, "in %s retrieval function\n", "png_get_x_offset_microns"); - if(info_ptr->offset_unit_type != PNG_OFFSET_MICROMETER) - return (0); - else return (info_ptr->x_offset); - } -#else - return (0); -#endif - return (0); -} - -png_int_32 PNGAPI -png_get_y_offset_microns(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) -#if defined(PNG_oFFs_SUPPORTED) - if (info_ptr->valid & PNG_INFO_oFFs) - { - png_debug1(1, "in %s retrieval function\n", "png_get_y_offset_microns"); - if(info_ptr->offset_unit_type != PNG_OFFSET_MICROMETER) - return (0); - else return (info_ptr->y_offset); - } -#else - return (0); -#endif - return (0); -} - -png_int_32 PNGAPI -png_get_x_offset_pixels(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) -#if defined(PNG_oFFs_SUPPORTED) - if (info_ptr->valid & PNG_INFO_oFFs) - { - png_debug1(1, "in %s retrieval function\n", "png_get_x_offset_microns"); - if(info_ptr->offset_unit_type != PNG_OFFSET_PIXEL) - return (0); - else return (info_ptr->x_offset); - } -#else - return (0); -#endif - return (0); -} - -png_int_32 PNGAPI -png_get_y_offset_pixels(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) -#if defined(PNG_oFFs_SUPPORTED) - if (info_ptr->valid & PNG_INFO_oFFs) - { - png_debug1(1, "in %s retrieval function\n", "png_get_y_offset_microns"); - if(info_ptr->offset_unit_type != PNG_OFFSET_PIXEL) - return (0); - else return (info_ptr->y_offset); - } -#else - return (0); -#endif - return (0); -} - -#if defined(PNG_INCH_CONVERSIONS) && defined(PNG_FLOATING_POINT_SUPPORTED) -png_uint_32 PNGAPI -png_get_pixels_per_inch(png_structp png_ptr, png_infop info_ptr) -{ - return ((png_uint_32)((float)png_get_pixels_per_meter(png_ptr, info_ptr) - *.0254 +.5)); -} - -png_uint_32 PNGAPI -png_get_x_pixels_per_inch(png_structp png_ptr, png_infop info_ptr) -{ - return ((png_uint_32)((float)png_get_x_pixels_per_meter(png_ptr, info_ptr) - *.0254 +.5)); -} - -png_uint_32 PNGAPI -png_get_y_pixels_per_inch(png_structp png_ptr, png_infop info_ptr) -{ - return ((png_uint_32)((float)png_get_y_pixels_per_meter(png_ptr, info_ptr) - *.0254 +.5)); -} - -float PNGAPI -png_get_x_offset_inches(png_structp png_ptr, png_infop info_ptr) -{ - return ((float)png_get_x_offset_microns(png_ptr, info_ptr) - *.00003937); -} - -float PNGAPI -png_get_y_offset_inches(png_structp png_ptr, png_infop info_ptr) -{ - return ((float)png_get_y_offset_microns(png_ptr, info_ptr) - *.00003937); -} - -#if defined(PNG_pHYs_SUPPORTED) -png_uint_32 PNGAPI -png_get_pHYs_dpi(png_structp png_ptr, png_infop info_ptr, - png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type) -{ - png_uint_32 retval = 0; - - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) - { - png_debug1(1, "in %s retrieval function\n", "pHYs"); - if (res_x != NULL) - { - *res_x = info_ptr->x_pixels_per_unit; - retval |= PNG_INFO_pHYs; - } - if (res_y != NULL) - { - *res_y = info_ptr->y_pixels_per_unit; - retval |= PNG_INFO_pHYs; - } - if (unit_type != NULL) - { - *unit_type = (int)info_ptr->phys_unit_type; - retval |= PNG_INFO_pHYs; - if(*unit_type == 1) - { - if (res_x != NULL) *res_x = (png_uint_32)(*res_x * .0254 + .50); - if (res_y != NULL) *res_y = (png_uint_32)(*res_y * .0254 + .50); - } - } - } - return (retval); -} -#endif /* PNG_pHYs_SUPPORTED */ -#endif /* PNG_INCH_CONVERSIONS && PNG_FLOATING_POINT_SUPPORTED */ - -/* png_get_channels really belongs in here, too, but it's been around longer */ - -#endif /* PNG_EASY_ACCESS_SUPPORTED */ - -png_byte PNGAPI -png_get_channels(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) - return(info_ptr->channels); - else - return (0); -} - -png_bytep PNGAPI -png_get_signature(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) - return(info_ptr->signature); - else - return (NULL); -} - -#if defined(PNG_bKGD_SUPPORTED) -png_uint_32 PNGAPI -png_get_bKGD(png_structp png_ptr, png_infop info_ptr, - png_color_16p *background) -{ - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD) - && background != NULL) - { - png_debug1(1, "in %s retrieval function\n", "bKGD"); - *background = &(info_ptr->background); - return (PNG_INFO_bKGD); - } - return (0); -} -#endif - -#if defined(PNG_cHRM_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED -png_uint_32 PNGAPI -png_get_cHRM(png_structp png_ptr, png_infop info_ptr, - double *white_x, double *white_y, double *red_x, double *red_y, - double *green_x, double *green_y, double *blue_x, double *blue_y) -{ - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) - { - png_debug1(1, "in %s retrieval function\n", "cHRM"); - if (white_x != NULL) - *white_x = (double)info_ptr->x_white; - if (white_y != NULL) - *white_y = (double)info_ptr->y_white; - if (red_x != NULL) - *red_x = (double)info_ptr->x_red; - if (red_y != NULL) - *red_y = (double)info_ptr->y_red; - if (green_x != NULL) - *green_x = (double)info_ptr->x_green; - if (green_y != NULL) - *green_y = (double)info_ptr->y_green; - if (blue_x != NULL) - *blue_x = (double)info_ptr->x_blue; - if (blue_y != NULL) - *blue_y = (double)info_ptr->y_blue; - return (PNG_INFO_cHRM); - } - return (0); -} -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED -png_uint_32 PNGAPI -png_get_cHRM_fixed(png_structp png_ptr, png_infop info_ptr, - png_fixed_point *white_x, png_fixed_point *white_y, png_fixed_point *red_x, - png_fixed_point *red_y, png_fixed_point *green_x, png_fixed_point *green_y, - png_fixed_point *blue_x, png_fixed_point *blue_y) -{ - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) - { - png_debug1(1, "in %s retrieval function\n", "cHRM"); - if (white_x != NULL) - *white_x = info_ptr->int_x_white; - if (white_y != NULL) - *white_y = info_ptr->int_y_white; - if (red_x != NULL) - *red_x = info_ptr->int_x_red; - if (red_y != NULL) - *red_y = info_ptr->int_y_red; - if (green_x != NULL) - *green_x = info_ptr->int_x_green; - if (green_y != NULL) - *green_y = info_ptr->int_y_green; - if (blue_x != NULL) - *blue_x = info_ptr->int_x_blue; - if (blue_y != NULL) - *blue_y = info_ptr->int_y_blue; - return (PNG_INFO_cHRM); - } - return (0); -} -#endif -#endif - -#if defined(PNG_gAMA_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED -png_uint_32 PNGAPI -png_get_gAMA(png_structp png_ptr, png_infop info_ptr, double *file_gamma) -{ - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA) - && file_gamma != NULL) - { - png_debug1(1, "in %s retrieval function\n", "gAMA"); - *file_gamma = (double)info_ptr->gamma; - return (PNG_INFO_gAMA); - } - return (0); -} -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED -png_uint_32 PNGAPI -png_get_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, - png_fixed_point *int_file_gamma) -{ - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA) - && int_file_gamma != NULL) - { - png_debug1(1, "in %s retrieval function\n", "gAMA"); - *int_file_gamma = info_ptr->int_gamma; - return (PNG_INFO_gAMA); - } - return (0); -} -#endif -#endif - -#if defined(PNG_sRGB_SUPPORTED) -png_uint_32 PNGAPI -png_get_sRGB(png_structp png_ptr, png_infop info_ptr, int *file_srgb_intent) -{ - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB) - && file_srgb_intent != NULL) - { - png_debug1(1, "in %s retrieval function\n", "sRGB"); - *file_srgb_intent = (int)info_ptr->srgb_intent; - return (PNG_INFO_sRGB); - } - return (0); -} -#endif - -#if defined(PNG_iCCP_SUPPORTED) -png_uint_32 PNGAPI -png_get_iCCP(png_structp png_ptr, png_infop info_ptr, - png_charpp name, int *compression_type, - png_charpp profile, png_uint_32 *proflen) -{ - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP) - && name != NULL && profile != NULL && proflen != NULL) - { - png_debug1(1, "in %s retrieval function\n", "iCCP"); - *name = info_ptr->iccp_name; - *profile = info_ptr->iccp_profile; - /* compression_type is a dummy so the API won't have to change - if we introduce multiple compression types later. */ - *proflen = (int)info_ptr->iccp_proflen; - *compression_type = (int)info_ptr->iccp_compression; - return (PNG_INFO_iCCP); - } - return (0); -} -#endif - -#if defined(PNG_sPLT_SUPPORTED) -png_uint_32 PNGAPI -png_get_sPLT(png_structp png_ptr, png_infop info_ptr, - png_sPLT_tpp spalettes) -{ - if (png_ptr != NULL && info_ptr != NULL && spalettes != NULL) - { - *spalettes = info_ptr->splt_palettes; - return ((png_uint_32)info_ptr->splt_palettes_num); - } - return (0); -} -#endif - -#if defined(PNG_hIST_SUPPORTED) -png_uint_32 PNGAPI -png_get_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_16p *hist) -{ - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST) - && hist != NULL) - { - png_debug1(1, "in %s retrieval function\n", "hIST"); - *hist = info_ptr->hist; - return (PNG_INFO_hIST); - } - return (0); -} -#endif - -png_uint_32 PNGAPI -png_get_IHDR(png_structp png_ptr, png_infop info_ptr, - png_uint_32 *width, png_uint_32 *height, int *bit_depth, - int *color_type, int *interlace_type, int *compression_type, - int *filter_type) - -{ - if (png_ptr != NULL && info_ptr != NULL && width != NULL && height != NULL && - bit_depth != NULL && color_type != NULL) - { - png_debug1(1, "in %s retrieval function\n", "IHDR"); - *width = info_ptr->width; - *height = info_ptr->height; - *bit_depth = info_ptr->bit_depth; - if (info_ptr->bit_depth < 1 || info_ptr->bit_depth > 16) - png_error(png_ptr, "Invalid bit depth"); - *color_type = info_ptr->color_type; - if (info_ptr->color_type > 6) - png_error(png_ptr, "Invalid color type"); - if (compression_type != NULL) - *compression_type = info_ptr->compression_type; - if (filter_type != NULL) - *filter_type = info_ptr->filter_type; - if (interlace_type != NULL) - *interlace_type = info_ptr->interlace_type; - - /* check for potential overflow of rowbytes */ - if (*width == 0 || *width > PNG_UINT_31_MAX) - png_error(png_ptr, "Invalid image width"); - if (*height == 0 || *height > PNG_UINT_31_MAX) - png_error(png_ptr, "Invalid image height"); - if (info_ptr->width > (PNG_UINT_32_MAX - >> 3) /* 8-byte RGBA pixels */ - - 64 /* bigrowbuf hack */ - - 1 /* filter byte */ - - 7*8 /* rounding of width to multiple of 8 pixels */ - - 8) /* extra max_pixel_depth pad */ - { - png_warning(png_ptr, - "Width too large for libpng to process image data."); - } - return (1); - } - return (0); -} - -#if defined(PNG_oFFs_SUPPORTED) -png_uint_32 PNGAPI -png_get_oFFs(png_structp png_ptr, png_infop info_ptr, - png_int_32 *offset_x, png_int_32 *offset_y, int *unit_type) -{ - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs) - && offset_x != NULL && offset_y != NULL && unit_type != NULL) - { - png_debug1(1, "in %s retrieval function\n", "oFFs"); - *offset_x = info_ptr->x_offset; - *offset_y = info_ptr->y_offset; - *unit_type = (int)info_ptr->offset_unit_type; - return (PNG_INFO_oFFs); - } - return (0); -} -#endif - -#if defined(PNG_pCAL_SUPPORTED) -png_uint_32 PNGAPI -png_get_pCAL(png_structp png_ptr, png_infop info_ptr, - png_charp *purpose, png_int_32 *X0, png_int_32 *X1, int *type, int *nparams, - png_charp *units, png_charpp *params) -{ - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL) - && purpose != NULL && X0 != NULL && X1 != NULL && type != NULL && - nparams != NULL && units != NULL && params != NULL) - { - png_debug1(1, "in %s retrieval function\n", "pCAL"); - *purpose = info_ptr->pcal_purpose; - *X0 = info_ptr->pcal_X0; - *X1 = info_ptr->pcal_X1; - *type = (int)info_ptr->pcal_type; - *nparams = (int)info_ptr->pcal_nparams; - *units = info_ptr->pcal_units; - *params = info_ptr->pcal_params; - return (PNG_INFO_pCAL); - } - return (0); -} -#endif - -#if defined(PNG_sCAL_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED -png_uint_32 PNGAPI -png_get_sCAL(png_structp png_ptr, png_infop info_ptr, - int *unit, double *width, double *height) -{ - if (png_ptr != NULL && info_ptr != NULL && - (info_ptr->valid & PNG_INFO_sCAL)) - { - *unit = info_ptr->scal_unit; - *width = info_ptr->scal_pixel_width; - *height = info_ptr->scal_pixel_height; - return (PNG_INFO_sCAL); - } - return(0); -} -#else -#ifdef PNG_FIXED_POINT_SUPPORTED -png_uint_32 PNGAPI -png_get_sCAL_s(png_structp png_ptr, png_infop info_ptr, - int *unit, png_charpp width, png_charpp height) -{ - if (png_ptr != NULL && info_ptr != NULL && - (info_ptr->valid & PNG_INFO_sCAL)) - { - *unit = info_ptr->scal_unit; - *width = info_ptr->scal_s_width; - *height = info_ptr->scal_s_height; - return (PNG_INFO_sCAL); - } - return(0); -} -#endif -#endif -#endif - -#if defined(PNG_pHYs_SUPPORTED) -png_uint_32 PNGAPI -png_get_pHYs(png_structp png_ptr, png_infop info_ptr, - png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type) -{ - png_uint_32 retval = 0; - - if (png_ptr != NULL && info_ptr != NULL && - (info_ptr->valid & PNG_INFO_pHYs)) - { - png_debug1(1, "in %s retrieval function\n", "pHYs"); - if (res_x != NULL) - { - *res_x = info_ptr->x_pixels_per_unit; - retval |= PNG_INFO_pHYs; - } - if (res_y != NULL) - { - *res_y = info_ptr->y_pixels_per_unit; - retval |= PNG_INFO_pHYs; - } - if (unit_type != NULL) - { - *unit_type = (int)info_ptr->phys_unit_type; - retval |= PNG_INFO_pHYs; - } - } - return (retval); -} -#endif - -png_uint_32 PNGAPI -png_get_PLTE(png_structp png_ptr, png_infop info_ptr, png_colorp *palette, - int *num_palette) -{ - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_PLTE) - && palette != NULL) - { - png_debug1(1, "in %s retrieval function\n", "PLTE"); - *palette = info_ptr->palette; - *num_palette = info_ptr->num_palette; - png_debug1(3, "num_palette = %d\n", *num_palette); - return (PNG_INFO_PLTE); - } - return (0); -} - -#if defined(PNG_sBIT_SUPPORTED) -png_uint_32 PNGAPI -png_get_sBIT(png_structp png_ptr, png_infop info_ptr, png_color_8p *sig_bit) -{ - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT) - && sig_bit != NULL) - { - png_debug1(1, "in %s retrieval function\n", "sBIT"); - *sig_bit = &(info_ptr->sig_bit); - return (PNG_INFO_sBIT); - } - return (0); -} -#endif - -#if defined(PNG_TEXT_SUPPORTED) -png_uint_32 PNGAPI -png_get_text(png_structp png_ptr, png_infop info_ptr, png_textp *text_ptr, - int *num_text) -{ - if (png_ptr != NULL && info_ptr != NULL && info_ptr->num_text > 0) - { - png_debug1(1, "in %s retrieval function\n", - (png_ptr->chunk_name[0] == '\0' ? "text" - : (png_const_charp)png_ptr->chunk_name)); - if (text_ptr != NULL) - *text_ptr = info_ptr->text; - if (num_text != NULL) - *num_text = info_ptr->num_text; - return ((png_uint_32)info_ptr->num_text); - } - if (num_text != NULL) - *num_text = 0; - return(0); -} -#endif - -#if defined(PNG_tIME_SUPPORTED) -png_uint_32 PNGAPI -png_get_tIME(png_structp png_ptr, png_infop info_ptr, png_timep *mod_time) -{ - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME) - && mod_time != NULL) - { - png_debug1(1, "in %s retrieval function\n", "tIME"); - *mod_time = &(info_ptr->mod_time); - return (PNG_INFO_tIME); - } - return (0); -} -#endif - -#if defined(PNG_tRNS_SUPPORTED) -png_uint_32 PNGAPI -png_get_tRNS(png_structp png_ptr, png_infop info_ptr, - png_bytep *trans, int *num_trans, png_color_16p *trans_values) -{ - png_uint_32 retval = 0; - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) - { - png_debug1(1, "in %s retrieval function\n", "tRNS"); - if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - { - if (trans != NULL) - { - *trans = info_ptr->trans; - retval |= PNG_INFO_tRNS; - } - if (trans_values != NULL) - *trans_values = &(info_ptr->trans_values); - } - else /* if (info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) */ - { - if (trans_values != NULL) - { - *trans_values = &(info_ptr->trans_values); - retval |= PNG_INFO_tRNS; - } - if(trans != NULL) - *trans = NULL; - } - if(num_trans != NULL) - { - *num_trans = info_ptr->num_trans; - retval |= PNG_INFO_tRNS; - } - } - return (retval); -} -#endif - -#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) -png_uint_32 PNGAPI -png_get_unknown_chunks(png_structp png_ptr, png_infop info_ptr, - png_unknown_chunkpp unknowns) -{ - if (png_ptr != NULL && info_ptr != NULL && unknowns != NULL) - { - *unknowns = info_ptr->unknown_chunks; - return ((png_uint_32)info_ptr->unknown_chunks_num); - } - return (0); -} -#endif - -#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) -png_byte PNGAPI -png_get_rgb_to_gray_status (png_structp png_ptr) -{ - return (png_byte)(png_ptr? png_ptr->rgb_to_gray_status : 0); -} -#endif - -#if defined(PNG_USER_CHUNKS_SUPPORTED) -png_voidp PNGAPI -png_get_user_chunk_ptr(png_structp png_ptr) -{ - return (png_ptr? png_ptr->user_chunk_ptr : NULL); -} -#endif - -#ifdef PNG_WRITE_SUPPORTED -png_uint_32 PNGAPI -png_get_compression_buffer_size(png_structp png_ptr) -{ - return (png_uint_32)(png_ptr? png_ptr->zbuf_size : 0L); -} -#endif - -#ifdef PNG_ASSEMBLER_CODE_SUPPORTED -#ifndef PNG_1_0_X -/* this function was added to libpng 1.2.0 and should exist by default */ -png_uint_32 PNGAPI -png_get_asm_flags (png_structp png_ptr) -{ - /* obsolete, to be removed from libpng-1.4.0 */ - return (png_ptr? 0L: 0L); -} - -/* this function was added to libpng 1.2.0 and should exist by default */ -png_uint_32 PNGAPI -png_get_asm_flagmask (int flag_select) -{ - /* obsolete, to be removed from libpng-1.4.0 */ - flag_select=flag_select; - return 0L; -} - - /* GRR: could add this: && defined(PNG_MMX_CODE_SUPPORTED) */ -/* this function was added to libpng 1.2.0 */ -png_uint_32 PNGAPI -png_get_mmx_flagmask (int flag_select, int *compilerID) -{ - /* obsolete, to be removed from libpng-1.4.0 */ - flag_select=flag_select; - *compilerID = -1; /* unknown (i.e., no asm/MMX code compiled) */ - return 0L; -} - -/* this function was added to libpng 1.2.0 */ -png_byte PNGAPI -png_get_mmx_bitdepth_threshold (png_structp png_ptr) -{ - /* obsolete, to be removed from libpng-1.4.0 */ - return (png_ptr? 0: 0); -} - -/* this function was added to libpng 1.2.0 */ -png_uint_32 PNGAPI -png_get_mmx_rowbytes_threshold (png_structp png_ptr) -{ - /* obsolete, to be removed from libpng-1.4.0 */ - return (png_ptr? 0L: 0L); -} -#endif /* ?PNG_1_0_X */ -#endif /* ?PNG_ASSEMBLER_CODE_SUPPORTED */ - -#ifdef PNG_SET_USER_LIMITS_SUPPORTED -/* these functions were added to libpng 1.2.6 */ -png_uint_32 PNGAPI -png_get_user_width_max (png_structp png_ptr) -{ - return (png_ptr? png_ptr->user_width_max : 0); -} -png_uint_32 PNGAPI -png_get_user_height_max (png_structp png_ptr) -{ - return (png_ptr? png_ptr->user_height_max : 0); -} -#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */ - - -#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/uppdev/plugin/png/lib/pngmem.c b/uppdev/plugin/png/lib/pngmem.c deleted file mode 100644 index 6aa70af4c..000000000 --- a/uppdev/plugin/png/lib/pngmem.c +++ /dev/null @@ -1,608 +0,0 @@ - -/* pngmem.c - stub functions for memory allocation - * - * Last changed in libpng 1.2.13 November 13, 2006 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2006 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This file provides a location for all memory allocation. Users who - * need special memory handling are expected to supply replacement - * functions for png_malloc() and png_free(), and to use - * png_create_read_struct_2() and png_create_write_struct_2() to - * identify the replacement functions. - */ - -#define PNG_INTERNAL -#include "png.h" - -#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) - -/* Borland DOS special memory handler */ -#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__) -/* if you change this, be sure to change the one in png.h also */ - -/* Allocate memory for a png_struct. The malloc and memset can be replaced - by a single call to calloc() if this is thought to improve performance. */ -png_voidp /* PRIVATE */ -png_create_struct(int type) -{ -#ifdef PNG_USER_MEM_SUPPORTED - return (png_create_struct_2(type, png_malloc_ptr_NULL, png_voidp_NULL)); -} - -/* Alternate version of png_create_struct, for use with user-defined malloc. */ -png_voidp /* PRIVATE */ -png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr) -{ -#endif /* PNG_USER_MEM_SUPPORTED */ - png_size_t size; - png_voidp struct_ptr; - - if (type == PNG_STRUCT_INFO) - size = png_sizeof(png_info); - else if (type == PNG_STRUCT_PNG) - size = png_sizeof(png_struct); - else - return (png_get_copyright(NULL)); - -#ifdef PNG_USER_MEM_SUPPORTED - if(malloc_fn != NULL) - { - png_struct dummy_struct; - png_structp png_ptr = &dummy_struct; - png_ptr->mem_ptr=mem_ptr; - struct_ptr = (*(malloc_fn))(png_ptr, (png_uint_32)size); - } - else -#endif /* PNG_USER_MEM_SUPPORTED */ - struct_ptr = (png_voidp)farmalloc(size); - if (struct_ptr != NULL) - png_memset(struct_ptr, 0, size); - return (struct_ptr); -} - -/* Free memory allocated by a png_create_struct() call */ -void /* PRIVATE */ -png_destroy_struct(png_voidp struct_ptr) -{ -#ifdef PNG_USER_MEM_SUPPORTED - png_destroy_struct_2(struct_ptr, png_free_ptr_NULL, png_voidp_NULL); -} - -/* Free memory allocated by a png_create_struct() call */ -void /* PRIVATE */ -png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn, - png_voidp mem_ptr) -{ -#endif - if (struct_ptr != NULL) - { -#ifdef PNG_USER_MEM_SUPPORTED - if(free_fn != NULL) - { - png_struct dummy_struct; - png_structp png_ptr = &dummy_struct; - png_ptr->mem_ptr=mem_ptr; - (*(free_fn))(png_ptr, struct_ptr); - return; - } -#endif /* PNG_USER_MEM_SUPPORTED */ - farfree (struct_ptr); - } -} - -/* Allocate memory. For reasonable files, size should never exceed - * 64K. However, zlib may allocate more then 64K if you don't tell - * it not to. See zconf.h and png.h for more information. zlib does - * need to allocate exactly 64K, so whatever you call here must - * have the ability to do that. - * - * Borland seems to have a problem in DOS mode for exactly 64K. - * It gives you a segment with an offset of 8 (perhaps to store its - * memory stuff). zlib doesn't like this at all, so we have to - * detect and deal with it. This code should not be needed in - * Windows or OS/2 modes, and only in 16 bit mode. This code has - * been updated by Alexander Lehmann for version 0.89 to waste less - * memory. - * - * Note that we can't use png_size_t for the "size" declaration, - * since on some systems a png_size_t is a 16-bit quantity, and as a - * result, we would be truncating potentially larger memory requests - * (which should cause a fatal error) and introducing major problems. - */ - -png_voidp PNGAPI -png_malloc(png_structp png_ptr, png_uint_32 size) -{ - png_voidp ret; - - if (png_ptr == NULL || size == 0) - return (NULL); - -#ifdef PNG_USER_MEM_SUPPORTED - if(png_ptr->malloc_fn != NULL) - ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size)); - else - ret = (png_malloc_default(png_ptr, size)); - if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) - png_error(png_ptr, "Out of memory!"); - return (ret); -} - -png_voidp PNGAPI -png_malloc_default(png_structp png_ptr, png_uint_32 size) -{ - png_voidp ret; -#endif /* PNG_USER_MEM_SUPPORTED */ - - if (png_ptr == NULL || size == 0) - return (NULL); - -#ifdef PNG_MAX_MALLOC_64K - if (size > (png_uint_32)65536L) - { - png_warning(png_ptr, "Cannot Allocate > 64K"); - ret = NULL; - } - else -#endif - - if (size != (size_t)size) - ret = NULL; - else if (size == (png_uint_32)65536L) - { - if (png_ptr->offset_table == NULL) - { - /* try to see if we need to do any of this fancy stuff */ - ret = farmalloc(size); - if (ret == NULL || ((png_size_t)ret & 0xffff)) - { - int num_blocks; - png_uint_32 total_size; - png_bytep table; - int i; - png_byte huge * hptr; - - if (ret != NULL) - { - farfree(ret); - ret = NULL; - } - - if(png_ptr->zlib_window_bits > 14) - num_blocks = (int)(1 << (png_ptr->zlib_window_bits - 14)); - else - num_blocks = 1; - if (png_ptr->zlib_mem_level >= 7) - num_blocks += (int)(1 << (png_ptr->zlib_mem_level - 7)); - else - num_blocks++; - - total_size = ((png_uint_32)65536L) * (png_uint_32)num_blocks+16; - - table = farmalloc(total_size); - - if (table == NULL) - { -#ifndef PNG_USER_MEM_SUPPORTED - if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) - png_error(png_ptr, "Out Of Memory."); /* Note "O" and "M" */ - else - png_warning(png_ptr, "Out Of Memory."); -#endif - return (NULL); - } - - if ((png_size_t)table & 0xfff0) - { -#ifndef PNG_USER_MEM_SUPPORTED - if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) - png_error(png_ptr, - "Farmalloc didn't return normalized pointer"); - else - png_warning(png_ptr, - "Farmalloc didn't return normalized pointer"); -#endif - return (NULL); - } - - png_ptr->offset_table = table; - png_ptr->offset_table_ptr = farmalloc(num_blocks * - png_sizeof (png_bytep)); - - if (png_ptr->offset_table_ptr == NULL) - { -#ifndef PNG_USER_MEM_SUPPORTED - if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) - png_error(png_ptr, "Out Of memory."); /* Note "O" and "M" */ - else - png_warning(png_ptr, "Out Of memory."); -#endif - return (NULL); - } - - hptr = (png_byte huge *)table; - if ((png_size_t)hptr & 0xf) - { - hptr = (png_byte huge *)((long)(hptr) & 0xfffffff0L); - hptr = hptr + 16L; /* "hptr += 16L" fails on Turbo C++ 3.0 */ - } - for (i = 0; i < num_blocks; i++) - { - png_ptr->offset_table_ptr[i] = (png_bytep)hptr; - hptr = hptr + (png_uint_32)65536L; /* "+=" fails on TC++3.0 */ - } - - png_ptr->offset_table_number = num_blocks; - png_ptr->offset_table_count = 0; - png_ptr->offset_table_count_free = 0; - } - } - - if (png_ptr->offset_table_count >= png_ptr->offset_table_number) - { -#ifndef PNG_USER_MEM_SUPPORTED - if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) - png_error(png_ptr, "Out of Memory."); /* Note "o" and "M" */ - else - png_warning(png_ptr, "Out of Memory."); -#endif - return (NULL); - } - - ret = png_ptr->offset_table_ptr[png_ptr->offset_table_count++]; - } - else - ret = farmalloc(size); - -#ifndef PNG_USER_MEM_SUPPORTED - if (ret == NULL) - { - if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) - png_error(png_ptr, "Out of memory."); /* Note "o" and "m" */ - else - png_warning(png_ptr, "Out of memory."); /* Note "o" and "m" */ - } -#endif - - return (ret); -} - -/* free a pointer allocated by png_malloc(). In the default - configuration, png_ptr is not used, but is passed in case it - is needed. If ptr is NULL, return without taking any action. */ -void PNGAPI -png_free(png_structp png_ptr, png_voidp ptr) -{ - if (png_ptr == NULL || ptr == NULL) - return; - -#ifdef PNG_USER_MEM_SUPPORTED - if (png_ptr->free_fn != NULL) - { - (*(png_ptr->free_fn))(png_ptr, ptr); - return; - } - else png_free_default(png_ptr, ptr); -} - -void PNGAPI -png_free_default(png_structp png_ptr, png_voidp ptr) -{ -#endif /* PNG_USER_MEM_SUPPORTED */ - - if(png_ptr == NULL) return; - - if (png_ptr->offset_table != NULL) - { - int i; - - for (i = 0; i < png_ptr->offset_table_count; i++) - { - if (ptr == png_ptr->offset_table_ptr[i]) - { - ptr = NULL; - png_ptr->offset_table_count_free++; - break; - } - } - if (png_ptr->offset_table_count_free == png_ptr->offset_table_count) - { - farfree(png_ptr->offset_table); - farfree(png_ptr->offset_table_ptr); - png_ptr->offset_table = NULL; - png_ptr->offset_table_ptr = NULL; - } - } - - if (ptr != NULL) - { - farfree(ptr); - } -} - -#else /* Not the Borland DOS special memory handler */ - -/* Allocate memory for a png_struct or a png_info. The malloc and - memset can be replaced by a single call to calloc() if this is thought - to improve performance noticably. */ -png_voidp /* PRIVATE */ -png_create_struct(int type) -{ -#ifdef PNG_USER_MEM_SUPPORTED - return (png_create_struct_2(type, png_malloc_ptr_NULL, png_voidp_NULL)); -} - -/* Allocate memory for a png_struct or a png_info. The malloc and - memset can be replaced by a single call to calloc() if this is thought - to improve performance noticably. */ -png_voidp /* PRIVATE */ -png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr) -{ -#endif /* PNG_USER_MEM_SUPPORTED */ - png_size_t size; - png_voidp struct_ptr; - - if (type == PNG_STRUCT_INFO) - size = png_sizeof(png_info); - else if (type == PNG_STRUCT_PNG) - size = png_sizeof(png_struct); - else - return (NULL); - -#ifdef PNG_USER_MEM_SUPPORTED - if(malloc_fn != NULL) - { - png_struct dummy_struct; - png_structp png_ptr = &dummy_struct; - png_ptr->mem_ptr=mem_ptr; - struct_ptr = (*(malloc_fn))(png_ptr, size); - if (struct_ptr != NULL) - png_memset(struct_ptr, 0, size); - return (struct_ptr); - } -#endif /* PNG_USER_MEM_SUPPORTED */ - -#if defined(__TURBOC__) && !defined(__FLAT__) - struct_ptr = (png_voidp)farmalloc(size); -#else -# if defined(_MSC_VER) && defined(MAXSEG_64K) - struct_ptr = (png_voidp)halloc(size,1); -# else - struct_ptr = (png_voidp)malloc(size); -# endif -#endif - if (struct_ptr != NULL) - png_memset(struct_ptr, 0, size); - - return (struct_ptr); -} - - -/* Free memory allocated by a png_create_struct() call */ -void /* PRIVATE */ -png_destroy_struct(png_voidp struct_ptr) -{ -#ifdef PNG_USER_MEM_SUPPORTED - png_destroy_struct_2(struct_ptr, png_free_ptr_NULL, png_voidp_NULL); -} - -/* Free memory allocated by a png_create_struct() call */ -void /* PRIVATE */ -png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn, - png_voidp mem_ptr) -{ -#endif /* PNG_USER_MEM_SUPPORTED */ - if (struct_ptr != NULL) - { -#ifdef PNG_USER_MEM_SUPPORTED - if(free_fn != NULL) - { - png_struct dummy_struct; - png_structp png_ptr = &dummy_struct; - png_ptr->mem_ptr=mem_ptr; - (*(free_fn))(png_ptr, struct_ptr); - return; - } -#endif /* PNG_USER_MEM_SUPPORTED */ -#if defined(__TURBOC__) && !defined(__FLAT__) - farfree(struct_ptr); -#else -# if defined(_MSC_VER) && defined(MAXSEG_64K) - hfree(struct_ptr); -# else - free(struct_ptr); -# endif -#endif - } -} - -/* Allocate memory. For reasonable files, size should never exceed - 64K. However, zlib may allocate more then 64K if you don't tell - it not to. See zconf.h and png.h for more information. zlib does - need to allocate exactly 64K, so whatever you call here must - have the ability to do that. */ - -png_voidp PNGAPI -png_malloc(png_structp png_ptr, png_uint_32 size) -{ - png_voidp ret; - -#ifdef PNG_USER_MEM_SUPPORTED - if (png_ptr == NULL || size == 0) - return (NULL); - - if(png_ptr->malloc_fn != NULL) - ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size)); - else - ret = (png_malloc_default(png_ptr, size)); - if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) - png_error(png_ptr, "Out of Memory!"); - return (ret); -} - -png_voidp PNGAPI -png_malloc_default(png_structp png_ptr, png_uint_32 size) -{ - png_voidp ret; -#endif /* PNG_USER_MEM_SUPPORTED */ - - if (png_ptr == NULL || size == 0) - return (NULL); - -#ifdef PNG_MAX_MALLOC_64K - if (size > (png_uint_32)65536L) - { -#ifndef PNG_USER_MEM_SUPPORTED - if(png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) - png_error(png_ptr, "Cannot Allocate > 64K"); - else -#endif - return NULL; - } -#endif - - /* Check for overflow */ -#if defined(__TURBOC__) && !defined(__FLAT__) - if (size != (unsigned long)size) - ret = NULL; - else - ret = farmalloc(size); -#else -# if defined(_MSC_VER) && defined(MAXSEG_64K) - if (size != (unsigned long)size) - ret = NULL; - else - ret = halloc(size, 1); -# else - if (size != (size_t)size) - ret = NULL; - else - ret = malloc((size_t)size); -# endif -#endif - -#ifndef PNG_USER_MEM_SUPPORTED - if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) - png_error(png_ptr, "Out of Memory"); -#endif - - return (ret); -} - -/* Free a pointer allocated by png_malloc(). If ptr is NULL, return - without taking any action. */ -void PNGAPI -png_free(png_structp png_ptr, png_voidp ptr) -{ - if (png_ptr == NULL || ptr == NULL) - return; - -#ifdef PNG_USER_MEM_SUPPORTED - if (png_ptr->free_fn != NULL) - { - (*(png_ptr->free_fn))(png_ptr, ptr); - return; - } - else png_free_default(png_ptr, ptr); -} -void PNGAPI -png_free_default(png_structp png_ptr, png_voidp ptr) -{ - if (png_ptr == NULL || ptr == NULL) - return; - -#endif /* PNG_USER_MEM_SUPPORTED */ - -#if defined(__TURBOC__) && !defined(__FLAT__) - farfree(ptr); -#else -# if defined(_MSC_VER) && defined(MAXSEG_64K) - hfree(ptr); -# else - free(ptr); -# endif -#endif -} - -#endif /* Not Borland DOS special memory handler */ - -#if defined(PNG_1_0_X) -# define png_malloc_warn png_malloc -#else -/* This function was added at libpng version 1.2.3. The png_malloc_warn() - * function will set up png_malloc() to issue a png_warning and return NULL - * instead of issuing a png_error, if it fails to allocate the requested - * memory. - */ -png_voidp PNGAPI -png_malloc_warn(png_structp png_ptr, png_uint_32 size) -{ - png_voidp ptr; - png_uint_32 save_flags; - if(png_ptr == NULL) return (NULL); - - save_flags=png_ptr->flags; - png_ptr->flags|=PNG_FLAG_MALLOC_NULL_MEM_OK; - ptr = (png_voidp)png_malloc((png_structp)png_ptr, size); - png_ptr->flags=save_flags; - return(ptr); -} -#endif - -png_voidp PNGAPI -png_memcpy_check (png_structp png_ptr, png_voidp s1, png_voidp s2, - png_uint_32 length) -{ - png_size_t size; - - size = (png_size_t)length; - if ((png_uint_32)size != length) - png_error(png_ptr,"Overflow in png_memcpy_check."); - - return(png_memcpy (s1, s2, size)); -} - -png_voidp PNGAPI -png_memset_check (png_structp png_ptr, png_voidp s1, int value, - png_uint_32 length) -{ - png_size_t size; - - size = (png_size_t)length; - if ((png_uint_32)size != length) - png_error(png_ptr,"Overflow in png_memset_check."); - - return (png_memset (s1, value, size)); - -} - -#ifdef PNG_USER_MEM_SUPPORTED -/* This function is called when the application wants to use another method - * of allocating and freeing memory. - */ -void PNGAPI -png_set_mem_fn(png_structp png_ptr, png_voidp mem_ptr, png_malloc_ptr - malloc_fn, png_free_ptr free_fn) -{ - if(png_ptr != NULL) { - png_ptr->mem_ptr = mem_ptr; - png_ptr->malloc_fn = malloc_fn; - png_ptr->free_fn = free_fn; - } -} - -/* This function returns a pointer to the mem_ptr associated with the user - * functions. The application should free any memory associated with this - * pointer before png_write_destroy and png_read_destroy are called. - */ -png_voidp PNGAPI -png_get_mem_ptr(png_structp png_ptr) -{ - if(png_ptr == NULL) return (NULL); - return ((png_voidp)png_ptr->mem_ptr); -} -#endif /* PNG_USER_MEM_SUPPORTED */ -#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/uppdev/plugin/png/lib/pngpread.c b/uppdev/plugin/png/lib/pngpread.c deleted file mode 100644 index fd4afb6ca..000000000 --- a/uppdev/plugin/png/lib/pngpread.c +++ /dev/null @@ -1,1584 +0,0 @@ - -/* pngpread.c - read a png file in push mode - * - * Last changed in libpng 1.2.22 [October 13, 2007] - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2007 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - */ - -#define PNG_INTERNAL -#include "png.h" - -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED - -/* push model modes */ -#define PNG_READ_SIG_MODE 0 -#define PNG_READ_CHUNK_MODE 1 -#define PNG_READ_IDAT_MODE 2 -#define PNG_SKIP_MODE 3 -#define PNG_READ_tEXt_MODE 4 -#define PNG_READ_zTXt_MODE 5 -#define PNG_READ_DONE_MODE 6 -#define PNG_READ_iTXt_MODE 7 -#define PNG_ERROR_MODE 8 - -void PNGAPI -png_process_data(png_structp png_ptr, png_infop info_ptr, - png_bytep buffer, png_size_t buffer_size) -{ - if(png_ptr == NULL) return; - png_push_restore_buffer(png_ptr, buffer, buffer_size); - - while (png_ptr->buffer_size) - { - png_process_some_data(png_ptr, info_ptr); - } -} - -/* What we do with the incoming data depends on what we were previously - * doing before we ran out of data... - */ -void /* PRIVATE */ -png_process_some_data(png_structp png_ptr, png_infop info_ptr) -{ - if(png_ptr == NULL) return; - switch (png_ptr->process_mode) - { - case PNG_READ_SIG_MODE: - { - png_push_read_sig(png_ptr, info_ptr); - break; - } - case PNG_READ_CHUNK_MODE: - { - png_push_read_chunk(png_ptr, info_ptr); - break; - } - case PNG_READ_IDAT_MODE: - { - png_push_read_IDAT(png_ptr); - break; - } -#if defined(PNG_READ_tEXt_SUPPORTED) - case PNG_READ_tEXt_MODE: - { - png_push_read_tEXt(png_ptr, info_ptr); - break; - } -#endif -#if defined(PNG_READ_zTXt_SUPPORTED) - case PNG_READ_zTXt_MODE: - { - png_push_read_zTXt(png_ptr, info_ptr); - break; - } -#endif -#if defined(PNG_READ_iTXt_SUPPORTED) - case PNG_READ_iTXt_MODE: - { - png_push_read_iTXt(png_ptr, info_ptr); - break; - } -#endif - case PNG_SKIP_MODE: - { - png_push_crc_finish(png_ptr); - break; - } - default: - { - png_ptr->buffer_size = 0; - break; - } - } -} - -/* Read any remaining signature bytes from the stream and compare them with - * the correct PNG signature. It is possible that this routine is called - * with bytes already read from the signature, either because they have been - * checked by the calling application, or because of multiple calls to this - * routine. - */ -void /* PRIVATE */ -png_push_read_sig(png_structp png_ptr, png_infop info_ptr) -{ - png_size_t num_checked = png_ptr->sig_bytes, - num_to_check = 8 - num_checked; - - if (png_ptr->buffer_size < num_to_check) - { - num_to_check = png_ptr->buffer_size; - } - - png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]), - num_to_check); - png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes+num_to_check); - - if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) - { - if (num_checked < 4 && - png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) - png_error(png_ptr, "Not a PNG file"); - else - png_error(png_ptr, "PNG file corrupted by ASCII conversion"); - } - else - { - if (png_ptr->sig_bytes >= 8) - { - png_ptr->process_mode = PNG_READ_CHUNK_MODE; - } - } -} - -void /* PRIVATE */ -png_push_read_chunk(png_structp png_ptr, png_infop info_ptr) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_CONST PNG_IHDR; - PNG_CONST PNG_IDAT; - PNG_CONST PNG_IEND; - PNG_CONST PNG_PLTE; -#if defined(PNG_READ_bKGD_SUPPORTED) - PNG_CONST PNG_bKGD; -#endif -#if defined(PNG_READ_cHRM_SUPPORTED) - PNG_CONST PNG_cHRM; -#endif -#if defined(PNG_READ_gAMA_SUPPORTED) - PNG_CONST PNG_gAMA; -#endif -#if defined(PNG_READ_hIST_SUPPORTED) - PNG_CONST PNG_hIST; -#endif -#if defined(PNG_READ_iCCP_SUPPORTED) - PNG_CONST PNG_iCCP; -#endif -#if defined(PNG_READ_iTXt_SUPPORTED) - PNG_CONST PNG_iTXt; -#endif -#if defined(PNG_READ_oFFs_SUPPORTED) - PNG_CONST PNG_oFFs; -#endif -#if defined(PNG_READ_pCAL_SUPPORTED) - PNG_CONST PNG_pCAL; -#endif -#if defined(PNG_READ_pHYs_SUPPORTED) - PNG_CONST PNG_pHYs; -#endif -#if defined(PNG_READ_sBIT_SUPPORTED) - PNG_CONST PNG_sBIT; -#endif -#if defined(PNG_READ_sCAL_SUPPORTED) - PNG_CONST PNG_sCAL; -#endif -#if defined(PNG_READ_sRGB_SUPPORTED) - PNG_CONST PNG_sRGB; -#endif -#if defined(PNG_READ_sPLT_SUPPORTED) - PNG_CONST PNG_sPLT; -#endif -#if defined(PNG_READ_tEXt_SUPPORTED) - PNG_CONST PNG_tEXt; -#endif -#if defined(PNG_READ_tIME_SUPPORTED) - PNG_CONST PNG_tIME; -#endif -#if defined(PNG_READ_tRNS_SUPPORTED) - PNG_CONST PNG_tRNS; -#endif -#if defined(PNG_READ_zTXt_SUPPORTED) - PNG_CONST PNG_zTXt; -#endif -#endif /* PNG_USE_LOCAL_ARRAYS */ - /* First we make sure we have enough data for the 4 byte chunk name - * and the 4 byte chunk length before proceeding with decoding the - * chunk data. To fully decode each of these chunks, we also make - * sure we have enough data in the buffer for the 4 byte CRC at the - * end of every chunk (except IDAT, which is handled separately). - */ - if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER)) - { - png_byte chunk_length[4]; - - if (png_ptr->buffer_size < 8) - { - png_push_save_buffer(png_ptr); - return; - } - - png_push_fill_buffer(png_ptr, chunk_length, 4); - png_ptr->push_length = png_get_uint_31(png_ptr,chunk_length); - png_reset_crc(png_ptr); - png_crc_read(png_ptr, png_ptr->chunk_name, 4); - png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; - } - - if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) - if(png_ptr->mode & PNG_AFTER_IDAT) - png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT; - - if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length); - } - else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length); - - png_ptr->process_mode = PNG_READ_DONE_MODE; - png_push_have_end(png_ptr, info_ptr); - } -#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED - else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) - png_ptr->mode |= PNG_HAVE_IDAT; - png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length); - if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) - png_ptr->mode |= PNG_HAVE_PLTE; - else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) - { - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before IDAT"); - else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && - !(png_ptr->mode & PNG_HAVE_PLTE)) - png_error(png_ptr, "Missing PLTE before IDAT"); - } - } -#endif - else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length); - } - else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) - { - /* If we reach an IDAT chunk, this means we have read all of the - * header chunks, and we can start reading the image (or if this - * is called after the image has been read - we have an error). - */ - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before IDAT"); - else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && - !(png_ptr->mode & PNG_HAVE_PLTE)) - png_error(png_ptr, "Missing PLTE before IDAT"); - - if (png_ptr->mode & PNG_HAVE_IDAT) - { - if (!(png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) - if (png_ptr->push_length == 0) - return; - - if (png_ptr->mode & PNG_AFTER_IDAT) - png_error(png_ptr, "Too many IDAT's found"); - } - - png_ptr->idat_size = png_ptr->push_length; - png_ptr->mode |= PNG_HAVE_IDAT; - png_ptr->process_mode = PNG_READ_IDAT_MODE; - png_push_have_info(png_ptr, info_ptr); - png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes; - png_ptr->zstream.next_out = png_ptr->row_buf; - return; - } -#if defined(PNG_READ_gAMA_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_sBIT_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_cHRM_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_sRGB_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_iCCP_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_sPLT_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_tRNS_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_bKGD_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_hIST_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_pHYs_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_oFFs_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_pCAL_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_sCAL_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_tIME_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_tEXt_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_push_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_zTXt_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_push_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_iTXt_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_push_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length); - } -#endif - else - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_push_handle_unknown(png_ptr, info_ptr, png_ptr->push_length); - } - - png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; -} - -void /* PRIVATE */ -png_push_crc_skip(png_structp png_ptr, png_uint_32 skip) -{ - png_ptr->process_mode = PNG_SKIP_MODE; - png_ptr->skip_length = skip; -} - -void /* PRIVATE */ -png_push_crc_finish(png_structp png_ptr) -{ - if (png_ptr->skip_length && png_ptr->save_buffer_size) - { - png_size_t save_size; - - if (png_ptr->skip_length < (png_uint_32)png_ptr->save_buffer_size) - save_size = (png_size_t)png_ptr->skip_length; - else - save_size = png_ptr->save_buffer_size; - - png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size); - - png_ptr->skip_length -= save_size; - png_ptr->buffer_size -= save_size; - png_ptr->save_buffer_size -= save_size; - png_ptr->save_buffer_ptr += save_size; - } - if (png_ptr->skip_length && png_ptr->current_buffer_size) - { - png_size_t save_size; - - if (png_ptr->skip_length < (png_uint_32)png_ptr->current_buffer_size) - save_size = (png_size_t)png_ptr->skip_length; - else - save_size = png_ptr->current_buffer_size; - - png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); - - png_ptr->skip_length -= save_size; - png_ptr->buffer_size -= save_size; - png_ptr->current_buffer_size -= save_size; - png_ptr->current_buffer_ptr += save_size; - } - if (!png_ptr->skip_length) - { - if (png_ptr->buffer_size < 4) - { - png_push_save_buffer(png_ptr); - return; - } - - png_crc_finish(png_ptr, 0); - png_ptr->process_mode = PNG_READ_CHUNK_MODE; - } -} - -void PNGAPI -png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length) -{ - png_bytep ptr; - - if(png_ptr == NULL) return; - ptr = buffer; - if (png_ptr->save_buffer_size) - { - png_size_t save_size; - - if (length < png_ptr->save_buffer_size) - save_size = length; - else - save_size = png_ptr->save_buffer_size; - - png_memcpy(ptr, png_ptr->save_buffer_ptr, save_size); - length -= save_size; - ptr += save_size; - png_ptr->buffer_size -= save_size; - png_ptr->save_buffer_size -= save_size; - png_ptr->save_buffer_ptr += save_size; - } - if (length && png_ptr->current_buffer_size) - { - png_size_t save_size; - - if (length < png_ptr->current_buffer_size) - save_size = length; - else - save_size = png_ptr->current_buffer_size; - - png_memcpy(ptr, png_ptr->current_buffer_ptr, save_size); - png_ptr->buffer_size -= save_size; - png_ptr->current_buffer_size -= save_size; - png_ptr->current_buffer_ptr += save_size; - } -} - -void /* PRIVATE */ -png_push_save_buffer(png_structp png_ptr) -{ - if (png_ptr->save_buffer_size) - { - if (png_ptr->save_buffer_ptr != png_ptr->save_buffer) - { - png_size_t i,istop; - png_bytep sp; - png_bytep dp; - - istop = png_ptr->save_buffer_size; - for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer; - i < istop; i++, sp++, dp++) - { - *dp = *sp; - } - } - } - if (png_ptr->save_buffer_size + png_ptr->current_buffer_size > - png_ptr->save_buffer_max) - { - png_size_t new_max; - png_bytep old_buffer; - - if (png_ptr->save_buffer_size > PNG_SIZE_MAX - - (png_ptr->current_buffer_size + 256)) - { - png_error(png_ptr, "Potential overflow of save_buffer"); - } - new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256; - old_buffer = png_ptr->save_buffer; - png_ptr->save_buffer = (png_bytep)png_malloc(png_ptr, - (png_uint_32)new_max); - png_memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size); - png_free(png_ptr, old_buffer); - png_ptr->save_buffer_max = new_max; - } - if (png_ptr->current_buffer_size) - { - png_memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size, - png_ptr->current_buffer_ptr, png_ptr->current_buffer_size); - png_ptr->save_buffer_size += png_ptr->current_buffer_size; - png_ptr->current_buffer_size = 0; - } - png_ptr->save_buffer_ptr = png_ptr->save_buffer; - png_ptr->buffer_size = 0; -} - -void /* PRIVATE */ -png_push_restore_buffer(png_structp png_ptr, png_bytep buffer, - png_size_t buffer_length) -{ - png_ptr->current_buffer = buffer; - png_ptr->current_buffer_size = buffer_length; - png_ptr->buffer_size = buffer_length + png_ptr->save_buffer_size; - png_ptr->current_buffer_ptr = png_ptr->current_buffer; -} - -void /* PRIVATE */ -png_push_read_IDAT(png_structp png_ptr) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_CONST PNG_IDAT; -#endif - if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER)) - { - png_byte chunk_length[4]; - - if (png_ptr->buffer_size < 8) - { - png_push_save_buffer(png_ptr); - return; - } - - png_push_fill_buffer(png_ptr, chunk_length, 4); - png_ptr->push_length = png_get_uint_31(png_ptr,chunk_length); - png_reset_crc(png_ptr); - png_crc_read(png_ptr, png_ptr->chunk_name, 4); - png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; - - if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) - { - png_ptr->process_mode = PNG_READ_CHUNK_MODE; - if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) - png_error(png_ptr, "Not enough compressed data"); - return; - } - - png_ptr->idat_size = png_ptr->push_length; - } - if (png_ptr->idat_size && png_ptr->save_buffer_size) - { - png_size_t save_size; - - if (png_ptr->idat_size < (png_uint_32)png_ptr->save_buffer_size) - { - save_size = (png_size_t)png_ptr->idat_size; - /* check for overflow */ - if((png_uint_32)save_size != png_ptr->idat_size) - png_error(png_ptr, "save_size overflowed in pngpread"); - } - else - save_size = png_ptr->save_buffer_size; - - png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size); - if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) - png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size); - png_ptr->idat_size -= save_size; - png_ptr->buffer_size -= save_size; - png_ptr->save_buffer_size -= save_size; - png_ptr->save_buffer_ptr += save_size; - } - if (png_ptr->idat_size && png_ptr->current_buffer_size) - { - png_size_t save_size; - - if (png_ptr->idat_size < (png_uint_32)png_ptr->current_buffer_size) - { - save_size = (png_size_t)png_ptr->idat_size; - /* check for overflow */ - if((png_uint_32)save_size != png_ptr->idat_size) - png_error(png_ptr, "save_size overflowed in pngpread"); - } - else - save_size = png_ptr->current_buffer_size; - - png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); - if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) - png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size); - - png_ptr->idat_size -= save_size; - png_ptr->buffer_size -= save_size; - png_ptr->current_buffer_size -= save_size; - png_ptr->current_buffer_ptr += save_size; - } - if (!png_ptr->idat_size) - { - if (png_ptr->buffer_size < 4) - { - png_push_save_buffer(png_ptr); - return; - } - - png_crc_finish(png_ptr, 0); - png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; - png_ptr->mode |= PNG_AFTER_IDAT; - } -} - -void /* PRIVATE */ -png_process_IDAT_data(png_structp png_ptr, png_bytep buffer, - png_size_t buffer_length) -{ - int ret; - - if ((png_ptr->flags & PNG_FLAG_ZLIB_FINISHED) && buffer_length) - png_error(png_ptr, "Extra compression data"); - - png_ptr->zstream.next_in = buffer; - png_ptr->zstream.avail_in = (uInt)buffer_length; - for(;;) - { - ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); - if (ret != Z_OK) - { - if (ret == Z_STREAM_END) - { - if (png_ptr->zstream.avail_in) - png_error(png_ptr, "Extra compressed data"); - if (!(png_ptr->zstream.avail_out)) - { - png_push_process_row(png_ptr); - } - - png_ptr->mode |= PNG_AFTER_IDAT; - png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; - break; - } - else if (ret == Z_BUF_ERROR) - break; - else - png_error(png_ptr, "Decompression Error"); - } - if (!(png_ptr->zstream.avail_out)) - { - if (( -#if defined(PNG_READ_INTERLACING_SUPPORTED) - png_ptr->interlaced && png_ptr->pass > 6) || - (!png_ptr->interlaced && -#endif - png_ptr->row_number == png_ptr->num_rows)) - { - if (png_ptr->zstream.avail_in) - png_warning(png_ptr, "Too much data in IDAT chunks"); - png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; - break; - } - png_push_process_row(png_ptr); - png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes; - png_ptr->zstream.next_out = png_ptr->row_buf; - } - else - break; - } -} - -void /* PRIVATE */ -png_push_process_row(png_structp png_ptr) -{ - png_ptr->row_info.color_type = png_ptr->color_type; - png_ptr->row_info.width = png_ptr->iwidth; - png_ptr->row_info.channels = png_ptr->channels; - png_ptr->row_info.bit_depth = png_ptr->bit_depth; - png_ptr->row_info.pixel_depth = png_ptr->pixel_depth; - - png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, - png_ptr->row_info.width); - - png_read_filter_row(png_ptr, &(png_ptr->row_info), - png_ptr->row_buf + 1, png_ptr->prev_row + 1, - (int)(png_ptr->row_buf[0])); - - png_memcpy_check(png_ptr, png_ptr->prev_row, png_ptr->row_buf, - png_ptr->rowbytes + 1); - - if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA)) - png_do_read_transformations(png_ptr); - -#if defined(PNG_READ_INTERLACING_SUPPORTED) - /* blow up interlaced rows to full size */ - if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) - { - if (png_ptr->pass < 6) -/* old interface (pre-1.0.9): - png_do_read_interlace(&(png_ptr->row_info), - png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations); - */ - png_do_read_interlace(png_ptr); - - switch (png_ptr->pass) - { - case 0: - { - int i; - for (i = 0; i < 8 && png_ptr->pass == 0; i++) - { - png_push_have_row(png_ptr, png_ptr->row_buf + 1); - png_read_push_finish_row(png_ptr); /* updates png_ptr->pass */ - } - if (png_ptr->pass == 2) /* pass 1 might be empty */ - { - for (i = 0; i < 4 && png_ptr->pass == 2; i++) - { - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - } - if (png_ptr->pass == 4 && png_ptr->height <= 4) - { - for (i = 0; i < 2 && png_ptr->pass == 4; i++) - { - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - } - if (png_ptr->pass == 6 && png_ptr->height <= 4) - { - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - break; - } - case 1: - { - int i; - for (i = 0; i < 8 && png_ptr->pass == 1; i++) - { - png_push_have_row(png_ptr, png_ptr->row_buf + 1); - png_read_push_finish_row(png_ptr); - } - if (png_ptr->pass == 2) /* skip top 4 generated rows */ - { - for (i = 0; i < 4 && png_ptr->pass == 2; i++) - { - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - } - break; - } - case 2: - { - int i; - for (i = 0; i < 4 && png_ptr->pass == 2; i++) - { - png_push_have_row(png_ptr, png_ptr->row_buf + 1); - png_read_push_finish_row(png_ptr); - } - for (i = 0; i < 4 && png_ptr->pass == 2; i++) - { - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - if (png_ptr->pass == 4) /* pass 3 might be empty */ - { - for (i = 0; i < 2 && png_ptr->pass == 4; i++) - { - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - } - break; - } - case 3: - { - int i; - for (i = 0; i < 4 && png_ptr->pass == 3; i++) - { - png_push_have_row(png_ptr, png_ptr->row_buf + 1); - png_read_push_finish_row(png_ptr); - } - if (png_ptr->pass == 4) /* skip top two generated rows */ - { - for (i = 0; i < 2 && png_ptr->pass == 4; i++) - { - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - } - break; - } - case 4: - { - int i; - for (i = 0; i < 2 && png_ptr->pass == 4; i++) - { - png_push_have_row(png_ptr, png_ptr->row_buf + 1); - png_read_push_finish_row(png_ptr); - } - for (i = 0; i < 2 && png_ptr->pass == 4; i++) - { - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - if (png_ptr->pass == 6) /* pass 5 might be empty */ - { - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - break; - } - case 5: - { - int i; - for (i = 0; i < 2 && png_ptr->pass == 5; i++) - { - png_push_have_row(png_ptr, png_ptr->row_buf + 1); - png_read_push_finish_row(png_ptr); - } - if (png_ptr->pass == 6) /* skip top generated row */ - { - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - break; - } - case 6: - { - png_push_have_row(png_ptr, png_ptr->row_buf + 1); - png_read_push_finish_row(png_ptr); - if (png_ptr->pass != 6) - break; - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - } - } - else -#endif - { - png_push_have_row(png_ptr, png_ptr->row_buf + 1); - png_read_push_finish_row(png_ptr); - } -} - -void /* PRIVATE */ -png_read_push_finish_row(png_structp png_ptr) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - - /* start of interlace block */ - PNG_CONST int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; - - /* offset to next interlace block */ - PNG_CONST int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; - - /* start of interlace block in the y direction */ - PNG_CONST int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; - - /* offset to next interlace block in the y direction */ - PNG_CONST int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2}; - - /* Height of interlace block. This is not currently used - if you need - * it, uncomment it here and in png.h - PNG_CONST int FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1}; - */ -#endif - - png_ptr->row_number++; - if (png_ptr->row_number < png_ptr->num_rows) - return; - - if (png_ptr->interlaced) - { - png_ptr->row_number = 0; - png_memset_check(png_ptr, png_ptr->prev_row, 0, - png_ptr->rowbytes + 1); - do - { - png_ptr->pass++; - if ((png_ptr->pass == 1 && png_ptr->width < 5) || - (png_ptr->pass == 3 && png_ptr->width < 3) || - (png_ptr->pass == 5 && png_ptr->width < 2)) - png_ptr->pass++; - - if (png_ptr->pass > 7) - png_ptr->pass--; - if (png_ptr->pass >= 7) - break; - - png_ptr->iwidth = (png_ptr->width + - png_pass_inc[png_ptr->pass] - 1 - - png_pass_start[png_ptr->pass]) / - png_pass_inc[png_ptr->pass]; - - png_ptr->irowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, - png_ptr->iwidth) + 1; - - if (png_ptr->transformations & PNG_INTERLACE) - break; - - png_ptr->num_rows = (png_ptr->height + - png_pass_yinc[png_ptr->pass] - 1 - - png_pass_ystart[png_ptr->pass]) / - png_pass_yinc[png_ptr->pass]; - - } while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0); - } -} - -#if defined(PNG_READ_tEXt_SUPPORTED) -void /* PRIVATE */ -png_push_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 - length) -{ - if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) - { - png_error(png_ptr, "Out of place tEXt"); - info_ptr = info_ptr; /* to quiet some compiler warnings */ - } - -#ifdef PNG_MAX_MALLOC_64K - png_ptr->skip_length = 0; /* This may not be necessary */ - - if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */ - { - png_warning(png_ptr, "tEXt chunk too large to fit in memory"); - png_ptr->skip_length = length - (png_uint_32)65535L; - length = (png_uint_32)65535L; - } -#endif - - png_ptr->current_text = (png_charp)png_malloc(png_ptr, - (png_uint_32)(length+1)); - png_ptr->current_text[length] = '\0'; - png_ptr->current_text_ptr = png_ptr->current_text; - png_ptr->current_text_size = (png_size_t)length; - png_ptr->current_text_left = (png_size_t)length; - png_ptr->process_mode = PNG_READ_tEXt_MODE; -} - -void /* PRIVATE */ -png_push_read_tEXt(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr->buffer_size && png_ptr->current_text_left) - { - png_size_t text_size; - - if (png_ptr->buffer_size < png_ptr->current_text_left) - text_size = png_ptr->buffer_size; - else - text_size = png_ptr->current_text_left; - png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); - png_ptr->current_text_left -= text_size; - png_ptr->current_text_ptr += text_size; - } - if (!(png_ptr->current_text_left)) - { - png_textp text_ptr; - png_charp text; - png_charp key; - int ret; - - if (png_ptr->buffer_size < 4) - { - png_push_save_buffer(png_ptr); - return; - } - - png_push_crc_finish(png_ptr); - -#if defined(PNG_MAX_MALLOC_64K) - if (png_ptr->skip_length) - return; -#endif - - key = png_ptr->current_text; - - for (text = key; *text; text++) - /* empty loop */ ; - - if (text < key + png_ptr->current_text_size) - text++; - - text_ptr = (png_textp)png_malloc(png_ptr, - (png_uint_32)png_sizeof(png_text)); - text_ptr->compression = PNG_TEXT_COMPRESSION_NONE; - text_ptr->key = key; -#ifdef PNG_iTXt_SUPPORTED - text_ptr->lang = NULL; - text_ptr->lang_key = NULL; -#endif - text_ptr->text = text; - - ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); - - png_free(png_ptr, key); - png_free(png_ptr, text_ptr); - png_ptr->current_text = NULL; - - if (ret) - png_warning(png_ptr, "Insufficient memory to store text chunk."); - } -} -#endif - -#if defined(PNG_READ_zTXt_SUPPORTED) -void /* PRIVATE */ -png_push_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 - length) -{ - if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) - { - png_error(png_ptr, "Out of place zTXt"); - info_ptr = info_ptr; /* to quiet some compiler warnings */ - } - -#ifdef PNG_MAX_MALLOC_64K - /* We can't handle zTXt chunks > 64K, since we don't have enough space - * to be able to store the uncompressed data. Actually, the threshold - * is probably around 32K, but it isn't as definite as 64K is. - */ - if (length > (png_uint_32)65535L) - { - png_warning(png_ptr, "zTXt chunk too large to fit in memory"); - png_push_crc_skip(png_ptr, length); - return; - } -#endif - - png_ptr->current_text = (png_charp)png_malloc(png_ptr, - (png_uint_32)(length+1)); - png_ptr->current_text[length] = '\0'; - png_ptr->current_text_ptr = png_ptr->current_text; - png_ptr->current_text_size = (png_size_t)length; - png_ptr->current_text_left = (png_size_t)length; - png_ptr->process_mode = PNG_READ_zTXt_MODE; -} - -void /* PRIVATE */ -png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr->buffer_size && png_ptr->current_text_left) - { - png_size_t text_size; - - if (png_ptr->buffer_size < (png_uint_32)png_ptr->current_text_left) - text_size = png_ptr->buffer_size; - else - text_size = png_ptr->current_text_left; - png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); - png_ptr->current_text_left -= text_size; - png_ptr->current_text_ptr += text_size; - } - if (!(png_ptr->current_text_left)) - { - png_textp text_ptr; - png_charp text; - png_charp key; - int ret; - png_size_t text_size, key_size; - - if (png_ptr->buffer_size < 4) - { - png_push_save_buffer(png_ptr); - return; - } - - png_push_crc_finish(png_ptr); - - key = png_ptr->current_text; - - for (text = key; *text; text++) - /* empty loop */ ; - - /* zTXt can't have zero text */ - if (text >= key + png_ptr->current_text_size) - { - png_ptr->current_text = NULL; - png_free(png_ptr, key); - return; - } - - text++; - - if (*text != PNG_TEXT_COMPRESSION_zTXt) /* check compression byte */ - { - png_ptr->current_text = NULL; - png_free(png_ptr, key); - return; - } - - text++; - - png_ptr->zstream.next_in = (png_bytep )text; - png_ptr->zstream.avail_in = (uInt)(png_ptr->current_text_size - - (text - key)); - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - - key_size = text - key; - text_size = 0; - text = NULL; - ret = Z_STREAM_END; - - while (png_ptr->zstream.avail_in) - { - ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); - if (ret != Z_OK && ret != Z_STREAM_END) - { - inflateReset(&png_ptr->zstream); - png_ptr->zstream.avail_in = 0; - png_ptr->current_text = NULL; - png_free(png_ptr, key); - png_free(png_ptr, text); - return; - } - if (!(png_ptr->zstream.avail_out) || ret == Z_STREAM_END) - { - if (text == NULL) - { - text = (png_charp)png_malloc(png_ptr, - (png_uint_32)(png_ptr->zbuf_size - png_ptr->zstream.avail_out - + key_size + 1)); - png_memcpy(text + key_size, png_ptr->zbuf, - png_ptr->zbuf_size - png_ptr->zstream.avail_out); - png_memcpy(text, key, key_size); - text_size = key_size + png_ptr->zbuf_size - - png_ptr->zstream.avail_out; - *(text + text_size) = '\0'; - } - else - { - png_charp tmp; - - tmp = text; - text = (png_charp)png_malloc(png_ptr, text_size + - (png_uint_32)(png_ptr->zbuf_size - png_ptr->zstream.avail_out - + 1)); - png_memcpy(text, tmp, text_size); - png_free(png_ptr, tmp); - png_memcpy(text + text_size, png_ptr->zbuf, - png_ptr->zbuf_size - png_ptr->zstream.avail_out); - text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out; - *(text + text_size) = '\0'; - } - if (ret != Z_STREAM_END) - { - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - } - } - else - { - break; - } - - if (ret == Z_STREAM_END) - break; - } - - inflateReset(&png_ptr->zstream); - png_ptr->zstream.avail_in = 0; - - if (ret != Z_STREAM_END) - { - png_ptr->current_text = NULL; - png_free(png_ptr, key); - png_free(png_ptr, text); - return; - } - - png_ptr->current_text = NULL; - png_free(png_ptr, key); - key = text; - text += key_size; - - text_ptr = (png_textp)png_malloc(png_ptr, - (png_uint_32)png_sizeof(png_text)); - text_ptr->compression = PNG_TEXT_COMPRESSION_zTXt; - text_ptr->key = key; -#ifdef PNG_iTXt_SUPPORTED - text_ptr->lang = NULL; - text_ptr->lang_key = NULL; -#endif - text_ptr->text = text; - - ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); - - png_free(png_ptr, key); - png_free(png_ptr, text_ptr); - - if (ret) - png_warning(png_ptr, "Insufficient memory to store text chunk."); - } -} -#endif - -#if defined(PNG_READ_iTXt_SUPPORTED) -void /* PRIVATE */ -png_push_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 - length) -{ - if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) - { - png_error(png_ptr, "Out of place iTXt"); - info_ptr = info_ptr; /* to quiet some compiler warnings */ - } - -#ifdef PNG_MAX_MALLOC_64K - png_ptr->skip_length = 0; /* This may not be necessary */ - - if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */ - { - png_warning(png_ptr, "iTXt chunk too large to fit in memory"); - png_ptr->skip_length = length - (png_uint_32)65535L; - length = (png_uint_32)65535L; - } -#endif - - png_ptr->current_text = (png_charp)png_malloc(png_ptr, - (png_uint_32)(length+1)); - png_ptr->current_text[length] = '\0'; - png_ptr->current_text_ptr = png_ptr->current_text; - png_ptr->current_text_size = (png_size_t)length; - png_ptr->current_text_left = (png_size_t)length; - png_ptr->process_mode = PNG_READ_iTXt_MODE; -} - -void /* PRIVATE */ -png_push_read_iTXt(png_structp png_ptr, png_infop info_ptr) -{ - - if (png_ptr->buffer_size && png_ptr->current_text_left) - { - png_size_t text_size; - - if (png_ptr->buffer_size < png_ptr->current_text_left) - text_size = png_ptr->buffer_size; - else - text_size = png_ptr->current_text_left; - png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); - png_ptr->current_text_left -= text_size; - png_ptr->current_text_ptr += text_size; - } - if (!(png_ptr->current_text_left)) - { - png_textp text_ptr; - png_charp key; - int comp_flag; - png_charp lang; - png_charp lang_key; - png_charp text; - int ret; - - if (png_ptr->buffer_size < 4) - { - png_push_save_buffer(png_ptr); - return; - } - - png_push_crc_finish(png_ptr); - -#if defined(PNG_MAX_MALLOC_64K) - if (png_ptr->skip_length) - return; -#endif - - key = png_ptr->current_text; - - for (lang = key; *lang; lang++) - /* empty loop */ ; - - if (lang < key + png_ptr->current_text_size - 3) - lang++; - - comp_flag = *lang++; - lang++; /* skip comp_type, always zero */ - - for (lang_key = lang; *lang_key; lang_key++) - /* empty loop */ ; - lang_key++; /* skip NUL separator */ - - text=lang_key; - if (lang_key < key + png_ptr->current_text_size - 1) - { - for (; *text; text++) - /* empty loop */ ; - } - - if (text < key + png_ptr->current_text_size) - text++; - - text_ptr = (png_textp)png_malloc(png_ptr, - (png_uint_32)png_sizeof(png_text)); - text_ptr->compression = comp_flag + 2; - text_ptr->key = key; - text_ptr->lang = lang; - text_ptr->lang_key = lang_key; - text_ptr->text = text; - text_ptr->text_length = 0; - text_ptr->itxt_length = png_strlen(text); - - ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); - - png_ptr->current_text = NULL; - - png_free(png_ptr, text_ptr); - if (ret) - png_warning(png_ptr, "Insufficient memory to store iTXt chunk."); - } -} -#endif - -/* This function is called when we haven't found a handler for this - * chunk. If there isn't a problem with the chunk itself (ie a bad chunk - * name or a critical chunk), the chunk is (currently) silently ignored. - */ -void /* PRIVATE */ -png_push_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 - length) -{ - png_uint_32 skip=0; - png_check_chunk_name(png_ptr, png_ptr->chunk_name); - - if (!(png_ptr->chunk_name[0] & 0x20)) - { -#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) - if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != - PNG_HANDLE_CHUNK_ALWAYS -#if defined(PNG_READ_USER_CHUNKS_SUPPORTED) - && png_ptr->read_user_chunk_fn == NULL -#endif - ) -#endif - png_chunk_error(png_ptr, "unknown critical chunk"); - - info_ptr = info_ptr; /* to quiet some compiler warnings */ - } - -#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) - if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) - { -#ifdef PNG_MAX_MALLOC_64K - if (length > (png_uint_32)65535L) - { - png_warning(png_ptr, "unknown chunk too large to fit in memory"); - skip = length - (png_uint_32)65535L; - length = (png_uint_32)65535L; - } -#endif - png_strncpy((png_charp)png_ptr->unknown_chunk.name, - (png_charp)png_ptr->chunk_name, 4); - png_ptr->unknown_chunk.name[4] = '\0'; - png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length); - png_ptr->unknown_chunk.size = (png_size_t)length; - png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length); -#if defined(PNG_READ_USER_CHUNKS_SUPPORTED) - if(png_ptr->read_user_chunk_fn != NULL) - { - /* callback to user unknown chunk handler */ - int ret; - ret = (*(png_ptr->read_user_chunk_fn)) - (png_ptr, &png_ptr->unknown_chunk); - if (ret < 0) - png_chunk_error(png_ptr, "error in user chunk"); - if (ret == 0) - { - if (!(png_ptr->chunk_name[0] & 0x20)) - if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != - PNG_HANDLE_CHUNK_ALWAYS) - png_chunk_error(png_ptr, "unknown critical chunk"); - png_set_unknown_chunks(png_ptr, info_ptr, - &png_ptr->unknown_chunk, 1); - } - } -#else - png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1); -#endif - png_free(png_ptr, png_ptr->unknown_chunk.data); - png_ptr->unknown_chunk.data = NULL; - } - else -#endif - skip=length; - png_push_crc_skip(png_ptr, skip); -} - -void /* PRIVATE */ -png_push_have_info(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr->info_fn != NULL) - (*(png_ptr->info_fn))(png_ptr, info_ptr); -} - -void /* PRIVATE */ -png_push_have_end(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr->end_fn != NULL) - (*(png_ptr->end_fn))(png_ptr, info_ptr); -} - -void /* PRIVATE */ -png_push_have_row(png_structp png_ptr, png_bytep row) -{ - if (png_ptr->row_fn != NULL) - (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number, - (int)png_ptr->pass); -} - -void PNGAPI -png_progressive_combine_row (png_structp png_ptr, - png_bytep old_row, png_bytep new_row) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_CONST int FARDATA png_pass_dsp_mask[7] = - {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff}; -#endif - if(png_ptr == NULL) return; - if (new_row != NULL) /* new_row must == png_ptr->row_buf here. */ - png_combine_row(png_ptr, old_row, png_pass_dsp_mask[png_ptr->pass]); -} - -void PNGAPI -png_set_progressive_read_fn(png_structp png_ptr, png_voidp progressive_ptr, - png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn, - png_progressive_end_ptr end_fn) -{ - if(png_ptr == NULL) return; - png_ptr->info_fn = info_fn; - png_ptr->row_fn = row_fn; - png_ptr->end_fn = end_fn; - - png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer); -} - -png_voidp PNGAPI -png_get_progressive_ptr(png_structp png_ptr) -{ - if(png_ptr == NULL) return (NULL); - return png_ptr->io_ptr; -} -#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ diff --git a/uppdev/plugin/png/lib/pngread.c b/uppdev/plugin/png/lib/pngread.c deleted file mode 100644 index 707561aee..000000000 --- a/uppdev/plugin/png/lib/pngread.c +++ /dev/null @@ -1,1472 +0,0 @@ - -/* pngread.c - read a PNG file - * - * Last changed in libpng 1.2.20 September 7, 2007 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2007 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This file contains routines that an application calls directly to - * read a PNG file or stream. - */ - -#define PNG_INTERNAL -#include "png.h" - -#if defined(PNG_READ_SUPPORTED) - -/* Create a PNG structure for reading, and allocate any memory needed. */ -png_structp PNGAPI -png_create_read_struct(png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn) -{ - -#ifdef PNG_USER_MEM_SUPPORTED - return (png_create_read_struct_2(user_png_ver, error_ptr, error_fn, - warn_fn, png_voidp_NULL, png_malloc_ptr_NULL, png_free_ptr_NULL)); -} - -/* Alternate create PNG structure for reading, and allocate any memory needed. */ -png_structp PNGAPI -png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, - png_malloc_ptr malloc_fn, png_free_ptr free_fn) -{ -#endif /* PNG_USER_MEM_SUPPORTED */ - - png_structp png_ptr; - -#ifdef PNG_SETJMP_SUPPORTED -#ifdef USE_FAR_KEYWORD - jmp_buf jmpbuf; -#endif -#endif - - int i; - - png_debug(1, "in png_create_read_struct\n"); -#ifdef PNG_USER_MEM_SUPPORTED - png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG, - (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr); -#else - png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); -#endif - if (png_ptr == NULL) - return (NULL); - - /* added at libpng-1.2.6 */ -#ifdef PNG_SET_USER_LIMITS_SUPPORTED - png_ptr->user_width_max=PNG_USER_WIDTH_MAX; - png_ptr->user_height_max=PNG_USER_HEIGHT_MAX; -#endif - -#ifdef PNG_SETJMP_SUPPORTED -#ifdef USE_FAR_KEYWORD - if (setjmp(jmpbuf)) -#else - if (setjmp(png_ptr->jmpbuf)) -#endif - { - png_free(png_ptr, png_ptr->zbuf); - png_ptr->zbuf=NULL; -#ifdef PNG_USER_MEM_SUPPORTED - png_destroy_struct_2((png_voidp)png_ptr, - (png_free_ptr)free_fn, (png_voidp)mem_ptr); -#else - png_destroy_struct((png_voidp)png_ptr); -#endif - return (NULL); - } -#ifdef USE_FAR_KEYWORD - png_memcpy(png_ptr->jmpbuf,jmpbuf,png_sizeof(jmp_buf)); -#endif -#endif - -#ifdef PNG_USER_MEM_SUPPORTED - png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn); -#endif - - png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn); - - i=0; - do - { - if(user_png_ver[i] != png_libpng_ver[i]) - png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; - } while (png_libpng_ver[i++]); - - if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) - { - /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so - * we must recompile any applications that use any older library version. - * For versions after libpng 1.0, we will be compatible, so we need - * only check the first digit. - */ - if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || - (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) || - (user_png_ver[0] == '0' && user_png_ver[2] < '9')) - { -#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) - char msg[80]; - if (user_png_ver) - { - png_snprintf(msg, 80, - "Application was compiled with png.h from libpng-%.20s", - user_png_ver); - png_warning(png_ptr, msg); - } - png_snprintf(msg, 80, - "Application is running with png.c from libpng-%.20s", - png_libpng_ver); - png_warning(png_ptr, msg); -#endif -#ifdef PNG_ERROR_NUMBERS_SUPPORTED - png_ptr->flags=0; -#endif - png_error(png_ptr, - "Incompatible libpng version in application and library"); - } - } - - /* initialize zbuf - compression buffer */ - png_ptr->zbuf_size = PNG_ZBUF_SIZE; - png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, - (png_uint_32)png_ptr->zbuf_size); - png_ptr->zstream.zalloc = png_zalloc; - png_ptr->zstream.zfree = png_zfree; - png_ptr->zstream.opaque = (voidpf)png_ptr; - - switch (inflateInit(&png_ptr->zstream)) - { - case Z_OK: /* Do nothing */ break; - case Z_MEM_ERROR: - case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory error"); break; - case Z_VERSION_ERROR: png_error(png_ptr, "zlib version error"); break; - default: png_error(png_ptr, "Unknown zlib error"); - } - - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - - png_set_read_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL); - -#ifdef PNG_SETJMP_SUPPORTED -/* Applications that neglect to set up their own setjmp() and then encounter - a png_error() will longjmp here. Since the jmpbuf is then meaningless we - abort instead of returning. */ -#ifdef USE_FAR_KEYWORD - if (setjmp(jmpbuf)) - PNG_ABORT(); - png_memcpy(png_ptr->jmpbuf,jmpbuf,png_sizeof(jmp_buf)); -#else - if (setjmp(png_ptr->jmpbuf)) - PNG_ABORT(); -#endif -#endif - return (png_ptr); -} - -#if defined(PNG_1_0_X) || defined(PNG_1_2_X) -/* Initialize PNG structure for reading, and allocate any memory needed. - This interface is deprecated in favour of the png_create_read_struct(), - and it will disappear as of libpng-1.3.0. */ -#undef png_read_init -void PNGAPI -png_read_init(png_structp png_ptr) -{ - /* We only come here via pre-1.0.7-compiled applications */ - png_read_init_2(png_ptr, "1.0.6 or earlier", 0, 0); -} - -void PNGAPI -png_read_init_2(png_structp png_ptr, png_const_charp user_png_ver, - png_size_t png_struct_size, png_size_t png_info_size) -{ - /* We only come here via pre-1.0.12-compiled applications */ - if(png_ptr == NULL) return; -#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) - if(png_sizeof(png_struct) > png_struct_size || - png_sizeof(png_info) > png_info_size) - { - char msg[80]; - png_ptr->warning_fn=NULL; - if (user_png_ver) - { - png_snprintf(msg, 80, - "Application was compiled with png.h from libpng-%.20s", - user_png_ver); - png_warning(png_ptr, msg); - } - png_snprintf(msg, 80, - "Application is running with png.c from libpng-%.20s", - png_libpng_ver); - png_warning(png_ptr, msg); - } -#endif - if(png_sizeof(png_struct) > png_struct_size) - { - png_ptr->error_fn=NULL; -#ifdef PNG_ERROR_NUMBERS_SUPPORTED - png_ptr->flags=0; -#endif - png_error(png_ptr, - "The png struct allocated by the application for reading is too small."); - } - if(png_sizeof(png_info) > png_info_size) - { - png_ptr->error_fn=NULL; -#ifdef PNG_ERROR_NUMBERS_SUPPORTED - png_ptr->flags=0; -#endif - png_error(png_ptr, - "The info struct allocated by application for reading is too small."); - } - png_read_init_3(&png_ptr, user_png_ver, png_struct_size); -} -#endif /* PNG_1_0_X || PNG_1_2_X */ - -void PNGAPI -png_read_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver, - png_size_t png_struct_size) -{ -#ifdef PNG_SETJMP_SUPPORTED - jmp_buf tmp_jmp; /* to save current jump buffer */ -#endif - - int i=0; - - png_structp png_ptr=*ptr_ptr; - - if(png_ptr == NULL) return; - - do - { - if(user_png_ver[i] != png_libpng_ver[i]) - { -#ifdef PNG_LEGACY_SUPPORTED - png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; -#else - png_ptr->warning_fn=NULL; - png_warning(png_ptr, - "Application uses deprecated png_read_init() and should be recompiled."); - break; -#endif - } - } while (png_libpng_ver[i++]); - - png_debug(1, "in png_read_init_3\n"); - -#ifdef PNG_SETJMP_SUPPORTED - /* save jump buffer and error functions */ - png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof (jmp_buf)); -#endif - - if(png_sizeof(png_struct) > png_struct_size) - { - png_destroy_struct(png_ptr); - *ptr_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); - png_ptr = *ptr_ptr; - } - - /* reset all variables to 0 */ - png_memset(png_ptr, 0, png_sizeof (png_struct)); - -#ifdef PNG_SETJMP_SUPPORTED - /* restore jump buffer */ - png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof (jmp_buf)); -#endif - - /* added at libpng-1.2.6 */ -#ifdef PNG_SET_USER_LIMITS_SUPPORTED - png_ptr->user_width_max=PNG_USER_WIDTH_MAX; - png_ptr->user_height_max=PNG_USER_HEIGHT_MAX; -#endif - - /* initialize zbuf - compression buffer */ - png_ptr->zbuf_size = PNG_ZBUF_SIZE; - png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, - (png_uint_32)png_ptr->zbuf_size); - png_ptr->zstream.zalloc = png_zalloc; - png_ptr->zstream.zfree = png_zfree; - png_ptr->zstream.opaque = (voidpf)png_ptr; - - switch (inflateInit(&png_ptr->zstream)) - { - case Z_OK: /* Do nothing */ break; - case Z_MEM_ERROR: - case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory"); break; - case Z_VERSION_ERROR: png_error(png_ptr, "zlib version"); break; - default: png_error(png_ptr, "Unknown zlib error"); - } - - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - - png_set_read_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL); -} - -#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED -/* Read the information before the actual image data. This has been - * changed in v0.90 to allow reading a file that already has the magic - * bytes read from the stream. You can tell libpng how many bytes have - * been read from the beginning of the stream (up to the maximum of 8) - * via png_set_sig_bytes(), and we will only check the remaining bytes - * here. The application can then have access to the signature bytes we - * read if it is determined that this isn't a valid PNG file. - */ -void PNGAPI -png_read_info(png_structp png_ptr, png_infop info_ptr) -{ - if(png_ptr == NULL) return; - png_debug(1, "in png_read_info\n"); - /* If we haven't checked all of the PNG signature bytes, do so now. */ - if (png_ptr->sig_bytes < 8) - { - png_size_t num_checked = png_ptr->sig_bytes, - num_to_check = 8 - num_checked; - - png_read_data(png_ptr, &(info_ptr->signature[num_checked]), num_to_check); - png_ptr->sig_bytes = 8; - - if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) - { - if (num_checked < 4 && - png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) - png_error(png_ptr, "Not a PNG file"); - else - png_error(png_ptr, "PNG file corrupted by ASCII conversion"); - } - if (num_checked < 3) - png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; - } - - for(;;) - { -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_CONST PNG_IHDR; - PNG_CONST PNG_IDAT; - PNG_CONST PNG_IEND; - PNG_CONST PNG_PLTE; -#if defined(PNG_READ_bKGD_SUPPORTED) - PNG_CONST PNG_bKGD; -#endif -#if defined(PNG_READ_cHRM_SUPPORTED) - PNG_CONST PNG_cHRM; -#endif -#if defined(PNG_READ_gAMA_SUPPORTED) - PNG_CONST PNG_gAMA; -#endif -#if defined(PNG_READ_hIST_SUPPORTED) - PNG_CONST PNG_hIST; -#endif -#if defined(PNG_READ_iCCP_SUPPORTED) - PNG_CONST PNG_iCCP; -#endif -#if defined(PNG_READ_iTXt_SUPPORTED) - PNG_CONST PNG_iTXt; -#endif -#if defined(PNG_READ_oFFs_SUPPORTED) - PNG_CONST PNG_oFFs; -#endif -#if defined(PNG_READ_pCAL_SUPPORTED) - PNG_CONST PNG_pCAL; -#endif -#if defined(PNG_READ_pHYs_SUPPORTED) - PNG_CONST PNG_pHYs; -#endif -#if defined(PNG_READ_sBIT_SUPPORTED) - PNG_CONST PNG_sBIT; -#endif -#if defined(PNG_READ_sCAL_SUPPORTED) - PNG_CONST PNG_sCAL; -#endif -#if defined(PNG_READ_sPLT_SUPPORTED) - PNG_CONST PNG_sPLT; -#endif -#if defined(PNG_READ_sRGB_SUPPORTED) - PNG_CONST PNG_sRGB; -#endif -#if defined(PNG_READ_tEXt_SUPPORTED) - PNG_CONST PNG_tEXt; -#endif -#if defined(PNG_READ_tIME_SUPPORTED) - PNG_CONST PNG_tIME; -#endif -#if defined(PNG_READ_tRNS_SUPPORTED) - PNG_CONST PNG_tRNS; -#endif -#if defined(PNG_READ_zTXt_SUPPORTED) - PNG_CONST PNG_zTXt; -#endif -#endif /* PNG_USE_LOCAL_ARRAYS */ - png_byte chunk_length[4]; - png_uint_32 length; - - png_read_data(png_ptr, chunk_length, 4); - length = png_get_uint_31(png_ptr,chunk_length); - - png_reset_crc(png_ptr); - png_crc_read(png_ptr, png_ptr->chunk_name, 4); - - png_debug2(0, "Reading %s chunk, length=%lu.\n", png_ptr->chunk_name, - length); - - /* This should be a binary subdivision search or a hash for - * matching the chunk name rather than a linear search. - */ - if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) - if(png_ptr->mode & PNG_AFTER_IDAT) - png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT; - - if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4)) - png_handle_IHDR(png_ptr, info_ptr, length); - else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4)) - png_handle_IEND(png_ptr, info_ptr, length); -#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED - else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name)) - { - if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) - png_ptr->mode |= PNG_HAVE_IDAT; - png_handle_unknown(png_ptr, info_ptr, length); - if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) - png_ptr->mode |= PNG_HAVE_PLTE; - else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) - { - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before IDAT"); - else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && - !(png_ptr->mode & PNG_HAVE_PLTE)) - png_error(png_ptr, "Missing PLTE before IDAT"); - break; - } - } -#endif - else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) - png_handle_PLTE(png_ptr, info_ptr, length); - else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) - { - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before IDAT"); - else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && - !(png_ptr->mode & PNG_HAVE_PLTE)) - png_error(png_ptr, "Missing PLTE before IDAT"); - - png_ptr->idat_size = length; - png_ptr->mode |= PNG_HAVE_IDAT; - break; - } -#if defined(PNG_READ_bKGD_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4)) - png_handle_bKGD(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_cHRM_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4)) - png_handle_cHRM(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_gAMA_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4)) - png_handle_gAMA(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_hIST_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4)) - png_handle_hIST(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_oFFs_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4)) - png_handle_oFFs(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_pCAL_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4)) - png_handle_pCAL(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_sCAL_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4)) - png_handle_sCAL(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_pHYs_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4)) - png_handle_pHYs(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_sBIT_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4)) - png_handle_sBIT(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_sRGB_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4)) - png_handle_sRGB(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_iCCP_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4)) - png_handle_iCCP(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_sPLT_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4)) - png_handle_sPLT(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_tEXt_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4)) - png_handle_tEXt(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_tIME_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4)) - png_handle_tIME(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_tRNS_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4)) - png_handle_tRNS(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_zTXt_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4)) - png_handle_zTXt(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_iTXt_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4)) - png_handle_iTXt(png_ptr, info_ptr, length); -#endif - else - png_handle_unknown(png_ptr, info_ptr, length); - } -} -#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ - -/* optional call to update the users info_ptr structure */ -void PNGAPI -png_read_update_info(png_structp png_ptr, png_infop info_ptr) -{ - png_debug(1, "in png_read_update_info\n"); - if(png_ptr == NULL) return; - if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) - png_read_start_row(png_ptr); - else - png_warning(png_ptr, - "Ignoring extra png_read_update_info() call; row buffer not reallocated"); - png_read_transform_info(png_ptr, info_ptr); -} - -#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED -/* Initialize palette, background, etc, after transformations - * are set, but before any reading takes place. This allows - * the user to obtain a gamma-corrected palette, for example. - * If the user doesn't call this, we will do it ourselves. - */ -void PNGAPI -png_start_read_image(png_structp png_ptr) -{ - png_debug(1, "in png_start_read_image\n"); - if(png_ptr == NULL) return; - if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) - png_read_start_row(png_ptr); -} -#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ - -#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED -void PNGAPI -png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_CONST PNG_IDAT; - PNG_CONST int png_pass_dsp_mask[7] = {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, - 0xff}; - PNG_CONST int png_pass_mask[7] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff}; -#endif - int ret; - if(png_ptr == NULL) return; - png_debug2(1, "in png_read_row (row %lu, pass %d)\n", - png_ptr->row_number, png_ptr->pass); - if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) - png_read_start_row(png_ptr); - if (png_ptr->row_number == 0 && png_ptr->pass == 0) - { - /* check for transforms that have been set but were defined out */ -#if defined(PNG_WRITE_INVERT_SUPPORTED) && !defined(PNG_READ_INVERT_SUPPORTED) - if (png_ptr->transformations & PNG_INVERT_MONO) - png_warning(png_ptr, "PNG_READ_INVERT_SUPPORTED is not defined."); -#endif -#if defined(PNG_WRITE_FILLER_SUPPORTED) && !defined(PNG_READ_FILLER_SUPPORTED) - if (png_ptr->transformations & PNG_FILLER) - png_warning(png_ptr, "PNG_READ_FILLER_SUPPORTED is not defined."); -#endif -#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) && !defined(PNG_READ_PACKSWAP_SUPPORTED) - if (png_ptr->transformations & PNG_PACKSWAP) - png_warning(png_ptr, "PNG_READ_PACKSWAP_SUPPORTED is not defined."); -#endif -#if defined(PNG_WRITE_PACK_SUPPORTED) && !defined(PNG_READ_PACK_SUPPORTED) - if (png_ptr->transformations & PNG_PACK) - png_warning(png_ptr, "PNG_READ_PACK_SUPPORTED is not defined."); -#endif -#if defined(PNG_WRITE_SHIFT_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) - if (png_ptr->transformations & PNG_SHIFT) - png_warning(png_ptr, "PNG_READ_SHIFT_SUPPORTED is not defined."); -#endif -#if defined(PNG_WRITE_BGR_SUPPORTED) && !defined(PNG_READ_BGR_SUPPORTED) - if (png_ptr->transformations & PNG_BGR) - png_warning(png_ptr, "PNG_READ_BGR_SUPPORTED is not defined."); -#endif -#if defined(PNG_WRITE_SWAP_SUPPORTED) && !defined(PNG_READ_SWAP_SUPPORTED) - if (png_ptr->transformations & PNG_SWAP_BYTES) - png_warning(png_ptr, "PNG_READ_SWAP_SUPPORTED is not defined."); -#endif - } - -#if defined(PNG_READ_INTERLACING_SUPPORTED) - /* if interlaced and we do not need a new row, combine row and return */ - if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) - { - switch (png_ptr->pass) - { - case 0: - if (png_ptr->row_number & 0x07) - { - if (dsp_row != NULL) - png_combine_row(png_ptr, dsp_row, - png_pass_dsp_mask[png_ptr->pass]); - png_read_finish_row(png_ptr); - return; - } - break; - case 1: - if ((png_ptr->row_number & 0x07) || png_ptr->width < 5) - { - if (dsp_row != NULL) - png_combine_row(png_ptr, dsp_row, - png_pass_dsp_mask[png_ptr->pass]); - png_read_finish_row(png_ptr); - return; - } - break; - case 2: - if ((png_ptr->row_number & 0x07) != 4) - { - if (dsp_row != NULL && (png_ptr->row_number & 4)) - png_combine_row(png_ptr, dsp_row, - png_pass_dsp_mask[png_ptr->pass]); - png_read_finish_row(png_ptr); - return; - } - break; - case 3: - if ((png_ptr->row_number & 3) || png_ptr->width < 3) - { - if (dsp_row != NULL) - png_combine_row(png_ptr, dsp_row, - png_pass_dsp_mask[png_ptr->pass]); - png_read_finish_row(png_ptr); - return; - } - break; - case 4: - if ((png_ptr->row_number & 3) != 2) - { - if (dsp_row != NULL && (png_ptr->row_number & 2)) - png_combine_row(png_ptr, dsp_row, - png_pass_dsp_mask[png_ptr->pass]); - png_read_finish_row(png_ptr); - return; - } - break; - case 5: - if ((png_ptr->row_number & 1) || png_ptr->width < 2) - { - if (dsp_row != NULL) - png_combine_row(png_ptr, dsp_row, - png_pass_dsp_mask[png_ptr->pass]); - png_read_finish_row(png_ptr); - return; - } - break; - case 6: - if (!(png_ptr->row_number & 1)) - { - png_read_finish_row(png_ptr); - return; - } - break; - } - } -#endif - - if (!(png_ptr->mode & PNG_HAVE_IDAT)) - png_error(png_ptr, "Invalid attempt to read row data"); - - png_ptr->zstream.next_out = png_ptr->row_buf; - png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes; - do - { - if (!(png_ptr->zstream.avail_in)) - { - while (!png_ptr->idat_size) - { - png_byte chunk_length[4]; - - png_crc_finish(png_ptr, 0); - - png_read_data(png_ptr, chunk_length, 4); - png_ptr->idat_size = png_get_uint_31(png_ptr,chunk_length); - - png_reset_crc(png_ptr); - png_crc_read(png_ptr, png_ptr->chunk_name, 4); - if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) - png_error(png_ptr, "Not enough image data"); - } - png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size; - png_ptr->zstream.next_in = png_ptr->zbuf; - if (png_ptr->zbuf_size > png_ptr->idat_size) - png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size; - png_crc_read(png_ptr, png_ptr->zbuf, - (png_size_t)png_ptr->zstream.avail_in); - png_ptr->idat_size -= png_ptr->zstream.avail_in; - } - ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); - if (ret == Z_STREAM_END) - { - if (png_ptr->zstream.avail_out || png_ptr->zstream.avail_in || - png_ptr->idat_size) - png_error(png_ptr, "Extra compressed data"); - png_ptr->mode |= PNG_AFTER_IDAT; - png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; - break; - } - if (ret != Z_OK) - png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg : - "Decompression error"); - - } while (png_ptr->zstream.avail_out); - - png_ptr->row_info.color_type = png_ptr->color_type; - png_ptr->row_info.width = png_ptr->iwidth; - png_ptr->row_info.channels = png_ptr->channels; - png_ptr->row_info.bit_depth = png_ptr->bit_depth; - png_ptr->row_info.pixel_depth = png_ptr->pixel_depth; - png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, - png_ptr->row_info.width); - - if(png_ptr->row_buf[0]) - png_read_filter_row(png_ptr, &(png_ptr->row_info), - png_ptr->row_buf + 1, png_ptr->prev_row + 1, - (int)(png_ptr->row_buf[0])); - - png_memcpy_check(png_ptr, png_ptr->prev_row, png_ptr->row_buf, - png_ptr->rowbytes + 1); - -#if defined(PNG_MNG_FEATURES_SUPPORTED) - if((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && - (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) - { - /* Intrapixel differencing */ - png_do_read_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1); - } -#endif - - - if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA)) - png_do_read_transformations(png_ptr); - -#if defined(PNG_READ_INTERLACING_SUPPORTED) - /* blow up interlaced rows to full size */ - if (png_ptr->interlaced && - (png_ptr->transformations & PNG_INTERLACE)) - { - if (png_ptr->pass < 6) -/* old interface (pre-1.0.9): - png_do_read_interlace(&(png_ptr->row_info), - png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations); - */ - png_do_read_interlace(png_ptr); - - if (dsp_row != NULL) - png_combine_row(png_ptr, dsp_row, - png_pass_dsp_mask[png_ptr->pass]); - if (row != NULL) - png_combine_row(png_ptr, row, - png_pass_mask[png_ptr->pass]); - } - else -#endif - { - if (row != NULL) - png_combine_row(png_ptr, row, 0xff); - if (dsp_row != NULL) - png_combine_row(png_ptr, dsp_row, 0xff); - } - png_read_finish_row(png_ptr); - - if (png_ptr->read_row_fn != NULL) - (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); -} -#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ - -#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED -/* Read one or more rows of image data. If the image is interlaced, - * and png_set_interlace_handling() has been called, the rows need to - * contain the contents of the rows from the previous pass. If the - * image has alpha or transparency, and png_handle_alpha()[*] has been - * called, the rows contents must be initialized to the contents of the - * screen. - * - * "row" holds the actual image, and pixels are placed in it - * as they arrive. If the image is displayed after each pass, it will - * appear to "sparkle" in. "display_row" can be used to display a - * "chunky" progressive image, with finer detail added as it becomes - * available. If you do not want this "chunky" display, you may pass - * NULL for display_row. If you do not want the sparkle display, and - * you have not called png_handle_alpha(), you may pass NULL for rows. - * If you have called png_handle_alpha(), and the image has either an - * alpha channel or a transparency chunk, you must provide a buffer for - * rows. In this case, you do not have to provide a display_row buffer - * also, but you may. If the image is not interlaced, or if you have - * not called png_set_interlace_handling(), the display_row buffer will - * be ignored, so pass NULL to it. - * - * [*] png_handle_alpha() does not exist yet, as of this version of libpng - */ - -void PNGAPI -png_read_rows(png_structp png_ptr, png_bytepp row, - png_bytepp display_row, png_uint_32 num_rows) -{ - png_uint_32 i; - png_bytepp rp; - png_bytepp dp; - - png_debug(1, "in png_read_rows\n"); - if(png_ptr == NULL) return; - rp = row; - dp = display_row; - if (rp != NULL && dp != NULL) - for (i = 0; i < num_rows; i++) - { - png_bytep rptr = *rp++; - png_bytep dptr = *dp++; - - png_read_row(png_ptr, rptr, dptr); - } - else if(rp != NULL) - for (i = 0; i < num_rows; i++) - { - png_bytep rptr = *rp; - png_read_row(png_ptr, rptr, png_bytep_NULL); - rp++; - } - else if(dp != NULL) - for (i = 0; i < num_rows; i++) - { - png_bytep dptr = *dp; - png_read_row(png_ptr, png_bytep_NULL, dptr); - dp++; - } -} -#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ - -#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED -/* Read the entire image. If the image has an alpha channel or a tRNS - * chunk, and you have called png_handle_alpha()[*], you will need to - * initialize the image to the current image that PNG will be overlaying. - * We set the num_rows again here, in case it was incorrectly set in - * png_read_start_row() by a call to png_read_update_info() or - * png_start_read_image() if png_set_interlace_handling() wasn't called - * prior to either of these functions like it should have been. You can - * only call this function once. If you desire to have an image for - * each pass of a interlaced image, use png_read_rows() instead. - * - * [*] png_handle_alpha() does not exist yet, as of this version of libpng - */ -void PNGAPI -png_read_image(png_structp png_ptr, png_bytepp image) -{ - png_uint_32 i,image_height; - int pass, j; - png_bytepp rp; - - png_debug(1, "in png_read_image\n"); - if(png_ptr == NULL) return; - -#ifdef PNG_READ_INTERLACING_SUPPORTED - pass = png_set_interlace_handling(png_ptr); -#else - if (png_ptr->interlaced) - png_error(png_ptr, - "Cannot read interlaced image -- interlace handler disabled."); - pass = 1; -#endif - - - image_height=png_ptr->height; - png_ptr->num_rows = image_height; /* Make sure this is set correctly */ - - for (j = 0; j < pass; j++) - { - rp = image; - for (i = 0; i < image_height; i++) - { - png_read_row(png_ptr, *rp, png_bytep_NULL); - rp++; - } - } -} -#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ - -#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED -/* Read the end of the PNG file. Will not read past the end of the - * file, will verify the end is accurate, and will read any comments - * or time information at the end of the file, if info is not NULL. - */ -void PNGAPI -png_read_end(png_structp png_ptr, png_infop info_ptr) -{ - png_byte chunk_length[4]; - png_uint_32 length; - - png_debug(1, "in png_read_end\n"); - if(png_ptr == NULL) return; - png_crc_finish(png_ptr, 0); /* Finish off CRC from last IDAT chunk */ - - do - { -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_CONST PNG_IHDR; - PNG_CONST PNG_IDAT; - PNG_CONST PNG_IEND; - PNG_CONST PNG_PLTE; -#if defined(PNG_READ_bKGD_SUPPORTED) - PNG_CONST PNG_bKGD; -#endif -#if defined(PNG_READ_cHRM_SUPPORTED) - PNG_CONST PNG_cHRM; -#endif -#if defined(PNG_READ_gAMA_SUPPORTED) - PNG_CONST PNG_gAMA; -#endif -#if defined(PNG_READ_hIST_SUPPORTED) - PNG_CONST PNG_hIST; -#endif -#if defined(PNG_READ_iCCP_SUPPORTED) - PNG_CONST PNG_iCCP; -#endif -#if defined(PNG_READ_iTXt_SUPPORTED) - PNG_CONST PNG_iTXt; -#endif -#if defined(PNG_READ_oFFs_SUPPORTED) - PNG_CONST PNG_oFFs; -#endif -#if defined(PNG_READ_pCAL_SUPPORTED) - PNG_CONST PNG_pCAL; -#endif -#if defined(PNG_READ_pHYs_SUPPORTED) - PNG_CONST PNG_pHYs; -#endif -#if defined(PNG_READ_sBIT_SUPPORTED) - PNG_CONST PNG_sBIT; -#endif -#if defined(PNG_READ_sCAL_SUPPORTED) - PNG_CONST PNG_sCAL; -#endif -#if defined(PNG_READ_sPLT_SUPPORTED) - PNG_CONST PNG_sPLT; -#endif -#if defined(PNG_READ_sRGB_SUPPORTED) - PNG_CONST PNG_sRGB; -#endif -#if defined(PNG_READ_tEXt_SUPPORTED) - PNG_CONST PNG_tEXt; -#endif -#if defined(PNG_READ_tIME_SUPPORTED) - PNG_CONST PNG_tIME; -#endif -#if defined(PNG_READ_tRNS_SUPPORTED) - PNG_CONST PNG_tRNS; -#endif -#if defined(PNG_READ_zTXt_SUPPORTED) - PNG_CONST PNG_zTXt; -#endif -#endif /* PNG_USE_LOCAL_ARRAYS */ - - png_read_data(png_ptr, chunk_length, 4); - length = png_get_uint_31(png_ptr,chunk_length); - - png_reset_crc(png_ptr); - png_crc_read(png_ptr, png_ptr->chunk_name, 4); - - png_debug1(0, "Reading %s chunk.\n", png_ptr->chunk_name); - - if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4)) - png_handle_IHDR(png_ptr, info_ptr, length); - else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4)) - png_handle_IEND(png_ptr, info_ptr, length); -#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED - else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name)) - { - if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) - { - if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) - png_error(png_ptr, "Too many IDAT's found"); - } - png_handle_unknown(png_ptr, info_ptr, length); - if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) - png_ptr->mode |= PNG_HAVE_PLTE; - } -#endif - else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) - { - /* Zero length IDATs are legal after the last IDAT has been - * read, but not after other chunks have been read. - */ - if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) - png_error(png_ptr, "Too many IDAT's found"); - png_crc_finish(png_ptr, length); - } - else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) - png_handle_PLTE(png_ptr, info_ptr, length); -#if defined(PNG_READ_bKGD_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4)) - png_handle_bKGD(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_cHRM_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4)) - png_handle_cHRM(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_gAMA_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4)) - png_handle_gAMA(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_hIST_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4)) - png_handle_hIST(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_oFFs_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4)) - png_handle_oFFs(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_pCAL_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4)) - png_handle_pCAL(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_sCAL_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4)) - png_handle_sCAL(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_pHYs_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4)) - png_handle_pHYs(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_sBIT_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4)) - png_handle_sBIT(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_sRGB_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4)) - png_handle_sRGB(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_iCCP_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4)) - png_handle_iCCP(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_sPLT_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4)) - png_handle_sPLT(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_tEXt_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4)) - png_handle_tEXt(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_tIME_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4)) - png_handle_tIME(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_tRNS_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4)) - png_handle_tRNS(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_zTXt_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4)) - png_handle_zTXt(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_iTXt_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4)) - png_handle_iTXt(png_ptr, info_ptr, length); -#endif - else - png_handle_unknown(png_ptr, info_ptr, length); - } while (!(png_ptr->mode & PNG_HAVE_IEND)); -} -#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ - -/* free all memory used by the read */ -void PNGAPI -png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr, - png_infopp end_info_ptr_ptr) -{ - png_structp png_ptr = NULL; - png_infop info_ptr = NULL, end_info_ptr = NULL; -#ifdef PNG_USER_MEM_SUPPORTED - png_free_ptr free_fn; - png_voidp mem_ptr; -#endif - - png_debug(1, "in png_destroy_read_struct\n"); - if (png_ptr_ptr != NULL) - png_ptr = *png_ptr_ptr; - - if (info_ptr_ptr != NULL) - info_ptr = *info_ptr_ptr; - - if (end_info_ptr_ptr != NULL) - end_info_ptr = *end_info_ptr_ptr; - -#ifdef PNG_USER_MEM_SUPPORTED - free_fn = png_ptr->free_fn; - mem_ptr = png_ptr->mem_ptr; -#endif - - png_read_destroy(png_ptr, info_ptr, end_info_ptr); - - if (info_ptr != NULL) - { -#if defined(PNG_TEXT_SUPPORTED) - png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, -1); -#endif - -#ifdef PNG_USER_MEM_SUPPORTED - png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn, - (png_voidp)mem_ptr); -#else - png_destroy_struct((png_voidp)info_ptr); -#endif - *info_ptr_ptr = NULL; - } - - if (end_info_ptr != NULL) - { -#if defined(PNG_READ_TEXT_SUPPORTED) - png_free_data(png_ptr, end_info_ptr, PNG_FREE_TEXT, -1); -#endif -#ifdef PNG_USER_MEM_SUPPORTED - png_destroy_struct_2((png_voidp)end_info_ptr, (png_free_ptr)free_fn, - (png_voidp)mem_ptr); -#else - png_destroy_struct((png_voidp)end_info_ptr); -#endif - *end_info_ptr_ptr = NULL; - } - - if (png_ptr != NULL) - { -#ifdef PNG_USER_MEM_SUPPORTED - png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn, - (png_voidp)mem_ptr); -#else - png_destroy_struct((png_voidp)png_ptr); -#endif - *png_ptr_ptr = NULL; - } -} - -/* free all memory used by the read (old method) */ -void /* PRIVATE */ -png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_infop end_info_ptr) -{ -#ifdef PNG_SETJMP_SUPPORTED - jmp_buf tmp_jmp; -#endif - png_error_ptr error_fn; - png_error_ptr warning_fn; - png_voidp error_ptr; -#ifdef PNG_USER_MEM_SUPPORTED - png_free_ptr free_fn; -#endif - - png_debug(1, "in png_read_destroy\n"); - if (info_ptr != NULL) - png_info_destroy(png_ptr, info_ptr); - - if (end_info_ptr != NULL) - png_info_destroy(png_ptr, end_info_ptr); - - png_free(png_ptr, png_ptr->zbuf); - png_free(png_ptr, png_ptr->big_row_buf); - png_free(png_ptr, png_ptr->prev_row); -#if defined(PNG_READ_DITHER_SUPPORTED) - png_free(png_ptr, png_ptr->palette_lookup); - png_free(png_ptr, png_ptr->dither_index); -#endif -#if defined(PNG_READ_GAMMA_SUPPORTED) - png_free(png_ptr, png_ptr->gamma_table); -#endif -#if defined(PNG_READ_BACKGROUND_SUPPORTED) - png_free(png_ptr, png_ptr->gamma_from_1); - png_free(png_ptr, png_ptr->gamma_to_1); -#endif -#ifdef PNG_FREE_ME_SUPPORTED - if (png_ptr->free_me & PNG_FREE_PLTE) - png_zfree(png_ptr, png_ptr->palette); - png_ptr->free_me &= ~PNG_FREE_PLTE; -#else - if (png_ptr->flags & PNG_FLAG_FREE_PLTE) - png_zfree(png_ptr, png_ptr->palette); - png_ptr->flags &= ~PNG_FLAG_FREE_PLTE; -#endif -#if defined(PNG_tRNS_SUPPORTED) || \ - defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) -#ifdef PNG_FREE_ME_SUPPORTED - if (png_ptr->free_me & PNG_FREE_TRNS) - png_free(png_ptr, png_ptr->trans); - png_ptr->free_me &= ~PNG_FREE_TRNS; -#else - if (png_ptr->flags & PNG_FLAG_FREE_TRNS) - png_free(png_ptr, png_ptr->trans); - png_ptr->flags &= ~PNG_FLAG_FREE_TRNS; -#endif -#endif -#if defined(PNG_READ_hIST_SUPPORTED) -#ifdef PNG_FREE_ME_SUPPORTED - if (png_ptr->free_me & PNG_FREE_HIST) - png_free(png_ptr, png_ptr->hist); - png_ptr->free_me &= ~PNG_FREE_HIST; -#else - if (png_ptr->flags & PNG_FLAG_FREE_HIST) - png_free(png_ptr, png_ptr->hist); - png_ptr->flags &= ~PNG_FLAG_FREE_HIST; -#endif -#endif -#if defined(PNG_READ_GAMMA_SUPPORTED) - if (png_ptr->gamma_16_table != NULL) - { - int i; - int istop = (1 << (8 - png_ptr->gamma_shift)); - for (i = 0; i < istop; i++) - { - png_free(png_ptr, png_ptr->gamma_16_table[i]); - } - png_free(png_ptr, png_ptr->gamma_16_table); - } -#if defined(PNG_READ_BACKGROUND_SUPPORTED) - if (png_ptr->gamma_16_from_1 != NULL) - { - int i; - int istop = (1 << (8 - png_ptr->gamma_shift)); - for (i = 0; i < istop; i++) - { - png_free(png_ptr, png_ptr->gamma_16_from_1[i]); - } - png_free(png_ptr, png_ptr->gamma_16_from_1); - } - if (png_ptr->gamma_16_to_1 != NULL) - { - int i; - int istop = (1 << (8 - png_ptr->gamma_shift)); - for (i = 0; i < istop; i++) - { - png_free(png_ptr, png_ptr->gamma_16_to_1[i]); - } - png_free(png_ptr, png_ptr->gamma_16_to_1); - } -#endif -#endif -#if defined(PNG_TIME_RFC1123_SUPPORTED) - png_free(png_ptr, png_ptr->time_buffer); -#endif - - inflateEnd(&png_ptr->zstream); -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED - png_free(png_ptr, png_ptr->save_buffer); -#endif - -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED -#ifdef PNG_TEXT_SUPPORTED - png_free(png_ptr, png_ptr->current_text); -#endif /* PNG_TEXT_SUPPORTED */ -#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ - - /* Save the important info out of the png_struct, in case it is - * being used again. - */ -#ifdef PNG_SETJMP_SUPPORTED - png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof (jmp_buf)); -#endif - - error_fn = png_ptr->error_fn; - warning_fn = png_ptr->warning_fn; - error_ptr = png_ptr->error_ptr; -#ifdef PNG_USER_MEM_SUPPORTED - free_fn = png_ptr->free_fn; -#endif - - png_memset(png_ptr, 0, png_sizeof (png_struct)); - - png_ptr->error_fn = error_fn; - png_ptr->warning_fn = warning_fn; - png_ptr->error_ptr = error_ptr; -#ifdef PNG_USER_MEM_SUPPORTED - png_ptr->free_fn = free_fn; -#endif - -#ifdef PNG_SETJMP_SUPPORTED - png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof (jmp_buf)); -#endif - -} - -void PNGAPI -png_set_read_status_fn(png_structp png_ptr, png_read_status_ptr read_row_fn) -{ - if(png_ptr == NULL) return; - png_ptr->read_row_fn = read_row_fn; -} - - -#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED -#if defined(PNG_INFO_IMAGE_SUPPORTED) -void PNGAPI -png_read_png(png_structp png_ptr, png_infop info_ptr, - int transforms, - voidp params) -{ - int row; - - if(png_ptr == NULL) return; -#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) - /* invert the alpha channel from opacity to transparency - */ - if (transforms & PNG_TRANSFORM_INVERT_ALPHA) - png_set_invert_alpha(png_ptr); -#endif - - /* png_read_info() gives us all of the information from the - * PNG file before the first IDAT (image data chunk). - */ - png_read_info(png_ptr, info_ptr); - if (info_ptr->height > PNG_UINT_32_MAX/png_sizeof(png_bytep)) - png_error(png_ptr,"Image is too high to process with png_read_png()"); - - /* -------------- image transformations start here ------------------- */ - -#if defined(PNG_READ_16_TO_8_SUPPORTED) - /* tell libpng to strip 16 bit/color files down to 8 bits per color - */ - if (transforms & PNG_TRANSFORM_STRIP_16) - png_set_strip_16(png_ptr); -#endif - -#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) - /* Strip alpha bytes from the input data without combining with - * the background (not recommended). - */ - if (transforms & PNG_TRANSFORM_STRIP_ALPHA) - png_set_strip_alpha(png_ptr); -#endif - -#if defined(PNG_READ_PACK_SUPPORTED) && !defined(PNG_READ_EXPAND_SUPPORTED) - /* Extract multiple pixels with bit depths of 1, 2, or 4 from a single - * byte into separate bytes (useful for paletted and grayscale images). - */ - if (transforms & PNG_TRANSFORM_PACKING) - png_set_packing(png_ptr); -#endif - -#if defined(PNG_READ_PACKSWAP_SUPPORTED) - /* Change the order of packed pixels to least significant bit first - * (not useful if you are using png_set_packing). - */ - if (transforms & PNG_TRANSFORM_PACKSWAP) - png_set_packswap(png_ptr); -#endif - -#if defined(PNG_READ_EXPAND_SUPPORTED) - /* Expand paletted colors into true RGB triplets - * Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel - * Expand paletted or RGB images with transparency to full alpha - * channels so the data will be available as RGBA quartets. - */ - if (transforms & PNG_TRANSFORM_EXPAND) - if ((png_ptr->bit_depth < 8) || - (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) || - (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))) - png_set_expand(png_ptr); -#endif - - /* We don't handle background color or gamma transformation or dithering. - */ - -#if defined(PNG_READ_INVERT_SUPPORTED) - /* invert monochrome files to have 0 as white and 1 as black - */ - if (transforms & PNG_TRANSFORM_INVERT_MONO) - png_set_invert_mono(png_ptr); -#endif - -#if defined(PNG_READ_SHIFT_SUPPORTED) - /* If you want to shift the pixel values from the range [0,255] or - * [0,65535] to the original [0,7] or [0,31], or whatever range the - * colors were originally in: - */ - if ((transforms & PNG_TRANSFORM_SHIFT) - && png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT)) - { - png_color_8p sig_bit; - - png_get_sBIT(png_ptr, info_ptr, &sig_bit); - png_set_shift(png_ptr, sig_bit); - } -#endif - -#if defined(PNG_READ_BGR_SUPPORTED) - /* flip the RGB pixels to BGR (or RGBA to BGRA) - */ - if (transforms & PNG_TRANSFORM_BGR) - png_set_bgr(png_ptr); -#endif - -#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) - /* swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) - */ - if (transforms & PNG_TRANSFORM_SWAP_ALPHA) - png_set_swap_alpha(png_ptr); -#endif - -#if defined(PNG_READ_SWAP_SUPPORTED) - /* swap bytes of 16 bit files to least significant byte first - */ - if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) - png_set_swap(png_ptr); -#endif - - /* We don't handle adding filler bytes */ - - /* Optional call to gamma correct and add the background to the palette - * and update info structure. REQUIRED if you are expecting libpng to - * update the palette for you (i.e., you selected such a transform above). - */ - png_read_update_info(png_ptr, info_ptr); - - /* -------------- image transformations end here ------------------- */ - -#ifdef PNG_FREE_ME_SUPPORTED - png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); -#endif - if(info_ptr->row_pointers == NULL) - { - info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr, - info_ptr->height * png_sizeof(png_bytep)); -#ifdef PNG_FREE_ME_SUPPORTED - info_ptr->free_me |= PNG_FREE_ROWS; -#endif - for (row = 0; row < (int)info_ptr->height; row++) - { - info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr, - png_get_rowbytes(png_ptr, info_ptr)); - } - } - - png_read_image(png_ptr, info_ptr->row_pointers); - info_ptr->valid |= PNG_INFO_IDAT; - - /* read rest of file, and get additional chunks in info_ptr - REQUIRED */ - png_read_end(png_ptr, info_ptr); - - transforms = transforms; /* quiet compiler warnings */ - params = params; - -} -#endif /* PNG_INFO_IMAGE_SUPPORTED */ -#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ -#endif /* PNG_READ_SUPPORTED */ diff --git a/uppdev/plugin/png/lib/pngrio.c b/uppdev/plugin/png/lib/pngrio.c deleted file mode 100644 index 22756832d..000000000 --- a/uppdev/plugin/png/lib/pngrio.c +++ /dev/null @@ -1,167 +0,0 @@ - -/* pngrio.c - functions for data input - * - * Last changed in libpng 1.2.13 November 13, 2006 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2006 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This file provides a location for all input. Users who need - * special handling are expected to write a function that has the same - * arguments as this and performs a similar function, but that possibly - * has a different input method. Note that you shouldn't change this - * function, but rather write a replacement function and then make - * libpng use it at run time with png_set_read_fn(...). - */ - -#define PNG_INTERNAL -#include "png.h" - -#if defined(PNG_READ_SUPPORTED) - -/* Read the data from whatever input you are using. The default routine - reads from a file pointer. Note that this routine sometimes gets called - with very small lengths, so you should implement some kind of simple - buffering if you are using unbuffered reads. This should never be asked - to read more then 64K on a 16 bit machine. */ -void /* PRIVATE */ -png_read_data(png_structp png_ptr, png_bytep data, png_size_t length) -{ - png_debug1(4,"reading %d bytes\n", (int)length); - if (png_ptr->read_data_fn != NULL) - (*(png_ptr->read_data_fn))(png_ptr, data, length); - else - png_error(png_ptr, "Call to NULL read function"); -} - -#if !defined(PNG_NO_STDIO) -/* This is the function that does the actual reading of data. If you are - not reading from a standard C stream, you should create a replacement - read_data function and use it at run time with png_set_read_fn(), rather - than changing the library. */ -#ifndef USE_FAR_KEYWORD -void PNGAPI -png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) -{ - png_size_t check; - - if(png_ptr == NULL) return; - /* fread() returns 0 on error, so it is OK to store this in a png_size_t - * instead of an int, which is what fread() actually returns. - */ -#if defined(_WIN32_WCE) - if ( !ReadFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) ) - check = 0; -#else - check = (png_size_t)fread(data, (png_size_t)1, length, - (png_FILE_p)png_ptr->io_ptr); -#endif - - if (check != length) - png_error(png_ptr, "Read Error"); -} -#else -/* this is the model-independent version. Since the standard I/O library - can't handle far buffers in the medium and small models, we have to copy - the data. -*/ - -#define NEAR_BUF_SIZE 1024 -#define MIN(a,b) (a <= b ? a : b) - -static void PNGAPI -png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) -{ - int check; - png_byte *n_data; - png_FILE_p io_ptr; - - if(png_ptr == NULL) return; - /* Check if data really is near. If so, use usual code. */ - n_data = (png_byte *)CVT_PTR_NOCHECK(data); - io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); - if ((png_bytep)n_data == data) - { -#if defined(_WIN32_WCE) - if ( !ReadFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) ) - check = 0; -#else - check = fread(n_data, 1, length, io_ptr); -#endif - } - else - { - png_byte buf[NEAR_BUF_SIZE]; - png_size_t read, remaining, err; - check = 0; - remaining = length; - do - { - read = MIN(NEAR_BUF_SIZE, remaining); -#if defined(_WIN32_WCE) - if ( !ReadFile((HANDLE)(io_ptr), buf, read, &err, NULL) ) - err = 0; -#else - err = fread(buf, (png_size_t)1, read, io_ptr); -#endif - png_memcpy(data, buf, read); /* copy far buffer to near buffer */ - if(err != read) - break; - else - check += err; - data += read; - remaining -= read; - } - while (remaining != 0); - } - if ((png_uint_32)check != (png_uint_32)length) - png_error(png_ptr, "read Error"); -} -#endif -#endif - -/* This function allows the application to supply a new input function - for libpng if standard C streams aren't being used. - - This function takes as its arguments: - png_ptr - pointer to a png input data structure - io_ptr - pointer to user supplied structure containing info about - the input functions. May be NULL. - read_data_fn - pointer to a new input function that takes as its - arguments a pointer to a png_struct, a pointer to - a location where input data can be stored, and a 32-bit - unsigned int that is the number of bytes to be read. - To exit and output any fatal error messages the new write - function should call png_error(png_ptr, "Error msg"). */ -void PNGAPI -png_set_read_fn(png_structp png_ptr, png_voidp io_ptr, - png_rw_ptr read_data_fn) -{ - if(png_ptr == NULL) return; - png_ptr->io_ptr = io_ptr; - -#if !defined(PNG_NO_STDIO) - if (read_data_fn != NULL) - png_ptr->read_data_fn = read_data_fn; - else - png_ptr->read_data_fn = png_default_read_data; -#else - png_ptr->read_data_fn = read_data_fn; -#endif - - /* It is an error to write to a read device */ - if (png_ptr->write_data_fn != NULL) - { - png_ptr->write_data_fn = NULL; - png_warning(png_ptr, - "It's an error to set both read_data_fn and write_data_fn in the "); - png_warning(png_ptr, - "same structure. Resetting write_data_fn to NULL."); - } - -#if defined(PNG_WRITE_FLUSH_SUPPORTED) - png_ptr->output_flush_fn = NULL; -#endif -} -#endif /* PNG_READ_SUPPORTED */ diff --git a/uppdev/plugin/png/lib/pngrtran.c b/uppdev/plugin/png/lib/pngrtran.c deleted file mode 100644 index 66820dfae..000000000 --- a/uppdev/plugin/png/lib/pngrtran.c +++ /dev/null @@ -1,4284 +0,0 @@ - -/* pngrtran.c - transforms the data in a row for PNG readers - * - * Last changed in libpng 1.2.22 [October 13, 2007] - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2007 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This file contains functions optionally called by an application - * in order to tell libpng how to handle data when reading a PNG. - * Transformations that are used in both reading and writing are - * in pngtrans.c. - */ - -#define PNG_INTERNAL -#include "png.h" - -#if defined(PNG_READ_SUPPORTED) - -/* Set the action on getting a CRC error for an ancillary or critical chunk. */ -void PNGAPI -png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action) -{ - png_debug(1, "in png_set_crc_action\n"); - /* Tell libpng how we react to CRC errors in critical chunks */ - if(png_ptr == NULL) return; - switch (crit_action) - { - case PNG_CRC_NO_CHANGE: /* leave setting as is */ - break; - case PNG_CRC_WARN_USE: /* warn/use data */ - png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; - png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE; - break; - case PNG_CRC_QUIET_USE: /* quiet/use data */ - png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; - png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE | - PNG_FLAG_CRC_CRITICAL_IGNORE; - break; - case PNG_CRC_WARN_DISCARD: /* not a valid action for critical data */ - png_warning(png_ptr, "Can't discard critical data on CRC error."); - case PNG_CRC_ERROR_QUIT: /* error/quit */ - case PNG_CRC_DEFAULT: - default: - png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; - break; - } - - switch (ancil_action) - { - case PNG_CRC_NO_CHANGE: /* leave setting as is */ - break; - case PNG_CRC_WARN_USE: /* warn/use data */ - png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; - png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE; - break; - case PNG_CRC_QUIET_USE: /* quiet/use data */ - png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; - png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE | - PNG_FLAG_CRC_ANCILLARY_NOWARN; - break; - case PNG_CRC_ERROR_QUIT: /* error/quit */ - png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; - png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN; - break; - case PNG_CRC_WARN_DISCARD: /* warn/discard data */ - case PNG_CRC_DEFAULT: - default: - png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; - break; - } -} - -#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ - defined(PNG_FLOATING_POINT_SUPPORTED) -/* handle alpha and tRNS via a background color */ -void PNGAPI -png_set_background(png_structp png_ptr, - png_color_16p background_color, int background_gamma_code, - int need_expand, double background_gamma) -{ - png_debug(1, "in png_set_background\n"); - if(png_ptr == NULL) return; - if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN) - { - png_warning(png_ptr, "Application must supply a known background gamma"); - return; - } - - png_ptr->transformations |= PNG_BACKGROUND; - png_memcpy(&(png_ptr->background), background_color, - png_sizeof(png_color_16)); - png_ptr->background_gamma = (float)background_gamma; - png_ptr->background_gamma_type = (png_byte)(background_gamma_code); - png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0); -} -#endif - -#if defined(PNG_READ_16_TO_8_SUPPORTED) -/* strip 16 bit depth files to 8 bit depth */ -void PNGAPI -png_set_strip_16(png_structp png_ptr) -{ - png_debug(1, "in png_set_strip_16\n"); - if(png_ptr == NULL) return; - png_ptr->transformations |= PNG_16_TO_8; -} -#endif - -#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) -void PNGAPI -png_set_strip_alpha(png_structp png_ptr) -{ - png_debug(1, "in png_set_strip_alpha\n"); - if(png_ptr == NULL) return; - png_ptr->flags |= PNG_FLAG_STRIP_ALPHA; -} -#endif - -#if defined(PNG_READ_DITHER_SUPPORTED) -/* Dither file to 8 bit. Supply a palette, the current number - * of elements in the palette, the maximum number of elements - * allowed, and a histogram if possible. If the current number - * of colors is greater then the maximum number, the palette will be - * modified to fit in the maximum number. "full_dither" indicates - * whether we need a dithering cube set up for RGB images, or if we - * simply are reducing the number of colors in a paletted image. - */ - -typedef struct png_dsort_struct -{ - struct png_dsort_struct FAR * next; - png_byte left; - png_byte right; -} png_dsort; -typedef png_dsort FAR * png_dsortp; -typedef png_dsort FAR * FAR * png_dsortpp; - -void PNGAPI -png_set_dither(png_structp png_ptr, png_colorp palette, - int num_palette, int maximum_colors, png_uint_16p histogram, - int full_dither) -{ - png_debug(1, "in png_set_dither\n"); - if(png_ptr == NULL) return; - png_ptr->transformations |= PNG_DITHER; - - if (!full_dither) - { - int i; - - png_ptr->dither_index = (png_bytep)png_malloc(png_ptr, - (png_uint_32)(num_palette * png_sizeof (png_byte))); - for (i = 0; i < num_palette; i++) - png_ptr->dither_index[i] = (png_byte)i; - } - - if (num_palette > maximum_colors) - { - if (histogram != NULL) - { - /* This is easy enough, just throw out the least used colors. - Perhaps not the best solution, but good enough. */ - - int i; - - /* initialize an array to sort colors */ - png_ptr->dither_sort = (png_bytep)png_malloc(png_ptr, - (png_uint_32)(num_palette * png_sizeof (png_byte))); - - /* initialize the dither_sort array */ - for (i = 0; i < num_palette; i++) - png_ptr->dither_sort[i] = (png_byte)i; - - /* Find the least used palette entries by starting a - bubble sort, and running it until we have sorted - out enough colors. Note that we don't care about - sorting all the colors, just finding which are - least used. */ - - for (i = num_palette - 1; i >= maximum_colors; i--) - { - int done; /* to stop early if the list is pre-sorted */ - int j; - - done = 1; - for (j = 0; j < i; j++) - { - if (histogram[png_ptr->dither_sort[j]] - < histogram[png_ptr->dither_sort[j + 1]]) - { - png_byte t; - - t = png_ptr->dither_sort[j]; - png_ptr->dither_sort[j] = png_ptr->dither_sort[j + 1]; - png_ptr->dither_sort[j + 1] = t; - done = 0; - } - } - if (done) - break; - } - - /* swap the palette around, and set up a table, if necessary */ - if (full_dither) - { - int j = num_palette; - - /* put all the useful colors within the max, but don't - move the others */ - for (i = 0; i < maximum_colors; i++) - { - if ((int)png_ptr->dither_sort[i] >= maximum_colors) - { - do - j--; - while ((int)png_ptr->dither_sort[j] >= maximum_colors); - palette[i] = palette[j]; - } - } - } - else - { - int j = num_palette; - - /* move all the used colors inside the max limit, and - develop a translation table */ - for (i = 0; i < maximum_colors; i++) - { - /* only move the colors we need to */ - if ((int)png_ptr->dither_sort[i] >= maximum_colors) - { - png_color tmp_color; - - do - j--; - while ((int)png_ptr->dither_sort[j] >= maximum_colors); - - tmp_color = palette[j]; - palette[j] = palette[i]; - palette[i] = tmp_color; - /* indicate where the color went */ - png_ptr->dither_index[j] = (png_byte)i; - png_ptr->dither_index[i] = (png_byte)j; - } - } - - /* find closest color for those colors we are not using */ - for (i = 0; i < num_palette; i++) - { - if ((int)png_ptr->dither_index[i] >= maximum_colors) - { - int min_d, k, min_k, d_index; - - /* find the closest color to one we threw out */ - d_index = png_ptr->dither_index[i]; - min_d = PNG_COLOR_DIST(palette[d_index], palette[0]); - for (k = 1, min_k = 0; k < maximum_colors; k++) - { - int d; - - d = PNG_COLOR_DIST(palette[d_index], palette[k]); - - if (d < min_d) - { - min_d = d; - min_k = k; - } - } - /* point to closest color */ - png_ptr->dither_index[i] = (png_byte)min_k; - } - } - } - png_free(png_ptr, png_ptr->dither_sort); - png_ptr->dither_sort=NULL; - } - else - { - /* This is much harder to do simply (and quickly). Perhaps - we need to go through a median cut routine, but those - don't always behave themselves with only a few colors - as input. So we will just find the closest two colors, - and throw out one of them (chosen somewhat randomly). - [We don't understand this at all, so if someone wants to - work on improving it, be our guest - AED, GRP] - */ - int i; - int max_d; - int num_new_palette; - png_dsortp t; - png_dsortpp hash; - - t=NULL; - - /* initialize palette index arrays */ - png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr, - (png_uint_32)(num_palette * png_sizeof (png_byte))); - png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr, - (png_uint_32)(num_palette * png_sizeof (png_byte))); - - /* initialize the sort array */ - for (i = 0; i < num_palette; i++) - { - png_ptr->index_to_palette[i] = (png_byte)i; - png_ptr->palette_to_index[i] = (png_byte)i; - } - - hash = (png_dsortpp)png_malloc(png_ptr, (png_uint_32)(769 * - png_sizeof (png_dsortp))); - for (i = 0; i < 769; i++) - hash[i] = NULL; -/* png_memset(hash, 0, 769 * png_sizeof (png_dsortp)); */ - - num_new_palette = num_palette; - - /* initial wild guess at how far apart the farthest pixel - pair we will be eliminating will be. Larger - numbers mean more areas will be allocated, Smaller - numbers run the risk of not saving enough data, and - having to do this all over again. - - I have not done extensive checking on this number. - */ - max_d = 96; - - while (num_new_palette > maximum_colors) - { - for (i = 0; i < num_new_palette - 1; i++) - { - int j; - - for (j = i + 1; j < num_new_palette; j++) - { - int d; - - d = PNG_COLOR_DIST(palette[i], palette[j]); - - if (d <= max_d) - { - - t = (png_dsortp)png_malloc_warn(png_ptr, - (png_uint_32)(png_sizeof(png_dsort))); - if (t == NULL) - break; - t->next = hash[d]; - t->left = (png_byte)i; - t->right = (png_byte)j; - hash[d] = t; - } - } - if (t == NULL) - break; - } - - if (t != NULL) - for (i = 0; i <= max_d; i++) - { - if (hash[i] != NULL) - { - png_dsortp p; - - for (p = hash[i]; p; p = p->next) - { - if ((int)png_ptr->index_to_palette[p->left] - < num_new_palette && - (int)png_ptr->index_to_palette[p->right] - < num_new_palette) - { - int j, next_j; - - if (num_new_palette & 0x01) - { - j = p->left; - next_j = p->right; - } - else - { - j = p->right; - next_j = p->left; - } - - num_new_palette--; - palette[png_ptr->index_to_palette[j]] - = palette[num_new_palette]; - if (!full_dither) - { - int k; - - for (k = 0; k < num_palette; k++) - { - if (png_ptr->dither_index[k] == - png_ptr->index_to_palette[j]) - png_ptr->dither_index[k] = - png_ptr->index_to_palette[next_j]; - if ((int)png_ptr->dither_index[k] == - num_new_palette) - png_ptr->dither_index[k] = - png_ptr->index_to_palette[j]; - } - } - - png_ptr->index_to_palette[png_ptr->palette_to_index - [num_new_palette]] = png_ptr->index_to_palette[j]; - png_ptr->palette_to_index[png_ptr->index_to_palette[j]] - = png_ptr->palette_to_index[num_new_palette]; - - png_ptr->index_to_palette[j] = (png_byte)num_new_palette; - png_ptr->palette_to_index[num_new_palette] = (png_byte)j; - } - if (num_new_palette <= maximum_colors) - break; - } - if (num_new_palette <= maximum_colors) - break; - } - } - - for (i = 0; i < 769; i++) - { - if (hash[i] != NULL) - { - png_dsortp p = hash[i]; - while (p) - { - t = p->next; - png_free(png_ptr, p); - p = t; - } - } - hash[i] = 0; - } - max_d += 96; - } - png_free(png_ptr, hash); - png_free(png_ptr, png_ptr->palette_to_index); - png_free(png_ptr, png_ptr->index_to_palette); - png_ptr->palette_to_index=NULL; - png_ptr->index_to_palette=NULL; - } - num_palette = maximum_colors; - } - if (png_ptr->palette == NULL) - { - png_ptr->palette = palette; - } - png_ptr->num_palette = (png_uint_16)num_palette; - - if (full_dither) - { - int i; - png_bytep distance; - int total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS + - PNG_DITHER_BLUE_BITS; - int num_red = (1 << PNG_DITHER_RED_BITS); - int num_green = (1 << PNG_DITHER_GREEN_BITS); - int num_blue = (1 << PNG_DITHER_BLUE_BITS); - png_size_t num_entries = ((png_size_t)1 << total_bits); - - png_ptr->palette_lookup = (png_bytep )png_malloc(png_ptr, - (png_uint_32)(num_entries * png_sizeof (png_byte))); - - png_memset(png_ptr->palette_lookup, 0, num_entries * - png_sizeof (png_byte)); - - distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries * - png_sizeof(png_byte))); - - png_memset(distance, 0xff, num_entries * png_sizeof(png_byte)); - - for (i = 0; i < num_palette; i++) - { - int ir, ig, ib; - int r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS)); - int g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS)); - int b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS)); - - for (ir = 0; ir < num_red; ir++) - { - /* int dr = abs(ir - r); */ - int dr = ((ir > r) ? ir - r : r - ir); - int index_r = (ir << (PNG_DITHER_BLUE_BITS + PNG_DITHER_GREEN_BITS)); - - for (ig = 0; ig < num_green; ig++) - { - /* int dg = abs(ig - g); */ - int dg = ((ig > g) ? ig - g : g - ig); - int dt = dr + dg; - int dm = ((dr > dg) ? dr : dg); - int index_g = index_r | (ig << PNG_DITHER_BLUE_BITS); - - for (ib = 0; ib < num_blue; ib++) - { - int d_index = index_g | ib; - /* int db = abs(ib - b); */ - int db = ((ib > b) ? ib - b : b - ib); - int dmax = ((dm > db) ? dm : db); - int d = dmax + dt + db; - - if (d < (int)distance[d_index]) - { - distance[d_index] = (png_byte)d; - png_ptr->palette_lookup[d_index] = (png_byte)i; - } - } - } - } - } - - png_free(png_ptr, distance); - } -} -#endif - -#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) -/* Transform the image from the file_gamma to the screen_gamma. We - * only do transformations on images where the file_gamma and screen_gamma - * are not close reciprocals, otherwise it slows things down slightly, and - * also needlessly introduces small errors. - * - * We will turn off gamma transformation later if no semitransparent entries - * are present in the tRNS array for palette images. We can't do it here - * because we don't necessarily have the tRNS chunk yet. - */ -void PNGAPI -png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma) -{ - png_debug(1, "in png_set_gamma\n"); - if(png_ptr == NULL) return; - if ((fabs(scrn_gamma * file_gamma - 1.0) > PNG_GAMMA_THRESHOLD) || - (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) || - (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)) - png_ptr->transformations |= PNG_GAMMA; - png_ptr->gamma = (float)file_gamma; - png_ptr->screen_gamma = (float)scrn_gamma; -} -#endif - -#if defined(PNG_READ_EXPAND_SUPPORTED) -/* Expand paletted images to RGB, expand grayscale images of - * less than 8-bit depth to 8-bit depth, and expand tRNS chunks - * to alpha channels. - */ -void PNGAPI -png_set_expand(png_structp png_ptr) -{ - png_debug(1, "in png_set_expand\n"); - if(png_ptr == NULL) return; - png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); -#ifdef PNG_WARN_UNINITIALIZED_ROW - png_ptr->flags &= ~PNG_FLAG_ROW_INIT; -#endif -} - -/* GRR 19990627: the following three functions currently are identical - * to png_set_expand(). However, it is entirely reasonable that someone - * might wish to expand an indexed image to RGB but *not* expand a single, - * fully transparent palette entry to a full alpha channel--perhaps instead - * convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace - * the transparent color with a particular RGB value, or drop tRNS entirely. - * IOW, a future version of the library may make the transformations flag - * a bit more fine-grained, with separate bits for each of these three - * functions. - * - * More to the point, these functions make it obvious what libpng will be - * doing, whereas "expand" can (and does) mean any number of things. - * - * GRP 20060307: In libpng-1.4.0, png_set_gray_1_2_4_to_8() was modified - * to expand only the sample depth but not to expand the tRNS to alpha. - */ - -/* Expand paletted images to RGB. */ -void PNGAPI -png_set_palette_to_rgb(png_structp png_ptr) -{ - png_debug(1, "in png_set_palette_to_rgb\n"); - if(png_ptr == NULL) return; - png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); -#ifdef PNG_WARN_UNINITIALIZED_ROW - png_ptr->flags &= ~PNG_FLAG_ROW_INIT; -#endif -} - -#if !defined(PNG_1_0_X) -/* Expand grayscale images of less than 8-bit depth to 8 bits. */ -void PNGAPI -png_set_expand_gray_1_2_4_to_8(png_structp png_ptr) -{ - png_debug(1, "in png_set_expand_gray_1_2_4_to_8\n"); - if(png_ptr == NULL) return; - png_ptr->transformations |= PNG_EXPAND; -#ifdef PNG_WARN_UNINITIALIZED_ROW - png_ptr->flags &= ~PNG_FLAG_ROW_INIT; -#endif -} -#endif - -#if defined(PNG_1_0_X) || defined(PNG_1_2_X) -/* Expand grayscale images of less than 8-bit depth to 8 bits. */ -/* Deprecated as of libpng-1.2.9 */ -void PNGAPI -png_set_gray_1_2_4_to_8(png_structp png_ptr) -{ - png_debug(1, "in png_set_gray_1_2_4_to_8\n"); - if(png_ptr == NULL) return; - png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); -} -#endif - - -/* Expand tRNS chunks to alpha channels. */ -void PNGAPI -png_set_tRNS_to_alpha(png_structp png_ptr) -{ - png_debug(1, "in png_set_tRNS_to_alpha\n"); - png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); -#ifdef PNG_WARN_UNINITIALIZED_ROW - png_ptr->flags &= ~PNG_FLAG_ROW_INIT; -#endif -} -#endif /* defined(PNG_READ_EXPAND_SUPPORTED) */ - -#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) -void PNGAPI -png_set_gray_to_rgb(png_structp png_ptr) -{ - png_debug(1, "in png_set_gray_to_rgb\n"); - png_ptr->transformations |= PNG_GRAY_TO_RGB; -#ifdef PNG_WARN_UNINITIALIZED_ROW - png_ptr->flags &= ~PNG_FLAG_ROW_INIT; -#endif -} -#endif - -#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) -#if defined(PNG_FLOATING_POINT_SUPPORTED) -/* Convert a RGB image to a grayscale of the same width. This allows us, - * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image. - */ - -void PNGAPI -png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red, - double green) -{ - int red_fixed = (int)((float)red*100000.0 + 0.5); - int green_fixed = (int)((float)green*100000.0 + 0.5); - if(png_ptr == NULL) return; - png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed); -} -#endif - -void PNGAPI -png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action, - png_fixed_point red, png_fixed_point green) -{ - png_debug(1, "in png_set_rgb_to_gray\n"); - if(png_ptr == NULL) return; - switch(error_action) - { - case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY; - break; - case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN; - break; - case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR; - } - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) -#if defined(PNG_READ_EXPAND_SUPPORTED) - png_ptr->transformations |= PNG_EXPAND; -#else - { - png_warning(png_ptr, "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED."); - png_ptr->transformations &= ~PNG_RGB_TO_GRAY; - } -#endif - { - png_uint_16 red_int, green_int; - if(red < 0 || green < 0) - { - red_int = 6968; /* .212671 * 32768 + .5 */ - green_int = 23434; /* .715160 * 32768 + .5 */ - } - else if(red + green < 100000L) - { - red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L); - green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L); - } - else - { - png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients"); - red_int = 6968; - green_int = 23434; - } - png_ptr->rgb_to_gray_red_coeff = red_int; - png_ptr->rgb_to_gray_green_coeff = green_int; - png_ptr->rgb_to_gray_blue_coeff = (png_uint_16)(32768-red_int-green_int); - } -} -#endif - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_LEGACY_SUPPORTED) -void PNGAPI -png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr - read_user_transform_fn) -{ - png_debug(1, "in png_set_read_user_transform_fn\n"); - if(png_ptr == NULL) return; -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) - png_ptr->transformations |= PNG_USER_TRANSFORM; - png_ptr->read_user_transform_fn = read_user_transform_fn; -#endif -#ifdef PNG_LEGACY_SUPPORTED - if(read_user_transform_fn) - png_warning(png_ptr, - "This version of libpng does not support user transforms"); -#endif -} -#endif - -/* Initialize everything needed for the read. This includes modifying - * the palette. - */ -void /* PRIVATE */ -png_init_read_transformations(png_structp png_ptr) -{ - png_debug(1, "in png_init_read_transformations\n"); -#if defined(PNG_USELESS_TESTS_SUPPORTED) - if(png_ptr != NULL) -#endif - { -#if defined(PNG_READ_BACKGROUND_SUPPORTED) || defined(PNG_READ_SHIFT_SUPPORTED) \ - || defined(PNG_READ_GAMMA_SUPPORTED) - int color_type = png_ptr->color_type; -#endif - -#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) - -#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) - /* Detect gray background and attempt to enable optimization - * for gray --> RGB case */ - /* Note: if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or - * RGB_ALPHA (in which case need_expand is superfluous anyway), the - * background color might actually be gray yet not be flagged as such. - * This is not a problem for the current code, which uses - * PNG_BACKGROUND_IS_GRAY only to decide when to do the - * png_do_gray_to_rgb() transformation. - */ - if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && - !(color_type & PNG_COLOR_MASK_COLOR)) - { - png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; - } else if ((png_ptr->transformations & PNG_BACKGROUND) && - !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) && - (png_ptr->transformations & PNG_GRAY_TO_RGB) && - png_ptr->background.red == png_ptr->background.green && - png_ptr->background.red == png_ptr->background.blue) - { - png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; - png_ptr->background.gray = png_ptr->background.red; - } -#endif - - if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && - (png_ptr->transformations & PNG_EXPAND)) - { - if (!(color_type & PNG_COLOR_MASK_COLOR)) /* i.e., GRAY or GRAY_ALPHA */ - { - /* expand background and tRNS chunks */ - switch (png_ptr->bit_depth) - { - case 1: - png_ptr->background.gray *= (png_uint_16)0xff; - png_ptr->background.red = png_ptr->background.green - = png_ptr->background.blue = png_ptr->background.gray; - if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) - { - png_ptr->trans_values.gray *= (png_uint_16)0xff; - png_ptr->trans_values.red = png_ptr->trans_values.green - = png_ptr->trans_values.blue = png_ptr->trans_values.gray; - } - break; - case 2: - png_ptr->background.gray *= (png_uint_16)0x55; - png_ptr->background.red = png_ptr->background.green - = png_ptr->background.blue = png_ptr->background.gray; - if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) - { - png_ptr->trans_values.gray *= (png_uint_16)0x55; - png_ptr->trans_values.red = png_ptr->trans_values.green - = png_ptr->trans_values.blue = png_ptr->trans_values.gray; - } - break; - case 4: - png_ptr->background.gray *= (png_uint_16)0x11; - png_ptr->background.red = png_ptr->background.green - = png_ptr->background.blue = png_ptr->background.gray; - if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) - { - png_ptr->trans_values.gray *= (png_uint_16)0x11; - png_ptr->trans_values.red = png_ptr->trans_values.green - = png_ptr->trans_values.blue = png_ptr->trans_values.gray; - } - break; - case 8: - case 16: - png_ptr->background.red = png_ptr->background.green - = png_ptr->background.blue = png_ptr->background.gray; - break; - } - } - else if (color_type == PNG_COLOR_TYPE_PALETTE) - { - png_ptr->background.red = - png_ptr->palette[png_ptr->background.index].red; - png_ptr->background.green = - png_ptr->palette[png_ptr->background.index].green; - png_ptr->background.blue = - png_ptr->palette[png_ptr->background.index].blue; - -#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) - if (png_ptr->transformations & PNG_INVERT_ALPHA) - { -#if defined(PNG_READ_EXPAND_SUPPORTED) - if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) -#endif - { - /* invert the alpha channel (in tRNS) unless the pixels are - going to be expanded, in which case leave it for later */ - int i,istop; - istop=(int)png_ptr->num_trans; - for (i=0; itrans[i] = (png_byte)(255 - png_ptr->trans[i]); - } - } -#endif - - } - } -#endif - -#if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED) - png_ptr->background_1 = png_ptr->background; -#endif -#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) - - if ((color_type == PNG_COLOR_TYPE_PALETTE && png_ptr->num_trans != 0) - && (fabs(png_ptr->screen_gamma * png_ptr->gamma - 1.0) - < PNG_GAMMA_THRESHOLD)) - { - int i,k; - k=0; - for (i=0; inum_trans; i++) - { - if (png_ptr->trans[i] != 0 && png_ptr->trans[i] != 0xff) - k=1; /* partial transparency is present */ - } - if (k == 0) - png_ptr->transformations &= ~PNG_GAMMA; - } - - if ((png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY)) && - png_ptr->gamma != 0.0) - { - png_build_gamma_table(png_ptr); -#if defined(PNG_READ_BACKGROUND_SUPPORTED) - if (png_ptr->transformations & PNG_BACKGROUND) - { - if (color_type == PNG_COLOR_TYPE_PALETTE) - { - /* could skip if no transparency and - */ - png_color back, back_1; - png_colorp palette = png_ptr->palette; - int num_palette = png_ptr->num_palette; - int i; - if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE) - { - back.red = png_ptr->gamma_table[png_ptr->background.red]; - back.green = png_ptr->gamma_table[png_ptr->background.green]; - back.blue = png_ptr->gamma_table[png_ptr->background.blue]; - - back_1.red = png_ptr->gamma_to_1[png_ptr->background.red]; - back_1.green = png_ptr->gamma_to_1[png_ptr->background.green]; - back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue]; - } - else - { - double g, gs; - - switch (png_ptr->background_gamma_type) - { - case PNG_BACKGROUND_GAMMA_SCREEN: - g = (png_ptr->screen_gamma); - gs = 1.0; - break; - case PNG_BACKGROUND_GAMMA_FILE: - g = 1.0 / (png_ptr->gamma); - gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); - break; - case PNG_BACKGROUND_GAMMA_UNIQUE: - g = 1.0 / (png_ptr->background_gamma); - gs = 1.0 / (png_ptr->background_gamma * - png_ptr->screen_gamma); - break; - default: - g = 1.0; /* back_1 */ - gs = 1.0; /* back */ - } - - if ( fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD) - { - back.red = (png_byte)png_ptr->background.red; - back.green = (png_byte)png_ptr->background.green; - back.blue = (png_byte)png_ptr->background.blue; - } - else - { - back.red = (png_byte)(pow( - (double)png_ptr->background.red/255, gs) * 255.0 + .5); - back.green = (png_byte)(pow( - (double)png_ptr->background.green/255, gs) * 255.0 + .5); - back.blue = (png_byte)(pow( - (double)png_ptr->background.blue/255, gs) * 255.0 + .5); - } - - back_1.red = (png_byte)(pow( - (double)png_ptr->background.red/255, g) * 255.0 + .5); - back_1.green = (png_byte)(pow( - (double)png_ptr->background.green/255, g) * 255.0 + .5); - back_1.blue = (png_byte)(pow( - (double)png_ptr->background.blue/255, g) * 255.0 + .5); - } - for (i = 0; i < num_palette; i++) - { - if (i < (int)png_ptr->num_trans && png_ptr->trans[i] != 0xff) - { - if (png_ptr->trans[i] == 0) - { - palette[i] = back; - } - else /* if (png_ptr->trans[i] != 0xff) */ - { - png_byte v, w; - - v = png_ptr->gamma_to_1[palette[i].red]; - png_composite(w, v, png_ptr->trans[i], back_1.red); - palette[i].red = png_ptr->gamma_from_1[w]; - - v = png_ptr->gamma_to_1[palette[i].green]; - png_composite(w, v, png_ptr->trans[i], back_1.green); - palette[i].green = png_ptr->gamma_from_1[w]; - - v = png_ptr->gamma_to_1[palette[i].blue]; - png_composite(w, v, png_ptr->trans[i], back_1.blue); - palette[i].blue = png_ptr->gamma_from_1[w]; - } - } - else - { - palette[i].red = png_ptr->gamma_table[palette[i].red]; - palette[i].green = png_ptr->gamma_table[palette[i].green]; - palette[i].blue = png_ptr->gamma_table[palette[i].blue]; - } - } - } - /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */ - else - /* color_type != PNG_COLOR_TYPE_PALETTE */ - { - double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1); - double g = 1.0; - double gs = 1.0; - - switch (png_ptr->background_gamma_type) - { - case PNG_BACKGROUND_GAMMA_SCREEN: - g = (png_ptr->screen_gamma); - gs = 1.0; - break; - case PNG_BACKGROUND_GAMMA_FILE: - g = 1.0 / (png_ptr->gamma); - gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); - break; - case PNG_BACKGROUND_GAMMA_UNIQUE: - g = 1.0 / (png_ptr->background_gamma); - gs = 1.0 / (png_ptr->background_gamma * - png_ptr->screen_gamma); - break; - } - - png_ptr->background_1.gray = (png_uint_16)(pow( - (double)png_ptr->background.gray / m, g) * m + .5); - png_ptr->background.gray = (png_uint_16)(pow( - (double)png_ptr->background.gray / m, gs) * m + .5); - - if ((png_ptr->background.red != png_ptr->background.green) || - (png_ptr->background.red != png_ptr->background.blue) || - (png_ptr->background.red != png_ptr->background.gray)) - { - /* RGB or RGBA with color background */ - png_ptr->background_1.red = (png_uint_16)(pow( - (double)png_ptr->background.red / m, g) * m + .5); - png_ptr->background_1.green = (png_uint_16)(pow( - (double)png_ptr->background.green / m, g) * m + .5); - png_ptr->background_1.blue = (png_uint_16)(pow( - (double)png_ptr->background.blue / m, g) * m + .5); - png_ptr->background.red = (png_uint_16)(pow( - (double)png_ptr->background.red / m, gs) * m + .5); - png_ptr->background.green = (png_uint_16)(pow( - (double)png_ptr->background.green / m, gs) * m + .5); - png_ptr->background.blue = (png_uint_16)(pow( - (double)png_ptr->background.blue / m, gs) * m + .5); - } - else - { - /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */ - png_ptr->background_1.red = png_ptr->background_1.green - = png_ptr->background_1.blue = png_ptr->background_1.gray; - png_ptr->background.red = png_ptr->background.green - = png_ptr->background.blue = png_ptr->background.gray; - } - } - } - else - /* transformation does not include PNG_BACKGROUND */ -#endif /* PNG_READ_BACKGROUND_SUPPORTED */ - if (color_type == PNG_COLOR_TYPE_PALETTE) - { - png_colorp palette = png_ptr->palette; - int num_palette = png_ptr->num_palette; - int i; - - for (i = 0; i < num_palette; i++) - { - palette[i].red = png_ptr->gamma_table[palette[i].red]; - palette[i].green = png_ptr->gamma_table[palette[i].green]; - palette[i].blue = png_ptr->gamma_table[palette[i].blue]; - } - } - } -#if defined(PNG_READ_BACKGROUND_SUPPORTED) - else -#endif -#endif /* PNG_READ_GAMMA_SUPPORTED && PNG_FLOATING_POINT_SUPPORTED */ -#if defined(PNG_READ_BACKGROUND_SUPPORTED) - /* No GAMMA transformation */ - if ((png_ptr->transformations & PNG_BACKGROUND) && - (color_type == PNG_COLOR_TYPE_PALETTE)) - { - int i; - int istop = (int)png_ptr->num_trans; - png_color back; - png_colorp palette = png_ptr->palette; - - back.red = (png_byte)png_ptr->background.red; - back.green = (png_byte)png_ptr->background.green; - back.blue = (png_byte)png_ptr->background.blue; - - for (i = 0; i < istop; i++) - { - if (png_ptr->trans[i] == 0) - { - palette[i] = back; - } - else if (png_ptr->trans[i] != 0xff) - { - /* The png_composite() macro is defined in png.h */ - png_composite(palette[i].red, palette[i].red, - png_ptr->trans[i], back.red); - png_composite(palette[i].green, palette[i].green, - png_ptr->trans[i], back.green); - png_composite(palette[i].blue, palette[i].blue, - png_ptr->trans[i], back.blue); - } - } - } -#endif /* PNG_READ_BACKGROUND_SUPPORTED */ - -#if defined(PNG_READ_SHIFT_SUPPORTED) - if ((png_ptr->transformations & PNG_SHIFT) && - (color_type == PNG_COLOR_TYPE_PALETTE)) - { - png_uint_16 i; - png_uint_16 istop = png_ptr->num_palette; - int sr = 8 - png_ptr->sig_bit.red; - int sg = 8 - png_ptr->sig_bit.green; - int sb = 8 - png_ptr->sig_bit.blue; - - if (sr < 0 || sr > 8) - sr = 0; - if (sg < 0 || sg > 8) - sg = 0; - if (sb < 0 || sb > 8) - sb = 0; - for (i = 0; i < istop; i++) - { - png_ptr->palette[i].red >>= sr; - png_ptr->palette[i].green >>= sg; - png_ptr->palette[i].blue >>= sb; - } - } -#endif /* PNG_READ_SHIFT_SUPPORTED */ - } -#if !defined(PNG_READ_GAMMA_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) \ - && !defined(PNG_READ_BACKGROUND_SUPPORTED) - if(png_ptr) - return; -#endif -} - -/* Modify the info structure to reflect the transformations. The - * info should be updated so a PNG file could be written with it, - * assuming the transformations result in valid PNG data. - */ -void /* PRIVATE */ -png_read_transform_info(png_structp png_ptr, png_infop info_ptr) -{ - png_debug(1, "in png_read_transform_info\n"); -#if defined(PNG_READ_EXPAND_SUPPORTED) - if (png_ptr->transformations & PNG_EXPAND) - { - if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - { - if (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND_tRNS)) - info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA; - else - info_ptr->color_type = PNG_COLOR_TYPE_RGB; - info_ptr->bit_depth = 8; - info_ptr->num_trans = 0; - } - else - { - if (png_ptr->num_trans) - { - if (png_ptr->transformations & PNG_EXPAND_tRNS) - info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; - else - info_ptr->color_type |= PNG_COLOR_MASK_COLOR; - } - if (info_ptr->bit_depth < 8) - info_ptr->bit_depth = 8; - info_ptr->num_trans = 0; - } - } -#endif - -#if defined(PNG_READ_BACKGROUND_SUPPORTED) - if (png_ptr->transformations & PNG_BACKGROUND) - { - info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA; - info_ptr->num_trans = 0; - info_ptr->background = png_ptr->background; - } -#endif - -#if defined(PNG_READ_GAMMA_SUPPORTED) - if (png_ptr->transformations & PNG_GAMMA) - { -#ifdef PNG_FLOATING_POINT_SUPPORTED - info_ptr->gamma = png_ptr->gamma; -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED - info_ptr->int_gamma = png_ptr->int_gamma; -#endif - } -#endif - -#if defined(PNG_READ_16_TO_8_SUPPORTED) - if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16)) - info_ptr->bit_depth = 8; -#endif - -#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) - if (png_ptr->transformations & PNG_GRAY_TO_RGB) - info_ptr->color_type |= PNG_COLOR_MASK_COLOR; -#endif - -#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) - if (png_ptr->transformations & PNG_RGB_TO_GRAY) - info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR; -#endif - -#if defined(PNG_READ_DITHER_SUPPORTED) - if (png_ptr->transformations & PNG_DITHER) - { - if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || - (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) && - png_ptr->palette_lookup && info_ptr->bit_depth == 8) - { - info_ptr->color_type = PNG_COLOR_TYPE_PALETTE; - } - } -#endif - -#if defined(PNG_READ_PACK_SUPPORTED) - if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8)) - info_ptr->bit_depth = 8; -#endif - - if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - info_ptr->channels = 1; - else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) - info_ptr->channels = 3; - else - info_ptr->channels = 1; - -#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) - if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA) - info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA; -#endif - - if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) - info_ptr->channels++; - -#if defined(PNG_READ_FILLER_SUPPORTED) - /* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */ - if ((png_ptr->transformations & PNG_FILLER) && - ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || - (info_ptr->color_type == PNG_COLOR_TYPE_GRAY))) - { - info_ptr->channels++; - /* if adding a true alpha channel not just filler */ -#if !defined(PNG_1_0_X) - if (png_ptr->transformations & PNG_ADD_ALPHA) - info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; -#endif - } -#endif - -#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \ -defined(PNG_READ_USER_TRANSFORM_SUPPORTED) - if(png_ptr->transformations & PNG_USER_TRANSFORM) - { - if(info_ptr->bit_depth < png_ptr->user_transform_depth) - info_ptr->bit_depth = png_ptr->user_transform_depth; - if(info_ptr->channels < png_ptr->user_transform_channels) - info_ptr->channels = png_ptr->user_transform_channels; - } -#endif - - info_ptr->pixel_depth = (png_byte)(info_ptr->channels * - info_ptr->bit_depth); - - info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth,info_ptr->width); - -#if !defined(PNG_READ_EXPAND_SUPPORTED) - if(png_ptr) - return; -#endif -} - -/* Transform the row. The order of transformations is significant, - * and is very touchy. If you add a transformation, take care to - * decide how it fits in with the other transformations here. - */ -void /* PRIVATE */ -png_do_read_transformations(png_structp png_ptr) -{ - png_debug(1, "in png_do_read_transformations\n"); - if (png_ptr->row_buf == NULL) - { -#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) - char msg[50]; - - png_snprintf2(msg, 50, - "NULL row buffer for row %ld, pass %d", png_ptr->row_number, - png_ptr->pass); - png_error(png_ptr, msg); -#else - png_error(png_ptr, "NULL row buffer"); -#endif - } -#ifdef PNG_WARN_UNINITIALIZED_ROW - if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) - /* Application has failed to call either png_read_start_image() - * or png_read_update_info() after setting transforms that expand - * pixels. This check added to libpng-1.2.19 */ -#if (PNG_WARN_UNINITIALIZED_ROW==1) - png_error(png_ptr, "Uninitialized row"); -#else - png_warning(png_ptr, "Uninitialized row"); -#endif -#endif - -#if defined(PNG_READ_EXPAND_SUPPORTED) - if (png_ptr->transformations & PNG_EXPAND) - { - if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE) - { - png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1, - png_ptr->palette, png_ptr->trans, png_ptr->num_trans); - } - else - { - if (png_ptr->num_trans && - (png_ptr->transformations & PNG_EXPAND_tRNS)) - png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1, - &(png_ptr->trans_values)); - else - png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1, - NULL); - } - } -#endif - -#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) - if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA) - png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, - PNG_FLAG_FILLER_AFTER | (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)); -#endif - -#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) - if (png_ptr->transformations & PNG_RGB_TO_GRAY) - { - int rgb_error = - png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), png_ptr->row_buf + 1); - if(rgb_error) - { - png_ptr->rgb_to_gray_status=1; - if((png_ptr->transformations & PNG_RGB_TO_GRAY) == - PNG_RGB_TO_GRAY_WARN) - png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel"); - if((png_ptr->transformations & PNG_RGB_TO_GRAY) == - PNG_RGB_TO_GRAY_ERR) - png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel"); - } - } -#endif - -/* -From Andreas Dilger e-mail to png-implement, 26 March 1998: - - In most cases, the "simple transparency" should be done prior to doing - gray-to-RGB, or you will have to test 3x as many bytes to check if a - pixel is transparent. You would also need to make sure that the - transparency information is upgraded to RGB. - - To summarize, the current flow is: - - Gray + simple transparency -> compare 1 or 2 gray bytes and composite - with background "in place" if transparent, - convert to RGB if necessary - - Gray + alpha -> composite with gray background and remove alpha bytes, - convert to RGB if necessary - - To support RGB backgrounds for gray images we need: - - Gray + simple transparency -> convert to RGB + simple transparency, compare - 3 or 6 bytes and composite with background - "in place" if transparent (3x compare/pixel - compared to doing composite with gray bkgrnd) - - Gray + alpha -> convert to RGB + alpha, composite with background and - remove alpha bytes (3x float operations/pixel - compared with composite on gray background) - - Greg's change will do this. The reason it wasn't done before is for - performance, as this increases the per-pixel operations. If we would check - in advance if the background was gray or RGB, and position the gray-to-RGB - transform appropriately, then it would save a lot of work/time. - */ - -#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) - /* if gray -> RGB, do so now only if background is non-gray; else do later - * for performance reasons */ - if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && - !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) - png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1); -#endif - -#if defined(PNG_READ_BACKGROUND_SUPPORTED) - if ((png_ptr->transformations & PNG_BACKGROUND) && - ((png_ptr->num_trans != 0 ) || - (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) - png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1, - &(png_ptr->trans_values), &(png_ptr->background) -#if defined(PNG_READ_GAMMA_SUPPORTED) - , &(png_ptr->background_1), - png_ptr->gamma_table, png_ptr->gamma_from_1, - png_ptr->gamma_to_1, png_ptr->gamma_16_table, - png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1, - png_ptr->gamma_shift -#endif -); -#endif - -#if defined(PNG_READ_GAMMA_SUPPORTED) - if ((png_ptr->transformations & PNG_GAMMA) && -#if defined(PNG_READ_BACKGROUND_SUPPORTED) - !((png_ptr->transformations & PNG_BACKGROUND) && - ((png_ptr->num_trans != 0) || - (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) && -#endif - (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)) - png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1, - png_ptr->gamma_table, png_ptr->gamma_16_table, - png_ptr->gamma_shift); -#endif - -#if defined(PNG_READ_16_TO_8_SUPPORTED) - if (png_ptr->transformations & PNG_16_TO_8) - png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1); -#endif - -#if defined(PNG_READ_DITHER_SUPPORTED) - if (png_ptr->transformations & PNG_DITHER) - { - png_do_dither((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1, - png_ptr->palette_lookup, png_ptr->dither_index); - if(png_ptr->row_info.rowbytes == (png_uint_32)0) - png_error(png_ptr, "png_do_dither returned rowbytes=0"); - } -#endif - -#if defined(PNG_READ_INVERT_SUPPORTED) - if (png_ptr->transformations & PNG_INVERT_MONO) - png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1); -#endif - -#if defined(PNG_READ_SHIFT_SUPPORTED) - if (png_ptr->transformations & PNG_SHIFT) - png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1, - &(png_ptr->shift)); -#endif - -#if defined(PNG_READ_PACK_SUPPORTED) - if (png_ptr->transformations & PNG_PACK) - png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1); -#endif - -#if defined(PNG_READ_BGR_SUPPORTED) - if (png_ptr->transformations & PNG_BGR) - png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1); -#endif - -#if defined(PNG_READ_PACKSWAP_SUPPORTED) - if (png_ptr->transformations & PNG_PACKSWAP) - png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1); -#endif - -#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) - /* if gray -> RGB, do so now only if we did not do so above */ - if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && - (png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) - png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1); -#endif - -#if defined(PNG_READ_FILLER_SUPPORTED) - if (png_ptr->transformations & PNG_FILLER) - png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, - (png_uint_32)png_ptr->filler, png_ptr->flags); -#endif - -#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) - if (png_ptr->transformations & PNG_INVERT_ALPHA) - png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); -#endif - -#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) - if (png_ptr->transformations & PNG_SWAP_ALPHA) - png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); -#endif - -#if defined(PNG_READ_SWAP_SUPPORTED) - if (png_ptr->transformations & PNG_SWAP_BYTES) - png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1); -#endif - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) - if (png_ptr->transformations & PNG_USER_TRANSFORM) - { - if(png_ptr->read_user_transform_fn != NULL) - (*(png_ptr->read_user_transform_fn)) /* user read transform function */ - (png_ptr, /* png_ptr */ - &(png_ptr->row_info), /* row_info: */ - /* png_uint_32 width; width of row */ - /* png_uint_32 rowbytes; number of bytes in row */ - /* png_byte color_type; color type of pixels */ - /* png_byte bit_depth; bit depth of samples */ - /* png_byte channels; number of channels (1-4) */ - /* png_byte pixel_depth; bits per pixel (depth*channels) */ - png_ptr->row_buf + 1); /* start of pixel data for row */ -#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) - if(png_ptr->user_transform_depth) - png_ptr->row_info.bit_depth = png_ptr->user_transform_depth; - if(png_ptr->user_transform_channels) - png_ptr->row_info.channels = png_ptr->user_transform_channels; -#endif - png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth * - png_ptr->row_info.channels); - png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, - png_ptr->row_info.width); - } -#endif - -} - -#if defined(PNG_READ_PACK_SUPPORTED) -/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel, - * without changing the actual values. Thus, if you had a row with - * a bit depth of 1, you would end up with bytes that only contained - * the numbers 0 or 1. If you would rather they contain 0 and 255, use - * png_do_shift() after this. - */ -void /* PRIVATE */ -png_do_unpack(png_row_infop row_info, png_bytep row) -{ - png_debug(1, "in png_do_unpack\n"); -#if defined(PNG_USELESS_TESTS_SUPPORTED) - if (row != NULL && row_info != NULL && row_info->bit_depth < 8) -#else - if (row_info->bit_depth < 8) -#endif - { - png_uint_32 i; - png_uint_32 row_width=row_info->width; - - switch (row_info->bit_depth) - { - case 1: - { - png_bytep sp = row + (png_size_t)((row_width - 1) >> 3); - png_bytep dp = row + (png_size_t)row_width - 1; - png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07); - for (i = 0; i < row_width; i++) - { - *dp = (png_byte)((*sp >> shift) & 0x01); - if (shift == 7) - { - shift = 0; - sp--; - } - else - shift++; - - dp--; - } - break; - } - case 2: - { - - png_bytep sp = row + (png_size_t)((row_width - 1) >> 2); - png_bytep dp = row + (png_size_t)row_width - 1; - png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); - for (i = 0; i < row_width; i++) - { - *dp = (png_byte)((*sp >> shift) & 0x03); - if (shift == 6) - { - shift = 0; - sp--; - } - else - shift += 2; - - dp--; - } - break; - } - case 4: - { - png_bytep sp = row + (png_size_t)((row_width - 1) >> 1); - png_bytep dp = row + (png_size_t)row_width - 1; - png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); - for (i = 0; i < row_width; i++) - { - *dp = (png_byte)((*sp >> shift) & 0x0f); - if (shift == 4) - { - shift = 0; - sp--; - } - else - shift = 4; - - dp--; - } - break; - } - } - row_info->bit_depth = 8; - row_info->pixel_depth = (png_byte)(8 * row_info->channels); - row_info->rowbytes = row_width * row_info->channels; - } -} -#endif - -#if defined(PNG_READ_SHIFT_SUPPORTED) -/* Reverse the effects of png_do_shift. This routine merely shifts the - * pixels back to their significant bits values. Thus, if you have - * a row of bit depth 8, but only 5 are significant, this will shift - * the values back to 0 through 31. - */ -void /* PRIVATE */ -png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits) -{ - png_debug(1, "in png_do_unshift\n"); - if ( -#if defined(PNG_USELESS_TESTS_SUPPORTED) - row != NULL && row_info != NULL && sig_bits != NULL && -#endif - row_info->color_type != PNG_COLOR_TYPE_PALETTE) - { - int shift[4]; - int channels = 0; - int c; - png_uint_16 value = 0; - png_uint_32 row_width = row_info->width; - - if (row_info->color_type & PNG_COLOR_MASK_COLOR) - { - shift[channels++] = row_info->bit_depth - sig_bits->red; - shift[channels++] = row_info->bit_depth - sig_bits->green; - shift[channels++] = row_info->bit_depth - sig_bits->blue; - } - else - { - shift[channels++] = row_info->bit_depth - sig_bits->gray; - } - if (row_info->color_type & PNG_COLOR_MASK_ALPHA) - { - shift[channels++] = row_info->bit_depth - sig_bits->alpha; - } - - for (c = 0; c < channels; c++) - { - if (shift[c] <= 0) - shift[c] = 0; - else - value = 1; - } - - if (!value) - return; - - switch (row_info->bit_depth) - { - case 2: - { - png_bytep bp; - png_uint_32 i; - png_uint_32 istop = row_info->rowbytes; - - for (bp = row, i = 0; i < istop; i++) - { - *bp >>= 1; - *bp++ &= 0x55; - } - break; - } - case 4: - { - png_bytep bp = row; - png_uint_32 i; - png_uint_32 istop = row_info->rowbytes; - png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) | - (png_byte)((int)0xf >> shift[0])); - - for (i = 0; i < istop; i++) - { - *bp >>= shift[0]; - *bp++ &= mask; - } - break; - } - case 8: - { - png_bytep bp = row; - png_uint_32 i; - png_uint_32 istop = row_width * channels; - - for (i = 0; i < istop; i++) - { - *bp++ >>= shift[i%channels]; - } - break; - } - case 16: - { - png_bytep bp = row; - png_uint_32 i; - png_uint_32 istop = channels * row_width; - - for (i = 0; i < istop; i++) - { - value = (png_uint_16)((*bp << 8) + *(bp + 1)); - value >>= shift[i%channels]; - *bp++ = (png_byte)(value >> 8); - *bp++ = (png_byte)(value & 0xff); - } - break; - } - } - } -} -#endif - -#if defined(PNG_READ_16_TO_8_SUPPORTED) -/* chop rows of bit depth 16 down to 8 */ -void /* PRIVATE */ -png_do_chop(png_row_infop row_info, png_bytep row) -{ - png_debug(1, "in png_do_chop\n"); -#if defined(PNG_USELESS_TESTS_SUPPORTED) - if (row != NULL && row_info != NULL && row_info->bit_depth == 16) -#else - if (row_info->bit_depth == 16) -#endif - { - png_bytep sp = row; - png_bytep dp = row; - png_uint_32 i; - png_uint_32 istop = row_info->width * row_info->channels; - - for (i = 0; i> 8)) >> 8; - * - * Approximate calculation with shift/add instead of multiply/divide: - * *dp = ((((png_uint_32)(*sp) << 8) | - * (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8; - * - * What we actually do to avoid extra shifting and conversion: - */ - - *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0); -#else - /* Simply discard the low order byte */ - *dp = *sp; -#endif - } - row_info->bit_depth = 8; - row_info->pixel_depth = (png_byte)(8 * row_info->channels); - row_info->rowbytes = row_info->width * row_info->channels; - } -} -#endif - -#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) -void /* PRIVATE */ -png_do_read_swap_alpha(png_row_infop row_info, png_bytep row) -{ - png_debug(1, "in png_do_read_swap_alpha\n"); -#if defined(PNG_USELESS_TESTS_SUPPORTED) - if (row != NULL && row_info != NULL) -#endif - { - png_uint_32 row_width = row_info->width; - if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - { - /* This converts from RGBA to ARGB */ - if (row_info->bit_depth == 8) - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_byte save; - png_uint_32 i; - - for (i = 0; i < row_width; i++) - { - save = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = save; - } - } - /* This converts from RRGGBBAA to AARRGGBB */ - else - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_byte save[2]; - png_uint_32 i; - - for (i = 0; i < row_width; i++) - { - save[0] = *(--sp); - save[1] = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = save[0]; - *(--dp) = save[1]; - } - } - } - else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - { - /* This converts from GA to AG */ - if (row_info->bit_depth == 8) - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_byte save; - png_uint_32 i; - - for (i = 0; i < row_width; i++) - { - save = *(--sp); - *(--dp) = *(--sp); - *(--dp) = save; - } - } - /* This converts from GGAA to AAGG */ - else - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_byte save[2]; - png_uint_32 i; - - for (i = 0; i < row_width; i++) - { - save[0] = *(--sp); - save[1] = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = save[0]; - *(--dp) = save[1]; - } - } - } - } -} -#endif - -#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) -void /* PRIVATE */ -png_do_read_invert_alpha(png_row_infop row_info, png_bytep row) -{ - png_debug(1, "in png_do_read_invert_alpha\n"); -#if defined(PNG_USELESS_TESTS_SUPPORTED) - if (row != NULL && row_info != NULL) -#endif - { - png_uint_32 row_width = row_info->width; - if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - { - /* This inverts the alpha channel in RGBA */ - if (row_info->bit_depth == 8) - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_uint_32 i; - - for (i = 0; i < row_width; i++) - { - *(--dp) = (png_byte)(255 - *(--sp)); - -/* This does nothing: - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - We can replace it with: -*/ - sp-=3; - dp=sp; - } - } - /* This inverts the alpha channel in RRGGBBAA */ - else - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_uint_32 i; - - for (i = 0; i < row_width; i++) - { - *(--dp) = (png_byte)(255 - *(--sp)); - *(--dp) = (png_byte)(255 - *(--sp)); - -/* This does nothing: - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - We can replace it with: -*/ - sp-=6; - dp=sp; - } - } - } - else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - { - /* This inverts the alpha channel in GA */ - if (row_info->bit_depth == 8) - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_uint_32 i; - - for (i = 0; i < row_width; i++) - { - *(--dp) = (png_byte)(255 - *(--sp)); - *(--dp) = *(--sp); - } - } - /* This inverts the alpha channel in GGAA */ - else - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_uint_32 i; - - for (i = 0; i < row_width; i++) - { - *(--dp) = (png_byte)(255 - *(--sp)); - *(--dp) = (png_byte)(255 - *(--sp)); -/* - *(--dp) = *(--sp); - *(--dp) = *(--sp); -*/ - sp-=2; - dp=sp; - } - } - } - } -} -#endif - -#if defined(PNG_READ_FILLER_SUPPORTED) -/* Add filler channel if we have RGB color */ -void /* PRIVATE */ -png_do_read_filler(png_row_infop row_info, png_bytep row, - png_uint_32 filler, png_uint_32 flags) -{ - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - png_byte hi_filler = (png_byte)((filler>>8) & 0xff); - png_byte lo_filler = (png_byte)(filler & 0xff); - - png_debug(1, "in png_do_read_filler\n"); - if ( -#if defined(PNG_USELESS_TESTS_SUPPORTED) - row != NULL && row_info != NULL && -#endif - row_info->color_type == PNG_COLOR_TYPE_GRAY) - { - if(row_info->bit_depth == 8) - { - /* This changes the data from G to GX */ - if (flags & PNG_FLAG_FILLER_AFTER) - { - png_bytep sp = row + (png_size_t)row_width; - png_bytep dp = sp + (png_size_t)row_width; - for (i = 1; i < row_width; i++) - { - *(--dp) = lo_filler; - *(--dp) = *(--sp); - } - *(--dp) = lo_filler; - row_info->channels = 2; - row_info->pixel_depth = 16; - row_info->rowbytes = row_width * 2; - } - /* This changes the data from G to XG */ - else - { - png_bytep sp = row + (png_size_t)row_width; - png_bytep dp = sp + (png_size_t)row_width; - for (i = 0; i < row_width; i++) - { - *(--dp) = *(--sp); - *(--dp) = lo_filler; - } - row_info->channels = 2; - row_info->pixel_depth = 16; - row_info->rowbytes = row_width * 2; - } - } - else if(row_info->bit_depth == 16) - { - /* This changes the data from GG to GGXX */ - if (flags & PNG_FLAG_FILLER_AFTER) - { - png_bytep sp = row + (png_size_t)row_width * 2; - png_bytep dp = sp + (png_size_t)row_width * 2; - for (i = 1; i < row_width; i++) - { - *(--dp) = hi_filler; - *(--dp) = lo_filler; - *(--dp) = *(--sp); - *(--dp) = *(--sp); - } - *(--dp) = hi_filler; - *(--dp) = lo_filler; - row_info->channels = 2; - row_info->pixel_depth = 32; - row_info->rowbytes = row_width * 4; - } - /* This changes the data from GG to XXGG */ - else - { - png_bytep sp = row + (png_size_t)row_width * 2; - png_bytep dp = sp + (png_size_t)row_width * 2; - for (i = 0; i < row_width; i++) - { - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = hi_filler; - *(--dp) = lo_filler; - } - row_info->channels = 2; - row_info->pixel_depth = 32; - row_info->rowbytes = row_width * 4; - } - } - } /* COLOR_TYPE == GRAY */ - else if (row_info->color_type == PNG_COLOR_TYPE_RGB) - { - if(row_info->bit_depth == 8) - { - /* This changes the data from RGB to RGBX */ - if (flags & PNG_FLAG_FILLER_AFTER) - { - png_bytep sp = row + (png_size_t)row_width * 3; - png_bytep dp = sp + (png_size_t)row_width; - for (i = 1; i < row_width; i++) - { - *(--dp) = lo_filler; - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - } - *(--dp) = lo_filler; - row_info->channels = 4; - row_info->pixel_depth = 32; - row_info->rowbytes = row_width * 4; - } - /* This changes the data from RGB to XRGB */ - else - { - png_bytep sp = row + (png_size_t)row_width * 3; - png_bytep dp = sp + (png_size_t)row_width; - for (i = 0; i < row_width; i++) - { - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = lo_filler; - } - row_info->channels = 4; - row_info->pixel_depth = 32; - row_info->rowbytes = row_width * 4; - } - } - else if(row_info->bit_depth == 16) - { - /* This changes the data from RRGGBB to RRGGBBXX */ - if (flags & PNG_FLAG_FILLER_AFTER) - { - png_bytep sp = row + (png_size_t)row_width * 6; - png_bytep dp = sp + (png_size_t)row_width * 2; - for (i = 1; i < row_width; i++) - { - *(--dp) = hi_filler; - *(--dp) = lo_filler; - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - } - *(--dp) = hi_filler; - *(--dp) = lo_filler; - row_info->channels = 4; - row_info->pixel_depth = 64; - row_info->rowbytes = row_width * 8; - } - /* This changes the data from RRGGBB to XXRRGGBB */ - else - { - png_bytep sp = row + (png_size_t)row_width * 6; - png_bytep dp = sp + (png_size_t)row_width * 2; - for (i = 0; i < row_width; i++) - { - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = hi_filler; - *(--dp) = lo_filler; - } - row_info->channels = 4; - row_info->pixel_depth = 64; - row_info->rowbytes = row_width * 8; - } - } - } /* COLOR_TYPE == RGB */ -} -#endif - -#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) -/* expand grayscale files to RGB, with or without alpha */ -void /* PRIVATE */ -png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) -{ - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - png_debug(1, "in png_do_gray_to_rgb\n"); - if (row_info->bit_depth >= 8 && -#if defined(PNG_USELESS_TESTS_SUPPORTED) - row != NULL && row_info != NULL && -#endif - !(row_info->color_type & PNG_COLOR_MASK_COLOR)) - { - if (row_info->color_type == PNG_COLOR_TYPE_GRAY) - { - if (row_info->bit_depth == 8) - { - png_bytep sp = row + (png_size_t)row_width - 1; - png_bytep dp = sp + (png_size_t)row_width * 2; - for (i = 0; i < row_width; i++) - { - *(dp--) = *sp; - *(dp--) = *sp; - *(dp--) = *(sp--); - } - } - else - { - png_bytep sp = row + (png_size_t)row_width * 2 - 1; - png_bytep dp = sp + (png_size_t)row_width * 4; - for (i = 0; i < row_width; i++) - { - *(dp--) = *sp; - *(dp--) = *(sp - 1); - *(dp--) = *sp; - *(dp--) = *(sp - 1); - *(dp--) = *(sp--); - *(dp--) = *(sp--); - } - } - } - else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - { - if (row_info->bit_depth == 8) - { - png_bytep sp = row + (png_size_t)row_width * 2 - 1; - png_bytep dp = sp + (png_size_t)row_width * 2; - for (i = 0; i < row_width; i++) - { - *(dp--) = *(sp--); - *(dp--) = *sp; - *(dp--) = *sp; - *(dp--) = *(sp--); - } - } - else - { - png_bytep sp = row + (png_size_t)row_width * 4 - 1; - png_bytep dp = sp + (png_size_t)row_width * 4; - for (i = 0; i < row_width; i++) - { - *(dp--) = *(sp--); - *(dp--) = *(sp--); - *(dp--) = *sp; - *(dp--) = *(sp - 1); - *(dp--) = *sp; - *(dp--) = *(sp - 1); - *(dp--) = *(sp--); - *(dp--) = *(sp--); - } - } - } - row_info->channels += (png_byte)2; - row_info->color_type |= PNG_COLOR_MASK_COLOR; - row_info->pixel_depth = (png_byte)(row_info->channels * - row_info->bit_depth); - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); - } -} -#endif - -#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) -/* reduce RGB files to grayscale, with or without alpha - * using the equation given in Poynton's ColorFAQ at - * - * Copyright (c) 1998-01-04 Charles Poynton poynton at inforamp.net - * - * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B - * - * We approximate this with - * - * Y = 0.21268 * R + 0.7151 * G + 0.07217 * B - * - * which can be expressed with integers as - * - * Y = (6969 * R + 23434 * G + 2365 * B)/32768 - * - * The calculation is to be done in a linear colorspace. - * - * Other integer coefficents can be used via png_set_rgb_to_gray(). - */ -int /* PRIVATE */ -png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row) - -{ - png_uint_32 i; - - png_uint_32 row_width = row_info->width; - int rgb_error = 0; - - png_debug(1, "in png_do_rgb_to_gray\n"); - if ( -#if defined(PNG_USELESS_TESTS_SUPPORTED) - row != NULL && row_info != NULL && -#endif - (row_info->color_type & PNG_COLOR_MASK_COLOR)) - { - png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff; - png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff; - png_uint_32 bc = png_ptr->rgb_to_gray_blue_coeff; - - if (row_info->color_type == PNG_COLOR_TYPE_RGB) - { - if (row_info->bit_depth == 8) - { -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) - { - png_bytep sp = row; - png_bytep dp = row; - - for (i = 0; i < row_width; i++) - { - png_byte red = png_ptr->gamma_to_1[*(sp++)]; - png_byte green = png_ptr->gamma_to_1[*(sp++)]; - png_byte blue = png_ptr->gamma_to_1[*(sp++)]; - if(red != green || red != blue) - { - rgb_error |= 1; - *(dp++) = png_ptr->gamma_from_1[ - (rc*red+gc*green+bc*blue)>>15]; - } - else - *(dp++) = *(sp-1); - } - } - else -#endif - { - png_bytep sp = row; - png_bytep dp = row; - for (i = 0; i < row_width; i++) - { - png_byte red = *(sp++); - png_byte green = *(sp++); - png_byte blue = *(sp++); - if(red != green || red != blue) - { - rgb_error |= 1; - *(dp++) = (png_byte)((rc*red+gc*green+bc*blue)>>15); - } - else - *(dp++) = *(sp-1); - } - } - } - - else /* RGB bit_depth == 16 */ - { -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - if (png_ptr->gamma_16_to_1 != NULL && - png_ptr->gamma_16_from_1 != NULL) - { - png_bytep sp = row; - png_bytep dp = row; - for (i = 0; i < row_width; i++) - { - png_uint_16 red, green, blue, w; - - red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; - green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; - blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; - - if(red == green && red == blue) - w = red; - else - { - png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >> - png_ptr->gamma_shift][red>>8]; - png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >> - png_ptr->gamma_shift][green>>8]; - png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >> - png_ptr->gamma_shift][blue>>8]; - png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1 - + bc*blue_1)>>15); - w = png_ptr->gamma_16_from_1[(gray16&0xff) >> - png_ptr->gamma_shift][gray16 >> 8]; - rgb_error |= 1; - } - - *(dp++) = (png_byte)((w>>8) & 0xff); - *(dp++) = (png_byte)(w & 0xff); - } - } - else -#endif - { - png_bytep sp = row; - png_bytep dp = row; - for (i = 0; i < row_width; i++) - { - png_uint_16 red, green, blue, gray16; - - red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; - green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; - blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; - - if(red != green || red != blue) - rgb_error |= 1; - gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15); - *(dp++) = (png_byte)((gray16>>8) & 0xff); - *(dp++) = (png_byte)(gray16 & 0xff); - } - } - } - } - if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - { - if (row_info->bit_depth == 8) - { -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) - { - png_bytep sp = row; - png_bytep dp = row; - for (i = 0; i < row_width; i++) - { - png_byte red = png_ptr->gamma_to_1[*(sp++)]; - png_byte green = png_ptr->gamma_to_1[*(sp++)]; - png_byte blue = png_ptr->gamma_to_1[*(sp++)]; - if(red != green || red != blue) - rgb_error |= 1; - *(dp++) = png_ptr->gamma_from_1 - [(rc*red + gc*green + bc*blue)>>15]; - *(dp++) = *(sp++); /* alpha */ - } - } - else -#endif - { - png_bytep sp = row; - png_bytep dp = row; - for (i = 0; i < row_width; i++) - { - png_byte red = *(sp++); - png_byte green = *(sp++); - png_byte blue = *(sp++); - if(red != green || red != blue) - rgb_error |= 1; - *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15); - *(dp++) = *(sp++); /* alpha */ - } - } - } - else /* RGBA bit_depth == 16 */ - { -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - if (png_ptr->gamma_16_to_1 != NULL && - png_ptr->gamma_16_from_1 != NULL) - { - png_bytep sp = row; - png_bytep dp = row; - for (i = 0; i < row_width; i++) - { - png_uint_16 red, green, blue, w; - - red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; - green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; - blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; - - if(red == green && red == blue) - w = red; - else - { - png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >> - png_ptr->gamma_shift][red>>8]; - png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >> - png_ptr->gamma_shift][green>>8]; - png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >> - png_ptr->gamma_shift][blue>>8]; - png_uint_16 gray16 = (png_uint_16)((rc * red_1 - + gc * green_1 + bc * blue_1)>>15); - w = png_ptr->gamma_16_from_1[(gray16&0xff) >> - png_ptr->gamma_shift][gray16 >> 8]; - rgb_error |= 1; - } - - *(dp++) = (png_byte)((w>>8) & 0xff); - *(dp++) = (png_byte)(w & 0xff); - *(dp++) = *(sp++); /* alpha */ - *(dp++) = *(sp++); - } - } - else -#endif - { - png_bytep sp = row; - png_bytep dp = row; - for (i = 0; i < row_width; i++) - { - png_uint_16 red, green, blue, gray16; - red = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; - green = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; - blue = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; - if(red != green || red != blue) - rgb_error |= 1; - gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15); - *(dp++) = (png_byte)((gray16>>8) & 0xff); - *(dp++) = (png_byte)(gray16 & 0xff); - *(dp++) = *(sp++); /* alpha */ - *(dp++) = *(sp++); - } - } - } - } - row_info->channels -= (png_byte)2; - row_info->color_type &= ~PNG_COLOR_MASK_COLOR; - row_info->pixel_depth = (png_byte)(row_info->channels * - row_info->bit_depth); - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); - } - return rgb_error; -} -#endif - -/* Build a grayscale palette. Palette is assumed to be 1 << bit_depth - * large of png_color. This lets grayscale images be treated as - * paletted. Most useful for gamma correction and simplification - * of code. - */ -void PNGAPI -png_build_grayscale_palette(int bit_depth, png_colorp palette) -{ - int num_palette; - int color_inc; - int i; - int v; - - png_debug(1, "in png_do_build_grayscale_palette\n"); - if (palette == NULL) - return; - - switch (bit_depth) - { - case 1: - num_palette = 2; - color_inc = 0xff; - break; - case 2: - num_palette = 4; - color_inc = 0x55; - break; - case 4: - num_palette = 16; - color_inc = 0x11; - break; - case 8: - num_palette = 256; - color_inc = 1; - break; - default: - num_palette = 0; - color_inc = 0; - break; - } - - for (i = 0, v = 0; i < num_palette; i++, v += color_inc) - { - palette[i].red = (png_byte)v; - palette[i].green = (png_byte)v; - palette[i].blue = (png_byte)v; - } -} - -/* This function is currently unused. Do we really need it? */ -#if defined(PNG_READ_DITHER_SUPPORTED) && defined(PNG_CORRECT_PALETTE_SUPPORTED) -void /* PRIVATE */ -png_correct_palette(png_structp png_ptr, png_colorp palette, - int num_palette) -{ - png_debug(1, "in png_correct_palette\n"); -#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ - defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) - if (png_ptr->transformations & (PNG_GAMMA | PNG_BACKGROUND)) - { - png_color back, back_1; - - if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE) - { - back.red = png_ptr->gamma_table[png_ptr->background.red]; - back.green = png_ptr->gamma_table[png_ptr->background.green]; - back.blue = png_ptr->gamma_table[png_ptr->background.blue]; - - back_1.red = png_ptr->gamma_to_1[png_ptr->background.red]; - back_1.green = png_ptr->gamma_to_1[png_ptr->background.green]; - back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue]; - } - else - { - double g; - - g = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma); - - if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_SCREEN || - fabs(g - 1.0) < PNG_GAMMA_THRESHOLD) - { - back.red = png_ptr->background.red; - back.green = png_ptr->background.green; - back.blue = png_ptr->background.blue; - } - else - { - back.red = - (png_byte)(pow((double)png_ptr->background.red/255, g) * - 255.0 + 0.5); - back.green = - (png_byte)(pow((double)png_ptr->background.green/255, g) * - 255.0 + 0.5); - back.blue = - (png_byte)(pow((double)png_ptr->background.blue/255, g) * - 255.0 + 0.5); - } - - g = 1.0 / png_ptr->background_gamma; - - back_1.red = - (png_byte)(pow((double)png_ptr->background.red/255, g) * - 255.0 + 0.5); - back_1.green = - (png_byte)(pow((double)png_ptr->background.green/255, g) * - 255.0 + 0.5); - back_1.blue = - (png_byte)(pow((double)png_ptr->background.blue/255, g) * - 255.0 + 0.5); - } - - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - { - png_uint_32 i; - - for (i = 0; i < (png_uint_32)num_palette; i++) - { - if (i < png_ptr->num_trans && png_ptr->trans[i] == 0) - { - palette[i] = back; - } - else if (i < png_ptr->num_trans && png_ptr->trans[i] != 0xff) - { - png_byte v, w; - - v = png_ptr->gamma_to_1[png_ptr->palette[i].red]; - png_composite(w, v, png_ptr->trans[i], back_1.red); - palette[i].red = png_ptr->gamma_from_1[w]; - - v = png_ptr->gamma_to_1[png_ptr->palette[i].green]; - png_composite(w, v, png_ptr->trans[i], back_1.green); - palette[i].green = png_ptr->gamma_from_1[w]; - - v = png_ptr->gamma_to_1[png_ptr->palette[i].blue]; - png_composite(w, v, png_ptr->trans[i], back_1.blue); - palette[i].blue = png_ptr->gamma_from_1[w]; - } - else - { - palette[i].red = png_ptr->gamma_table[palette[i].red]; - palette[i].green = png_ptr->gamma_table[palette[i].green]; - palette[i].blue = png_ptr->gamma_table[palette[i].blue]; - } - } - } - else - { - int i; - - for (i = 0; i < num_palette; i++) - { - if (palette[i].red == (png_byte)png_ptr->trans_values.gray) - { - palette[i] = back; - } - else - { - palette[i].red = png_ptr->gamma_table[palette[i].red]; - palette[i].green = png_ptr->gamma_table[palette[i].green]; - palette[i].blue = png_ptr->gamma_table[palette[i].blue]; - } - } - } - } - else -#endif -#if defined(PNG_READ_GAMMA_SUPPORTED) - if (png_ptr->transformations & PNG_GAMMA) - { - int i; - - for (i = 0; i < num_palette; i++) - { - palette[i].red = png_ptr->gamma_table[palette[i].red]; - palette[i].green = png_ptr->gamma_table[palette[i].green]; - palette[i].blue = png_ptr->gamma_table[palette[i].blue]; - } - } -#if defined(PNG_READ_BACKGROUND_SUPPORTED) - else -#endif -#endif -#if defined(PNG_READ_BACKGROUND_SUPPORTED) - if (png_ptr->transformations & PNG_BACKGROUND) - { - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - { - png_color back; - - back.red = (png_byte)png_ptr->background.red; - back.green = (png_byte)png_ptr->background.green; - back.blue = (png_byte)png_ptr->background.blue; - - for (i = 0; i < (int)png_ptr->num_trans; i++) - { - if (png_ptr->trans[i] == 0) - { - palette[i].red = back.red; - palette[i].green = back.green; - palette[i].blue = back.blue; - } - else if (png_ptr->trans[i] != 0xff) - { - png_composite(palette[i].red, png_ptr->palette[i].red, - png_ptr->trans[i], back.red); - png_composite(palette[i].green, png_ptr->palette[i].green, - png_ptr->trans[i], back.green); - png_composite(palette[i].blue, png_ptr->palette[i].blue, - png_ptr->trans[i], back.blue); - } - } - } - else /* assume grayscale palette (what else could it be?) */ - { - int i; - - for (i = 0; i < num_palette; i++) - { - if (i == (png_byte)png_ptr->trans_values.gray) - { - palette[i].red = (png_byte)png_ptr->background.red; - palette[i].green = (png_byte)png_ptr->background.green; - palette[i].blue = (png_byte)png_ptr->background.blue; - } - } - } - } -#endif -} -#endif - -#if defined(PNG_READ_BACKGROUND_SUPPORTED) -/* Replace any alpha or transparency with the supplied background color. - * "background" is already in the screen gamma, while "background_1" is - * at a gamma of 1.0. Paletted files have already been taken care of. - */ -void /* PRIVATE */ -png_do_background(png_row_infop row_info, png_bytep row, - png_color_16p trans_values, png_color_16p background -#if defined(PNG_READ_GAMMA_SUPPORTED) - , png_color_16p background_1, - png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1, - png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1, - png_uint_16pp gamma_16_to_1, int gamma_shift -#endif - ) -{ - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width=row_info->width; - int shift; - - png_debug(1, "in png_do_background\n"); - if (background != NULL && -#if defined(PNG_USELESS_TESTS_SUPPORTED) - row != NULL && row_info != NULL && -#endif - (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) || - (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_values))) - { - switch (row_info->color_type) - { - case PNG_COLOR_TYPE_GRAY: - { - switch (row_info->bit_depth) - { - case 1: - { - sp = row; - shift = 7; - for (i = 0; i < row_width; i++) - { - if ((png_uint_16)((*sp >> shift) & 0x01) - == trans_values->gray) - { - *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); - *sp |= (png_byte)(background->gray << shift); - } - if (!shift) - { - shift = 7; - sp++; - } - else - shift--; - } - break; - } - case 2: - { -#if defined(PNG_READ_GAMMA_SUPPORTED) - if (gamma_table != NULL) - { - sp = row; - shift = 6; - for (i = 0; i < row_width; i++) - { - if ((png_uint_16)((*sp >> shift) & 0x03) - == trans_values->gray) - { - *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); - *sp |= (png_byte)(background->gray << shift); - } - else - { - png_byte p = (png_byte)((*sp >> shift) & 0x03); - png_byte g = (png_byte)((gamma_table [p | (p << 2) | - (p << 4) | (p << 6)] >> 6) & 0x03); - *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); - *sp |= (png_byte)(g << shift); - } - if (!shift) - { - shift = 6; - sp++; - } - else - shift -= 2; - } - } - else -#endif - { - sp = row; - shift = 6; - for (i = 0; i < row_width; i++) - { - if ((png_uint_16)((*sp >> shift) & 0x03) - == trans_values->gray) - { - *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); - *sp |= (png_byte)(background->gray << shift); - } - if (!shift) - { - shift = 6; - sp++; - } - else - shift -= 2; - } - } - break; - } - case 4: - { -#if defined(PNG_READ_GAMMA_SUPPORTED) - if (gamma_table != NULL) - { - sp = row; - shift = 4; - for (i = 0; i < row_width; i++) - { - if ((png_uint_16)((*sp >> shift) & 0x0f) - == trans_values->gray) - { - *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); - *sp |= (png_byte)(background->gray << shift); - } - else - { - png_byte p = (png_byte)((*sp >> shift) & 0x0f); - png_byte g = (png_byte)((gamma_table[p | - (p << 4)] >> 4) & 0x0f); - *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); - *sp |= (png_byte)(g << shift); - } - if (!shift) - { - shift = 4; - sp++; - } - else - shift -= 4; - } - } - else -#endif - { - sp = row; - shift = 4; - for (i = 0; i < row_width; i++) - { - if ((png_uint_16)((*sp >> shift) & 0x0f) - == trans_values->gray) - { - *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); - *sp |= (png_byte)(background->gray << shift); - } - if (!shift) - { - shift = 4; - sp++; - } - else - shift -= 4; - } - } - break; - } - case 8: - { -#if defined(PNG_READ_GAMMA_SUPPORTED) - if (gamma_table != NULL) - { - sp = row; - for (i = 0; i < row_width; i++, sp++) - { - if (*sp == trans_values->gray) - { - *sp = (png_byte)background->gray; - } - else - { - *sp = gamma_table[*sp]; - } - } - } - else -#endif - { - sp = row; - for (i = 0; i < row_width; i++, sp++) - { - if (*sp == trans_values->gray) - { - *sp = (png_byte)background->gray; - } - } - } - break; - } - case 16: - { -#if defined(PNG_READ_GAMMA_SUPPORTED) - if (gamma_16 != NULL) - { - sp = row; - for (i = 0; i < row_width; i++, sp += 2) - { - png_uint_16 v; - - v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - if (v == trans_values->gray) - { - /* background is already in screen gamma */ - *sp = (png_byte)((background->gray >> 8) & 0xff); - *(sp + 1) = (png_byte)(background->gray & 0xff); - } - else - { - v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - } - } - } - else -#endif - { - sp = row; - for (i = 0; i < row_width; i++, sp += 2) - { - png_uint_16 v; - - v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - if (v == trans_values->gray) - { - *sp = (png_byte)((background->gray >> 8) & 0xff); - *(sp + 1) = (png_byte)(background->gray & 0xff); - } - } - } - break; - } - } - break; - } - case PNG_COLOR_TYPE_RGB: - { - if (row_info->bit_depth == 8) - { -#if defined(PNG_READ_GAMMA_SUPPORTED) - if (gamma_table != NULL) - { - sp = row; - for (i = 0; i < row_width; i++, sp += 3) - { - if (*sp == trans_values->red && - *(sp + 1) == trans_values->green && - *(sp + 2) == trans_values->blue) - { - *sp = (png_byte)background->red; - *(sp + 1) = (png_byte)background->green; - *(sp + 2) = (png_byte)background->blue; - } - else - { - *sp = gamma_table[*sp]; - *(sp + 1) = gamma_table[*(sp + 1)]; - *(sp + 2) = gamma_table[*(sp + 2)]; - } - } - } - else -#endif - { - sp = row; - for (i = 0; i < row_width; i++, sp += 3) - { - if (*sp == trans_values->red && - *(sp + 1) == trans_values->green && - *(sp + 2) == trans_values->blue) - { - *sp = (png_byte)background->red; - *(sp + 1) = (png_byte)background->green; - *(sp + 2) = (png_byte)background->blue; - } - } - } - } - else /* if (row_info->bit_depth == 16) */ - { -#if defined(PNG_READ_GAMMA_SUPPORTED) - if (gamma_16 != NULL) - { - sp = row; - for (i = 0; i < row_width; i++, sp += 6) - { - png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); - png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5)); - if (r == trans_values->red && g == trans_values->green && - b == trans_values->blue) - { - /* background is already in screen gamma */ - *sp = (png_byte)((background->red >> 8) & 0xff); - *(sp + 1) = (png_byte)(background->red & 0xff); - *(sp + 2) = (png_byte)((background->green >> 8) & 0xff); - *(sp + 3) = (png_byte)(background->green & 0xff); - *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff); - *(sp + 5) = (png_byte)(background->blue & 0xff); - } - else - { - png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; - *(sp + 2) = (png_byte)((v >> 8) & 0xff); - *(sp + 3) = (png_byte)(v & 0xff); - v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; - *(sp + 4) = (png_byte)((v >> 8) & 0xff); - *(sp + 5) = (png_byte)(v & 0xff); - } - } - } - else -#endif - { - sp = row; - for (i = 0; i < row_width; i++, sp += 6) - { - png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp+1)); - png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); - png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5)); - - if (r == trans_values->red && g == trans_values->green && - b == trans_values->blue) - { - *sp = (png_byte)((background->red >> 8) & 0xff); - *(sp + 1) = (png_byte)(background->red & 0xff); - *(sp + 2) = (png_byte)((background->green >> 8) & 0xff); - *(sp + 3) = (png_byte)(background->green & 0xff); - *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff); - *(sp + 5) = (png_byte)(background->blue & 0xff); - } - } - } - } - break; - } - case PNG_COLOR_TYPE_GRAY_ALPHA: - { - if (row_info->bit_depth == 8) - { -#if defined(PNG_READ_GAMMA_SUPPORTED) - if (gamma_to_1 != NULL && gamma_from_1 != NULL && - gamma_table != NULL) - { - sp = row; - dp = row; - for (i = 0; i < row_width; i++, sp += 2, dp++) - { - png_uint_16 a = *(sp + 1); - - if (a == 0xff) - { - *dp = gamma_table[*sp]; - } - else if (a == 0) - { - /* background is already in screen gamma */ - *dp = (png_byte)background->gray; - } - else - { - png_byte v, w; - - v = gamma_to_1[*sp]; - png_composite(w, v, a, background_1->gray); - *dp = gamma_from_1[w]; - } - } - } - else -#endif - { - sp = row; - dp = row; - for (i = 0; i < row_width; i++, sp += 2, dp++) - { - png_byte a = *(sp + 1); - - if (a == 0xff) - { - *dp = *sp; - } -#if defined(PNG_READ_GAMMA_SUPPORTED) - else if (a == 0) - { - *dp = (png_byte)background->gray; - } - else - { - png_composite(*dp, *sp, a, background_1->gray); - } -#else - *dp = (png_byte)background->gray; -#endif - } - } - } - else /* if (png_ptr->bit_depth == 16) */ - { -#if defined(PNG_READ_GAMMA_SUPPORTED) - if (gamma_16 != NULL && gamma_16_from_1 != NULL && - gamma_16_to_1 != NULL) - { - sp = row; - dp = row; - for (i = 0; i < row_width; i++, sp += 4, dp += 2) - { - png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); - - if (a == (png_uint_16)0xffff) - { - png_uint_16 v; - - v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; - *dp = (png_byte)((v >> 8) & 0xff); - *(dp + 1) = (png_byte)(v & 0xff); - } -#if defined(PNG_READ_GAMMA_SUPPORTED) - else if (a == 0) -#else - else -#endif - { - /* background is already in screen gamma */ - *dp = (png_byte)((background->gray >> 8) & 0xff); - *(dp + 1) = (png_byte)(background->gray & 0xff); - } -#if defined(PNG_READ_GAMMA_SUPPORTED) - else - { - png_uint_16 g, v, w; - - g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; - png_composite_16(v, g, a, background_1->gray); - w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8]; - *dp = (png_byte)((w >> 8) & 0xff); - *(dp + 1) = (png_byte)(w & 0xff); - } -#endif - } - } - else -#endif - { - sp = row; - dp = row; - for (i = 0; i < row_width; i++, sp += 4, dp += 2) - { - png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); - if (a == (png_uint_16)0xffff) - { - png_memcpy(dp, sp, 2); - } -#if defined(PNG_READ_GAMMA_SUPPORTED) - else if (a == 0) -#else - else -#endif - { - *dp = (png_byte)((background->gray >> 8) & 0xff); - *(dp + 1) = (png_byte)(background->gray & 0xff); - } -#if defined(PNG_READ_GAMMA_SUPPORTED) - else - { - png_uint_16 g, v; - - g = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - png_composite_16(v, g, a, background_1->gray); - *dp = (png_byte)((v >> 8) & 0xff); - *(dp + 1) = (png_byte)(v & 0xff); - } -#endif - } - } - } - break; - } - case PNG_COLOR_TYPE_RGB_ALPHA: - { - if (row_info->bit_depth == 8) - { -#if defined(PNG_READ_GAMMA_SUPPORTED) - if (gamma_to_1 != NULL && gamma_from_1 != NULL && - gamma_table != NULL) - { - sp = row; - dp = row; - for (i = 0; i < row_width; i++, sp += 4, dp += 3) - { - png_byte a = *(sp + 3); - - if (a == 0xff) - { - *dp = gamma_table[*sp]; - *(dp + 1) = gamma_table[*(sp + 1)]; - *(dp + 2) = gamma_table[*(sp + 2)]; - } - else if (a == 0) - { - /* background is already in screen gamma */ - *dp = (png_byte)background->red; - *(dp + 1) = (png_byte)background->green; - *(dp + 2) = (png_byte)background->blue; - } - else - { - png_byte v, w; - - v = gamma_to_1[*sp]; - png_composite(w, v, a, background_1->red); - *dp = gamma_from_1[w]; - v = gamma_to_1[*(sp + 1)]; - png_composite(w, v, a, background_1->green); - *(dp + 1) = gamma_from_1[w]; - v = gamma_to_1[*(sp + 2)]; - png_composite(w, v, a, background_1->blue); - *(dp + 2) = gamma_from_1[w]; - } - } - } - else -#endif - { - sp = row; - dp = row; - for (i = 0; i < row_width; i++, sp += 4, dp += 3) - { - png_byte a = *(sp + 3); - - if (a == 0xff) - { - *dp = *sp; - *(dp + 1) = *(sp + 1); - *(dp + 2) = *(sp + 2); - } - else if (a == 0) - { - *dp = (png_byte)background->red; - *(dp + 1) = (png_byte)background->green; - *(dp + 2) = (png_byte)background->blue; - } - else - { - png_composite(*dp, *sp, a, background->red); - png_composite(*(dp + 1), *(sp + 1), a, - background->green); - png_composite(*(dp + 2), *(sp + 2), a, - background->blue); - } - } - } - } - else /* if (row_info->bit_depth == 16) */ - { -#if defined(PNG_READ_GAMMA_SUPPORTED) - if (gamma_16 != NULL && gamma_16_from_1 != NULL && - gamma_16_to_1 != NULL) - { - sp = row; - dp = row; - for (i = 0; i < row_width; i++, sp += 8, dp += 6) - { - png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) - << 8) + (png_uint_16)(*(sp + 7))); - if (a == (png_uint_16)0xffff) - { - png_uint_16 v; - - v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; - *dp = (png_byte)((v >> 8) & 0xff); - *(dp + 1) = (png_byte)(v & 0xff); - v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; - *(dp + 2) = (png_byte)((v >> 8) & 0xff); - *(dp + 3) = (png_byte)(v & 0xff); - v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; - *(dp + 4) = (png_byte)((v >> 8) & 0xff); - *(dp + 5) = (png_byte)(v & 0xff); - } - else if (a == 0) - { - /* background is already in screen gamma */ - *dp = (png_byte)((background->red >> 8) & 0xff); - *(dp + 1) = (png_byte)(background->red & 0xff); - *(dp + 2) = (png_byte)((background->green >> 8) & 0xff); - *(dp + 3) = (png_byte)(background->green & 0xff); - *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff); - *(dp + 5) = (png_byte)(background->blue & 0xff); - } - else - { - png_uint_16 v, w, x; - - v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; - png_composite_16(w, v, a, background_1->red); - x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; - *dp = (png_byte)((x >> 8) & 0xff); - *(dp + 1) = (png_byte)(x & 0xff); - v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)]; - png_composite_16(w, v, a, background_1->green); - x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; - *(dp + 2) = (png_byte)((x >> 8) & 0xff); - *(dp + 3) = (png_byte)(x & 0xff); - v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)]; - png_composite_16(w, v, a, background_1->blue); - x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8]; - *(dp + 4) = (png_byte)((x >> 8) & 0xff); - *(dp + 5) = (png_byte)(x & 0xff); - } - } - } - else -#endif - { - sp = row; - dp = row; - for (i = 0; i < row_width; i++, sp += 8, dp += 6) - { - png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) - << 8) + (png_uint_16)(*(sp + 7))); - if (a == (png_uint_16)0xffff) - { - png_memcpy(dp, sp, 6); - } - else if (a == 0) - { - *dp = (png_byte)((background->red >> 8) & 0xff); - *(dp + 1) = (png_byte)(background->red & 0xff); - *(dp + 2) = (png_byte)((background->green >> 8) & 0xff); - *(dp + 3) = (png_byte)(background->green & 0xff); - *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff); - *(dp + 5) = (png_byte)(background->blue & 0xff); - } - else - { - png_uint_16 v; - - png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) - + *(sp + 3)); - png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) - + *(sp + 5)); - - png_composite_16(v, r, a, background->red); - *dp = (png_byte)((v >> 8) & 0xff); - *(dp + 1) = (png_byte)(v & 0xff); - png_composite_16(v, g, a, background->green); - *(dp + 2) = (png_byte)((v >> 8) & 0xff); - *(dp + 3) = (png_byte)(v & 0xff); - png_composite_16(v, b, a, background->blue); - *(dp + 4) = (png_byte)((v >> 8) & 0xff); - *(dp + 5) = (png_byte)(v & 0xff); - } - } - } - } - break; - } - } - - if (row_info->color_type & PNG_COLOR_MASK_ALPHA) - { - row_info->color_type &= ~PNG_COLOR_MASK_ALPHA; - row_info->channels--; - row_info->pixel_depth = (png_byte)(row_info->channels * - row_info->bit_depth); - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); - } - } -} -#endif - -#if defined(PNG_READ_GAMMA_SUPPORTED) -/* Gamma correct the image, avoiding the alpha channel. Make sure - * you do this after you deal with the transparency issue on grayscale - * or RGB images. If your bit depth is 8, use gamma_table, if it - * is 16, use gamma_16_table and gamma_shift. Build these with - * build_gamma_table(). - */ -void /* PRIVATE */ -png_do_gamma(png_row_infop row_info, png_bytep row, - png_bytep gamma_table, png_uint_16pp gamma_16_table, - int gamma_shift) -{ - png_bytep sp; - png_uint_32 i; - png_uint_32 row_width=row_info->width; - - png_debug(1, "in png_do_gamma\n"); - if ( -#if defined(PNG_USELESS_TESTS_SUPPORTED) - row != NULL && row_info != NULL && -#endif - ((row_info->bit_depth <= 8 && gamma_table != NULL) || - (row_info->bit_depth == 16 && gamma_16_table != NULL))) - { - switch (row_info->color_type) - { - case PNG_COLOR_TYPE_RGB: - { - if (row_info->bit_depth == 8) - { - sp = row; - for (i = 0; i < row_width; i++) - { - *sp = gamma_table[*sp]; - sp++; - *sp = gamma_table[*sp]; - sp++; - *sp = gamma_table[*sp]; - sp++; - } - } - else /* if (row_info->bit_depth == 16) */ - { - sp = row; - for (i = 0; i < row_width; i++) - { - png_uint_16 v; - - v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - sp += 2; - v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - sp += 2; - v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - sp += 2; - } - } - break; - } - case PNG_COLOR_TYPE_RGB_ALPHA: - { - if (row_info->bit_depth == 8) - { - sp = row; - for (i = 0; i < row_width; i++) - { - *sp = gamma_table[*sp]; - sp++; - *sp = gamma_table[*sp]; - sp++; - *sp = gamma_table[*sp]; - sp++; - sp++; - } - } - else /* if (row_info->bit_depth == 16) */ - { - sp = row; - for (i = 0; i < row_width; i++) - { - png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - sp += 2; - v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - sp += 2; - v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - sp += 4; - } - } - break; - } - case PNG_COLOR_TYPE_GRAY_ALPHA: - { - if (row_info->bit_depth == 8) - { - sp = row; - for (i = 0; i < row_width; i++) - { - *sp = gamma_table[*sp]; - sp += 2; - } - } - else /* if (row_info->bit_depth == 16) */ - { - sp = row; - for (i = 0; i < row_width; i++) - { - png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - sp += 4; - } - } - break; - } - case PNG_COLOR_TYPE_GRAY: - { - if (row_info->bit_depth == 2) - { - sp = row; - for (i = 0; i < row_width; i += 4) - { - int a = *sp & 0xc0; - int b = *sp & 0x30; - int c = *sp & 0x0c; - int d = *sp & 0x03; - - *sp = (png_byte)( - ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)| - ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)| - ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)| - ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) )); - sp++; - } - } - if (row_info->bit_depth == 4) - { - sp = row; - for (i = 0; i < row_width; i += 2) - { - int msb = *sp & 0xf0; - int lsb = *sp & 0x0f; - - *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0) - | (((int)gamma_table[(lsb << 4) | lsb]) >> 4)); - sp++; - } - } - else if (row_info->bit_depth == 8) - { - sp = row; - for (i = 0; i < row_width; i++) - { - *sp = gamma_table[*sp]; - sp++; - } - } - else if (row_info->bit_depth == 16) - { - sp = row; - for (i = 0; i < row_width; i++) - { - png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - sp += 2; - } - } - break; - } - } - } -} -#endif - -#if defined(PNG_READ_EXPAND_SUPPORTED) -/* Expands a palette row to an RGB or RGBA row depending - * upon whether you supply trans and num_trans. - */ -void /* PRIVATE */ -png_do_expand_palette(png_row_infop row_info, png_bytep row, - png_colorp palette, png_bytep trans, int num_trans) -{ - int shift, value; - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width=row_info->width; - - png_debug(1, "in png_do_expand_palette\n"); - if ( -#if defined(PNG_USELESS_TESTS_SUPPORTED) - row != NULL && row_info != NULL && -#endif - row_info->color_type == PNG_COLOR_TYPE_PALETTE) - { - if (row_info->bit_depth < 8) - { - switch (row_info->bit_depth) - { - case 1: - { - sp = row + (png_size_t)((row_width - 1) >> 3); - dp = row + (png_size_t)row_width - 1; - shift = 7 - (int)((row_width + 7) & 0x07); - for (i = 0; i < row_width; i++) - { - if ((*sp >> shift) & 0x01) - *dp = 1; - else - *dp = 0; - if (shift == 7) - { - shift = 0; - sp--; - } - else - shift++; - - dp--; - } - break; - } - case 2: - { - sp = row + (png_size_t)((row_width - 1) >> 2); - dp = row + (png_size_t)row_width - 1; - shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); - for (i = 0; i < row_width; i++) - { - value = (*sp >> shift) & 0x03; - *dp = (png_byte)value; - if (shift == 6) - { - shift = 0; - sp--; - } - else - shift += 2; - - dp--; - } - break; - } - case 4: - { - sp = row + (png_size_t)((row_width - 1) >> 1); - dp = row + (png_size_t)row_width - 1; - shift = (int)((row_width & 0x01) << 2); - for (i = 0; i < row_width; i++) - { - value = (*sp >> shift) & 0x0f; - *dp = (png_byte)value; - if (shift == 4) - { - shift = 0; - sp--; - } - else - shift += 4; - - dp--; - } - break; - } - } - row_info->bit_depth = 8; - row_info->pixel_depth = 8; - row_info->rowbytes = row_width; - } - switch (row_info->bit_depth) - { - case 8: - { - if (trans != NULL) - { - sp = row + (png_size_t)row_width - 1; - dp = row + (png_size_t)(row_width << 2) - 1; - - for (i = 0; i < row_width; i++) - { - if ((int)(*sp) >= num_trans) - *dp-- = 0xff; - else - *dp-- = trans[*sp]; - *dp-- = palette[*sp].blue; - *dp-- = palette[*sp].green; - *dp-- = palette[*sp].red; - sp--; - } - row_info->bit_depth = 8; - row_info->pixel_depth = 32; - row_info->rowbytes = row_width * 4; - row_info->color_type = 6; - row_info->channels = 4; - } - else - { - sp = row + (png_size_t)row_width - 1; - dp = row + (png_size_t)(row_width * 3) - 1; - - for (i = 0; i < row_width; i++) - { - *dp-- = palette[*sp].blue; - *dp-- = palette[*sp].green; - *dp-- = palette[*sp].red; - sp--; - } - row_info->bit_depth = 8; - row_info->pixel_depth = 24; - row_info->rowbytes = row_width * 3; - row_info->color_type = 2; - row_info->channels = 3; - } - break; - } - } - } -} - -/* If the bit depth < 8, it is expanded to 8. Also, if the already - * expanded transparency value is supplied, an alpha channel is built. - */ -void /* PRIVATE */ -png_do_expand(png_row_infop row_info, png_bytep row, - png_color_16p trans_value) -{ - int shift, value; - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width=row_info->width; - - png_debug(1, "in png_do_expand\n"); -#if defined(PNG_USELESS_TESTS_SUPPORTED) - if (row != NULL && row_info != NULL) -#endif - { - if (row_info->color_type == PNG_COLOR_TYPE_GRAY) - { - png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0); - - if (row_info->bit_depth < 8) - { - switch (row_info->bit_depth) - { - case 1: - { - gray = (png_uint_16)((gray&0x01)*0xff); - sp = row + (png_size_t)((row_width - 1) >> 3); - dp = row + (png_size_t)row_width - 1; - shift = 7 - (int)((row_width + 7) & 0x07); - for (i = 0; i < row_width; i++) - { - if ((*sp >> shift) & 0x01) - *dp = 0xff; - else - *dp = 0; - if (shift == 7) - { - shift = 0; - sp--; - } - else - shift++; - - dp--; - } - break; - } - case 2: - { - gray = (png_uint_16)((gray&0x03)*0x55); - sp = row + (png_size_t)((row_width - 1) >> 2); - dp = row + (png_size_t)row_width - 1; - shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); - for (i = 0; i < row_width; i++) - { - value = (*sp >> shift) & 0x03; - *dp = (png_byte)(value | (value << 2) | (value << 4) | - (value << 6)); - if (shift == 6) - { - shift = 0; - sp--; - } - else - shift += 2; - - dp--; - } - break; - } - case 4: - { - gray = (png_uint_16)((gray&0x0f)*0x11); - sp = row + (png_size_t)((row_width - 1) >> 1); - dp = row + (png_size_t)row_width - 1; - shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); - for (i = 0; i < row_width; i++) - { - value = (*sp >> shift) & 0x0f; - *dp = (png_byte)(value | (value << 4)); - if (shift == 4) - { - shift = 0; - sp--; - } - else - shift = 4; - - dp--; - } - break; - } - } - row_info->bit_depth = 8; - row_info->pixel_depth = 8; - row_info->rowbytes = row_width; - } - - if (trans_value != NULL) - { - if (row_info->bit_depth == 8) - { - gray = gray & 0xff; - sp = row + (png_size_t)row_width - 1; - dp = row + (png_size_t)(row_width << 1) - 1; - for (i = 0; i < row_width; i++) - { - if (*sp == gray) - *dp-- = 0; - else - *dp-- = 0xff; - *dp-- = *sp--; - } - } - else if (row_info->bit_depth == 16) - { - png_byte gray_high = (gray >> 8) & 0xff; - png_byte gray_low = gray & 0xff; - sp = row + row_info->rowbytes - 1; - dp = row + (row_info->rowbytes << 1) - 1; - for (i = 0; i < row_width; i++) - { - if (*(sp-1) == gray_high && *(sp) == gray_low) - { - *dp-- = 0; - *dp-- = 0; - } - else - { - *dp-- = 0xff; - *dp-- = 0xff; - } - *dp-- = *sp--; - *dp-- = *sp--; - } - } - row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA; - row_info->channels = 2; - row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1); - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, - row_width); - } - } - else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value) - { - if (row_info->bit_depth == 8) - { - png_byte red = trans_value->red & 0xff; - png_byte green = trans_value->green & 0xff; - png_byte blue = trans_value->blue & 0xff; - sp = row + (png_size_t)row_info->rowbytes - 1; - dp = row + (png_size_t)(row_width << 2) - 1; - for (i = 0; i < row_width; i++) - { - if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue) - *dp-- = 0; - else - *dp-- = 0xff; - *dp-- = *sp--; - *dp-- = *sp--; - *dp-- = *sp--; - } - } - else if (row_info->bit_depth == 16) - { - png_byte red_high = (trans_value->red >> 8) & 0xff; - png_byte green_high = (trans_value->green >> 8) & 0xff; - png_byte blue_high = (trans_value->blue >> 8) & 0xff; - png_byte red_low = trans_value->red & 0xff; - png_byte green_low = trans_value->green & 0xff; - png_byte blue_low = trans_value->blue & 0xff; - sp = row + row_info->rowbytes - 1; - dp = row + (png_size_t)(row_width << 3) - 1; - for (i = 0; i < row_width; i++) - { - if (*(sp - 5) == red_high && - *(sp - 4) == red_low && - *(sp - 3) == green_high && - *(sp - 2) == green_low && - *(sp - 1) == blue_high && - *(sp ) == blue_low) - { - *dp-- = 0; - *dp-- = 0; - } - else - { - *dp-- = 0xff; - *dp-- = 0xff; - } - *dp-- = *sp--; - *dp-- = *sp--; - *dp-- = *sp--; - *dp-- = *sp--; - *dp-- = *sp--; - *dp-- = *sp--; - } - } - row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA; - row_info->channels = 4; - row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2); - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); - } - } -} -#endif - -#if defined(PNG_READ_DITHER_SUPPORTED) -void /* PRIVATE */ -png_do_dither(png_row_infop row_info, png_bytep row, - png_bytep palette_lookup, png_bytep dither_lookup) -{ - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width=row_info->width; - - png_debug(1, "in png_do_dither\n"); -#if defined(PNG_USELESS_TESTS_SUPPORTED) - if (row != NULL && row_info != NULL) -#endif - { - if (row_info->color_type == PNG_COLOR_TYPE_RGB && - palette_lookup && row_info->bit_depth == 8) - { - int r, g, b, p; - sp = row; - dp = row; - for (i = 0; i < row_width; i++) - { - r = *sp++; - g = *sp++; - b = *sp++; - - /* this looks real messy, but the compiler will reduce - it down to a reasonable formula. For example, with - 5 bits per color, we get: - p = (((r >> 3) & 0x1f) << 10) | - (((g >> 3) & 0x1f) << 5) | - ((b >> 3) & 0x1f); - */ - p = (((r >> (8 - PNG_DITHER_RED_BITS)) & - ((1 << PNG_DITHER_RED_BITS) - 1)) << - (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) | - (((g >> (8 - PNG_DITHER_GREEN_BITS)) & - ((1 << PNG_DITHER_GREEN_BITS) - 1)) << - (PNG_DITHER_BLUE_BITS)) | - ((b >> (8 - PNG_DITHER_BLUE_BITS)) & - ((1 << PNG_DITHER_BLUE_BITS) - 1)); - - *dp++ = palette_lookup[p]; - } - row_info->color_type = PNG_COLOR_TYPE_PALETTE; - row_info->channels = 1; - row_info->pixel_depth = row_info->bit_depth; - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); - } - else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA && - palette_lookup != NULL && row_info->bit_depth == 8) - { - int r, g, b, p; - sp = row; - dp = row; - for (i = 0; i < row_width; i++) - { - r = *sp++; - g = *sp++; - b = *sp++; - sp++; - - p = (((r >> (8 - PNG_DITHER_RED_BITS)) & - ((1 << PNG_DITHER_RED_BITS) - 1)) << - (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) | - (((g >> (8 - PNG_DITHER_GREEN_BITS)) & - ((1 << PNG_DITHER_GREEN_BITS) - 1)) << - (PNG_DITHER_BLUE_BITS)) | - ((b >> (8 - PNG_DITHER_BLUE_BITS)) & - ((1 << PNG_DITHER_BLUE_BITS) - 1)); - - *dp++ = palette_lookup[p]; - } - row_info->color_type = PNG_COLOR_TYPE_PALETTE; - row_info->channels = 1; - row_info->pixel_depth = row_info->bit_depth; - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); - } - else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE && - dither_lookup && row_info->bit_depth == 8) - { - sp = row; - for (i = 0; i < row_width; i++, sp++) - { - *sp = dither_lookup[*sp]; - } - } - } -} -#endif - -#ifdef PNG_FLOATING_POINT_SUPPORTED -#if defined(PNG_READ_GAMMA_SUPPORTED) -static PNG_CONST int png_gamma_shift[] = - {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0, 0x00}; - -/* We build the 8- or 16-bit gamma tables here. Note that for 16-bit - * tables, we don't make a full table if we are reducing to 8-bit in - * the future. Note also how the gamma_16 tables are segmented so that - * we don't need to allocate > 64K chunks for a full 16-bit table. - */ -void /* PRIVATE */ -png_build_gamma_table(png_structp png_ptr) -{ - png_debug(1, "in png_build_gamma_table\n"); - - if (png_ptr->bit_depth <= 8) - { - int i; - double g; - - if (png_ptr->screen_gamma > .000001) - g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); - else - g = 1.0; - - png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr, - (png_uint_32)256); - - for (i = 0; i < 256; i++) - { - png_ptr->gamma_table[i] = (png_byte)(pow((double)i / 255.0, - g) * 255.0 + .5); - } - -#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ - defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) - if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY)) - { - - g = 1.0 / (png_ptr->gamma); - - png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr, - (png_uint_32)256); - - for (i = 0; i < 256; i++) - { - png_ptr->gamma_to_1[i] = (png_byte)(pow((double)i / 255.0, - g) * 255.0 + .5); - } - - - png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr, - (png_uint_32)256); - - if(png_ptr->screen_gamma > 0.000001) - g = 1.0 / png_ptr->screen_gamma; - else - g = png_ptr->gamma; /* probably doing rgb_to_gray */ - - for (i = 0; i < 256; i++) - { - png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0, - g) * 255.0 + .5); - - } - } -#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */ - } - else - { - double g; - int i, j, shift, num; - int sig_bit; - png_uint_32 ig; - - if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) - { - sig_bit = (int)png_ptr->sig_bit.red; - if ((int)png_ptr->sig_bit.green > sig_bit) - sig_bit = png_ptr->sig_bit.green; - if ((int)png_ptr->sig_bit.blue > sig_bit) - sig_bit = png_ptr->sig_bit.blue; - } - else - { - sig_bit = (int)png_ptr->sig_bit.gray; - } - - if (sig_bit > 0) - shift = 16 - sig_bit; - else - shift = 0; - - if (png_ptr->transformations & PNG_16_TO_8) - { - if (shift < (16 - PNG_MAX_GAMMA_8)) - shift = (16 - PNG_MAX_GAMMA_8); - } - - if (shift > 8) - shift = 8; - if (shift < 0) - shift = 0; - - png_ptr->gamma_shift = (png_byte)shift; - - num = (1 << (8 - shift)); - - if (png_ptr->screen_gamma > .000001) - g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); - else - g = 1.0; - - png_ptr->gamma_16_table = (png_uint_16pp)png_malloc(png_ptr, - (png_uint_32)(num * png_sizeof (png_uint_16p))); - - if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND)) - { - double fin, fout; - png_uint_32 last, max; - - for (i = 0; i < num; i++) - { - png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr, - (png_uint_32)(256 * png_sizeof (png_uint_16))); - } - - g = 1.0 / g; - last = 0; - for (i = 0; i < 256; i++) - { - fout = ((double)i + 0.5) / 256.0; - fin = pow(fout, g); - max = (png_uint_32)(fin * (double)((png_uint_32)num << 8)); - while (last <= max) - { - png_ptr->gamma_16_table[(int)(last & (0xff >> shift))] - [(int)(last >> (8 - shift))] = (png_uint_16)( - (png_uint_16)i | ((png_uint_16)i << 8)); - last++; - } - } - while (last < ((png_uint_32)num << 8)) - { - png_ptr->gamma_16_table[(int)(last & (0xff >> shift))] - [(int)(last >> (8 - shift))] = (png_uint_16)65535L; - last++; - } - } - else - { - for (i = 0; i < num; i++) - { - png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr, - (png_uint_32)(256 * png_sizeof (png_uint_16))); - - ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4); - for (j = 0; j < 256; j++) - { - png_ptr->gamma_16_table[i][j] = - (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / - 65535.0, g) * 65535.0 + .5); - } - } - } - -#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ - defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) - if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY)) - { - - g = 1.0 / (png_ptr->gamma); - - png_ptr->gamma_16_to_1 = (png_uint_16pp)png_malloc(png_ptr, - (png_uint_32)(num * png_sizeof (png_uint_16p ))); - - for (i = 0; i < num; i++) - { - png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr, - (png_uint_32)(256 * png_sizeof (png_uint_16))); - - ig = (((png_uint_32)i * - (png_uint_32)png_gamma_shift[shift]) >> 4); - for (j = 0; j < 256; j++) - { - png_ptr->gamma_16_to_1[i][j] = - (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / - 65535.0, g) * 65535.0 + .5); - } - } - - if(png_ptr->screen_gamma > 0.000001) - g = 1.0 / png_ptr->screen_gamma; - else - g = png_ptr->gamma; /* probably doing rgb_to_gray */ - - png_ptr->gamma_16_from_1 = (png_uint_16pp)png_malloc(png_ptr, - (png_uint_32)(num * png_sizeof (png_uint_16p))); - - for (i = 0; i < num; i++) - { - png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr, - (png_uint_32)(256 * png_sizeof (png_uint_16))); - - ig = (((png_uint_32)i * - (png_uint_32)png_gamma_shift[shift]) >> 4); - for (j = 0; j < 256; j++) - { - png_ptr->gamma_16_from_1[i][j] = - (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / - 65535.0, g) * 65535.0 + .5); - } - } - } -#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */ - } -} -#endif -/* To do: install integer version of png_build_gamma_table here */ -#endif - -#if defined(PNG_MNG_FEATURES_SUPPORTED) -/* undoes intrapixel differencing */ -void /* PRIVATE */ -png_do_read_intrapixel(png_row_infop row_info, png_bytep row) -{ - png_debug(1, "in png_do_read_intrapixel\n"); - if ( -#if defined(PNG_USELESS_TESTS_SUPPORTED) - row != NULL && row_info != NULL && -#endif - (row_info->color_type & PNG_COLOR_MASK_COLOR)) - { - int bytes_per_pixel; - png_uint_32 row_width = row_info->width; - if (row_info->bit_depth == 8) - { - png_bytep rp; - png_uint_32 i; - - if (row_info->color_type == PNG_COLOR_TYPE_RGB) - bytes_per_pixel = 3; - else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - bytes_per_pixel = 4; - else - return; - - for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) - { - *(rp) = (png_byte)((256 + *rp + *(rp+1))&0xff); - *(rp+2) = (png_byte)((256 + *(rp+2) + *(rp+1))&0xff); - } - } - else if (row_info->bit_depth == 16) - { - png_bytep rp; - png_uint_32 i; - - if (row_info->color_type == PNG_COLOR_TYPE_RGB) - bytes_per_pixel = 6; - else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - bytes_per_pixel = 8; - else - return; - - for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) - { - png_uint_32 s0 = (*(rp ) << 8) | *(rp+1); - png_uint_32 s1 = (*(rp+2) << 8) | *(rp+3); - png_uint_32 s2 = (*(rp+4) << 8) | *(rp+5); - png_uint_32 red = (png_uint_32)((s0+s1+65536L) & 0xffffL); - png_uint_32 blue = (png_uint_32)((s2+s1+65536L) & 0xffffL); - *(rp ) = (png_byte)((red >> 8) & 0xff); - *(rp+1) = (png_byte)(red & 0xff); - *(rp+4) = (png_byte)((blue >> 8) & 0xff); - *(rp+5) = (png_byte)(blue & 0xff); - } - } - } -} -#endif /* PNG_MNG_FEATURES_SUPPORTED */ -#endif /* PNG_READ_SUPPORTED */ diff --git a/uppdev/plugin/png/lib/pngrutil.c b/uppdev/plugin/png/lib/pngrutil.c deleted file mode 100644 index 769056dc7..000000000 --- a/uppdev/plugin/png/lib/pngrutil.c +++ /dev/null @@ -1,3163 +0,0 @@ - -/* pngrutil.c - utilities to read a PNG file - * - * Last changed in libpng 1.2.22 [October 13, 2007] - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2007 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This file contains routines that are only called from within - * libpng itself during the course of reading an image. - */ - -#define PNG_INTERNAL -#include "png.h" - -#if defined(PNG_READ_SUPPORTED) - -#if defined(_WIN32_WCE) && (_WIN32_WCE<0x500) -# define WIN32_WCE_OLD -#endif - -#ifdef PNG_FLOATING_POINT_SUPPORTED -# if defined(WIN32_WCE_OLD) -/* strtod() function is not supported on WindowsCE */ -__inline double png_strtod(png_structp png_ptr, PNG_CONST char *nptr, char **endptr) -{ - double result = 0; - int len; - wchar_t *str, *end; - - len = MultiByteToWideChar(CP_ACP, 0, nptr, -1, NULL, 0); - str = (wchar_t *)png_malloc(png_ptr, len * sizeof(wchar_t)); - if ( NULL != str ) - { - MultiByteToWideChar(CP_ACP, 0, nptr, -1, str, len); - result = wcstod(str, &end); - len = WideCharToMultiByte(CP_ACP, 0, end, -1, NULL, 0, NULL, NULL); - *endptr = (char *)nptr + (png_strlen(nptr) - len + 1); - png_free(png_ptr, str); - } - return result; -} -# else -# define png_strtod(p,a,b) strtod(a,b) -# endif -#endif - -png_uint_32 PNGAPI -png_get_uint_31(png_structp png_ptr, png_bytep buf) -{ - png_uint_32 i = png_get_uint_32(buf); - if (i > PNG_UINT_31_MAX) - png_error(png_ptr, "PNG unsigned integer out of range."); - return (i); -} -#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED -/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */ -png_uint_32 PNGAPI -png_get_uint_32(png_bytep buf) -{ - png_uint_32 i = ((png_uint_32)(*buf) << 24) + - ((png_uint_32)(*(buf + 1)) << 16) + - ((png_uint_32)(*(buf + 2)) << 8) + - (png_uint_32)(*(buf + 3)); - - return (i); -} - -/* Grab a signed 32-bit integer from a buffer in big-endian format. The - * data is stored in the PNG file in two's complement format, and it is - * assumed that the machine format for signed integers is the same. */ -png_int_32 PNGAPI -png_get_int_32(png_bytep buf) -{ - png_int_32 i = ((png_int_32)(*buf) << 24) + - ((png_int_32)(*(buf + 1)) << 16) + - ((png_int_32)(*(buf + 2)) << 8) + - (png_int_32)(*(buf + 3)); - - return (i); -} - -/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */ -png_uint_16 PNGAPI -png_get_uint_16(png_bytep buf) -{ - png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) + - (png_uint_16)(*(buf + 1))); - - return (i); -} -#endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */ - -/* Read data, and (optionally) run it through the CRC. */ -void /* PRIVATE */ -png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length) -{ - if(png_ptr == NULL) return; - png_read_data(png_ptr, buf, length); - png_calculate_crc(png_ptr, buf, length); -} - -/* Optionally skip data and then check the CRC. Depending on whether we - are reading a ancillary or critical chunk, and how the program has set - things up, we may calculate the CRC on the data and print a message. - Returns '1' if there was a CRC error, '0' otherwise. */ -int /* PRIVATE */ -png_crc_finish(png_structp png_ptr, png_uint_32 skip) -{ - png_size_t i; - png_size_t istop = png_ptr->zbuf_size; - - for (i = (png_size_t)skip; i > istop; i -= istop) - { - png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); - } - if (i) - { - png_crc_read(png_ptr, png_ptr->zbuf, i); - } - - if (png_crc_error(png_ptr)) - { - if (((png_ptr->chunk_name[0] & 0x20) && /* Ancillary */ - !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) || - (!(png_ptr->chunk_name[0] & 0x20) && /* Critical */ - (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE))) - { - png_chunk_warning(png_ptr, "CRC error"); - } - else - { - png_chunk_error(png_ptr, "CRC error"); - } - return (1); - } - - return (0); -} - -/* Compare the CRC stored in the PNG file with that calculated by libpng from - the data it has read thus far. */ -int /* PRIVATE */ -png_crc_error(png_structp png_ptr) -{ - png_byte crc_bytes[4]; - png_uint_32 crc; - int need_crc = 1; - - if (png_ptr->chunk_name[0] & 0x20) /* ancillary */ - { - if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) == - (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) - need_crc = 0; - } - else /* critical */ - { - if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) - need_crc = 0; - } - - png_read_data(png_ptr, crc_bytes, 4); - - if (need_crc) - { - crc = png_get_uint_32(crc_bytes); - return ((int)(crc != png_ptr->crc)); - } - else - return (0); -} - -#if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \ - defined(PNG_READ_iCCP_SUPPORTED) -/* - * Decompress trailing data in a chunk. The assumption is that chunkdata - * points at an allocated area holding the contents of a chunk with a - * trailing compressed part. What we get back is an allocated area - * holding the original prefix part and an uncompressed version of the - * trailing part (the malloc area passed in is freed). - */ -png_charp /* PRIVATE */ -png_decompress_chunk(png_structp png_ptr, int comp_type, - png_charp chunkdata, png_size_t chunklength, - png_size_t prefix_size, png_size_t *newlength) -{ - static PNG_CONST char msg[] = "Error decoding compressed text"; - png_charp text; - png_size_t text_size; - - if (comp_type == PNG_COMPRESSION_TYPE_BASE) - { - int ret = Z_OK; - png_ptr->zstream.next_in = (png_bytep)(chunkdata + prefix_size); - png_ptr->zstream.avail_in = (uInt)(chunklength - prefix_size); - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - - text_size = 0; - text = NULL; - - while (png_ptr->zstream.avail_in) - { - ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); - if (ret != Z_OK && ret != Z_STREAM_END) - { - if (png_ptr->zstream.msg != NULL) - png_warning(png_ptr, png_ptr->zstream.msg); - else - png_warning(png_ptr, msg); - inflateReset(&png_ptr->zstream); - png_ptr->zstream.avail_in = 0; - - if (text == NULL) - { - text_size = prefix_size + png_sizeof(msg) + 1; - text = (png_charp)png_malloc_warn(png_ptr, text_size); - if (text == NULL) - { - png_free(png_ptr,chunkdata); - png_error(png_ptr,"Not enough memory to decompress chunk"); - } - png_memcpy(text, chunkdata, prefix_size); - } - - text[text_size - 1] = 0x00; - - /* Copy what we can of the error message into the text chunk */ - text_size = (png_size_t)(chunklength - (text - chunkdata) - 1); - text_size = png_sizeof(msg) > text_size ? text_size : - png_sizeof(msg); - png_memcpy(text + prefix_size, msg, text_size + 1); - break; - } - if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END) - { - if (text == NULL) - { - text_size = prefix_size + - png_ptr->zbuf_size - png_ptr->zstream.avail_out; - text = (png_charp)png_malloc_warn(png_ptr, text_size + 1); - if (text == NULL) - { - png_free(png_ptr,chunkdata); - png_error(png_ptr,"Not enough memory to decompress chunk."); - } - png_memcpy(text + prefix_size, png_ptr->zbuf, - text_size - prefix_size); - png_memcpy(text, chunkdata, prefix_size); - *(text + text_size) = 0x00; - } - else - { - png_charp tmp; - - tmp = text; - text = (png_charp)png_malloc_warn(png_ptr, - (png_uint_32)(text_size + - png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1)); - if (text == NULL) - { - png_free(png_ptr, tmp); - png_free(png_ptr, chunkdata); - png_error(png_ptr,"Not enough memory to decompress chunk.."); - } - png_memcpy(text, tmp, text_size); - png_free(png_ptr, tmp); - png_memcpy(text + text_size, png_ptr->zbuf, - (png_ptr->zbuf_size - png_ptr->zstream.avail_out)); - text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out; - *(text + text_size) = 0x00; - } - if (ret == Z_STREAM_END) - break; - else - { - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - } - } - } - if (ret != Z_STREAM_END) - { -#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) - char umsg[52]; - - if (ret == Z_BUF_ERROR) - png_snprintf(umsg, 52, - "Buffer error in compressed datastream in %s chunk", - png_ptr->chunk_name); - else if (ret == Z_DATA_ERROR) - png_snprintf(umsg, 52, - "Data error in compressed datastream in %s chunk", - png_ptr->chunk_name); - else - png_snprintf(umsg, 52, - "Incomplete compressed datastream in %s chunk", - png_ptr->chunk_name); - png_warning(png_ptr, umsg); -#else - png_warning(png_ptr, - "Incomplete compressed datastream in chunk other than IDAT"); -#endif - text_size=prefix_size; - if (text == NULL) - { - text = (png_charp)png_malloc_warn(png_ptr, text_size+1); - if (text == NULL) - { - png_free(png_ptr, chunkdata); - png_error(png_ptr,"Not enough memory for text."); - } - png_memcpy(text, chunkdata, prefix_size); - } - *(text + text_size) = 0x00; - } - - inflateReset(&png_ptr->zstream); - png_ptr->zstream.avail_in = 0; - - png_free(png_ptr, chunkdata); - chunkdata = text; - *newlength=text_size; - } - else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */ - { -#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) - char umsg[50]; - - png_snprintf(umsg, 50, - "Unknown zTXt compression type %d", comp_type); - png_warning(png_ptr, umsg); -#else - png_warning(png_ptr, "Unknown zTXt compression type"); -#endif - - *(chunkdata + prefix_size) = 0x00; - *newlength=prefix_size; - } - - return chunkdata; -} -#endif - -/* read and check the IDHR chunk */ -void /* PRIVATE */ -png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -{ - png_byte buf[13]; - png_uint_32 width, height; - int bit_depth, color_type, compression_type, filter_type; - int interlace_type; - - png_debug(1, "in png_handle_IHDR\n"); - - if (png_ptr->mode & PNG_HAVE_IHDR) - png_error(png_ptr, "Out of place IHDR"); - - /* check the length */ - if (length != 13) - png_error(png_ptr, "Invalid IHDR chunk"); - - png_ptr->mode |= PNG_HAVE_IHDR; - - png_crc_read(png_ptr, buf, 13); - png_crc_finish(png_ptr, 0); - - width = png_get_uint_31(png_ptr, buf); - height = png_get_uint_31(png_ptr, buf + 4); - bit_depth = buf[8]; - color_type = buf[9]; - compression_type = buf[10]; - filter_type = buf[11]; - interlace_type = buf[12]; - - /* set internal variables */ - png_ptr->width = width; - png_ptr->height = height; - png_ptr->bit_depth = (png_byte)bit_depth; - png_ptr->interlaced = (png_byte)interlace_type; - png_ptr->color_type = (png_byte)color_type; -#if defined(PNG_MNG_FEATURES_SUPPORTED) - png_ptr->filter_type = (png_byte)filter_type; -#endif - png_ptr->compression_type = (png_byte)compression_type; - - /* find number of channels */ - switch (png_ptr->color_type) - { - case PNG_COLOR_TYPE_GRAY: - case PNG_COLOR_TYPE_PALETTE: - png_ptr->channels = 1; - break; - case PNG_COLOR_TYPE_RGB: - png_ptr->channels = 3; - break; - case PNG_COLOR_TYPE_GRAY_ALPHA: - png_ptr->channels = 2; - break; - case PNG_COLOR_TYPE_RGB_ALPHA: - png_ptr->channels = 4; - break; - } - - /* set up other useful info */ - png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth * - png_ptr->channels); - png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->width); - png_debug1(3,"bit_depth = %d\n", png_ptr->bit_depth); - png_debug1(3,"channels = %d\n", png_ptr->channels); - png_debug1(3,"rowbytes = %lu\n", png_ptr->rowbytes); - png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, - color_type, interlace_type, compression_type, filter_type); -} - -/* read and check the palette */ -void /* PRIVATE */ -png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -{ - png_color palette[PNG_MAX_PALETTE_LENGTH]; - int num, i; -#ifndef PNG_NO_POINTER_INDEXING - png_colorp pal_ptr; -#endif - - png_debug(1, "in png_handle_PLTE\n"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before PLTE"); - else if (png_ptr->mode & PNG_HAVE_IDAT) - { - png_warning(png_ptr, "Invalid PLTE after IDAT"); - png_crc_finish(png_ptr, length); - return; - } - else if (png_ptr->mode & PNG_HAVE_PLTE) - png_error(png_ptr, "Duplicate PLTE chunk"); - - png_ptr->mode |= PNG_HAVE_PLTE; - - if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR)) - { - png_warning(png_ptr, - "Ignoring PLTE chunk in grayscale PNG"); - png_crc_finish(png_ptr, length); - return; - } -#if !defined(PNG_READ_OPT_PLTE_SUPPORTED) - if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) - { - png_crc_finish(png_ptr, length); - return; - } -#endif - - if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3) - { - if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) - { - png_warning(png_ptr, "Invalid palette chunk"); - png_crc_finish(png_ptr, length); - return; - } - else - { - png_error(png_ptr, "Invalid palette chunk"); - } - } - - num = (int)length / 3; - -#ifndef PNG_NO_POINTER_INDEXING - for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++) - { - png_byte buf[3]; - - png_crc_read(png_ptr, buf, 3); - pal_ptr->red = buf[0]; - pal_ptr->green = buf[1]; - pal_ptr->blue = buf[2]; - } -#else - for (i = 0; i < num; i++) - { - png_byte buf[3]; - - png_crc_read(png_ptr, buf, 3); - /* don't depend upon png_color being any order */ - palette[i].red = buf[0]; - palette[i].green = buf[1]; - palette[i].blue = buf[2]; - } -#endif - - /* If we actually NEED the PLTE chunk (ie for a paletted image), we do - whatever the normal CRC configuration tells us. However, if we - have an RGB image, the PLTE can be considered ancillary, so - we will act as though it is. */ -#if !defined(PNG_READ_OPT_PLTE_SUPPORTED) - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) -#endif - { - png_crc_finish(png_ptr, 0); - } -#if !defined(PNG_READ_OPT_PLTE_SUPPORTED) - else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */ - { - /* If we don't want to use the data from an ancillary chunk, - we have two options: an error abort, or a warning and we - ignore the data in this chunk (which should be OK, since - it's considered ancillary for a RGB or RGBA image). */ - if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE)) - { - if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) - { - png_chunk_error(png_ptr, "CRC error"); - } - else - { - png_chunk_warning(png_ptr, "CRC error"); - return; - } - } - /* Otherwise, we (optionally) emit a warning and use the chunk. */ - else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) - { - png_chunk_warning(png_ptr, "CRC error"); - } - } -#endif - - png_set_PLTE(png_ptr, info_ptr, palette, num); - -#if defined(PNG_READ_tRNS_SUPPORTED) - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - { - if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) - { - if (png_ptr->num_trans > (png_uint_16)num) - { - png_warning(png_ptr, "Truncating incorrect tRNS chunk length"); - png_ptr->num_trans = (png_uint_16)num; - } - if (info_ptr->num_trans > (png_uint_16)num) - { - png_warning(png_ptr, "Truncating incorrect info tRNS chunk length"); - info_ptr->num_trans = (png_uint_16)num; - } - } - } -#endif - -} - -void /* PRIVATE */ -png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -{ - png_debug(1, "in png_handle_IEND\n"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT)) - { - png_error(png_ptr, "No image in file"); - } - - png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND); - - if (length != 0) - { - png_warning(png_ptr, "Incorrect IEND chunk length"); - } - png_crc_finish(png_ptr, length); - - info_ptr =info_ptr; /* quiet compiler warnings about unused info_ptr */ -} - -#if defined(PNG_READ_gAMA_SUPPORTED) -void /* PRIVATE */ -png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -{ - png_fixed_point igamma; -#ifdef PNG_FLOATING_POINT_SUPPORTED - float file_gamma; -#endif - png_byte buf[4]; - - png_debug(1, "in png_handle_gAMA\n"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before gAMA"); - else if (png_ptr->mode & PNG_HAVE_IDAT) - { - png_warning(png_ptr, "Invalid gAMA after IDAT"); - png_crc_finish(png_ptr, length); - return; - } - else if (png_ptr->mode & PNG_HAVE_PLTE) - /* Should be an error, but we can cope with it */ - png_warning(png_ptr, "Out of place gAMA chunk"); - - if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA) -#if defined(PNG_READ_sRGB_SUPPORTED) - && !(info_ptr->valid & PNG_INFO_sRGB) -#endif - ) - { - png_warning(png_ptr, "Duplicate gAMA chunk"); - png_crc_finish(png_ptr, length); - return; - } - - if (length != 4) - { - png_warning(png_ptr, "Incorrect gAMA chunk length"); - png_crc_finish(png_ptr, length); - return; - } - - png_crc_read(png_ptr, buf, 4); - if (png_crc_finish(png_ptr, 0)) - return; - - igamma = (png_fixed_point)png_get_uint_32(buf); - /* check for zero gamma */ - if (igamma == 0) - { - png_warning(png_ptr, - "Ignoring gAMA chunk with gamma=0"); - return; - } - -#if defined(PNG_READ_sRGB_SUPPORTED) - if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB)) - if (PNG_OUT_OF_RANGE(igamma, 45500L, 500)) - { - png_warning(png_ptr, - "Ignoring incorrect gAMA value when sRGB is also present"); -#ifndef PNG_NO_CONSOLE_IO - fprintf(stderr, "gamma = (%d/100000)\n", (int)igamma); -#endif - return; - } -#endif /* PNG_READ_sRGB_SUPPORTED */ - -#ifdef PNG_FLOATING_POINT_SUPPORTED - file_gamma = (float)igamma / (float)100000.0; -# ifdef PNG_READ_GAMMA_SUPPORTED - png_ptr->gamma = file_gamma; -# endif - png_set_gAMA(png_ptr, info_ptr, file_gamma); -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED - png_set_gAMA_fixed(png_ptr, info_ptr, igamma); -#endif -} -#endif - -#if defined(PNG_READ_sBIT_SUPPORTED) -void /* PRIVATE */ -png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -{ - png_size_t truelen; - png_byte buf[4]; - - png_debug(1, "in png_handle_sBIT\n"); - - buf[0] = buf[1] = buf[2] = buf[3] = 0; - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before sBIT"); - else if (png_ptr->mode & PNG_HAVE_IDAT) - { - png_warning(png_ptr, "Invalid sBIT after IDAT"); - png_crc_finish(png_ptr, length); - return; - } - else if (png_ptr->mode & PNG_HAVE_PLTE) - { - /* Should be an error, but we can cope with it */ - png_warning(png_ptr, "Out of place sBIT chunk"); - } - if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT)) - { - png_warning(png_ptr, "Duplicate sBIT chunk"); - png_crc_finish(png_ptr, length); - return; - } - - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - truelen = 3; - else - truelen = (png_size_t)png_ptr->channels; - - if (length != truelen || length > 4) - { - png_warning(png_ptr, "Incorrect sBIT chunk length"); - png_crc_finish(png_ptr, length); - return; - } - - png_crc_read(png_ptr, buf, truelen); - if (png_crc_finish(png_ptr, 0)) - return; - - if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) - { - png_ptr->sig_bit.red = buf[0]; - png_ptr->sig_bit.green = buf[1]; - png_ptr->sig_bit.blue = buf[2]; - png_ptr->sig_bit.alpha = buf[3]; - } - else - { - png_ptr->sig_bit.gray = buf[0]; - png_ptr->sig_bit.red = buf[0]; - png_ptr->sig_bit.green = buf[0]; - png_ptr->sig_bit.blue = buf[0]; - png_ptr->sig_bit.alpha = buf[1]; - } - png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit)); -} -#endif - -#if defined(PNG_READ_cHRM_SUPPORTED) -void /* PRIVATE */ -png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -{ - png_byte buf[4]; -#ifdef PNG_FLOATING_POINT_SUPPORTED - float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y; -#endif - png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green, - int_y_green, int_x_blue, int_y_blue; - - png_uint_32 uint_x, uint_y; - - png_debug(1, "in png_handle_cHRM\n"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before cHRM"); - else if (png_ptr->mode & PNG_HAVE_IDAT) - { - png_warning(png_ptr, "Invalid cHRM after IDAT"); - png_crc_finish(png_ptr, length); - return; - } - else if (png_ptr->mode & PNG_HAVE_PLTE) - /* Should be an error, but we can cope with it */ - png_warning(png_ptr, "Missing PLTE before cHRM"); - - if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM) -#if defined(PNG_READ_sRGB_SUPPORTED) - && !(info_ptr->valid & PNG_INFO_sRGB) -#endif - ) - { - png_warning(png_ptr, "Duplicate cHRM chunk"); - png_crc_finish(png_ptr, length); - return; - } - - if (length != 32) - { - png_warning(png_ptr, "Incorrect cHRM chunk length"); - png_crc_finish(png_ptr, length); - return; - } - - png_crc_read(png_ptr, buf, 4); - uint_x = png_get_uint_32(buf); - - png_crc_read(png_ptr, buf, 4); - uint_y = png_get_uint_32(buf); - - if (uint_x > 80000L || uint_y > 80000L || - uint_x + uint_y > 100000L) - { - png_warning(png_ptr, "Invalid cHRM white point"); - png_crc_finish(png_ptr, 24); - return; - } - int_x_white = (png_fixed_point)uint_x; - int_y_white = (png_fixed_point)uint_y; - - png_crc_read(png_ptr, buf, 4); - uint_x = png_get_uint_32(buf); - - png_crc_read(png_ptr, buf, 4); - uint_y = png_get_uint_32(buf); - - if (uint_x + uint_y > 100000L) - { - png_warning(png_ptr, "Invalid cHRM red point"); - png_crc_finish(png_ptr, 16); - return; - } - int_x_red = (png_fixed_point)uint_x; - int_y_red = (png_fixed_point)uint_y; - - png_crc_read(png_ptr, buf, 4); - uint_x = png_get_uint_32(buf); - - png_crc_read(png_ptr, buf, 4); - uint_y = png_get_uint_32(buf); - - if (uint_x + uint_y > 100000L) - { - png_warning(png_ptr, "Invalid cHRM green point"); - png_crc_finish(png_ptr, 8); - return; - } - int_x_green = (png_fixed_point)uint_x; - int_y_green = (png_fixed_point)uint_y; - - png_crc_read(png_ptr, buf, 4); - uint_x = png_get_uint_32(buf); - - png_crc_read(png_ptr, buf, 4); - uint_y = png_get_uint_32(buf); - - if (uint_x + uint_y > 100000L) - { - png_warning(png_ptr, "Invalid cHRM blue point"); - png_crc_finish(png_ptr, 0); - return; - } - int_x_blue = (png_fixed_point)uint_x; - int_y_blue = (png_fixed_point)uint_y; - -#ifdef PNG_FLOATING_POINT_SUPPORTED - white_x = (float)int_x_white / (float)100000.0; - white_y = (float)int_y_white / (float)100000.0; - red_x = (float)int_x_red / (float)100000.0; - red_y = (float)int_y_red / (float)100000.0; - green_x = (float)int_x_green / (float)100000.0; - green_y = (float)int_y_green / (float)100000.0; - blue_x = (float)int_x_blue / (float)100000.0; - blue_y = (float)int_y_blue / (float)100000.0; -#endif - -#if defined(PNG_READ_sRGB_SUPPORTED) - if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB)) - { - if (PNG_OUT_OF_RANGE(int_x_white, 31270, 1000) || - PNG_OUT_OF_RANGE(int_y_white, 32900, 1000) || - PNG_OUT_OF_RANGE(int_x_red, 64000L, 1000) || - PNG_OUT_OF_RANGE(int_y_red, 33000, 1000) || - PNG_OUT_OF_RANGE(int_x_green, 30000, 1000) || - PNG_OUT_OF_RANGE(int_y_green, 60000L, 1000) || - PNG_OUT_OF_RANGE(int_x_blue, 15000, 1000) || - PNG_OUT_OF_RANGE(int_y_blue, 6000, 1000)) - { - png_warning(png_ptr, - "Ignoring incorrect cHRM value when sRGB is also present"); -#ifndef PNG_NO_CONSOLE_IO -#ifdef PNG_FLOATING_POINT_SUPPORTED - fprintf(stderr,"wx=%f, wy=%f, rx=%f, ry=%f\n", - white_x, white_y, red_x, red_y); - fprintf(stderr,"gx=%f, gy=%f, bx=%f, by=%f\n", - green_x, green_y, blue_x, blue_y); -#else - fprintf(stderr,"wx=%ld, wy=%ld, rx=%ld, ry=%ld\n", - int_x_white, int_y_white, int_x_red, int_y_red); - fprintf(stderr,"gx=%ld, gy=%ld, bx=%ld, by=%ld\n", - int_x_green, int_y_green, int_x_blue, int_y_blue); -#endif -#endif /* PNG_NO_CONSOLE_IO */ - } - png_crc_finish(png_ptr, 0); - return; - } -#endif /* PNG_READ_sRGB_SUPPORTED */ - -#ifdef PNG_FLOATING_POINT_SUPPORTED - png_set_cHRM(png_ptr, info_ptr, - white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y); -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED - png_set_cHRM_fixed(png_ptr, info_ptr, - int_x_white, int_y_white, int_x_red, int_y_red, int_x_green, - int_y_green, int_x_blue, int_y_blue); -#endif - if (png_crc_finish(png_ptr, 0)) - return; -} -#endif - -#if defined(PNG_READ_sRGB_SUPPORTED) -void /* PRIVATE */ -png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -{ - int intent; - png_byte buf[1]; - - png_debug(1, "in png_handle_sRGB\n"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before sRGB"); - else if (png_ptr->mode & PNG_HAVE_IDAT) - { - png_warning(png_ptr, "Invalid sRGB after IDAT"); - png_crc_finish(png_ptr, length); - return; - } - else if (png_ptr->mode & PNG_HAVE_PLTE) - /* Should be an error, but we can cope with it */ - png_warning(png_ptr, "Out of place sRGB chunk"); - - if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB)) - { - png_warning(png_ptr, "Duplicate sRGB chunk"); - png_crc_finish(png_ptr, length); - return; - } - - if (length != 1) - { - png_warning(png_ptr, "Incorrect sRGB chunk length"); - png_crc_finish(png_ptr, length); - return; - } - - png_crc_read(png_ptr, buf, 1); - if (png_crc_finish(png_ptr, 0)) - return; - - intent = buf[0]; - /* check for bad intent */ - if (intent >= PNG_sRGB_INTENT_LAST) - { - png_warning(png_ptr, "Unknown sRGB intent"); - return; - } - -#if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED) - if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)) - { - png_fixed_point igamma; -#ifdef PNG_FIXED_POINT_SUPPORTED - igamma=info_ptr->int_gamma; -#else -# ifdef PNG_FLOATING_POINT_SUPPORTED - igamma=(png_fixed_point)(info_ptr->gamma * 100000.); -# endif -#endif - if (PNG_OUT_OF_RANGE(igamma, 45500L, 500)) - { - png_warning(png_ptr, - "Ignoring incorrect gAMA value when sRGB is also present"); -#ifndef PNG_NO_CONSOLE_IO -# ifdef PNG_FIXED_POINT_SUPPORTED - fprintf(stderr,"incorrect gamma=(%d/100000)\n",(int)png_ptr->int_gamma); -# else -# ifdef PNG_FLOATING_POINT_SUPPORTED - fprintf(stderr,"incorrect gamma=%f\n",png_ptr->gamma); -# endif -# endif -#endif - } - } -#endif /* PNG_READ_gAMA_SUPPORTED */ - -#ifdef PNG_READ_cHRM_SUPPORTED -#ifdef PNG_FIXED_POINT_SUPPORTED - if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) - if (PNG_OUT_OF_RANGE(info_ptr->int_x_white, 31270, 1000) || - PNG_OUT_OF_RANGE(info_ptr->int_y_white, 32900, 1000) || - PNG_OUT_OF_RANGE(info_ptr->int_x_red, 64000L, 1000) || - PNG_OUT_OF_RANGE(info_ptr->int_y_red, 33000, 1000) || - PNG_OUT_OF_RANGE(info_ptr->int_x_green, 30000, 1000) || - PNG_OUT_OF_RANGE(info_ptr->int_y_green, 60000L, 1000) || - PNG_OUT_OF_RANGE(info_ptr->int_x_blue, 15000, 1000) || - PNG_OUT_OF_RANGE(info_ptr->int_y_blue, 6000, 1000)) - { - png_warning(png_ptr, - "Ignoring incorrect cHRM value when sRGB is also present"); - } -#endif /* PNG_FIXED_POINT_SUPPORTED */ -#endif /* PNG_READ_cHRM_SUPPORTED */ - - png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent); -} -#endif /* PNG_READ_sRGB_SUPPORTED */ - -#if defined(PNG_READ_iCCP_SUPPORTED) -void /* PRIVATE */ -png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -/* Note: this does not properly handle chunks that are > 64K under DOS */ -{ - png_charp chunkdata; - png_byte compression_type; - png_bytep pC; - png_charp profile; - png_uint_32 skip = 0; - png_uint_32 profile_size, profile_length; - png_size_t slength, prefix_length, data_length; - - png_debug(1, "in png_handle_iCCP\n"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before iCCP"); - else if (png_ptr->mode & PNG_HAVE_IDAT) - { - png_warning(png_ptr, "Invalid iCCP after IDAT"); - png_crc_finish(png_ptr, length); - return; - } - else if (png_ptr->mode & PNG_HAVE_PLTE) - /* Should be an error, but we can cope with it */ - png_warning(png_ptr, "Out of place iCCP chunk"); - - if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP)) - { - png_warning(png_ptr, "Duplicate iCCP chunk"); - png_crc_finish(png_ptr, length); - return; - } - -#ifdef PNG_MAX_MALLOC_64K - if (length > (png_uint_32)65535L) - { - png_warning(png_ptr, "iCCP chunk too large to fit in memory"); - skip = length - (png_uint_32)65535L; - length = (png_uint_32)65535L; - } -#endif - - chunkdata = (png_charp)png_malloc(png_ptr, length + 1); - slength = (png_size_t)length; - png_crc_read(png_ptr, (png_bytep)chunkdata, slength); - - if (png_crc_finish(png_ptr, skip)) - { - png_free(png_ptr, chunkdata); - return; - } - - chunkdata[slength] = 0x00; - - for (profile = chunkdata; *profile; profile++) - /* empty loop to find end of name */ ; - - ++profile; - - /* there should be at least one zero (the compression type byte) - following the separator, and we should be on it */ - if ( profile >= chunkdata + slength - 1) - { - png_free(png_ptr, chunkdata); - png_warning(png_ptr, "Malformed iCCP chunk"); - return; - } - - /* compression_type should always be zero */ - compression_type = *profile++; - if (compression_type) - { - png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk"); - compression_type=0x00; /* Reset it to zero (libpng-1.0.6 through 1.0.8 - wrote nonzero) */ - } - - prefix_length = profile - chunkdata; - chunkdata = png_decompress_chunk(png_ptr, compression_type, chunkdata, - slength, prefix_length, &data_length); - - profile_length = data_length - prefix_length; - - if ( prefix_length > data_length || profile_length < 4) - { - png_free(png_ptr, chunkdata); - png_warning(png_ptr, "Profile size field missing from iCCP chunk"); - return; - } - - /* Check the profile_size recorded in the first 32 bits of the ICC profile */ - pC = (png_bytep)(chunkdata+prefix_length); - profile_size = ((*(pC ))<<24) | - ((*(pC+1))<<16) | - ((*(pC+2))<< 8) | - ((*(pC+3)) ); - - if(profile_size < profile_length) - profile_length = profile_size; - - if(profile_size > profile_length) - { - png_free(png_ptr, chunkdata); - png_warning(png_ptr, "Ignoring truncated iCCP profile."); - return; - } - - png_set_iCCP(png_ptr, info_ptr, chunkdata, compression_type, - chunkdata + prefix_length, profile_length); - png_free(png_ptr, chunkdata); -} -#endif /* PNG_READ_iCCP_SUPPORTED */ - -#if defined(PNG_READ_sPLT_SUPPORTED) -void /* PRIVATE */ -png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -/* Note: this does not properly handle chunks that are > 64K under DOS */ -{ - png_bytep chunkdata; - png_bytep entry_start; - png_sPLT_t new_palette; -#ifdef PNG_NO_POINTER_INDEXING - png_sPLT_entryp pp; -#endif - int data_length, entry_size, i; - png_uint_32 skip = 0; - png_size_t slength; - - png_debug(1, "in png_handle_sPLT\n"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before sPLT"); - else if (png_ptr->mode & PNG_HAVE_IDAT) - { - png_warning(png_ptr, "Invalid sPLT after IDAT"); - png_crc_finish(png_ptr, length); - return; - } - -#ifdef PNG_MAX_MALLOC_64K - if (length > (png_uint_32)65535L) - { - png_warning(png_ptr, "sPLT chunk too large to fit in memory"); - skip = length - (png_uint_32)65535L; - length = (png_uint_32)65535L; - } -#endif - - chunkdata = (png_bytep)png_malloc(png_ptr, length + 1); - slength = (png_size_t)length; - png_crc_read(png_ptr, (png_bytep)chunkdata, slength); - - if (png_crc_finish(png_ptr, skip)) - { - png_free(png_ptr, chunkdata); - return; - } - - chunkdata[slength] = 0x00; - - for (entry_start = chunkdata; *entry_start; entry_start++) - /* empty loop to find end of name */ ; - ++entry_start; - - /* a sample depth should follow the separator, and we should be on it */ - if (entry_start > chunkdata + slength - 2) - { - png_free(png_ptr, chunkdata); - png_warning(png_ptr, "malformed sPLT chunk"); - return; - } - - new_palette.depth = *entry_start++; - entry_size = (new_palette.depth == 8 ? 6 : 10); - data_length = (slength - (entry_start - chunkdata)); - - /* integrity-check the data length */ - if (data_length % entry_size) - { - png_free(png_ptr, chunkdata); - png_warning(png_ptr, "sPLT chunk has bad length"); - return; - } - - new_palette.nentries = (png_int_32) ( data_length / entry_size); - if ((png_uint_32) new_palette.nentries > (png_uint_32) (PNG_SIZE_MAX / - png_sizeof(png_sPLT_entry))) - { - png_warning(png_ptr, "sPLT chunk too long"); - return; - } - new_palette.entries = (png_sPLT_entryp)png_malloc_warn( - png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry)); - if (new_palette.entries == NULL) - { - png_warning(png_ptr, "sPLT chunk requires too much memory"); - return; - } - -#ifndef PNG_NO_POINTER_INDEXING - for (i = 0; i < new_palette.nentries; i++) - { - png_sPLT_entryp pp = new_palette.entries + i; - - if (new_palette.depth == 8) - { - pp->red = *entry_start++; - pp->green = *entry_start++; - pp->blue = *entry_start++; - pp->alpha = *entry_start++; - } - else - { - pp->red = png_get_uint_16(entry_start); entry_start += 2; - pp->green = png_get_uint_16(entry_start); entry_start += 2; - pp->blue = png_get_uint_16(entry_start); entry_start += 2; - pp->alpha = png_get_uint_16(entry_start); entry_start += 2; - } - pp->frequency = png_get_uint_16(entry_start); entry_start += 2; - } -#else - pp = new_palette.entries; - for (i = 0; i < new_palette.nentries; i++) - { - - if (new_palette.depth == 8) - { - pp[i].red = *entry_start++; - pp[i].green = *entry_start++; - pp[i].blue = *entry_start++; - pp[i].alpha = *entry_start++; - } - else - { - pp[i].red = png_get_uint_16(entry_start); entry_start += 2; - pp[i].green = png_get_uint_16(entry_start); entry_start += 2; - pp[i].blue = png_get_uint_16(entry_start); entry_start += 2; - pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2; - } - pp->frequency = png_get_uint_16(entry_start); entry_start += 2; - } -#endif - - /* discard all chunk data except the name and stash that */ - new_palette.name = (png_charp)chunkdata; - - png_set_sPLT(png_ptr, info_ptr, &new_palette, 1); - - png_free(png_ptr, chunkdata); - png_free(png_ptr, new_palette.entries); -} -#endif /* PNG_READ_sPLT_SUPPORTED */ - -#if defined(PNG_READ_tRNS_SUPPORTED) -void /* PRIVATE */ -png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -{ - png_byte readbuf[PNG_MAX_PALETTE_LENGTH]; - int bit_mask; - - png_debug(1, "in png_handle_tRNS\n"); - - /* For non-indexed color, mask off any bits in the tRNS value that - * exceed the bit depth. Some creators were writing extra bits there. - * This is not needed for indexed color. */ - bit_mask = (1 << png_ptr->bit_depth) - 1; - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before tRNS"); - else if (png_ptr->mode & PNG_HAVE_IDAT) - { - png_warning(png_ptr, "Invalid tRNS after IDAT"); - png_crc_finish(png_ptr, length); - return; - } - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) - { - png_warning(png_ptr, "Duplicate tRNS chunk"); - png_crc_finish(png_ptr, length); - return; - } - - if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) - { - png_byte buf[2]; - - if (length != 2) - { - png_warning(png_ptr, "Incorrect tRNS chunk length"); - png_crc_finish(png_ptr, length); - return; - } - - png_crc_read(png_ptr, buf, 2); - png_ptr->num_trans = 1; - png_ptr->trans_values.gray = png_get_uint_16(buf) & bit_mask; - } - else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) - { - png_byte buf[6]; - - if (length != 6) - { - png_warning(png_ptr, "Incorrect tRNS chunk length"); - png_crc_finish(png_ptr, length); - return; - } - png_crc_read(png_ptr, buf, (png_size_t)length); - png_ptr->num_trans = 1; - png_ptr->trans_values.red = png_get_uint_16(buf) & bit_mask; - png_ptr->trans_values.green = png_get_uint_16(buf + 2) & bit_mask; - png_ptr->trans_values.blue = png_get_uint_16(buf + 4) & bit_mask; - } - else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - { - if (!(png_ptr->mode & PNG_HAVE_PLTE)) - { - /* Should be an error, but we can cope with it. */ - png_warning(png_ptr, "Missing PLTE before tRNS"); - } - if (length > (png_uint_32)png_ptr->num_palette || - length > PNG_MAX_PALETTE_LENGTH) - { - png_warning(png_ptr, "Incorrect tRNS chunk length"); - png_crc_finish(png_ptr, length); - return; - } - if (length == 0) - { - png_warning(png_ptr, "Zero length tRNS chunk"); - png_crc_finish(png_ptr, length); - return; - } - png_crc_read(png_ptr, readbuf, (png_size_t)length); - png_ptr->num_trans = (png_uint_16)length; - } - else - { - png_warning(png_ptr, "tRNS chunk not allowed with alpha channel"); - png_crc_finish(png_ptr, length); - return; - } - - if (png_crc_finish(png_ptr, 0)) - { - png_ptr->num_trans = 0; - return; - } - - png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans, - &(png_ptr->trans_values)); -} -#endif - -#if defined(PNG_READ_bKGD_SUPPORTED) -void /* PRIVATE */ -png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -{ - png_size_t truelen; - png_byte buf[6]; - - png_debug(1, "in png_handle_bKGD\n"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before bKGD"); - else if (png_ptr->mode & PNG_HAVE_IDAT) - { - png_warning(png_ptr, "Invalid bKGD after IDAT"); - png_crc_finish(png_ptr, length); - return; - } - else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && - !(png_ptr->mode & PNG_HAVE_PLTE)) - { - png_warning(png_ptr, "Missing PLTE before bKGD"); - png_crc_finish(png_ptr, length); - return; - } - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD)) - { - png_warning(png_ptr, "Duplicate bKGD chunk"); - png_crc_finish(png_ptr, length); - return; - } - - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - truelen = 1; - else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) - truelen = 6; - else - truelen = 2; - - if (length != truelen) - { - png_warning(png_ptr, "Incorrect bKGD chunk length"); - png_crc_finish(png_ptr, length); - return; - } - - png_crc_read(png_ptr, buf, truelen); - if (png_crc_finish(png_ptr, 0)) - return; - - /* We convert the index value into RGB components so that we can allow - * arbitrary RGB values for background when we have transparency, and - * so it is easy to determine the RGB values of the background color - * from the info_ptr struct. */ - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - { - png_ptr->background.index = buf[0]; - if(info_ptr->num_palette) - { - if(buf[0] > info_ptr->num_palette) - { - png_warning(png_ptr, "Incorrect bKGD chunk index value"); - return; - } - png_ptr->background.red = - (png_uint_16)png_ptr->palette[buf[0]].red; - png_ptr->background.green = - (png_uint_16)png_ptr->palette[buf[0]].green; - png_ptr->background.blue = - (png_uint_16)png_ptr->palette[buf[0]].blue; - } - } - else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */ - { - png_ptr->background.red = - png_ptr->background.green = - png_ptr->background.blue = - png_ptr->background.gray = png_get_uint_16(buf); - } - else - { - png_ptr->background.red = png_get_uint_16(buf); - png_ptr->background.green = png_get_uint_16(buf + 2); - png_ptr->background.blue = png_get_uint_16(buf + 4); - } - - png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background)); -} -#endif - -#if defined(PNG_READ_hIST_SUPPORTED) -void /* PRIVATE */ -png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -{ - unsigned int num, i; - png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH]; - - png_debug(1, "in png_handle_hIST\n"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before hIST"); - else if (png_ptr->mode & PNG_HAVE_IDAT) - { - png_warning(png_ptr, "Invalid hIST after IDAT"); - png_crc_finish(png_ptr, length); - return; - } - else if (!(png_ptr->mode & PNG_HAVE_PLTE)) - { - png_warning(png_ptr, "Missing PLTE before hIST"); - png_crc_finish(png_ptr, length); - return; - } - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST)) - { - png_warning(png_ptr, "Duplicate hIST chunk"); - png_crc_finish(png_ptr, length); - return; - } - - num = length / 2 ; - if (num != (unsigned int) png_ptr->num_palette || num > - (unsigned int) PNG_MAX_PALETTE_LENGTH) - { - png_warning(png_ptr, "Incorrect hIST chunk length"); - png_crc_finish(png_ptr, length); - return; - } - - for (i = 0; i < num; i++) - { - png_byte buf[2]; - - png_crc_read(png_ptr, buf, 2); - readbuf[i] = png_get_uint_16(buf); - } - - if (png_crc_finish(png_ptr, 0)) - return; - - png_set_hIST(png_ptr, info_ptr, readbuf); -} -#endif - -#if defined(PNG_READ_pHYs_SUPPORTED) -void /* PRIVATE */ -png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -{ - png_byte buf[9]; - png_uint_32 res_x, res_y; - int unit_type; - - png_debug(1, "in png_handle_pHYs\n"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before pHYs"); - else if (png_ptr->mode & PNG_HAVE_IDAT) - { - png_warning(png_ptr, "Invalid pHYs after IDAT"); - png_crc_finish(png_ptr, length); - return; - } - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) - { - png_warning(png_ptr, "Duplicate pHYs chunk"); - png_crc_finish(png_ptr, length); - return; - } - - if (length != 9) - { - png_warning(png_ptr, "Incorrect pHYs chunk length"); - png_crc_finish(png_ptr, length); - return; - } - - png_crc_read(png_ptr, buf, 9); - if (png_crc_finish(png_ptr, 0)) - return; - - res_x = png_get_uint_32(buf); - res_y = png_get_uint_32(buf + 4); - unit_type = buf[8]; - png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type); -} -#endif - -#if defined(PNG_READ_oFFs_SUPPORTED) -void /* PRIVATE */ -png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -{ - png_byte buf[9]; - png_int_32 offset_x, offset_y; - int unit_type; - - png_debug(1, "in png_handle_oFFs\n"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before oFFs"); - else if (png_ptr->mode & PNG_HAVE_IDAT) - { - png_warning(png_ptr, "Invalid oFFs after IDAT"); - png_crc_finish(png_ptr, length); - return; - } - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) - { - png_warning(png_ptr, "Duplicate oFFs chunk"); - png_crc_finish(png_ptr, length); - return; - } - - if (length != 9) - { - png_warning(png_ptr, "Incorrect oFFs chunk length"); - png_crc_finish(png_ptr, length); - return; - } - - png_crc_read(png_ptr, buf, 9); - if (png_crc_finish(png_ptr, 0)) - return; - - offset_x = png_get_int_32(buf); - offset_y = png_get_int_32(buf + 4); - unit_type = buf[8]; - png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type); -} -#endif - -#if defined(PNG_READ_pCAL_SUPPORTED) -/* read the pCAL chunk (described in the PNG Extensions document) */ -void /* PRIVATE */ -png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -{ - png_charp purpose; - png_int_32 X0, X1; - png_byte type, nparams; - png_charp buf, units, endptr; - png_charpp params; - png_size_t slength; - int i; - - png_debug(1, "in png_handle_pCAL\n"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before pCAL"); - else if (png_ptr->mode & PNG_HAVE_IDAT) - { - png_warning(png_ptr, "Invalid pCAL after IDAT"); - png_crc_finish(png_ptr, length); - return; - } - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL)) - { - png_warning(png_ptr, "Duplicate pCAL chunk"); - png_crc_finish(png_ptr, length); - return; - } - - png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)\n", - length + 1); - purpose = (png_charp)png_malloc_warn(png_ptr, length + 1); - if (purpose == NULL) - { - png_warning(png_ptr, "No memory for pCAL purpose."); - return; - } - slength = (png_size_t)length; - png_crc_read(png_ptr, (png_bytep)purpose, slength); - - if (png_crc_finish(png_ptr, 0)) - { - png_free(png_ptr, purpose); - return; - } - - purpose[slength] = 0x00; /* null terminate the last string */ - - png_debug(3, "Finding end of pCAL purpose string\n"); - for (buf = purpose; *buf; buf++) - /* empty loop */ ; - - endptr = purpose + slength; - - /* We need to have at least 12 bytes after the purpose string - in order to get the parameter information. */ - if (endptr <= buf + 12) - { - png_warning(png_ptr, "Invalid pCAL data"); - png_free(png_ptr, purpose); - return; - } - - png_debug(3, "Reading pCAL X0, X1, type, nparams, and units\n"); - X0 = png_get_int_32((png_bytep)buf+1); - X1 = png_get_int_32((png_bytep)buf+5); - type = buf[9]; - nparams = buf[10]; - units = buf + 11; - - png_debug(3, "Checking pCAL equation type and number of parameters\n"); - /* Check that we have the right number of parameters for known - equation types. */ - if ((type == PNG_EQUATION_LINEAR && nparams != 2) || - (type == PNG_EQUATION_BASE_E && nparams != 3) || - (type == PNG_EQUATION_ARBITRARY && nparams != 3) || - (type == PNG_EQUATION_HYPERBOLIC && nparams != 4)) - { - png_warning(png_ptr, "Invalid pCAL parameters for equation type"); - png_free(png_ptr, purpose); - return; - } - else if (type >= PNG_EQUATION_LAST) - { - png_warning(png_ptr, "Unrecognized equation type for pCAL chunk"); - } - - for (buf = units; *buf; buf++) - /* Empty loop to move past the units string. */ ; - - png_debug(3, "Allocating pCAL parameters array\n"); - params = (png_charpp)png_malloc_warn(png_ptr, (png_uint_32)(nparams - *png_sizeof(png_charp))) ; - if (params == NULL) - { - png_free(png_ptr, purpose); - png_warning(png_ptr, "No memory for pCAL params."); - return; - } - - /* Get pointers to the start of each parameter string. */ - for (i = 0; i < (int)nparams; i++) - { - buf++; /* Skip the null string terminator from previous parameter. */ - - png_debug1(3, "Reading pCAL parameter %d\n", i); - for (params[i] = buf; buf <= endptr && *buf != 0x00; buf++) - /* Empty loop to move past each parameter string */ ; - - /* Make sure we haven't run out of data yet */ - if (buf > endptr) - { - png_warning(png_ptr, "Invalid pCAL data"); - png_free(png_ptr, purpose); - png_free(png_ptr, params); - return; - } - } - - png_set_pCAL(png_ptr, info_ptr, purpose, X0, X1, type, nparams, - units, params); - - png_free(png_ptr, purpose); - png_free(png_ptr, params); -} -#endif - -#if defined(PNG_READ_sCAL_SUPPORTED) -/* read the sCAL chunk */ -void /* PRIVATE */ -png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -{ - png_charp buffer, ep; -#ifdef PNG_FLOATING_POINT_SUPPORTED - double width, height; - png_charp vp; -#else -#ifdef PNG_FIXED_POINT_SUPPORTED - png_charp swidth, sheight; -#endif -#endif - png_size_t slength; - - png_debug(1, "in png_handle_sCAL\n"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before sCAL"); - else if (png_ptr->mode & PNG_HAVE_IDAT) - { - png_warning(png_ptr, "Invalid sCAL after IDAT"); - png_crc_finish(png_ptr, length); - return; - } - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL)) - { - png_warning(png_ptr, "Duplicate sCAL chunk"); - png_crc_finish(png_ptr, length); - return; - } - - png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)\n", - length + 1); - buffer = (png_charp)png_malloc_warn(png_ptr, length + 1); - if (buffer == NULL) - { - png_warning(png_ptr, "Out of memory while processing sCAL chunk"); - return; - } - slength = (png_size_t)length; - png_crc_read(png_ptr, (png_bytep)buffer, slength); - - if (png_crc_finish(png_ptr, 0)) - { - png_free(png_ptr, buffer); - return; - } - - buffer[slength] = 0x00; /* null terminate the last string */ - - ep = buffer + 1; /* skip unit byte */ - -#ifdef PNG_FLOATING_POINT_SUPPORTED - width = png_strtod(png_ptr, ep, &vp); - if (*vp) - { - png_warning(png_ptr, "malformed width string in sCAL chunk"); - return; - } -#else -#ifdef PNG_FIXED_POINT_SUPPORTED - swidth = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1); - if (swidth == NULL) - { - png_warning(png_ptr, "Out of memory while processing sCAL chunk width"); - return; - } - png_memcpy(swidth, ep, (png_size_t)png_strlen(ep)); -#endif -#endif - - for (ep = buffer; *ep; ep++) - /* empty loop */ ; - ep++; - - if (buffer + slength < ep) - { - png_warning(png_ptr, "Truncated sCAL chunk"); -#if defined(PNG_FIXED_POINT_SUPPORTED) && \ - !defined(PNG_FLOATING_POINT_SUPPORTED) - png_free(png_ptr, swidth); -#endif - png_free(png_ptr, buffer); - return; - } - -#ifdef PNG_FLOATING_POINT_SUPPORTED - height = png_strtod(png_ptr, ep, &vp); - if (*vp) - { - png_warning(png_ptr, "malformed height string in sCAL chunk"); - return; - } -#else -#ifdef PNG_FIXED_POINT_SUPPORTED - sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1); - if (swidth == NULL) - { - png_warning(png_ptr, "Out of memory while processing sCAL chunk height"); - return; - } - png_memcpy(sheight, ep, (png_size_t)png_strlen(ep)); -#endif -#endif - - if (buffer + slength < ep -#ifdef PNG_FLOATING_POINT_SUPPORTED - || width <= 0. || height <= 0. -#endif - ) - { - png_warning(png_ptr, "Invalid sCAL data"); - png_free(png_ptr, buffer); -#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED) - png_free(png_ptr, swidth); - png_free(png_ptr, sheight); -#endif - return; - } - - -#ifdef PNG_FLOATING_POINT_SUPPORTED - png_set_sCAL(png_ptr, info_ptr, buffer[0], width, height); -#else -#ifdef PNG_FIXED_POINT_SUPPORTED - png_set_sCAL_s(png_ptr, info_ptr, buffer[0], swidth, sheight); -#endif -#endif - - png_free(png_ptr, buffer); -#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED) - png_free(png_ptr, swidth); - png_free(png_ptr, sheight); -#endif -} -#endif - -#if defined(PNG_READ_tIME_SUPPORTED) -void /* PRIVATE */ -png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -{ - png_byte buf[7]; - png_time mod_time; - - png_debug(1, "in png_handle_tIME\n"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Out of place tIME chunk"); - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME)) - { - png_warning(png_ptr, "Duplicate tIME chunk"); - png_crc_finish(png_ptr, length); - return; - } - - if (png_ptr->mode & PNG_HAVE_IDAT) - png_ptr->mode |= PNG_AFTER_IDAT; - - if (length != 7) - { - png_warning(png_ptr, "Incorrect tIME chunk length"); - png_crc_finish(png_ptr, length); - return; - } - - png_crc_read(png_ptr, buf, 7); - if (png_crc_finish(png_ptr, 0)) - return; - - mod_time.second = buf[6]; - mod_time.minute = buf[5]; - mod_time.hour = buf[4]; - mod_time.day = buf[3]; - mod_time.month = buf[2]; - mod_time.year = png_get_uint_16(buf); - - png_set_tIME(png_ptr, info_ptr, &mod_time); -} -#endif - -#if defined(PNG_READ_tEXt_SUPPORTED) -/* Note: this does not properly handle chunks that are > 64K under DOS */ -void /* PRIVATE */ -png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -{ - png_textp text_ptr; - png_charp key; - png_charp text; - png_uint_32 skip = 0; - png_size_t slength; - int ret; - - png_debug(1, "in png_handle_tEXt\n"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before tEXt"); - - if (png_ptr->mode & PNG_HAVE_IDAT) - png_ptr->mode |= PNG_AFTER_IDAT; - -#ifdef PNG_MAX_MALLOC_64K - if (length > (png_uint_32)65535L) - { - png_warning(png_ptr, "tEXt chunk too large to fit in memory"); - skip = length - (png_uint_32)65535L; - length = (png_uint_32)65535L; - } -#endif - - key = (png_charp)png_malloc_warn(png_ptr, length + 1); - if (key == NULL) - { - png_warning(png_ptr, "No memory to process text chunk."); - return; - } - slength = (png_size_t)length; - png_crc_read(png_ptr, (png_bytep)key, slength); - - if (png_crc_finish(png_ptr, skip)) - { - png_free(png_ptr, key); - return; - } - - key[slength] = 0x00; - - for (text = key; *text; text++) - /* empty loop to find end of key */ ; - - if (text != key + slength) - text++; - - text_ptr = (png_textp)png_malloc_warn(png_ptr, - (png_uint_32)png_sizeof(png_text)); - if (text_ptr == NULL) - { - png_warning(png_ptr, "Not enough memory to process text chunk."); - png_free(png_ptr, key); - return; - } - text_ptr->compression = PNG_TEXT_COMPRESSION_NONE; - text_ptr->key = key; -#ifdef PNG_iTXt_SUPPORTED - text_ptr->lang = NULL; - text_ptr->lang_key = NULL; - text_ptr->itxt_length = 0; -#endif - text_ptr->text = text; - text_ptr->text_length = png_strlen(text); - - ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1); - - png_free(png_ptr, key); - png_free(png_ptr, text_ptr); - if (ret) - png_warning(png_ptr, "Insufficient memory to process text chunk."); -} -#endif - -#if defined(PNG_READ_zTXt_SUPPORTED) -/* note: this does not correctly handle chunks that are > 64K under DOS */ -void /* PRIVATE */ -png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -{ - png_textp text_ptr; - png_charp chunkdata; - png_charp text; - int comp_type; - int ret; - png_size_t slength, prefix_len, data_len; - - png_debug(1, "in png_handle_zTXt\n"); - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before zTXt"); - - if (png_ptr->mode & PNG_HAVE_IDAT) - png_ptr->mode |= PNG_AFTER_IDAT; - -#ifdef PNG_MAX_MALLOC_64K - /* We will no doubt have problems with chunks even half this size, but - there is no hard and fast rule to tell us where to stop. */ - if (length > (png_uint_32)65535L) - { - png_warning(png_ptr,"zTXt chunk too large to fit in memory"); - png_crc_finish(png_ptr, length); - return; - } -#endif - - chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); - if (chunkdata == NULL) - { - png_warning(png_ptr,"Out of memory processing zTXt chunk."); - return; - } - slength = (png_size_t)length; - png_crc_read(png_ptr, (png_bytep)chunkdata, slength); - if (png_crc_finish(png_ptr, 0)) - { - png_free(png_ptr, chunkdata); - return; - } - - chunkdata[slength] = 0x00; - - for (text = chunkdata; *text; text++) - /* empty loop */ ; - - /* zTXt must have some text after the chunkdataword */ - if (text >= chunkdata + slength - 2) - { - png_warning(png_ptr, "Truncated zTXt chunk"); - png_free(png_ptr, chunkdata); - return; - } - else - { - comp_type = *(++text); - if (comp_type != PNG_TEXT_COMPRESSION_zTXt) - { - png_warning(png_ptr, "Unknown compression type in zTXt chunk"); - comp_type = PNG_TEXT_COMPRESSION_zTXt; - } - text++; /* skip the compression_method byte */ - } - prefix_len = text - chunkdata; - - chunkdata = (png_charp)png_decompress_chunk(png_ptr, comp_type, chunkdata, - (png_size_t)length, prefix_len, &data_len); - - text_ptr = (png_textp)png_malloc_warn(png_ptr, - (png_uint_32)png_sizeof(png_text)); - if (text_ptr == NULL) - { - png_warning(png_ptr,"Not enough memory to process zTXt chunk."); - png_free(png_ptr, chunkdata); - return; - } - text_ptr->compression = comp_type; - text_ptr->key = chunkdata; -#ifdef PNG_iTXt_SUPPORTED - text_ptr->lang = NULL; - text_ptr->lang_key = NULL; - text_ptr->itxt_length = 0; -#endif - text_ptr->text = chunkdata + prefix_len; - text_ptr->text_length = data_len; - - ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1); - - png_free(png_ptr, text_ptr); - png_free(png_ptr, chunkdata); - if (ret) - png_error(png_ptr, "Insufficient memory to store zTXt chunk."); -} -#endif - -#if defined(PNG_READ_iTXt_SUPPORTED) -/* note: this does not correctly handle chunks that are > 64K under DOS */ -void /* PRIVATE */ -png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -{ - png_textp text_ptr; - png_charp chunkdata; - png_charp key, lang, text, lang_key; - int comp_flag; - int comp_type = 0; - int ret; - png_size_t slength, prefix_len, data_len; - - png_debug(1, "in png_handle_iTXt\n"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before iTXt"); - - if (png_ptr->mode & PNG_HAVE_IDAT) - png_ptr->mode |= PNG_AFTER_IDAT; - -#ifdef PNG_MAX_MALLOC_64K - /* We will no doubt have problems with chunks even half this size, but - there is no hard and fast rule to tell us where to stop. */ - if (length > (png_uint_32)65535L) - { - png_warning(png_ptr,"iTXt chunk too large to fit in memory"); - png_crc_finish(png_ptr, length); - return; - } -#endif - - chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); - if (chunkdata == NULL) - { - png_warning(png_ptr, "No memory to process iTXt chunk."); - return; - } - slength = (png_size_t)length; - png_crc_read(png_ptr, (png_bytep)chunkdata, slength); - if (png_crc_finish(png_ptr, 0)) - { - png_free(png_ptr, chunkdata); - return; - } - - chunkdata[slength] = 0x00; - - for (lang = chunkdata; *lang; lang++) - /* empty loop */ ; - lang++; /* skip NUL separator */ - - /* iTXt must have a language tag (possibly empty), two compression bytes, - translated keyword (possibly empty), and possibly some text after the - keyword */ - - if (lang >= chunkdata + slength - 3) - { - png_warning(png_ptr, "Truncated iTXt chunk"); - png_free(png_ptr, chunkdata); - return; - } - else - { - comp_flag = *lang++; - comp_type = *lang++; - } - - for (lang_key = lang; *lang_key; lang_key++) - /* empty loop */ ; - lang_key++; /* skip NUL separator */ - - if (lang_key >= chunkdata + slength) - { - png_warning(png_ptr, "Truncated iTXt chunk"); - png_free(png_ptr, chunkdata); - return; - } - - for (text = lang_key; *text; text++) - /* empty loop */ ; - text++; /* skip NUL separator */ - if (text >= chunkdata + slength) - { - png_warning(png_ptr, "Malformed iTXt chunk"); - png_free(png_ptr, chunkdata); - return; - } - - prefix_len = text - chunkdata; - - key=chunkdata; - if (comp_flag) - chunkdata = png_decompress_chunk(png_ptr, comp_type, chunkdata, - (size_t)length, prefix_len, &data_len); - else - data_len=png_strlen(chunkdata + prefix_len); - text_ptr = (png_textp)png_malloc_warn(png_ptr, - (png_uint_32)png_sizeof(png_text)); - if (text_ptr == NULL) - { - png_warning(png_ptr,"Not enough memory to process iTXt chunk."); - png_free(png_ptr, chunkdata); - return; - } - text_ptr->compression = (int)comp_flag + 1; - text_ptr->lang_key = chunkdata+(lang_key-key); - text_ptr->lang = chunkdata+(lang-key); - text_ptr->itxt_length = data_len; - text_ptr->text_length = 0; - text_ptr->key = chunkdata; - text_ptr->text = chunkdata + prefix_len; - - ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1); - - png_free(png_ptr, text_ptr); - png_free(png_ptr, chunkdata); - if (ret) - png_error(png_ptr, "Insufficient memory to store iTXt chunk."); -} -#endif - -/* This function is called when we haven't found a handler for a - chunk. If there isn't a problem with the chunk itself (ie bad - chunk name, CRC, or a critical chunk), the chunk is silently ignored - -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which - case it will be saved away to be written out later. */ -void /* PRIVATE */ -png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -{ - png_uint_32 skip = 0; - - png_debug(1, "in png_handle_unknown\n"); - - if (png_ptr->mode & PNG_HAVE_IDAT) - { -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_CONST PNG_IDAT; -#endif - if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* not an IDAT */ - png_ptr->mode |= PNG_AFTER_IDAT; - } - - png_check_chunk_name(png_ptr, png_ptr->chunk_name); - - if (!(png_ptr->chunk_name[0] & 0x20)) - { -#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) - if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != - PNG_HANDLE_CHUNK_ALWAYS -#if defined(PNG_READ_USER_CHUNKS_SUPPORTED) - && png_ptr->read_user_chunk_fn == NULL -#endif - ) -#endif - png_chunk_error(png_ptr, "unknown critical chunk"); - } - -#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) - if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) || - (png_ptr->read_user_chunk_fn != NULL)) - { -#ifdef PNG_MAX_MALLOC_64K - if (length > (png_uint_32)65535L) - { - png_warning(png_ptr, "unknown chunk too large to fit in memory"); - skip = length - (png_uint_32)65535L; - length = (png_uint_32)65535L; - } -#endif - png_strncpy((png_charp)png_ptr->unknown_chunk.name, - (png_charp)png_ptr->chunk_name, 4); - png_ptr->unknown_chunk.name[4] = '\0'; - png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length); - png_ptr->unknown_chunk.size = (png_size_t)length; - png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length); -#if defined(PNG_READ_USER_CHUNKS_SUPPORTED) - if(png_ptr->read_user_chunk_fn != NULL) - { - /* callback to user unknown chunk handler */ - int ret; - ret = (*(png_ptr->read_user_chunk_fn)) - (png_ptr, &png_ptr->unknown_chunk); - if (ret < 0) - png_chunk_error(png_ptr, "error in user chunk"); - if (ret == 0) - { - if (!(png_ptr->chunk_name[0] & 0x20)) - if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != - PNG_HANDLE_CHUNK_ALWAYS) - png_chunk_error(png_ptr, "unknown critical chunk"); - png_set_unknown_chunks(png_ptr, info_ptr, - &png_ptr->unknown_chunk, 1); - } - } -#else - png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1); -#endif - png_free(png_ptr, png_ptr->unknown_chunk.data); - png_ptr->unknown_chunk.data = NULL; - } - else -#endif - skip = length; - - png_crc_finish(png_ptr, skip); - -#if !defined(PNG_READ_USER_CHUNKS_SUPPORTED) - info_ptr = info_ptr; /* quiet compiler warnings about unused info_ptr */ -#endif -} - -/* This function is called to verify that a chunk name is valid. - This function can't have the "critical chunk check" incorporated - into it, since in the future we will need to be able to call user - functions to handle unknown critical chunks after we check that - the chunk name itself is valid. */ - -#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) - -void /* PRIVATE */ -png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name) -{ - png_debug(1, "in png_check_chunk_name\n"); - if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) || - isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3])) - { - png_chunk_error(png_ptr, "invalid chunk type"); - } -} - -/* Combines the row recently read in with the existing pixels in the - row. This routine takes care of alpha and transparency if requested. - This routine also handles the two methods of progressive display - of interlaced images, depending on the mask value. - The mask value describes which pixels are to be combined with - the row. The pattern always repeats every 8 pixels, so just 8 - bits are needed. A one indicates the pixel is to be combined, - a zero indicates the pixel is to be skipped. This is in addition - to any alpha or transparency value associated with the pixel. If - you want all pixels to be combined, pass 0xff (255) in mask. */ - -void /* PRIVATE */ -png_combine_row(png_structp png_ptr, png_bytep row, int mask) -{ - png_debug(1,"in png_combine_row\n"); - if (mask == 0xff) - { - png_memcpy(row, png_ptr->row_buf + 1, - PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width)); - } - else - { - switch (png_ptr->row_info.pixel_depth) - { - case 1: - { - png_bytep sp = png_ptr->row_buf + 1; - png_bytep dp = row; - int s_inc, s_start, s_end; - int m = 0x80; - int shift; - png_uint_32 i; - png_uint_32 row_width = png_ptr->width; - -#if defined(PNG_READ_PACKSWAP_SUPPORTED) - if (png_ptr->transformations & PNG_PACKSWAP) - { - s_start = 0; - s_end = 7; - s_inc = 1; - } - else -#endif - { - s_start = 7; - s_end = 0; - s_inc = -1; - } - - shift = s_start; - - for (i = 0; i < row_width; i++) - { - if (m & mask) - { - int value; - - value = (*sp >> shift) & 0x01; - *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); - *dp |= (png_byte)(value << shift); - } - - if (shift == s_end) - { - shift = s_start; - sp++; - dp++; - } - else - shift += s_inc; - - if (m == 1) - m = 0x80; - else - m >>= 1; - } - break; - } - case 2: - { - png_bytep sp = png_ptr->row_buf + 1; - png_bytep dp = row; - int s_start, s_end, s_inc; - int m = 0x80; - int shift; - png_uint_32 i; - png_uint_32 row_width = png_ptr->width; - int value; - -#if defined(PNG_READ_PACKSWAP_SUPPORTED) - if (png_ptr->transformations & PNG_PACKSWAP) - { - s_start = 0; - s_end = 6; - s_inc = 2; - } - else -#endif - { - s_start = 6; - s_end = 0; - s_inc = -2; - } - - shift = s_start; - - for (i = 0; i < row_width; i++) - { - if (m & mask) - { - value = (*sp >> shift) & 0x03; - *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); - *dp |= (png_byte)(value << shift); - } - - if (shift == s_end) - { - shift = s_start; - sp++; - dp++; - } - else - shift += s_inc; - if (m == 1) - m = 0x80; - else - m >>= 1; - } - break; - } - case 4: - { - png_bytep sp = png_ptr->row_buf + 1; - png_bytep dp = row; - int s_start, s_end, s_inc; - int m = 0x80; - int shift; - png_uint_32 i; - png_uint_32 row_width = png_ptr->width; - int value; - -#if defined(PNG_READ_PACKSWAP_SUPPORTED) - if (png_ptr->transformations & PNG_PACKSWAP) - { - s_start = 0; - s_end = 4; - s_inc = 4; - } - else -#endif - { - s_start = 4; - s_end = 0; - s_inc = -4; - } - shift = s_start; - - for (i = 0; i < row_width; i++) - { - if (m & mask) - { - value = (*sp >> shift) & 0xf; - *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); - *dp |= (png_byte)(value << shift); - } - - if (shift == s_end) - { - shift = s_start; - sp++; - dp++; - } - else - shift += s_inc; - if (m == 1) - m = 0x80; - else - m >>= 1; - } - break; - } - default: - { - png_bytep sp = png_ptr->row_buf + 1; - png_bytep dp = row; - png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3); - png_uint_32 i; - png_uint_32 row_width = png_ptr->width; - png_byte m = 0x80; - - - for (i = 0; i < row_width; i++) - { - if (m & mask) - { - png_memcpy(dp, sp, pixel_bytes); - } - - sp += pixel_bytes; - dp += pixel_bytes; - - if (m == 1) - m = 0x80; - else - m >>= 1; - } - break; - } - } - } -} - -#ifdef PNG_READ_INTERLACING_SUPPORTED -/* OLD pre-1.0.9 interface: -void png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, - png_uint_32 transformations) - */ -void /* PRIVATE */ -png_do_read_interlace(png_structp png_ptr) -{ - png_row_infop row_info = &(png_ptr->row_info); - png_bytep row = png_ptr->row_buf + 1; - int pass = png_ptr->pass; - png_uint_32 transformations = png_ptr->transformations; -#ifdef PNG_USE_LOCAL_ARRAYS - /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - /* offset to next interlace block */ - PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; -#endif - - png_debug(1,"in png_do_read_interlace\n"); - if (row != NULL && row_info != NULL) - { - png_uint_32 final_width; - - final_width = row_info->width * png_pass_inc[pass]; - - switch (row_info->pixel_depth) - { - case 1: - { - png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3); - png_bytep dp = row + (png_size_t)((final_width - 1) >> 3); - int sshift, dshift; - int s_start, s_end, s_inc; - int jstop = png_pass_inc[pass]; - png_byte v; - png_uint_32 i; - int j; - -#if defined(PNG_READ_PACKSWAP_SUPPORTED) - if (transformations & PNG_PACKSWAP) - { - sshift = (int)((row_info->width + 7) & 0x07); - dshift = (int)((final_width + 7) & 0x07); - s_start = 7; - s_end = 0; - s_inc = -1; - } - else -#endif - { - sshift = 7 - (int)((row_info->width + 7) & 0x07); - dshift = 7 - (int)((final_width + 7) & 0x07); - s_start = 0; - s_end = 7; - s_inc = 1; - } - - for (i = 0; i < row_info->width; i++) - { - v = (png_byte)((*sp >> sshift) & 0x01); - for (j = 0; j < jstop; j++) - { - *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff); - *dp |= (png_byte)(v << dshift); - if (dshift == s_end) - { - dshift = s_start; - dp--; - } - else - dshift += s_inc; - } - if (sshift == s_end) - { - sshift = s_start; - sp--; - } - else - sshift += s_inc; - } - break; - } - case 2: - { - png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2); - png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2); - int sshift, dshift; - int s_start, s_end, s_inc; - int jstop = png_pass_inc[pass]; - png_uint_32 i; - -#if defined(PNG_READ_PACKSWAP_SUPPORTED) - if (transformations & PNG_PACKSWAP) - { - sshift = (int)(((row_info->width + 3) & 0x03) << 1); - dshift = (int)(((final_width + 3) & 0x03) << 1); - s_start = 6; - s_end = 0; - s_inc = -2; - } - else -#endif - { - sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1); - dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1); - s_start = 0; - s_end = 6; - s_inc = 2; - } - - for (i = 0; i < row_info->width; i++) - { - png_byte v; - int j; - - v = (png_byte)((*sp >> sshift) & 0x03); - for (j = 0; j < jstop; j++) - { - *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff); - *dp |= (png_byte)(v << dshift); - if (dshift == s_end) - { - dshift = s_start; - dp--; - } - else - dshift += s_inc; - } - if (sshift == s_end) - { - sshift = s_start; - sp--; - } - else - sshift += s_inc; - } - break; - } - case 4: - { - png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1); - png_bytep dp = row + (png_size_t)((final_width - 1) >> 1); - int sshift, dshift; - int s_start, s_end, s_inc; - png_uint_32 i; - int jstop = png_pass_inc[pass]; - -#if defined(PNG_READ_PACKSWAP_SUPPORTED) - if (transformations & PNG_PACKSWAP) - { - sshift = (int)(((row_info->width + 1) & 0x01) << 2); - dshift = (int)(((final_width + 1) & 0x01) << 2); - s_start = 4; - s_end = 0; - s_inc = -4; - } - else -#endif - { - sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2); - dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2); - s_start = 0; - s_end = 4; - s_inc = 4; - } - - for (i = 0; i < row_info->width; i++) - { - png_byte v = (png_byte)((*sp >> sshift) & 0xf); - int j; - - for (j = 0; j < jstop; j++) - { - *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff); - *dp |= (png_byte)(v << dshift); - if (dshift == s_end) - { - dshift = s_start; - dp--; - } - else - dshift += s_inc; - } - if (sshift == s_end) - { - sshift = s_start; - sp--; - } - else - sshift += s_inc; - } - break; - } - default: - { - png_size_t pixel_bytes = (row_info->pixel_depth >> 3); - png_bytep sp = row + (png_size_t)(row_info->width - 1) * pixel_bytes; - png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes; - - int jstop = png_pass_inc[pass]; - png_uint_32 i; - - for (i = 0; i < row_info->width; i++) - { - png_byte v[8]; - int j; - - png_memcpy(v, sp, pixel_bytes); - for (j = 0; j < jstop; j++) - { - png_memcpy(dp, v, pixel_bytes); - dp -= pixel_bytes; - } - sp -= pixel_bytes; - } - break; - } - } - row_info->width = final_width; - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,final_width); - } -#if !defined(PNG_READ_PACKSWAP_SUPPORTED) - transformations = transformations; /* silence compiler warning */ -#endif -} -#endif /* PNG_READ_INTERLACING_SUPPORTED */ - -void /* PRIVATE */ -png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row, - png_bytep prev_row, int filter) -{ - png_debug(1, "in png_read_filter_row\n"); - png_debug2(2,"row = %lu, filter = %d\n", png_ptr->row_number, filter); - switch (filter) - { - case PNG_FILTER_VALUE_NONE: - break; - case PNG_FILTER_VALUE_SUB: - { - png_uint_32 i; - png_uint_32 istop = row_info->rowbytes; - png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; - png_bytep rp = row + bpp; - png_bytep lp = row; - - for (i = bpp; i < istop; i++) - { - *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff); - rp++; - } - break; - } - case PNG_FILTER_VALUE_UP: - { - png_uint_32 i; - png_uint_32 istop = row_info->rowbytes; - png_bytep rp = row; - png_bytep pp = prev_row; - - for (i = 0; i < istop; i++) - { - *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); - rp++; - } - break; - } - case PNG_FILTER_VALUE_AVG: - { - png_uint_32 i; - png_bytep rp = row; - png_bytep pp = prev_row; - png_bytep lp = row; - png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; - png_uint_32 istop = row_info->rowbytes - bpp; - - for (i = 0; i < bpp; i++) - { - *rp = (png_byte)(((int)(*rp) + - ((int)(*pp++) / 2 )) & 0xff); - rp++; - } - - for (i = 0; i < istop; i++) - { - *rp = (png_byte)(((int)(*rp) + - (int)(*pp++ + *lp++) / 2 ) & 0xff); - rp++; - } - break; - } - case PNG_FILTER_VALUE_PAETH: - { - png_uint_32 i; - png_bytep rp = row; - png_bytep pp = prev_row; - png_bytep lp = row; - png_bytep cp = prev_row; - png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; - png_uint_32 istop=row_info->rowbytes - bpp; - - for (i = 0; i < bpp; i++) - { - *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); - rp++; - } - - for (i = 0; i < istop; i++) /* use leftover rp,pp */ - { - int a, b, c, pa, pb, pc, p; - - a = *lp++; - b = *pp++; - c = *cp++; - - p = b - c; - pc = a - c; - -#ifdef PNG_USE_ABS - pa = abs(p); - pb = abs(pc); - pc = abs(p + pc); -#else - pa = p < 0 ? -p : p; - pb = pc < 0 ? -pc : pc; - pc = (p + pc) < 0 ? -(p + pc) : p + pc; -#endif - - /* - if (pa <= pb && pa <= pc) - p = a; - else if (pb <= pc) - p = b; - else - p = c; - */ - - p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; - - *rp = (png_byte)(((int)(*rp) + p) & 0xff); - rp++; - } - break; - } - default: - png_warning(png_ptr, "Ignoring bad adaptive filter type"); - *row=0; - break; - } -} - -void /* PRIVATE */ -png_read_finish_row(png_structp png_ptr) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - - /* start of interlace block */ - PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; - - /* offset to next interlace block */ - PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; - - /* start of interlace block in the y direction */ - PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; - - /* offset to next interlace block in the y direction */ - PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; -#endif - - png_debug(1, "in png_read_finish_row\n"); - png_ptr->row_number++; - if (png_ptr->row_number < png_ptr->num_rows) - return; - - if (png_ptr->interlaced) - { - png_ptr->row_number = 0; - png_memset_check(png_ptr, png_ptr->prev_row, 0, - png_ptr->rowbytes + 1); - do - { - png_ptr->pass++; - if (png_ptr->pass >= 7) - break; - png_ptr->iwidth = (png_ptr->width + - png_pass_inc[png_ptr->pass] - 1 - - png_pass_start[png_ptr->pass]) / - png_pass_inc[png_ptr->pass]; - - png_ptr->irowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, - png_ptr->iwidth) + 1; - - if (!(png_ptr->transformations & PNG_INTERLACE)) - { - png_ptr->num_rows = (png_ptr->height + - png_pass_yinc[png_ptr->pass] - 1 - - png_pass_ystart[png_ptr->pass]) / - png_pass_yinc[png_ptr->pass]; - if (!(png_ptr->num_rows)) - continue; - } - else /* if (png_ptr->transformations & PNG_INTERLACE) */ - break; - } while (png_ptr->iwidth == 0); - - if (png_ptr->pass < 7) - return; - } - - if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) - { -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_CONST PNG_IDAT; -#endif - char extra; - int ret; - - png_ptr->zstream.next_out = (Byte *)&extra; - png_ptr->zstream.avail_out = (uInt)1; - for(;;) - { - if (!(png_ptr->zstream.avail_in)) - { - while (!png_ptr->idat_size) - { - png_byte chunk_length[4]; - - png_crc_finish(png_ptr, 0); - - png_read_data(png_ptr, chunk_length, 4); - png_ptr->idat_size = png_get_uint_31(png_ptr, chunk_length); - png_reset_crc(png_ptr); - png_crc_read(png_ptr, png_ptr->chunk_name, 4); - if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) - png_error(png_ptr, "Not enough image data"); - - } - png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size; - png_ptr->zstream.next_in = png_ptr->zbuf; - if (png_ptr->zbuf_size > png_ptr->idat_size) - png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size; - png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in); - png_ptr->idat_size -= png_ptr->zstream.avail_in; - } - ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); - if (ret == Z_STREAM_END) - { - if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in || - png_ptr->idat_size) - png_warning(png_ptr, "Extra compressed data"); - png_ptr->mode |= PNG_AFTER_IDAT; - png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; - break; - } - if (ret != Z_OK) - png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg : - "Decompression Error"); - - if (!(png_ptr->zstream.avail_out)) - { - png_warning(png_ptr, "Extra compressed data."); - png_ptr->mode |= PNG_AFTER_IDAT; - png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; - break; - } - - } - png_ptr->zstream.avail_out = 0; - } - - if (png_ptr->idat_size || png_ptr->zstream.avail_in) - png_warning(png_ptr, "Extra compression data"); - - inflateReset(&png_ptr->zstream); - - png_ptr->mode |= PNG_AFTER_IDAT; -} - -void /* PRIVATE */ -png_read_start_row(png_structp png_ptr) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - - /* start of interlace block */ - PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; - - /* offset to next interlace block */ - PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; - - /* start of interlace block in the y direction */ - PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; - - /* offset to next interlace block in the y direction */ - PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; -#endif - - int max_pixel_depth; - png_uint_32 row_bytes; - - png_debug(1, "in png_read_start_row\n"); - png_ptr->zstream.avail_in = 0; - png_init_read_transformations(png_ptr); - if (png_ptr->interlaced) - { - if (!(png_ptr->transformations & PNG_INTERLACE)) - png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - - png_pass_ystart[0]) / png_pass_yinc[0]; - else - png_ptr->num_rows = png_ptr->height; - - png_ptr->iwidth = (png_ptr->width + - png_pass_inc[png_ptr->pass] - 1 - - png_pass_start[png_ptr->pass]) / - png_pass_inc[png_ptr->pass]; - - row_bytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->iwidth) + 1; - - png_ptr->irowbytes = (png_size_t)row_bytes; - if((png_uint_32)png_ptr->irowbytes != row_bytes) - png_error(png_ptr, "Rowbytes overflow in png_read_start_row"); - } - else - { - png_ptr->num_rows = png_ptr->height; - png_ptr->iwidth = png_ptr->width; - png_ptr->irowbytes = png_ptr->rowbytes + 1; - } - max_pixel_depth = png_ptr->pixel_depth; - -#if defined(PNG_READ_PACK_SUPPORTED) - if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8) - max_pixel_depth = 8; -#endif - -#if defined(PNG_READ_EXPAND_SUPPORTED) - if (png_ptr->transformations & PNG_EXPAND) - { - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - { - if (png_ptr->num_trans) - max_pixel_depth = 32; - else - max_pixel_depth = 24; - } - else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) - { - if (max_pixel_depth < 8) - max_pixel_depth = 8; - if (png_ptr->num_trans) - max_pixel_depth *= 2; - } - else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) - { - if (png_ptr->num_trans) - { - max_pixel_depth *= 4; - max_pixel_depth /= 3; - } - } - } -#endif - -#if defined(PNG_READ_FILLER_SUPPORTED) - if (png_ptr->transformations & (PNG_FILLER)) - { - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - max_pixel_depth = 32; - else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) - { - if (max_pixel_depth <= 8) - max_pixel_depth = 16; - else - max_pixel_depth = 32; - } - else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) - { - if (max_pixel_depth <= 32) - max_pixel_depth = 32; - else - max_pixel_depth = 64; - } - } -#endif - -#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) - if (png_ptr->transformations & PNG_GRAY_TO_RGB) - { - if ( -#if defined(PNG_READ_EXPAND_SUPPORTED) - (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) || -#endif -#if defined(PNG_READ_FILLER_SUPPORTED) - (png_ptr->transformations & (PNG_FILLER)) || -#endif - png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - { - if (max_pixel_depth <= 16) - max_pixel_depth = 32; - else - max_pixel_depth = 64; - } - else - { - if (max_pixel_depth <= 8) - { - if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - max_pixel_depth = 32; - else - max_pixel_depth = 24; - } - else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - max_pixel_depth = 64; - else - max_pixel_depth = 48; - } - } -#endif - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \ -defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) - if(png_ptr->transformations & PNG_USER_TRANSFORM) - { - int user_pixel_depth=png_ptr->user_transform_depth* - png_ptr->user_transform_channels; - if(user_pixel_depth > max_pixel_depth) - max_pixel_depth=user_pixel_depth; - } -#endif - - /* align the width on the next larger 8 pixels. Mainly used - for interlacing */ - row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7)); - /* calculate the maximum bytes needed, adding a byte and a pixel - for safety's sake */ - row_bytes = PNG_ROWBYTES(max_pixel_depth,row_bytes) + - 1 + ((max_pixel_depth + 7) >> 3); -#ifdef PNG_MAX_MALLOC_64K - if (row_bytes > (png_uint_32)65536L) - png_error(png_ptr, "This image requires a row greater than 64KB"); -#endif - png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes+64); - png_ptr->row_buf = png_ptr->big_row_buf+32; - -#ifdef PNG_MAX_MALLOC_64K - if ((png_uint_32)png_ptr->rowbytes + 1 > (png_uint_32)65536L) - png_error(png_ptr, "This image requires a row greater than 64KB"); -#endif - if ((png_uint_32)png_ptr->rowbytes > (png_uint_32)(PNG_SIZE_MAX - 1)) - png_error(png_ptr, "Row has too many bytes to allocate in memory."); - png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)( - png_ptr->rowbytes + 1)); - - png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1); - - png_debug1(3, "width = %lu,\n", png_ptr->width); - png_debug1(3, "height = %lu,\n", png_ptr->height); - png_debug1(3, "iwidth = %lu,\n", png_ptr->iwidth); - png_debug1(3, "num_rows = %lu\n", png_ptr->num_rows); - png_debug1(3, "rowbytes = %lu,\n", png_ptr->rowbytes); - png_debug1(3, "irowbytes = %lu,\n", png_ptr->irowbytes); - - png_ptr->flags |= PNG_FLAG_ROW_INIT; -} -#endif /* PNG_READ_SUPPORTED */ diff --git a/uppdev/plugin/png/lib/pngset.c b/uppdev/plugin/png/lib/pngset.c deleted file mode 100644 index 761ea70c9..000000000 --- a/uppdev/plugin/png/lib/pngset.c +++ /dev/null @@ -1,1246 +0,0 @@ - -/* pngset.c - storage of image information into info struct - * - * Last changed in libpng 1.2.22 [October 13, 2007] - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2007 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * The functions here are used during reads to store data from the file - * into the info struct, and during writes to store application data - * into the info struct for writing into the file. This abstracts the - * info struct and allows us to change the structure in the future. - */ - -#define PNG_INTERNAL -#include "png.h" - -#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) - -#if defined(PNG_bKGD_SUPPORTED) -void PNGAPI -png_set_bKGD(png_structp png_ptr, png_infop info_ptr, png_color_16p background) -{ - png_debug1(1, "in %s storage function\n", "bKGD"); - if (png_ptr == NULL || info_ptr == NULL) - return; - - png_memcpy(&(info_ptr->background), background, png_sizeof(png_color_16)); - info_ptr->valid |= PNG_INFO_bKGD; -} -#endif - -#if defined(PNG_cHRM_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED -void PNGAPI -png_set_cHRM(png_structp png_ptr, png_infop info_ptr, - double white_x, double white_y, double red_x, double red_y, - double green_x, double green_y, double blue_x, double blue_y) -{ - png_debug1(1, "in %s storage function\n", "cHRM"); - if (png_ptr == NULL || info_ptr == NULL) - return; - - if (white_x < 0.0 || white_y < 0.0 || - red_x < 0.0 || red_y < 0.0 || - green_x < 0.0 || green_y < 0.0 || - blue_x < 0.0 || blue_y < 0.0) - { - png_warning(png_ptr, - "Ignoring attempt to set negative chromaticity value"); - return; - } - if (white_x > 21474.83 || white_y > 21474.83 || - red_x > 21474.83 || red_y > 21474.83 || - green_x > 21474.83 || green_y > 21474.83 || - blue_x > 21474.83 || blue_y > 21474.83) - { - png_warning(png_ptr, - "Ignoring attempt to set chromaticity value exceeding 21474.83"); - return; - } - - info_ptr->x_white = (float)white_x; - info_ptr->y_white = (float)white_y; - info_ptr->x_red = (float)red_x; - info_ptr->y_red = (float)red_y; - info_ptr->x_green = (float)green_x; - info_ptr->y_green = (float)green_y; - info_ptr->x_blue = (float)blue_x; - info_ptr->y_blue = (float)blue_y; -#ifdef PNG_FIXED_POINT_SUPPORTED - info_ptr->int_x_white = (png_fixed_point)(white_x*100000.+0.5); - info_ptr->int_y_white = (png_fixed_point)(white_y*100000.+0.5); - info_ptr->int_x_red = (png_fixed_point)( red_x*100000.+0.5); - info_ptr->int_y_red = (png_fixed_point)( red_y*100000.+0.5); - info_ptr->int_x_green = (png_fixed_point)(green_x*100000.+0.5); - info_ptr->int_y_green = (png_fixed_point)(green_y*100000.+0.5); - info_ptr->int_x_blue = (png_fixed_point)( blue_x*100000.+0.5); - info_ptr->int_y_blue = (png_fixed_point)( blue_y*100000.+0.5); -#endif - info_ptr->valid |= PNG_INFO_cHRM; -} -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED -void PNGAPI -png_set_cHRM_fixed(png_structp png_ptr, png_infop info_ptr, - png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x, - png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y, - png_fixed_point blue_x, png_fixed_point blue_y) -{ - png_debug1(1, "in %s storage function\n", "cHRM"); - if (png_ptr == NULL || info_ptr == NULL) - return; - - if (white_x < 0 || white_y < 0 || - red_x < 0 || red_y < 0 || - green_x < 0 || green_y < 0 || - blue_x < 0 || blue_y < 0) - { - png_warning(png_ptr, - "Ignoring attempt to set negative chromaticity value"); - return; - } -#ifdef PNG_FLOATING_POINT_SUPPORTED - if (white_x > (double) PNG_UINT_31_MAX || - white_y > (double) PNG_UINT_31_MAX || - red_x > (double) PNG_UINT_31_MAX || - red_y > (double) PNG_UINT_31_MAX || - green_x > (double) PNG_UINT_31_MAX || - green_y > (double) PNG_UINT_31_MAX || - blue_x > (double) PNG_UINT_31_MAX || - blue_y > (double) PNG_UINT_31_MAX) -#else - if (white_x > (png_fixed_point) PNG_UINT_31_MAX/100000L || - white_y > (png_fixed_point) PNG_UINT_31_MAX/100000L || - red_x > (png_fixed_point) PNG_UINT_31_MAX/100000L || - red_y > (png_fixed_point) PNG_UINT_31_MAX/100000L || - green_x > (png_fixed_point) PNG_UINT_31_MAX/100000L || - green_y > (png_fixed_point) PNG_UINT_31_MAX/100000L || - blue_x > (png_fixed_point) PNG_UINT_31_MAX/100000L || - blue_y > (png_fixed_point) PNG_UINT_31_MAX/100000L) -#endif - { - png_warning(png_ptr, - "Ignoring attempt to set chromaticity value exceeding 21474.83"); - return; - } - info_ptr->int_x_white = white_x; - info_ptr->int_y_white = white_y; - info_ptr->int_x_red = red_x; - info_ptr->int_y_red = red_y; - info_ptr->int_x_green = green_x; - info_ptr->int_y_green = green_y; - info_ptr->int_x_blue = blue_x; - info_ptr->int_y_blue = blue_y; -#ifdef PNG_FLOATING_POINT_SUPPORTED - info_ptr->x_white = (float)(white_x/100000.); - info_ptr->y_white = (float)(white_y/100000.); - info_ptr->x_red = (float)( red_x/100000.); - info_ptr->y_red = (float)( red_y/100000.); - info_ptr->x_green = (float)(green_x/100000.); - info_ptr->y_green = (float)(green_y/100000.); - info_ptr->x_blue = (float)( blue_x/100000.); - info_ptr->y_blue = (float)( blue_y/100000.); -#endif - info_ptr->valid |= PNG_INFO_cHRM; -} -#endif -#endif - -#if defined(PNG_gAMA_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED -void PNGAPI -png_set_gAMA(png_structp png_ptr, png_infop info_ptr, double file_gamma) -{ - double gamma; - png_debug1(1, "in %s storage function\n", "gAMA"); - if (png_ptr == NULL || info_ptr == NULL) - return; - - /* Check for overflow */ - if (file_gamma > 21474.83) - { - png_warning(png_ptr, "Limiting gamma to 21474.83"); - gamma=21474.83; - } - else - gamma=file_gamma; - info_ptr->gamma = (float)gamma; -#ifdef PNG_FIXED_POINT_SUPPORTED - info_ptr->int_gamma = (int)(gamma*100000.+.5); -#endif - info_ptr->valid |= PNG_INFO_gAMA; - if(gamma == 0.0) - png_warning(png_ptr, "Setting gamma=0"); -} -#endif -void PNGAPI -png_set_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, png_fixed_point - int_gamma) -{ - png_fixed_point gamma; - - png_debug1(1, "in %s storage function\n", "gAMA"); - if (png_ptr == NULL || info_ptr == NULL) - return; - - if (int_gamma > (png_fixed_point) PNG_UINT_31_MAX) - { - png_warning(png_ptr, "Limiting gamma to 21474.83"); - gamma=PNG_UINT_31_MAX; - } - else - { - if (int_gamma < 0) - { - png_warning(png_ptr, "Setting negative gamma to zero"); - gamma=0; - } - else - gamma=int_gamma; - } -#ifdef PNG_FLOATING_POINT_SUPPORTED - info_ptr->gamma = (float)(gamma/100000.); -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED - info_ptr->int_gamma = gamma; -#endif - info_ptr->valid |= PNG_INFO_gAMA; - if(gamma == 0) - png_warning(png_ptr, "Setting gamma=0"); -} -#endif - -#if defined(PNG_hIST_SUPPORTED) -void PNGAPI -png_set_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_16p hist) -{ - int i; - - png_debug1(1, "in %s storage function\n", "hIST"); - if (png_ptr == NULL || info_ptr == NULL) - return; - if (info_ptr->num_palette == 0 || info_ptr->num_palette - > PNG_MAX_PALETTE_LENGTH) - { - png_warning(png_ptr, - "Invalid palette size, hIST allocation skipped."); - return; - } - -#ifdef PNG_FREE_ME_SUPPORTED - png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0); -#endif - /* Changed from info->num_palette to PNG_MAX_PALETTE_LENGTH in version - 1.2.1 */ - png_ptr->hist = (png_uint_16p)png_malloc_warn(png_ptr, - (png_uint_32)(PNG_MAX_PALETTE_LENGTH * png_sizeof (png_uint_16))); - if (png_ptr->hist == NULL) - { - png_warning(png_ptr, "Insufficient memory for hIST chunk data."); - return; - } - - for (i = 0; i < info_ptr->num_palette; i++) - png_ptr->hist[i] = hist[i]; - info_ptr->hist = png_ptr->hist; - info_ptr->valid |= PNG_INFO_hIST; - -#ifdef PNG_FREE_ME_SUPPORTED - info_ptr->free_me |= PNG_FREE_HIST; -#else - png_ptr->flags |= PNG_FLAG_FREE_HIST; -#endif -} -#endif - -void PNGAPI -png_set_IHDR(png_structp png_ptr, png_infop info_ptr, - png_uint_32 width, png_uint_32 height, int bit_depth, - int color_type, int interlace_type, int compression_type, - int filter_type) -{ - png_debug1(1, "in %s storage function\n", "IHDR"); - if (png_ptr == NULL || info_ptr == NULL) - return; - - /* check for width and height valid values */ - if (width == 0 || height == 0) - png_error(png_ptr, "Image width or height is zero in IHDR"); -#ifdef PNG_SET_USER_LIMITS_SUPPORTED - if (width > png_ptr->user_width_max || height > png_ptr->user_height_max) - png_error(png_ptr, "image size exceeds user limits in IHDR"); -#else - if (width > PNG_USER_WIDTH_MAX || height > PNG_USER_HEIGHT_MAX) - png_error(png_ptr, "image size exceeds user limits in IHDR"); -#endif - if (width > PNG_UINT_31_MAX || height > PNG_UINT_31_MAX) - png_error(png_ptr, "Invalid image size in IHDR"); - if ( width > (PNG_UINT_32_MAX - >> 3) /* 8-byte RGBA pixels */ - - 64 /* bigrowbuf hack */ - - 1 /* filter byte */ - - 7*8 /* rounding of width to multiple of 8 pixels */ - - 8) /* extra max_pixel_depth pad */ - png_warning(png_ptr, "Width is too large for libpng to process pixels"); - - /* check other values */ - if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 && - bit_depth != 8 && bit_depth != 16) - png_error(png_ptr, "Invalid bit depth in IHDR"); - - if (color_type < 0 || color_type == 1 || - color_type == 5 || color_type > 6) - png_error(png_ptr, "Invalid color type in IHDR"); - - if (((color_type == PNG_COLOR_TYPE_PALETTE) && bit_depth > 8) || - ((color_type == PNG_COLOR_TYPE_RGB || - color_type == PNG_COLOR_TYPE_GRAY_ALPHA || - color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8)) - png_error(png_ptr, "Invalid color type/bit depth combination in IHDR"); - - if (interlace_type >= PNG_INTERLACE_LAST) - png_error(png_ptr, "Unknown interlace method in IHDR"); - - if (compression_type != PNG_COMPRESSION_TYPE_BASE) - png_error(png_ptr, "Unknown compression method in IHDR"); - -#if defined(PNG_MNG_FEATURES_SUPPORTED) - /* Accept filter_method 64 (intrapixel differencing) only if - * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and - * 2. Libpng did not read a PNG signature (this filter_method is only - * used in PNG datastreams that are embedded in MNG datastreams) and - * 3. The application called png_permit_mng_features with a mask that - * included PNG_FLAG_MNG_FILTER_64 and - * 4. The filter_method is 64 and - * 5. The color_type is RGB or RGBA - */ - if((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)&&png_ptr->mng_features_permitted) - png_warning(png_ptr,"MNG features are not allowed in a PNG datastream"); - if(filter_type != PNG_FILTER_TYPE_BASE) - { - if(!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && - (filter_type == PNG_INTRAPIXEL_DIFFERENCING) && - ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) && - (color_type == PNG_COLOR_TYPE_RGB || - color_type == PNG_COLOR_TYPE_RGB_ALPHA))) - png_error(png_ptr, "Unknown filter method in IHDR"); - if(png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) - png_warning(png_ptr, "Invalid filter method in IHDR"); - } -#else - if(filter_type != PNG_FILTER_TYPE_BASE) - png_error(png_ptr, "Unknown filter method in IHDR"); -#endif - - info_ptr->width = width; - info_ptr->height = height; - info_ptr->bit_depth = (png_byte)bit_depth; - info_ptr->color_type =(png_byte) color_type; - info_ptr->compression_type = (png_byte)compression_type; - info_ptr->filter_type = (png_byte)filter_type; - info_ptr->interlace_type = (png_byte)interlace_type; - if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - info_ptr->channels = 1; - else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) - info_ptr->channels = 3; - else - info_ptr->channels = 1; - if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) - info_ptr->channels++; - info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth); - - /* check for potential overflow */ - if (width > (PNG_UINT_32_MAX - >> 3) /* 8-byte RGBA pixels */ - - 64 /* bigrowbuf hack */ - - 1 /* filter byte */ - - 7*8 /* rounding of width to multiple of 8 pixels */ - - 8) /* extra max_pixel_depth pad */ - info_ptr->rowbytes = (png_size_t)0; - else - info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth,width); -} - -#if defined(PNG_oFFs_SUPPORTED) -void PNGAPI -png_set_oFFs(png_structp png_ptr, png_infop info_ptr, - png_int_32 offset_x, png_int_32 offset_y, int unit_type) -{ - png_debug1(1, "in %s storage function\n", "oFFs"); - if (png_ptr == NULL || info_ptr == NULL) - return; - - info_ptr->x_offset = offset_x; - info_ptr->y_offset = offset_y; - info_ptr->offset_unit_type = (png_byte)unit_type; - info_ptr->valid |= PNG_INFO_oFFs; -} -#endif - -#if defined(PNG_pCAL_SUPPORTED) -void PNGAPI -png_set_pCAL(png_structp png_ptr, png_infop info_ptr, - png_charp purpose, png_int_32 X0, png_int_32 X1, int type, int nparams, - png_charp units, png_charpp params) -{ - png_uint_32 length; - int i; - - png_debug1(1, "in %s storage function\n", "pCAL"); - if (png_ptr == NULL || info_ptr == NULL) - return; - - length = png_strlen(purpose) + 1; - png_debug1(3, "allocating purpose for info (%lu bytes)\n", length); - info_ptr->pcal_purpose = (png_charp)png_malloc_warn(png_ptr, length); - if (info_ptr->pcal_purpose == NULL) - { - png_warning(png_ptr, "Insufficient memory for pCAL purpose."); - return; - } - png_memcpy(info_ptr->pcal_purpose, purpose, (png_size_t)length); - - png_debug(3, "storing X0, X1, type, and nparams in info\n"); - info_ptr->pcal_X0 = X0; - info_ptr->pcal_X1 = X1; - info_ptr->pcal_type = (png_byte)type; - info_ptr->pcal_nparams = (png_byte)nparams; - - length = png_strlen(units) + 1; - png_debug1(3, "allocating units for info (%lu bytes)\n", length); - info_ptr->pcal_units = (png_charp)png_malloc_warn(png_ptr, length); - if (info_ptr->pcal_units == NULL) - { - png_warning(png_ptr, "Insufficient memory for pCAL units."); - return; - } - png_memcpy(info_ptr->pcal_units, units, (png_size_t)length); - - info_ptr->pcal_params = (png_charpp)png_malloc_warn(png_ptr, - (png_uint_32)((nparams + 1) * png_sizeof(png_charp))); - if (info_ptr->pcal_params == NULL) - { - png_warning(png_ptr, "Insufficient memory for pCAL params."); - return; - } - - info_ptr->pcal_params[nparams] = NULL; - - for (i = 0; i < nparams; i++) - { - length = png_strlen(params[i]) + 1; - png_debug2(3, "allocating parameter %d for info (%lu bytes)\n", i, length); - info_ptr->pcal_params[i] = (png_charp)png_malloc_warn(png_ptr, length); - if (info_ptr->pcal_params[i] == NULL) - { - png_warning(png_ptr, "Insufficient memory for pCAL parameter."); - return; - } - png_memcpy(info_ptr->pcal_params[i], params[i], (png_size_t)length); - } - - info_ptr->valid |= PNG_INFO_pCAL; -#ifdef PNG_FREE_ME_SUPPORTED - info_ptr->free_me |= PNG_FREE_PCAL; -#endif -} -#endif - -#if defined(PNG_READ_sCAL_SUPPORTED) || defined(PNG_WRITE_sCAL_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED -void PNGAPI -png_set_sCAL(png_structp png_ptr, png_infop info_ptr, - int unit, double width, double height) -{ - png_debug1(1, "in %s storage function\n", "sCAL"); - if (png_ptr == NULL || info_ptr == NULL) - return; - - info_ptr->scal_unit = (png_byte)unit; - info_ptr->scal_pixel_width = width; - info_ptr->scal_pixel_height = height; - - info_ptr->valid |= PNG_INFO_sCAL; -} -#else -#ifdef PNG_FIXED_POINT_SUPPORTED -void PNGAPI -png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr, - int unit, png_charp swidth, png_charp sheight) -{ - png_uint_32 length; - - png_debug1(1, "in %s storage function\n", "sCAL"); - if (png_ptr == NULL || info_ptr == NULL) - return; - - info_ptr->scal_unit = (png_byte)unit; - - length = png_strlen(swidth) + 1; - png_debug1(3, "allocating unit for info (%d bytes)\n", length); - info_ptr->scal_s_width = (png_charp)png_malloc_warn(png_ptr, length); - if (info_ptr->scal_s_width == NULL) - { - png_warning(png_ptr, - "Memory allocation failed while processing sCAL."); - } - png_memcpy(info_ptr->scal_s_width, swidth, (png_size_t)length); - - length = png_strlen(sheight) + 1; - png_debug1(3, "allocating unit for info (%d bytes)\n", length); - info_ptr->scal_s_height = (png_charp)png_malloc_warn(png_ptr, length); - if (info_ptr->scal_s_height == NULL) - { - png_free (png_ptr, info_ptr->scal_s_width); - png_warning(png_ptr, - "Memory allocation failed while processing sCAL."); - } - png_memcpy(info_ptr->scal_s_height, sheight, (png_size_t)length); - - info_ptr->valid |= PNG_INFO_sCAL; -#ifdef PNG_FREE_ME_SUPPORTED - info_ptr->free_me |= PNG_FREE_SCAL; -#endif -} -#endif -#endif -#endif - -#if defined(PNG_pHYs_SUPPORTED) -void PNGAPI -png_set_pHYs(png_structp png_ptr, png_infop info_ptr, - png_uint_32 res_x, png_uint_32 res_y, int unit_type) -{ - png_debug1(1, "in %s storage function\n", "pHYs"); - if (png_ptr == NULL || info_ptr == NULL) - return; - - info_ptr->x_pixels_per_unit = res_x; - info_ptr->y_pixels_per_unit = res_y; - info_ptr->phys_unit_type = (png_byte)unit_type; - info_ptr->valid |= PNG_INFO_pHYs; -} -#endif - -void PNGAPI -png_set_PLTE(png_structp png_ptr, png_infop info_ptr, - png_colorp palette, int num_palette) -{ - - png_debug1(1, "in %s storage function\n", "PLTE"); - if (png_ptr == NULL || info_ptr == NULL) - return; - - if (num_palette < 0 || num_palette > PNG_MAX_PALETTE_LENGTH) - { - if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - png_error(png_ptr, "Invalid palette length"); - else - { - png_warning(png_ptr, "Invalid palette length"); - return; - } - } - - /* - * It may not actually be necessary to set png_ptr->palette here; - * we do it for backward compatibility with the way the png_handle_tRNS - * function used to do the allocation. - */ -#ifdef PNG_FREE_ME_SUPPORTED - png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0); -#endif - - /* Changed in libpng-1.2.1 to allocate PNG_MAX_PALETTE_LENGTH instead - of num_palette entries, - in case of an invalid PNG file that has too-large sample values. */ - png_ptr->palette = (png_colorp)png_malloc(png_ptr, - PNG_MAX_PALETTE_LENGTH * png_sizeof(png_color)); - png_memset(png_ptr->palette, 0, PNG_MAX_PALETTE_LENGTH * - png_sizeof(png_color)); - png_memcpy(png_ptr->palette, palette, num_palette * png_sizeof (png_color)); - info_ptr->palette = png_ptr->palette; - info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette; - -#ifdef PNG_FREE_ME_SUPPORTED - info_ptr->free_me |= PNG_FREE_PLTE; -#else - png_ptr->flags |= PNG_FLAG_FREE_PLTE; -#endif - - info_ptr->valid |= PNG_INFO_PLTE; -} - -#if defined(PNG_sBIT_SUPPORTED) -void PNGAPI -png_set_sBIT(png_structp png_ptr, png_infop info_ptr, - png_color_8p sig_bit) -{ - png_debug1(1, "in %s storage function\n", "sBIT"); - if (png_ptr == NULL || info_ptr == NULL) - return; - - png_memcpy(&(info_ptr->sig_bit), sig_bit, png_sizeof (png_color_8)); - info_ptr->valid |= PNG_INFO_sBIT; -} -#endif - -#if defined(PNG_sRGB_SUPPORTED) -void PNGAPI -png_set_sRGB(png_structp png_ptr, png_infop info_ptr, int intent) -{ - png_debug1(1, "in %s storage function\n", "sRGB"); - if (png_ptr == NULL || info_ptr == NULL) - return; - - info_ptr->srgb_intent = (png_byte)intent; - info_ptr->valid |= PNG_INFO_sRGB; -} - -void PNGAPI -png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr, - int intent) -{ -#if defined(PNG_gAMA_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED - float file_gamma; -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED - png_fixed_point int_file_gamma; -#endif -#endif -#if defined(PNG_cHRM_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED - float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y; -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED - png_fixed_point int_white_x, int_white_y, int_red_x, int_red_y, int_green_x, - int_green_y, int_blue_x, int_blue_y; -#endif -#endif - png_debug1(1, "in %s storage function\n", "sRGB_gAMA_and_cHRM"); - if (png_ptr == NULL || info_ptr == NULL) - return; - - png_set_sRGB(png_ptr, info_ptr, intent); - -#if defined(PNG_gAMA_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED - file_gamma = (float).45455; - png_set_gAMA(png_ptr, info_ptr, file_gamma); -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED - int_file_gamma = 45455L; - png_set_gAMA_fixed(png_ptr, info_ptr, int_file_gamma); -#endif -#endif - -#if defined(PNG_cHRM_SUPPORTED) -#ifdef PNG_FIXED_POINT_SUPPORTED - int_white_x = 31270L; - int_white_y = 32900L; - int_red_x = 64000L; - int_red_y = 33000L; - int_green_x = 30000L; - int_green_y = 60000L; - int_blue_x = 15000L; - int_blue_y = 6000L; - - png_set_cHRM_fixed(png_ptr, info_ptr, - int_white_x, int_white_y, int_red_x, int_red_y, int_green_x, int_green_y, - int_blue_x, int_blue_y); -#endif -#ifdef PNG_FLOATING_POINT_SUPPORTED - white_x = (float).3127; - white_y = (float).3290; - red_x = (float).64; - red_y = (float).33; - green_x = (float).30; - green_y = (float).60; - blue_x = (float).15; - blue_y = (float).06; - - png_set_cHRM(png_ptr, info_ptr, - white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y); -#endif -#endif -} -#endif - - -#if defined(PNG_iCCP_SUPPORTED) -void PNGAPI -png_set_iCCP(png_structp png_ptr, png_infop info_ptr, - png_charp name, int compression_type, - png_charp profile, png_uint_32 proflen) -{ - png_charp new_iccp_name; - png_charp new_iccp_profile; - - png_debug1(1, "in %s storage function\n", "iCCP"); - if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL) - return; - - new_iccp_name = (png_charp)png_malloc_warn(png_ptr, png_strlen(name)+1); - if (new_iccp_name == NULL) - { - png_warning(png_ptr, "Insufficient memory to process iCCP chunk."); - return; - } - png_strncpy(new_iccp_name, name, png_strlen(name)); - new_iccp_name[png_strlen(name)] = '\0'; - new_iccp_profile = (png_charp)png_malloc_warn(png_ptr, proflen); - if (new_iccp_profile == NULL) - { - png_free (png_ptr, new_iccp_name); - png_warning(png_ptr, "Insufficient memory to process iCCP profile."); - return; - } - png_memcpy(new_iccp_profile, profile, (png_size_t)proflen); - - png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0); - - info_ptr->iccp_proflen = proflen; - info_ptr->iccp_name = new_iccp_name; - info_ptr->iccp_profile = new_iccp_profile; - /* Compression is always zero but is here so the API and info structure - * does not have to change if we introduce multiple compression types */ - info_ptr->iccp_compression = (png_byte)compression_type; -#ifdef PNG_FREE_ME_SUPPORTED - info_ptr->free_me |= PNG_FREE_ICCP; -#endif - info_ptr->valid |= PNG_INFO_iCCP; -} -#endif - -#if defined(PNG_TEXT_SUPPORTED) -void PNGAPI -png_set_text(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr, - int num_text) -{ - int ret; - ret=png_set_text_2(png_ptr, info_ptr, text_ptr, num_text); - if (ret) - png_error(png_ptr, "Insufficient memory to store text"); -} - -int /* PRIVATE */ -png_set_text_2(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr, - int num_text) -{ - int i; - - png_debug1(1, "in %s storage function\n", (png_ptr->chunk_name[0] == '\0' ? - "text" : (png_const_charp)png_ptr->chunk_name)); - - if (png_ptr == NULL || info_ptr == NULL || num_text == 0) - return(0); - - /* Make sure we have enough space in the "text" array in info_struct - * to hold all of the incoming text_ptr objects. - */ - if (info_ptr->num_text + num_text > info_ptr->max_text) - { - if (info_ptr->text != NULL) - { - png_textp old_text; - int old_max; - - old_max = info_ptr->max_text; - info_ptr->max_text = info_ptr->num_text + num_text + 8; - old_text = info_ptr->text; - info_ptr->text = (png_textp)png_malloc_warn(png_ptr, - (png_uint_32)(info_ptr->max_text * png_sizeof (png_text))); - if (info_ptr->text == NULL) - { - png_free(png_ptr, old_text); - return(1); - } - png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max * - png_sizeof(png_text))); - png_free(png_ptr, old_text); - } - else - { - info_ptr->max_text = num_text + 8; - info_ptr->num_text = 0; - info_ptr->text = (png_textp)png_malloc_warn(png_ptr, - (png_uint_32)(info_ptr->max_text * png_sizeof (png_text))); - if (info_ptr->text == NULL) - return(1); -#ifdef PNG_FREE_ME_SUPPORTED - info_ptr->free_me |= PNG_FREE_TEXT; -#endif - } - png_debug1(3, "allocated %d entries for info_ptr->text\n", - info_ptr->max_text); - } - for (i = 0; i < num_text; i++) - { - png_size_t text_length,key_len; - png_size_t lang_len,lang_key_len; - png_textp textp = &(info_ptr->text[info_ptr->num_text]); - - if (text_ptr[i].key == NULL) - continue; - - key_len = png_strlen(text_ptr[i].key); - - if(text_ptr[i].compression <= 0) - { - lang_len = 0; - lang_key_len = 0; - } - else -#ifdef PNG_iTXt_SUPPORTED - { - /* set iTXt data */ - if (text_ptr[i].lang != NULL) - lang_len = png_strlen(text_ptr[i].lang); - else - lang_len = 0; - if (text_ptr[i].lang_key != NULL) - lang_key_len = png_strlen(text_ptr[i].lang_key); - else - lang_key_len = 0; - } -#else - { - png_warning(png_ptr, "iTXt chunk not supported."); - continue; - } -#endif - - if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0') - { - text_length = 0; -#ifdef PNG_iTXt_SUPPORTED - if(text_ptr[i].compression > 0) - textp->compression = PNG_ITXT_COMPRESSION_NONE; - else -#endif - textp->compression = PNG_TEXT_COMPRESSION_NONE; - } - else - { - text_length = png_strlen(text_ptr[i].text); - textp->compression = text_ptr[i].compression; - } - - textp->key = (png_charp)png_malloc_warn(png_ptr, - (png_uint_32)(key_len + text_length + lang_len + lang_key_len + 4)); - if (textp->key == NULL) - return(1); - png_debug2(2, "Allocated %lu bytes at %x in png_set_text\n", - (png_uint_32)(key_len + lang_len + lang_key_len + text_length + 4), - (int)textp->key); - - png_memcpy(textp->key, text_ptr[i].key, - (png_size_t)(key_len)); - *(textp->key+key_len) = '\0'; -#ifdef PNG_iTXt_SUPPORTED - if (text_ptr[i].compression > 0) - { - textp->lang=textp->key + key_len + 1; - png_memcpy(textp->lang, text_ptr[i].lang, lang_len); - *(textp->lang+lang_len) = '\0'; - textp->lang_key=textp->lang + lang_len + 1; - png_memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len); - *(textp->lang_key+lang_key_len) = '\0'; - textp->text=textp->lang_key + lang_key_len + 1; - } - else -#endif - { -#ifdef PNG_iTXt_SUPPORTED - textp->lang=NULL; - textp->lang_key=NULL; -#endif - textp->text=textp->key + key_len + 1; - } - if(text_length) - png_memcpy(textp->text, text_ptr[i].text, - (png_size_t)(text_length)); - *(textp->text+text_length) = '\0'; - -#ifdef PNG_iTXt_SUPPORTED - if(textp->compression > 0) - { - textp->text_length = 0; - textp->itxt_length = text_length; - } - else -#endif - { - textp->text_length = text_length; -#ifdef PNG_iTXt_SUPPORTED - textp->itxt_length = 0; -#endif - } - info_ptr->num_text++; - png_debug1(3, "transferred text chunk %d\n", info_ptr->num_text); - } - return(0); -} -#endif - -#if defined(PNG_tIME_SUPPORTED) -void PNGAPI -png_set_tIME(png_structp png_ptr, png_infop info_ptr, png_timep mod_time) -{ - png_debug1(1, "in %s storage function\n", "tIME"); - if (png_ptr == NULL || info_ptr == NULL || - (png_ptr->mode & PNG_WROTE_tIME)) - return; - - png_memcpy(&(info_ptr->mod_time), mod_time, png_sizeof (png_time)); - info_ptr->valid |= PNG_INFO_tIME; -} -#endif - -#if defined(PNG_tRNS_SUPPORTED) -void PNGAPI -png_set_tRNS(png_structp png_ptr, png_infop info_ptr, - png_bytep trans, int num_trans, png_color_16p trans_values) -{ - png_debug1(1, "in %s storage function\n", "tRNS"); - if (png_ptr == NULL || info_ptr == NULL) - return; - - if (trans != NULL) - { - /* - * It may not actually be necessary to set png_ptr->trans here; - * we do it for backward compatibility with the way the png_handle_tRNS - * function used to do the allocation. - */ -#ifdef PNG_FREE_ME_SUPPORTED - png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0); -#endif - /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */ - png_ptr->trans = info_ptr->trans = (png_bytep)png_malloc(png_ptr, - (png_uint_32)PNG_MAX_PALETTE_LENGTH); - if (num_trans <= PNG_MAX_PALETTE_LENGTH) - png_memcpy(info_ptr->trans, trans, (png_size_t)num_trans); -#ifdef PNG_FREE_ME_SUPPORTED - info_ptr->free_me |= PNG_FREE_TRNS; -#else - png_ptr->flags |= PNG_FLAG_FREE_TRNS; -#endif - } - - if (trans_values != NULL) - { - png_memcpy(&(info_ptr->trans_values), trans_values, - png_sizeof(png_color_16)); - if (num_trans == 0) - num_trans = 1; - } - info_ptr->num_trans = (png_uint_16)num_trans; - info_ptr->valid |= PNG_INFO_tRNS; -} -#endif - -#if defined(PNG_sPLT_SUPPORTED) -void PNGAPI -png_set_sPLT(png_structp png_ptr, - png_infop info_ptr, png_sPLT_tp entries, int nentries) -{ - png_sPLT_tp np; - int i; - - if (png_ptr == NULL || info_ptr == NULL) - return; - - np = (png_sPLT_tp)png_malloc_warn(png_ptr, - (info_ptr->splt_palettes_num + nentries) * png_sizeof(png_sPLT_t)); - if (np == NULL) - { - png_warning(png_ptr, "No memory for sPLT palettes."); - return; - } - - png_memcpy(np, info_ptr->splt_palettes, - info_ptr->splt_palettes_num * png_sizeof(png_sPLT_t)); - png_free(png_ptr, info_ptr->splt_palettes); - info_ptr->splt_palettes=NULL; - - for (i = 0; i < nentries; i++) - { - png_sPLT_tp to = np + info_ptr->splt_palettes_num + i; - png_sPLT_tp from = entries + i; - - to->name = (png_charp)png_malloc_warn(png_ptr, - png_strlen(from->name) + 1); - if (to->name == NULL) - { - png_warning(png_ptr, - "Out of memory while processing sPLT chunk"); - } - /* TODO: use png_malloc_warn */ - png_strncpy(to->name, from->name, png_strlen(from->name)); - to->name[png_strlen(from->name)] = '\0'; - to->entries = (png_sPLT_entryp)png_malloc_warn(png_ptr, - from->nentries * png_sizeof(png_sPLT_entry)); - /* TODO: use png_malloc_warn */ - png_memcpy(to->entries, from->entries, - from->nentries * png_sizeof(png_sPLT_entry)); - if (to->entries == NULL) - { - png_warning(png_ptr, - "Out of memory while processing sPLT chunk"); - png_free(png_ptr,to->name); - to->name = NULL; - } - to->nentries = from->nentries; - to->depth = from->depth; - } - - info_ptr->splt_palettes = np; - info_ptr->splt_palettes_num += nentries; - info_ptr->valid |= PNG_INFO_sPLT; -#ifdef PNG_FREE_ME_SUPPORTED - info_ptr->free_me |= PNG_FREE_SPLT; -#endif -} -#endif /* PNG_sPLT_SUPPORTED */ - -#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) -void PNGAPI -png_set_unknown_chunks(png_structp png_ptr, - png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns) -{ - png_unknown_chunkp np; - int i; - - if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0) - return; - - np = (png_unknown_chunkp)png_malloc_warn(png_ptr, - (info_ptr->unknown_chunks_num + num_unknowns) * - png_sizeof(png_unknown_chunk)); - if (np == NULL) - { - png_warning(png_ptr, - "Out of memory while processing unknown chunk."); - return; - } - - png_memcpy(np, info_ptr->unknown_chunks, - info_ptr->unknown_chunks_num * png_sizeof(png_unknown_chunk)); - png_free(png_ptr, info_ptr->unknown_chunks); - info_ptr->unknown_chunks=NULL; - - for (i = 0; i < num_unknowns; i++) - { - png_unknown_chunkp to = np + info_ptr->unknown_chunks_num + i; - png_unknown_chunkp from = unknowns + i; - - png_strncpy((png_charp)to->name, (png_charp)from->name, 4); - to->name[4] = '\0'; - to->data = (png_bytep)png_malloc_warn(png_ptr, from->size); - if (to->data == NULL) - { - png_warning(png_ptr, - "Out of memory while processing unknown chunk."); - } - else - { - png_memcpy(to->data, from->data, from->size); - to->size = from->size; - - /* note our location in the read or write sequence */ - to->location = (png_byte)(png_ptr->mode & 0xff); - } - } - - info_ptr->unknown_chunks = np; - info_ptr->unknown_chunks_num += num_unknowns; -#ifdef PNG_FREE_ME_SUPPORTED - info_ptr->free_me |= PNG_FREE_UNKN; -#endif -} -void PNGAPI -png_set_unknown_chunk_location(png_structp png_ptr, png_infop info_ptr, - int chunk, int location) -{ - if(png_ptr != NULL && info_ptr != NULL && chunk >= 0 && chunk < - (int)info_ptr->unknown_chunks_num) - info_ptr->unknown_chunks[chunk].location = (png_byte)location; -} -#endif - -#if defined(PNG_1_0_X) || defined(PNG_1_2_X) -#if defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \ - defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) -void PNGAPI -png_permit_empty_plte (png_structp png_ptr, int empty_plte_permitted) -{ - /* This function is deprecated in favor of png_permit_mng_features() - and will be removed from libpng-1.3.0 */ - png_debug(1, "in png_permit_empty_plte, DEPRECATED.\n"); - if (png_ptr == NULL) - return; - png_ptr->mng_features_permitted = (png_byte) - ((png_ptr->mng_features_permitted & (~PNG_FLAG_MNG_EMPTY_PLTE)) | - ((empty_plte_permitted & PNG_FLAG_MNG_EMPTY_PLTE))); -} -#endif -#endif - -#if defined(PNG_MNG_FEATURES_SUPPORTED) -png_uint_32 PNGAPI -png_permit_mng_features (png_structp png_ptr, png_uint_32 mng_features) -{ - png_debug(1, "in png_permit_mng_features\n"); - if (png_ptr == NULL) - return (png_uint_32)0; - png_ptr->mng_features_permitted = - (png_byte)(mng_features & PNG_ALL_MNG_FEATURES); - return (png_uint_32)png_ptr->mng_features_permitted; -} -#endif - -#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) -void PNGAPI -png_set_keep_unknown_chunks(png_structp png_ptr, int keep, png_bytep - chunk_list, int num_chunks) -{ - png_bytep new_list, p; - int i, old_num_chunks; - if (png_ptr == NULL) - return; - if (num_chunks == 0) - { - if(keep == PNG_HANDLE_CHUNK_ALWAYS || keep == PNG_HANDLE_CHUNK_IF_SAFE) - png_ptr->flags |= PNG_FLAG_KEEP_UNKNOWN_CHUNKS; - else - png_ptr->flags &= ~PNG_FLAG_KEEP_UNKNOWN_CHUNKS; - - if(keep == PNG_HANDLE_CHUNK_ALWAYS) - png_ptr->flags |= PNG_FLAG_KEEP_UNSAFE_CHUNKS; - else - png_ptr->flags &= ~PNG_FLAG_KEEP_UNSAFE_CHUNKS; - return; - } - if (chunk_list == NULL) - return; - old_num_chunks=png_ptr->num_chunk_list; - new_list=(png_bytep)png_malloc(png_ptr, - (png_uint_32)(5*(num_chunks+old_num_chunks))); - if(png_ptr->chunk_list != NULL) - { - png_memcpy(new_list, png_ptr->chunk_list, - (png_size_t)(5*old_num_chunks)); - png_free(png_ptr, png_ptr->chunk_list); - png_ptr->chunk_list=NULL; - } - png_memcpy(new_list+5*old_num_chunks, chunk_list, - (png_size_t)(5*num_chunks)); - for (p=new_list+5*old_num_chunks+4, i=0; inum_chunk_list=old_num_chunks+num_chunks; - png_ptr->chunk_list=new_list; -#ifdef PNG_FREE_ME_SUPPORTED - png_ptr->free_me |= PNG_FREE_LIST; -#endif -} -#endif - -#if defined(PNG_READ_USER_CHUNKS_SUPPORTED) -void PNGAPI -png_set_read_user_chunk_fn(png_structp png_ptr, png_voidp user_chunk_ptr, - png_user_chunk_ptr read_user_chunk_fn) -{ - png_debug(1, "in png_set_read_user_chunk_fn\n"); - if (png_ptr == NULL) - return; - png_ptr->read_user_chunk_fn = read_user_chunk_fn; - png_ptr->user_chunk_ptr = user_chunk_ptr; -} -#endif - -#if defined(PNG_INFO_IMAGE_SUPPORTED) -void PNGAPI -png_set_rows(png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers) -{ - png_debug1(1, "in %s storage function\n", "rows"); - - if (png_ptr == NULL || info_ptr == NULL) - return; - - if(info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers)) - png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); - info_ptr->row_pointers = row_pointers; - if(row_pointers) - info_ptr->valid |= PNG_INFO_IDAT; -} -#endif - -#ifdef PNG_WRITE_SUPPORTED -void PNGAPI -png_set_compression_buffer_size(png_structp png_ptr, png_uint_32 size) -{ - if (png_ptr == NULL) - return; - if(png_ptr->zbuf) - png_free(png_ptr, png_ptr->zbuf); - png_ptr->zbuf_size = (png_size_t)size; - png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, size); - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; -} -#endif - -void PNGAPI -png_set_invalid(png_structp png_ptr, png_infop info_ptr, int mask) -{ - if (png_ptr && info_ptr) - info_ptr->valid &= ~mask; -} - - -#ifndef PNG_1_0_X -#ifdef PNG_ASSEMBLER_CODE_SUPPORTED -/* function was added to libpng 1.2.0 and should always exist by default */ -void PNGAPI -png_set_asm_flags (png_structp png_ptr, png_uint_32 asm_flags) -{ -/* Obsolete as of libpng-1.2.20 and will be removed from libpng-1.4.0 */ - if (png_ptr != NULL) - png_ptr->asm_flags = 0; -} - -/* this function was added to libpng 1.2.0 */ -void PNGAPI -png_set_mmx_thresholds (png_structp png_ptr, - png_byte mmx_bitdepth_threshold, - png_uint_32 mmx_rowbytes_threshold) -{ -/* Obsolete as of libpng-1.2.20 and will be removed from libpng-1.4.0 */ - if (png_ptr == NULL) - return; -} -#endif /* ?PNG_ASSEMBLER_CODE_SUPPORTED */ - -#ifdef PNG_SET_USER_LIMITS_SUPPORTED -/* this function was added to libpng 1.2.6 */ -void PNGAPI -png_set_user_limits (png_structp png_ptr, png_uint_32 user_width_max, - png_uint_32 user_height_max) -{ - /* Images with dimensions larger than these limits will be - * rejected by png_set_IHDR(). To accept any PNG datastream - * regardless of dimensions, set both limits to 0x7ffffffL. - */ - if(png_ptr == NULL) return; - png_ptr->user_width_max = user_width_max; - png_ptr->user_height_max = user_height_max; -} -#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */ - -#endif /* ?PNG_1_0_X */ -#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/uppdev/plugin/png/lib/pngtest.c b/uppdev/plugin/png/lib/pngtest.c deleted file mode 100644 index 64f1a707e..000000000 --- a/uppdev/plugin/png/lib/pngtest.c +++ /dev/null @@ -1,1553 +0,0 @@ - -/* pngtest.c - a simple test program to test libpng - * - * Last changed in libpng 1.2.22 - [October 13, 2007] - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2004 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This program reads in a PNG image, writes it out again, and then - * compares the two files. If the files are identical, this shows that - * the basic chunk handling, filtering, and (de)compression code is working - * properly. It does not currently test all of the transforms, although - * it probably should. - * - * The program will report "FAIL" in certain legitimate cases: - * 1) when the compression level or filter selection method is changed. - * 2) when the maximum IDAT size (PNG_ZBUF_SIZE in pngconf.h) is not 8192. - * 3) unknown unsafe-to-copy ancillary chunks or unknown critical chunks - * exist in the input file. - * 4) others not listed here... - * In these cases, it is best to check with another tool such as "pngcheck" - * to see what the differences between the two files are. - * - * If a filename is given on the command-line, then this file is used - * for the input, rather than the default "pngtest.png". This allows - * testing a wide variety of files easily. You can also test a number - * of files at once by typing "pngtest -m file1.png file2.png ..." - */ - -#include "png.h" - -#if defined(_WIN32_WCE) -# if _WIN32_WCE < 211 - __error__ (f|w)printf functions are not supported on old WindowsCE.; -# endif -# include -# include -# define READFILE(file, data, length, check) \ - if (ReadFile(file, data, length, &check,NULL)) check = 0 -# define WRITEFILE(file, data, length, check)) \ - if (WriteFile(file, data, length, &check, NULL)) check = 0 -# define FCLOSE(file) CloseHandle(file) -#else -# include -# include -# define READFILE(file, data, length, check) \ - check=(png_size_t)fread(data,(png_size_t)1,length,file) -# define WRITEFILE(file, data, length, check) \ - check=(png_size_t)fwrite(data,(png_size_t)1, length, file) -# define FCLOSE(file) fclose(file) -#endif - -#if defined(PNG_NO_STDIO) -# if defined(_WIN32_WCE) - typedef HANDLE png_FILE_p; -# else - typedef FILE * png_FILE_p; -# endif -#endif - -/* Makes pngtest verbose so we can find problems (needs to be before png.h) */ -#ifndef PNG_DEBUG -# define PNG_DEBUG 0 -#endif - -#if !PNG_DEBUG -# define SINGLE_ROWBUF_ALLOC /* makes buffer overruns easier to nail */ -#endif - -/* Turn on CPU timing -#define PNGTEST_TIMING -*/ - -#ifdef PNG_NO_FLOATING_POINT_SUPPORTED -#undef PNGTEST_TIMING -#endif - -#ifdef PNGTEST_TIMING -static float t_start, t_stop, t_decode, t_encode, t_misc; -#include -#endif - -#if defined(PNG_TIME_RFC1123_SUPPORTED) -static int tIME_chunk_present=0; -static char tIME_string[30] = "no tIME chunk present in file"; -#endif - -static int verbose = 0; - -int test_one_file PNGARG((PNG_CONST char *inname, PNG_CONST char *outname)); - -#ifdef __TURBOC__ -#include -#endif - -/* defined so I can write to a file on gui/windowing platforms */ -/* #define STDERR stderr */ -#define STDERR stdout /* for DOS */ - -/* example of using row callbacks to make a simple progress meter */ -static int status_pass=1; -static int status_dots_requested=0; -static int status_dots=1; - -/* In case a system header (e.g., on AIX) defined jmpbuf */ -#ifdef jmpbuf -# undef jmpbuf -#endif - -/* Define png_jmpbuf() in case we are using a pre-1.0.6 version of libpng */ -#ifndef png_jmpbuf -# define png_jmpbuf(png_ptr) png_ptr->jmpbuf -#endif - -void -#ifdef PNG_1_0_X -PNGAPI -#endif -read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass); -void -#ifdef PNG_1_0_X -PNGAPI -#endif -read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass) -{ - if(png_ptr == NULL || row_number > PNG_UINT_31_MAX) return; - if(status_pass != pass) - { - fprintf(stdout,"\n Pass %d: ",pass); - status_pass = pass; - status_dots = 31; - } - status_dots--; - if(status_dots == 0) - { - fprintf(stdout, "\n "); - status_dots=30; - } - fprintf(stdout, "r"); -} - -void -#ifdef PNG_1_0_X -PNGAPI -#endif -write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass); -void -#ifdef PNG_1_0_X -PNGAPI -#endif -write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass) -{ - if(png_ptr == NULL || row_number > PNG_UINT_31_MAX || pass > 7) return; - fprintf(stdout, "w"); -} - - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) -/* Example of using user transform callback (we don't transform anything, - but merely examine the row filters. We set this to 256 rather than - 5 in case illegal filter values are present.) */ -static png_uint_32 filters_used[256]; -void -#ifdef PNG_1_0_X -PNGAPI -#endif -count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data); -void -#ifdef PNG_1_0_X -PNGAPI -#endif -count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data) -{ - if(png_ptr != NULL && row_info != NULL) - ++filters_used[*(data-1)]; -} -#endif - -#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) -/* example of using user transform callback (we don't transform anything, - but merely count the zero samples) */ - -static png_uint_32 zero_samples; - -void -#ifdef PNG_1_0_X -PNGAPI -#endif -count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data); -void -#ifdef PNG_1_0_X -PNGAPI -#endif -count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data) -{ - png_bytep dp = data; - if(png_ptr == NULL)return; - - /* contents of row_info: - * png_uint_32 width width of row - * png_uint_32 rowbytes number of bytes in row - * png_byte color_type color type of pixels - * png_byte bit_depth bit depth of samples - * png_byte channels number of channels (1-4) - * png_byte pixel_depth bits per pixel (depth*channels) - */ - - - /* counts the number of zero samples (or zero pixels if color_type is 3 */ - - if(row_info->color_type == 0 || row_info->color_type == 3) - { - int pos=0; - png_uint_32 n, nstop; - for (n=0, nstop=row_info->width; nbit_depth == 1) - { - if(((*dp << pos++ ) & 0x80) == 0) zero_samples++; - if(pos == 8) - { - pos = 0; - dp++; - } - } - if(row_info->bit_depth == 2) - { - if(((*dp << (pos+=2)) & 0xc0) == 0) zero_samples++; - if(pos == 8) - { - pos = 0; - dp++; - } - } - if(row_info->bit_depth == 4) - { - if(((*dp << (pos+=4)) & 0xf0) == 0) zero_samples++; - if(pos == 8) - { - pos = 0; - dp++; - } - } - if(row_info->bit_depth == 8) - if(*dp++ == 0) zero_samples++; - if(row_info->bit_depth == 16) - { - if((*dp | *(dp+1)) == 0) zero_samples++; - dp+=2; - } - } - } - else /* other color types */ - { - png_uint_32 n, nstop; - int channel; - int color_channels = row_info->channels; - if(row_info->color_type > 3)color_channels--; - - for (n=0, nstop=row_info->width; nbit_depth == 8) - if(*dp++ == 0) zero_samples++; - if(row_info->bit_depth == 16) - { - if((*dp | *(dp+1)) == 0) zero_samples++; - dp+=2; - } - } - if(row_info->color_type > 3) - { - dp++; - if(row_info->bit_depth == 16)dp++; - } - } - } -} -#endif /* PNG_WRITE_USER_TRANSFORM_SUPPORTED */ - -static int wrote_question = 0; - -#if defined(PNG_NO_STDIO) -/* START of code to validate stdio-free compilation */ -/* These copies of the default read/write functions come from pngrio.c and */ -/* pngwio.c. They allow "don't include stdio" testing of the library. */ -/* This is the function that does the actual reading of data. If you are - not reading from a standard C stream, you should create a replacement - read_data function and use it at run time with png_set_read_fn(), rather - than changing the library. */ - -#ifndef USE_FAR_KEYWORD -static void -pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length) -{ - png_size_t check; - - /* fread() returns 0 on error, so it is OK to store this in a png_size_t - * instead of an int, which is what fread() actually returns. - */ - READFILE((png_FILE_p)png_ptr->io_ptr, data, length, check); - - if (check != length) - { - png_error(png_ptr, "Read Error!"); - } -} -#else -/* this is the model-independent version. Since the standard I/O library - can't handle far buffers in the medium and small models, we have to copy - the data. -*/ - -#define NEAR_BUF_SIZE 1024 -#define MIN(a,b) (a <= b ? a : b) - -static void -pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length) -{ - int check; - png_byte *n_data; - png_FILE_p io_ptr; - - /* Check if data really is near. If so, use usual code. */ - n_data = (png_byte *)CVT_PTR_NOCHECK(data); - io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); - if ((png_bytep)n_data == data) - { - READFILE(io_ptr, n_data, length, check); - } - else - { - png_byte buf[NEAR_BUF_SIZE]; - png_size_t read, remaining, err; - check = 0; - remaining = length; - do - { - read = MIN(NEAR_BUF_SIZE, remaining); - READFILE(io_ptr, buf, 1, err); - png_memcpy(data, buf, read); /* copy far buffer to near buffer */ - if(err != read) - break; - else - check += err; - data += read; - remaining -= read; - } - while (remaining != 0); - } - if (check != length) - { - png_error(png_ptr, "read Error"); - } -} -#endif /* USE_FAR_KEYWORD */ - -#if defined(PNG_WRITE_FLUSH_SUPPORTED) -static void -pngtest_flush(png_structp png_ptr) -{ -#if !defined(_WIN32_WCE) - png_FILE_p io_ptr; - io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr)); - if (io_ptr != NULL) - fflush(io_ptr); -#endif -} -#endif - -/* This is the function that does the actual writing of data. If you are - not writing to a standard C stream, you should create a replacement - write_data function and use it at run time with png_set_write_fn(), rather - than changing the library. */ -#ifndef USE_FAR_KEYWORD -static void -pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length) -{ - png_uint_32 check; - - WRITEFILE((png_FILE_p)png_ptr->io_ptr, data, length, check); - if (check != length) - { - png_error(png_ptr, "Write Error"); - } -} -#else -/* this is the model-independent version. Since the standard I/O library - can't handle far buffers in the medium and small models, we have to copy - the data. -*/ - -#define NEAR_BUF_SIZE 1024 -#define MIN(a,b) (a <= b ? a : b) - -static void -pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length) -{ - png_uint_32 check; - png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */ - png_FILE_p io_ptr; - - /* Check if data really is near. If so, use usual code. */ - near_data = (png_byte *)CVT_PTR_NOCHECK(data); - io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); - if ((png_bytep)near_data == data) - { - WRITEFILE(io_ptr, near_data, length, check); - } - else - { - png_byte buf[NEAR_BUF_SIZE]; - png_size_t written, remaining, err; - check = 0; - remaining = length; - do - { - written = MIN(NEAR_BUF_SIZE, remaining); - png_memcpy(buf, data, written); /* copy far buffer to near buffer */ - WRITEFILE(io_ptr, buf, written, err); - if (err != written) - break; - else - check += err; - data += written; - remaining -= written; - } - while (remaining != 0); - } - if (check != length) - { - png_error(png_ptr, "Write Error"); - } -} -#endif /* USE_FAR_KEYWORD */ -#endif /* PNG_NO_STDIO */ -/* END of code to validate stdio-free compilation */ - -/* This function is called when there is a warning, but the library thinks - * it can continue anyway. Replacement functions don't have to do anything - * here if you don't want to. In the default configuration, png_ptr is - * not used, but it is passed in case it may be useful. - */ -static void -pngtest_warning(png_structp png_ptr, png_const_charp message) -{ - PNG_CONST char *name = "UNKNOWN (ERROR!)"; - if (png_ptr != NULL && png_ptr->error_ptr != NULL) - name = png_ptr->error_ptr; - fprintf(STDERR, "%s: libpng warning: %s\n", name, message); -} - -/* This is the default error handling function. Note that replacements for - * this function MUST NOT RETURN, or the program will likely crash. This - * function is used by default, or if the program supplies NULL for the - * error function pointer in png_set_error_fn(). - */ -static void -pngtest_error(png_structp png_ptr, png_const_charp message) -{ - pngtest_warning(png_ptr, message); - /* We can return because png_error calls the default handler, which is - * actually OK in this case. */ -} - -/* START of code to validate memory allocation and deallocation */ -#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG - -/* Allocate memory. For reasonable files, size should never exceed - 64K. However, zlib may allocate more then 64K if you don't tell - it not to. See zconf.h and png.h for more information. zlib does - need to allocate exactly 64K, so whatever you call here must - have the ability to do that. - - This piece of code can be compiled to validate max 64K allocations - by setting MAXSEG_64K in zlib zconf.h *or* PNG_MAX_MALLOC_64K. */ -typedef struct memory_information -{ - png_uint_32 size; - png_voidp pointer; - struct memory_information FAR *next; -} memory_information; -typedef memory_information FAR *memory_infop; - -static memory_infop pinformation = NULL; -static int current_allocation = 0; -static int maximum_allocation = 0; -static int total_allocation = 0; -static int num_allocations = 0; - -png_voidp png_debug_malloc PNGARG((png_structp png_ptr, png_uint_32 size)); -void png_debug_free PNGARG((png_structp png_ptr, png_voidp ptr)); - -png_voidp -png_debug_malloc(png_structp png_ptr, png_uint_32 size) -{ - - /* png_malloc has already tested for NULL; png_create_struct calls - png_debug_malloc directly, with png_ptr == NULL which is OK */ - - if (size == 0) - return (NULL); - - /* This calls the library allocator twice, once to get the requested - buffer and once to get a new free list entry. */ - { - /* Disable malloc_fn and free_fn */ - memory_infop pinfo; - png_set_mem_fn(png_ptr, NULL, NULL, NULL); - pinfo = (memory_infop)png_malloc(png_ptr, - (png_uint_32)png_sizeof (*pinfo)); - pinfo->size = size; - current_allocation += size; - total_allocation += size; - num_allocations ++; - if (current_allocation > maximum_allocation) - maximum_allocation = current_allocation; - pinfo->pointer = (png_voidp)png_malloc(png_ptr, size); - /* Restore malloc_fn and free_fn */ - png_set_mem_fn(png_ptr, png_voidp_NULL, (png_malloc_ptr)png_debug_malloc, - (png_free_ptr)png_debug_free); - if (size != 0 && pinfo->pointer == NULL) - { - current_allocation -= size; - total_allocation -= size; - png_error(png_ptr, - "out of memory in pngtest->png_debug_malloc."); - } - pinfo->next = pinformation; - pinformation = pinfo; - /* Make sure the caller isn't assuming zeroed memory. */ - png_memset(pinfo->pointer, 0xdd, pinfo->size); - if(verbose) - printf("png_malloc %lu bytes at %x\n",(unsigned long)size, - pinfo->pointer); - return (png_voidp)(pinfo->pointer); - } -} - -/* Free a pointer. It is removed from the list at the same time. */ -void -png_debug_free(png_structp png_ptr, png_voidp ptr) -{ - if (png_ptr == NULL) - fprintf(STDERR, "NULL pointer to png_debug_free.\n"); - if (ptr == 0) - { -#if 0 /* This happens all the time. */ - fprintf(STDERR, "WARNING: freeing NULL pointer\n"); -#endif - return; - } - - /* Unlink the element from the list. */ - { - memory_infop FAR *ppinfo = &pinformation; - for (;;) - { - memory_infop pinfo = *ppinfo; - if (pinfo->pointer == ptr) - { - *ppinfo = pinfo->next; - current_allocation -= pinfo->size; - if (current_allocation < 0) - fprintf(STDERR, "Duplicate free of memory\n"); - /* We must free the list element too, but first kill - the memory that is to be freed. */ - png_memset(ptr, 0x55, pinfo->size); - png_free_default(png_ptr, pinfo); - pinfo=NULL; - break; - } - if (pinfo->next == NULL) - { - fprintf(STDERR, "Pointer %x not found\n", (unsigned int)ptr); - break; - } - ppinfo = &pinfo->next; - } - } - - /* Finally free the data. */ - if(verbose) - printf("Freeing %x\n",ptr); - png_free_default(png_ptr, ptr); - ptr=NULL; -} -#endif /* PNG_USER_MEM_SUPPORTED && PNG_DEBUG */ -/* END of code to test memory allocation/deallocation */ - -/* Test one file */ -int -test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) -{ - static png_FILE_p fpin; - static png_FILE_p fpout; /* "static" prevents setjmp corruption */ - png_structp read_ptr; - png_infop read_info_ptr, end_info_ptr; -#ifdef PNG_WRITE_SUPPORTED - png_structp write_ptr; - png_infop write_info_ptr; - png_infop write_end_info_ptr; -#else - png_structp write_ptr = NULL; - png_infop write_info_ptr = NULL; - png_infop write_end_info_ptr = NULL; -#endif - png_bytep row_buf; - png_uint_32 y; - png_uint_32 width, height; - int num_pass, pass; - int bit_depth, color_type; -#ifdef PNG_SETJMP_SUPPORTED -#ifdef USE_FAR_KEYWORD - jmp_buf jmpbuf; -#endif -#endif - -#if defined(_WIN32_WCE) - TCHAR path[MAX_PATH]; -#endif - char inbuf[256], outbuf[256]; - - row_buf = NULL; - -#if defined(_WIN32_WCE) - MultiByteToWideChar(CP_ACP, 0, inname, -1, path, MAX_PATH); - if ((fpin = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) -#else - if ((fpin = fopen(inname, "rb")) == NULL) -#endif - { - fprintf(STDERR, "Could not find input file %s\n", inname); - return (1); - } - -#if defined(_WIN32_WCE) - MultiByteToWideChar(CP_ACP, 0, outname, -1, path, MAX_PATH); - if ((fpout = CreateFile(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL)) == INVALID_HANDLE_VALUE) -#else - if ((fpout = fopen(outname, "wb")) == NULL) -#endif - { - fprintf(STDERR, "Could not open output file %s\n", outname); - FCLOSE(fpin); - return (1); - } - - png_debug(0, "Allocating read and write structures\n"); -#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG - read_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, png_voidp_NULL, - png_error_ptr_NULL, png_error_ptr_NULL, png_voidp_NULL, - (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free); -#else - read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, png_voidp_NULL, - png_error_ptr_NULL, png_error_ptr_NULL); -#endif - png_set_error_fn(read_ptr, (png_voidp)inname, pngtest_error, - pngtest_warning); -#ifdef PNG_WRITE_SUPPORTED -#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG - write_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING, png_voidp_NULL, - png_error_ptr_NULL, png_error_ptr_NULL, png_voidp_NULL, - (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free); -#else - write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, png_voidp_NULL, - png_error_ptr_NULL, png_error_ptr_NULL); -#endif - png_set_error_fn(write_ptr, (png_voidp)inname, pngtest_error, - pngtest_warning); -#endif - png_debug(0, "Allocating read_info, write_info and end_info structures\n"); - read_info_ptr = png_create_info_struct(read_ptr); - end_info_ptr = png_create_info_struct(read_ptr); -#ifdef PNG_WRITE_SUPPORTED - write_info_ptr = png_create_info_struct(write_ptr); - write_end_info_ptr = png_create_info_struct(write_ptr); -#endif - -#ifdef PNG_SETJMP_SUPPORTED - png_debug(0, "Setting jmpbuf for read struct\n"); -#ifdef USE_FAR_KEYWORD - if (setjmp(jmpbuf)) -#else - if (setjmp(png_jmpbuf(read_ptr))) -#endif - { - fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname); - if (row_buf) - png_free(read_ptr, row_buf); - png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); -#ifdef PNG_WRITE_SUPPORTED - png_destroy_info_struct(write_ptr, &write_end_info_ptr); - png_destroy_write_struct(&write_ptr, &write_info_ptr); -#endif - FCLOSE(fpin); - FCLOSE(fpout); - return (1); - } -#ifdef USE_FAR_KEYWORD - png_memcpy(png_jmpbuf(read_ptr),jmpbuf,png_sizeof(jmp_buf)); -#endif - -#ifdef PNG_WRITE_SUPPORTED - png_debug(0, "Setting jmpbuf for write struct\n"); -#ifdef USE_FAR_KEYWORD - if (setjmp(jmpbuf)) -#else - if (setjmp(png_jmpbuf(write_ptr))) -#endif - { - fprintf(STDERR, "%s -> %s: libpng write error\n", inname, outname); - png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); - png_destroy_info_struct(write_ptr, &write_end_info_ptr); -#ifdef PNG_WRITE_SUPPORTED - png_destroy_write_struct(&write_ptr, &write_info_ptr); -#endif - FCLOSE(fpin); - FCLOSE(fpout); - return (1); - } -#ifdef USE_FAR_KEYWORD - png_memcpy(png_jmpbuf(write_ptr),jmpbuf,png_sizeof(jmp_buf)); -#endif -#endif -#endif - - png_debug(0, "Initializing input and output streams\n"); -#if !defined(PNG_NO_STDIO) - png_init_io(read_ptr, fpin); -# ifdef PNG_WRITE_SUPPORTED - png_init_io(write_ptr, fpout); -# endif -#else - png_set_read_fn(read_ptr, (png_voidp)fpin, pngtest_read_data); -# ifdef PNG_WRITE_SUPPORTED - png_set_write_fn(write_ptr, (png_voidp)fpout, pngtest_write_data, -# if defined(PNG_WRITE_FLUSH_SUPPORTED) - pngtest_flush); -# else - NULL); -# endif -# endif -#endif - if(status_dots_requested == 1) - { -#ifdef PNG_WRITE_SUPPORTED - png_set_write_status_fn(write_ptr, write_row_callback); -#endif - png_set_read_status_fn(read_ptr, read_row_callback); - } - else - { -#ifdef PNG_WRITE_SUPPORTED - png_set_write_status_fn(write_ptr, png_write_status_ptr_NULL); -#endif - png_set_read_status_fn(read_ptr, png_read_status_ptr_NULL); - } - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) - { - int i; - for(i=0; i<256; i++) - filters_used[i]=0; - png_set_read_user_transform_fn(read_ptr, count_filters); - } -#endif -#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) - zero_samples=0; - png_set_write_user_transform_fn(write_ptr, count_zero_samples); -#endif - -#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) -# ifndef PNG_HANDLE_CHUNK_ALWAYS -# define PNG_HANDLE_CHUNK_ALWAYS 3 -# endif - png_set_keep_unknown_chunks(read_ptr, PNG_HANDLE_CHUNK_ALWAYS, - png_bytep_NULL, 0); -#endif -#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) -# ifndef PNG_HANDLE_CHUNK_IF_SAFE -# define PNG_HANDLE_CHUNK_IF_SAFE 2 -# endif - png_set_keep_unknown_chunks(write_ptr, PNG_HANDLE_CHUNK_IF_SAFE, - png_bytep_NULL, 0); -#endif - - png_debug(0, "Reading info struct\n"); - png_read_info(read_ptr, read_info_ptr); - - png_debug(0, "Transferring info struct\n"); - { - int interlace_type, compression_type, filter_type; - - if (png_get_IHDR(read_ptr, read_info_ptr, &width, &height, &bit_depth, - &color_type, &interlace_type, &compression_type, &filter_type)) - { - png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth, -#if defined(PNG_WRITE_INTERLACING_SUPPORTED) - color_type, interlace_type, compression_type, filter_type); -#else - color_type, PNG_INTERLACE_NONE, compression_type, filter_type); -#endif - } - } -#if defined(PNG_FIXED_POINT_SUPPORTED) -#if defined(PNG_cHRM_SUPPORTED) - { - png_fixed_point white_x, white_y, red_x, red_y, green_x, green_y, blue_x, - blue_y; - if (png_get_cHRM_fixed(read_ptr, read_info_ptr, &white_x, &white_y, &red_x, - &red_y, &green_x, &green_y, &blue_x, &blue_y)) - { - png_set_cHRM_fixed(write_ptr, write_info_ptr, white_x, white_y, red_x, - red_y, green_x, green_y, blue_x, blue_y); - } - } -#endif -#if defined(PNG_gAMA_SUPPORTED) - { - png_fixed_point gamma; - - if (png_get_gAMA_fixed(read_ptr, read_info_ptr, &gamma)) - { - png_set_gAMA_fixed(write_ptr, write_info_ptr, gamma); - } - } -#endif -#else /* Use floating point versions */ -#if defined(PNG_FLOATING_POINT_SUPPORTED) -#if defined(PNG_cHRM_SUPPORTED) - { - double white_x, white_y, red_x, red_y, green_x, green_y, blue_x, - blue_y; - if (png_get_cHRM(read_ptr, read_info_ptr, &white_x, &white_y, &red_x, - &red_y, &green_x, &green_y, &blue_x, &blue_y)) - { - png_set_cHRM(write_ptr, write_info_ptr, white_x, white_y, red_x, - red_y, green_x, green_y, blue_x, blue_y); - } - } -#endif -#if defined(PNG_gAMA_SUPPORTED) - { - double gamma; - - if (png_get_gAMA(read_ptr, read_info_ptr, &gamma)) - { - png_set_gAMA(write_ptr, write_info_ptr, gamma); - } - } -#endif -#endif /* floating point */ -#endif /* fixed point */ -#if defined(PNG_iCCP_SUPPORTED) - { - png_charp name; - png_charp profile; - png_uint_32 proflen; - int compression_type; - - if (png_get_iCCP(read_ptr, read_info_ptr, &name, &compression_type, - &profile, &proflen)) - { - png_set_iCCP(write_ptr, write_info_ptr, name, compression_type, - profile, proflen); - } - } -#endif -#if defined(PNG_sRGB_SUPPORTED) - { - int intent; - - if (png_get_sRGB(read_ptr, read_info_ptr, &intent)) - { - png_set_sRGB(write_ptr, write_info_ptr, intent); - } - } -#endif - { - png_colorp palette; - int num_palette; - - if (png_get_PLTE(read_ptr, read_info_ptr, &palette, &num_palette)) - { - png_set_PLTE(write_ptr, write_info_ptr, palette, num_palette); - } - } -#if defined(PNG_bKGD_SUPPORTED) - { - png_color_16p background; - - if (png_get_bKGD(read_ptr, read_info_ptr, &background)) - { - png_set_bKGD(write_ptr, write_info_ptr, background); - } - } -#endif -#if defined(PNG_hIST_SUPPORTED) - { - png_uint_16p hist; - - if (png_get_hIST(read_ptr, read_info_ptr, &hist)) - { - png_set_hIST(write_ptr, write_info_ptr, hist); - } - } -#endif -#if defined(PNG_oFFs_SUPPORTED) - { - png_int_32 offset_x, offset_y; - int unit_type; - - if (png_get_oFFs(read_ptr, read_info_ptr,&offset_x,&offset_y,&unit_type)) - { - png_set_oFFs(write_ptr, write_info_ptr, offset_x, offset_y, unit_type); - } - } -#endif -#if defined(PNG_pCAL_SUPPORTED) - { - png_charp purpose, units; - png_charpp params; - png_int_32 X0, X1; - int type, nparams; - - if (png_get_pCAL(read_ptr, read_info_ptr, &purpose, &X0, &X1, &type, - &nparams, &units, ¶ms)) - { - png_set_pCAL(write_ptr, write_info_ptr, purpose, X0, X1, type, - nparams, units, params); - } - } -#endif -#if defined(PNG_pHYs_SUPPORTED) - { - png_uint_32 res_x, res_y; - int unit_type; - - if (png_get_pHYs(read_ptr, read_info_ptr, &res_x, &res_y, &unit_type)) - { - png_set_pHYs(write_ptr, write_info_ptr, res_x, res_y, unit_type); - } - } -#endif -#if defined(PNG_sBIT_SUPPORTED) - { - png_color_8p sig_bit; - - if (png_get_sBIT(read_ptr, read_info_ptr, &sig_bit)) - { - png_set_sBIT(write_ptr, write_info_ptr, sig_bit); - } - } -#endif -#if defined(PNG_sCAL_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED - { - int unit; - double scal_width, scal_height; - - if (png_get_sCAL(read_ptr, read_info_ptr, &unit, &scal_width, - &scal_height)) - { - png_set_sCAL(write_ptr, write_info_ptr, unit, scal_width, scal_height); - } - } -#else -#ifdef PNG_FIXED_POINT_SUPPORTED - { - int unit; - png_charp scal_width, scal_height; - - if (png_get_sCAL_s(read_ptr, read_info_ptr, &unit, &scal_width, - &scal_height)) - { - png_set_sCAL_s(write_ptr, write_info_ptr, unit, scal_width, scal_height); - } - } -#endif -#endif -#endif -#if defined(PNG_TEXT_SUPPORTED) - { - png_textp text_ptr; - int num_text; - - if (png_get_text(read_ptr, read_info_ptr, &text_ptr, &num_text) > 0) - { - png_debug1(0, "Handling %d iTXt/tEXt/zTXt chunks\n", num_text); - png_set_text(write_ptr, write_info_ptr, text_ptr, num_text); - } - } -#endif -#if defined(PNG_tIME_SUPPORTED) - { - png_timep mod_time; - - if (png_get_tIME(read_ptr, read_info_ptr, &mod_time)) - { - png_set_tIME(write_ptr, write_info_ptr, mod_time); -#if defined(PNG_TIME_RFC1123_SUPPORTED) - /* we have to use png_strncpy instead of "=" because the string - pointed to by png_convert_to_rfc1123() gets free'ed before - we use it */ - png_strncpy(tIME_string,png_convert_to_rfc1123(read_ptr, - mod_time),29); - tIME_string[29] = '\0'; - tIME_chunk_present++; -#endif /* PNG_TIME_RFC1123_SUPPORTED */ - } - } -#endif -#if defined(PNG_tRNS_SUPPORTED) - { - png_bytep trans; - int num_trans; - png_color_16p trans_values; - - if (png_get_tRNS(read_ptr, read_info_ptr, &trans, &num_trans, - &trans_values)) - { - png_set_tRNS(write_ptr, write_info_ptr, trans, num_trans, - trans_values); - } - } -#endif -#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) - { - png_unknown_chunkp unknowns; - int num_unknowns = (int)png_get_unknown_chunks(read_ptr, read_info_ptr, - &unknowns); - if (num_unknowns) - { - png_size_t i; - png_set_unknown_chunks(write_ptr, write_info_ptr, unknowns, - num_unknowns); - /* copy the locations from the read_info_ptr. The automatically - generated locations in write_info_ptr are wrong because we - haven't written anything yet */ - for (i = 0; i < (png_size_t)num_unknowns; i++) - png_set_unknown_chunk_location(write_ptr, write_info_ptr, i, - unknowns[i].location); - } - } -#endif - -#ifdef PNG_WRITE_SUPPORTED - png_debug(0, "\nWriting info struct\n"); - -/* If we wanted, we could write info in two steps: - png_write_info_before_PLTE(write_ptr, write_info_ptr); - */ - png_write_info(write_ptr, write_info_ptr); -#endif - -#ifdef SINGLE_ROWBUF_ALLOC - png_debug(0, "\nAllocating row buffer..."); - row_buf = (png_bytep)png_malloc(read_ptr, - png_get_rowbytes(read_ptr, read_info_ptr)); - png_debug1(0, "0x%08lx\n\n", (unsigned long)row_buf); -#endif /* SINGLE_ROWBUF_ALLOC */ - png_debug(0, "Writing row data\n"); - -#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ - defined(PNG_WRITE_INTERLACING_SUPPORTED) - num_pass = png_set_interlace_handling(read_ptr); -# ifdef PNG_WRITE_SUPPORTED - png_set_interlace_handling(write_ptr); -# endif -#else - num_pass=1; -#endif - -#ifdef PNGTEST_TIMING - t_stop = (float)clock(); - t_misc += (t_stop - t_start); - t_start = t_stop; -#endif - for (pass = 0; pass < num_pass; pass++) - { - png_debug1(0, "Writing row data for pass %d\n",pass); - for (y = 0; y < height; y++) - { -#ifndef SINGLE_ROWBUF_ALLOC - png_debug2(0, "\nAllocating row buffer (pass %d, y = %ld)...", pass,y); - row_buf = (png_bytep)png_malloc(read_ptr, - png_get_rowbytes(read_ptr, read_info_ptr)); - png_debug2(0, "0x%08lx (%ld bytes)\n", (unsigned long)row_buf, - png_get_rowbytes(read_ptr, read_info_ptr)); -#endif /* !SINGLE_ROWBUF_ALLOC */ - png_read_rows(read_ptr, (png_bytepp)&row_buf, png_bytepp_NULL, 1); - -#ifdef PNG_WRITE_SUPPORTED -#ifdef PNGTEST_TIMING - t_stop = (float)clock(); - t_decode += (t_stop - t_start); - t_start = t_stop; -#endif - png_write_rows(write_ptr, (png_bytepp)&row_buf, 1); -#ifdef PNGTEST_TIMING - t_stop = (float)clock(); - t_encode += (t_stop - t_start); - t_start = t_stop; -#endif -#endif /* PNG_WRITE_SUPPORTED */ - -#ifndef SINGLE_ROWBUF_ALLOC - png_debug2(0, "Freeing row buffer (pass %d, y = %ld)\n\n", pass, y); - png_free(read_ptr, row_buf); -#endif /* !SINGLE_ROWBUF_ALLOC */ - } - } - -#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) - png_free_data(read_ptr, read_info_ptr, PNG_FREE_UNKN, -1); -#endif -#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) - png_free_data(write_ptr, write_info_ptr, PNG_FREE_UNKN, -1); -#endif - - png_debug(0, "Reading and writing end_info data\n"); - - png_read_end(read_ptr, end_info_ptr); -#if defined(PNG_TEXT_SUPPORTED) - { - png_textp text_ptr; - int num_text; - - if (png_get_text(read_ptr, end_info_ptr, &text_ptr, &num_text) > 0) - { - png_debug1(0, "Handling %d iTXt/tEXt/zTXt chunks\n", num_text); - png_set_text(write_ptr, write_end_info_ptr, text_ptr, num_text); - } - } -#endif -#if defined(PNG_tIME_SUPPORTED) - { - png_timep mod_time; - - if (png_get_tIME(read_ptr, end_info_ptr, &mod_time)) - { - png_set_tIME(write_ptr, write_end_info_ptr, mod_time); -#if defined(PNG_TIME_RFC1123_SUPPORTED) - /* we have to use png_strncpy instead of "=" because the string - pointed to by png_convert_to_rfc1123() gets free'ed before - we use it */ - png_strncpy(tIME_string,png_convert_to_rfc1123(read_ptr, - mod_time),29); - tIME_string[29] = '\0'; - tIME_chunk_present++; -#endif /* PNG_TIME_RFC1123_SUPPORTED */ - } - } -#endif -#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) - { - png_unknown_chunkp unknowns; - int num_unknowns; - num_unknowns = (int)png_get_unknown_chunks(read_ptr, end_info_ptr, - &unknowns); - if (num_unknowns) - { - png_size_t i; - png_set_unknown_chunks(write_ptr, write_end_info_ptr, unknowns, - num_unknowns); - /* copy the locations from the read_info_ptr. The automatically - generated locations in write_end_info_ptr are wrong because we - haven't written the end_info yet */ - for (i = 0; i < (png_size_t)num_unknowns; i++) - png_set_unknown_chunk_location(write_ptr, write_end_info_ptr, i, - unknowns[i].location); - } - } -#endif -#ifdef PNG_WRITE_SUPPORTED - png_write_end(write_ptr, write_end_info_ptr); -#endif - -#ifdef PNG_EASY_ACCESS_SUPPORTED - if(verbose) - { - png_uint_32 iwidth, iheight; - iwidth = png_get_image_width(write_ptr, write_info_ptr); - iheight = png_get_image_height(write_ptr, write_info_ptr); - fprintf(STDERR, "Image width = %lu, height = %lu\n", - (unsigned long)iwidth, (unsigned long)iheight); - } -#endif - - png_debug(0, "Destroying data structs\n"); -#ifdef SINGLE_ROWBUF_ALLOC - png_debug(1, "destroying row_buf for read_ptr\n"); - png_free(read_ptr, row_buf); - row_buf=NULL; -#endif /* SINGLE_ROWBUF_ALLOC */ - png_debug(1, "destroying read_ptr, read_info_ptr, end_info_ptr\n"); - png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); -#ifdef PNG_WRITE_SUPPORTED - png_debug(1, "destroying write_end_info_ptr\n"); - png_destroy_info_struct(write_ptr, &write_end_info_ptr); - png_debug(1, "destroying write_ptr, write_info_ptr\n"); - png_destroy_write_struct(&write_ptr, &write_info_ptr); -#endif - png_debug(0, "Destruction complete.\n"); - - FCLOSE(fpin); - FCLOSE(fpout); - - png_debug(0, "Opening files for comparison\n"); -#if defined(_WIN32_WCE) - MultiByteToWideChar(CP_ACP, 0, inname, -1, path, MAX_PATH); - if ((fpin = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) -#else - if ((fpin = fopen(inname, "rb")) == NULL) -#endif - { - fprintf(STDERR, "Could not find file %s\n", inname); - return (1); - } - -#if defined(_WIN32_WCE) - MultiByteToWideChar(CP_ACP, 0, outname, -1, path, MAX_PATH); - if ((fpout = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) -#else - if ((fpout = fopen(outname, "rb")) == NULL) -#endif - { - fprintf(STDERR, "Could not find file %s\n", outname); - FCLOSE(fpin); - return (1); - } - - for(;;) - { - png_size_t num_in, num_out; - - READFILE(fpin, inbuf, 1, num_in); - READFILE(fpout, outbuf, 1, num_out); - - if (num_in != num_out) - { - fprintf(STDERR, "\nFiles %s and %s are of a different size\n", - inname, outname); - if(wrote_question == 0) - { - fprintf(STDERR, - " Was %s written with the same maximum IDAT chunk size (%d bytes),", - inname,PNG_ZBUF_SIZE); - fprintf(STDERR, - "\n filtering heuristic (libpng default), compression"); - fprintf(STDERR, - " level (zlib default),\n and zlib version (%s)?\n\n", - ZLIB_VERSION); - wrote_question=1; - } - FCLOSE(fpin); - FCLOSE(fpout); - return (0); - } - - if (!num_in) - break; - - if (png_memcmp(inbuf, outbuf, num_in)) - { - fprintf(STDERR, "\nFiles %s and %s are different\n", inname, outname); - if(wrote_question == 0) - { - fprintf(STDERR, - " Was %s written with the same maximum IDAT chunk size (%d bytes),", - inname,PNG_ZBUF_SIZE); - fprintf(STDERR, - "\n filtering heuristic (libpng default), compression"); - fprintf(STDERR, - " level (zlib default),\n and zlib version (%s)?\n\n", - ZLIB_VERSION); - wrote_question=1; - } - FCLOSE(fpin); - FCLOSE(fpout); - return (0); - } - } - - FCLOSE(fpin); - FCLOSE(fpout); - - return (0); -} - -/* input and output filenames */ -#ifdef RISCOS -static PNG_CONST char *inname = "pngtest/png"; -static PNG_CONST char *outname = "pngout/png"; -#else -static PNG_CONST char *inname = "pngtest.png"; -static PNG_CONST char *outname = "pngout.png"; -#endif - -int -main(int argc, char *argv[]) -{ - int multiple = 0; - int ierror = 0; - - fprintf(STDERR, "Testing libpng version %s\n", PNG_LIBPNG_VER_STRING); - fprintf(STDERR, " with zlib version %s\n", ZLIB_VERSION); - fprintf(STDERR,"%s",png_get_copyright(NULL)); - /* Show the version of libpng used in building the library */ - fprintf(STDERR," library (%lu):%s", - (unsigned long)png_access_version_number(), - png_get_header_version(NULL)); - /* Show the version of libpng used in building the application */ - fprintf(STDERR," pngtest (%lu):%s", (unsigned long)PNG_LIBPNG_VER, - PNG_HEADER_VERSION_STRING); - fprintf(STDERR," png_sizeof(png_struct)=%ld, png_sizeof(png_info)=%ld\n", - (long)png_sizeof(png_struct), (long)png_sizeof(png_info)); - - /* Do some consistency checking on the memory allocation settings, I'm - not sure this matters, but it is nice to know, the first of these - tests should be impossible because of the way the macros are set - in pngconf.h */ -#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K) - fprintf(STDERR, " NOTE: Zlib compiled for max 64k, libpng not\n"); -#endif - /* I think the following can happen. */ -#if !defined(MAXSEG_64K) && defined(PNG_MAX_MALLOC_64K) - fprintf(STDERR, " NOTE: libpng compiled for max 64k, zlib not\n"); -#endif - - if (strcmp(png_libpng_ver, PNG_LIBPNG_VER_STRING)) - { - fprintf(STDERR, - "Warning: versions are different between png.h and png.c\n"); - fprintf(STDERR, " png.h version: %s\n", PNG_LIBPNG_VER_STRING); - fprintf(STDERR, " png.c version: %s\n\n", png_libpng_ver); - ++ierror; - } - - if (argc > 1) - { - if (strcmp(argv[1], "-m") == 0) - { - multiple = 1; - status_dots_requested = 0; - } - else if (strcmp(argv[1], "-mv") == 0 || - strcmp(argv[1], "-vm") == 0 ) - { - multiple = 1; - verbose = 1; - status_dots_requested = 1; - } - else if (strcmp(argv[1], "-v") == 0) - { - verbose = 1; - status_dots_requested = 1; - inname = argv[2]; - } - else - { - inname = argv[1]; - status_dots_requested = 0; - } - } - - if (!multiple && argc == 3+verbose) - outname = argv[2+verbose]; - - if ((!multiple && argc > 3+verbose) || (multiple && argc < 2)) - { - fprintf(STDERR, - "usage: %s [infile.png] [outfile.png]\n\t%s -m {infile.png}\n", - argv[0], argv[0]); - fprintf(STDERR, - " reads/writes one PNG file (without -m) or multiple files (-m)\n"); - fprintf(STDERR, - " with -m %s is used as a temporary file\n", outname); - exit(1); - } - - if (multiple) - { - int i; -#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG - int allocation_now = current_allocation; -#endif - for (i=2; isize, - (unsigned int) pinfo->pointer); - pinfo = pinfo->next; - } - } -#endif - } -#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG - fprintf(STDERR, " Current memory allocation: %10d bytes\n", - current_allocation); - fprintf(STDERR, " Maximum memory allocation: %10d bytes\n", - maximum_allocation); - fprintf(STDERR, " Total memory allocation: %10d bytes\n", - total_allocation); - fprintf(STDERR, " Number of allocations: %10d\n", - num_allocations); -#endif - } - else - { - int i; - for (i=0; i<3; ++i) - { - int kerror; -#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG - int allocation_now = current_allocation; -#endif - if (i == 1) status_dots_requested = 1; - else if(verbose == 0)status_dots_requested = 0; - if (i == 0 || verbose == 1 || ierror != 0) - fprintf(STDERR, "Testing %s:",inname); - kerror = test_one_file(inname, outname); - if(kerror == 0) - { - if(verbose == 1 || i == 2) - { -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) - int k; -#endif -#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) - fprintf(STDERR, "\n PASS (%lu zero samples)\n", - (unsigned long)zero_samples); -#else - fprintf(STDERR, " PASS\n"); -#endif -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) - for (k=0; k<256; k++) - if(filters_used[k]) - fprintf(STDERR, " Filter %d was used %lu times\n", - k,(unsigned long)filters_used[k]); -#endif -#if defined(PNG_TIME_RFC1123_SUPPORTED) - if(tIME_chunk_present != 0) - fprintf(STDERR, " tIME = %s\n",tIME_string); -#endif /* PNG_TIME_RFC1123_SUPPORTED */ - } - } - else - { - if(verbose == 0 && i != 2) - fprintf(STDERR, "Testing %s:",inname); - fprintf(STDERR, " FAIL\n"); - ierror += kerror; - } -#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG - if (allocation_now != current_allocation) - fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n", - current_allocation-allocation_now); - if (current_allocation != 0) - { - memory_infop pinfo = pinformation; - - fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n", - current_allocation); - while (pinfo != NULL) - { - fprintf(STDERR," %lu bytes at %x\n", - (unsigned long)pinfo->size, (unsigned int)pinfo->pointer); - pinfo = pinfo->next; - } - } -#endif - } -#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG - fprintf(STDERR, " Current memory allocation: %10d bytes\n", - current_allocation); - fprintf(STDERR, " Maximum memory allocation: %10d bytes\n", - maximum_allocation); - fprintf(STDERR, " Total memory allocation: %10d bytes\n", - total_allocation); - fprintf(STDERR, " Number of allocations: %10d\n", - num_allocations); -#endif - } - -#ifdef PNGTEST_TIMING - t_stop = (float)clock(); - t_misc += (t_stop - t_start); - t_start = t_stop; - fprintf(STDERR," CPU time used = %.3f seconds", - (t_misc+t_decode+t_encode)/(float)CLOCKS_PER_SEC); - fprintf(STDERR," (decoding %.3f,\n", - t_decode/(float)CLOCKS_PER_SEC); - fprintf(STDERR," encoding %.3f ,", - t_encode/(float)CLOCKS_PER_SEC); - fprintf(STDERR," other %.3f seconds)\n\n", - t_misc/(float)CLOCKS_PER_SEC); -#endif - - if (ierror == 0) - fprintf(STDERR, "libpng passes test\n"); - else - fprintf(STDERR, "libpng FAILS test\n"); - return (int)(ierror != 0); -} - -/* Generate a compiler error if there is an old png.h in the search path. */ -typedef version_1_2_22 your_png_h_is_not_version_1_2_22; diff --git a/uppdev/plugin/png/lib/pngtrans.c b/uppdev/plugin/png/lib/pngtrans.c deleted file mode 100644 index 8c8faa13c..000000000 --- a/uppdev/plugin/png/lib/pngtrans.c +++ /dev/null @@ -1,662 +0,0 @@ - -/* pngtrans.c - transforms the data in a row (used by both readers and writers) - * - * Last changed in libpng 1.2.17 May 15, 2007 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2007 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - */ - -#define PNG_INTERNAL -#include "png.h" - -#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) -#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) -/* turn on BGR-to-RGB mapping */ -void PNGAPI -png_set_bgr(png_structp png_ptr) -{ - png_debug(1, "in png_set_bgr\n"); - if(png_ptr == NULL) return; - png_ptr->transformations |= PNG_BGR; -} -#endif - -#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) -/* turn on 16 bit byte swapping */ -void PNGAPI -png_set_swap(png_structp png_ptr) -{ - png_debug(1, "in png_set_swap\n"); - if(png_ptr == NULL) return; - if (png_ptr->bit_depth == 16) - png_ptr->transformations |= PNG_SWAP_BYTES; -} -#endif - -#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) -/* turn on pixel packing */ -void PNGAPI -png_set_packing(png_structp png_ptr) -{ - png_debug(1, "in png_set_packing\n"); - if(png_ptr == NULL) return; - if (png_ptr->bit_depth < 8) - { - png_ptr->transformations |= PNG_PACK; - png_ptr->usr_bit_depth = 8; - } -} -#endif - -#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED) -/* turn on packed pixel swapping */ -void PNGAPI -png_set_packswap(png_structp png_ptr) -{ - png_debug(1, "in png_set_packswap\n"); - if(png_ptr == NULL) return; - if (png_ptr->bit_depth < 8) - png_ptr->transformations |= PNG_PACKSWAP; -} -#endif - -#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) -void PNGAPI -png_set_shift(png_structp png_ptr, png_color_8p true_bits) -{ - png_debug(1, "in png_set_shift\n"); - if(png_ptr == NULL) return; - png_ptr->transformations |= PNG_SHIFT; - png_ptr->shift = *true_bits; -} -#endif - -#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ - defined(PNG_WRITE_INTERLACING_SUPPORTED) -int PNGAPI -png_set_interlace_handling(png_structp png_ptr) -{ - png_debug(1, "in png_set_interlace handling\n"); - if (png_ptr && png_ptr->interlaced) - { - png_ptr->transformations |= PNG_INTERLACE; - return (7); - } - - return (1); -} -#endif - -#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) -/* Add a filler byte on read, or remove a filler or alpha byte on write. - * The filler type has changed in v0.95 to allow future 2-byte fillers - * for 48-bit input data, as well as to avoid problems with some compilers - * that don't like bytes as parameters. - */ -void PNGAPI -png_set_filler(png_structp png_ptr, png_uint_32 filler, int filler_loc) -{ - png_debug(1, "in png_set_filler\n"); - if(png_ptr == NULL) return; - png_ptr->transformations |= PNG_FILLER; - png_ptr->filler = (png_byte)filler; - if (filler_loc == PNG_FILLER_AFTER) - png_ptr->flags |= PNG_FLAG_FILLER_AFTER; - else - png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER; - - /* This should probably go in the "do_read_filler" routine. - * I attempted to do that in libpng-1.0.1a but that caused problems - * so I restored it in libpng-1.0.2a - */ - - if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) - { - png_ptr->usr_channels = 4; - } - - /* Also I added this in libpng-1.0.2a (what happens when we expand - * a less-than-8-bit grayscale to GA? */ - - if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY && png_ptr->bit_depth >= 8) - { - png_ptr->usr_channels = 2; - } -} - -#if !defined(PNG_1_0_X) -/* Added to libpng-1.2.7 */ -void PNGAPI -png_set_add_alpha(png_structp png_ptr, png_uint_32 filler, int filler_loc) -{ - png_debug(1, "in png_set_add_alpha\n"); - if(png_ptr == NULL) return; - png_set_filler(png_ptr, filler, filler_loc); - png_ptr->transformations |= PNG_ADD_ALPHA; -} -#endif - -#endif - -#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ - defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) -void PNGAPI -png_set_swap_alpha(png_structp png_ptr) -{ - png_debug(1, "in png_set_swap_alpha\n"); - if(png_ptr == NULL) return; - png_ptr->transformations |= PNG_SWAP_ALPHA; -} -#endif - -#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ - defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) -void PNGAPI -png_set_invert_alpha(png_structp png_ptr) -{ - png_debug(1, "in png_set_invert_alpha\n"); - if(png_ptr == NULL) return; - png_ptr->transformations |= PNG_INVERT_ALPHA; -} -#endif - -#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) -void PNGAPI -png_set_invert_mono(png_structp png_ptr) -{ - png_debug(1, "in png_set_invert_mono\n"); - if(png_ptr == NULL) return; - png_ptr->transformations |= PNG_INVERT_MONO; -} - -/* invert monochrome grayscale data */ -void /* PRIVATE */ -png_do_invert(png_row_infop row_info, png_bytep row) -{ - png_debug(1, "in png_do_invert\n"); - /* This test removed from libpng version 1.0.13 and 1.2.0: - * if (row_info->bit_depth == 1 && - */ -#if defined(PNG_USELESS_TESTS_SUPPORTED) - if (row == NULL || row_info == NULL) - return; -#endif - if (row_info->color_type == PNG_COLOR_TYPE_GRAY) - { - png_bytep rp = row; - png_uint_32 i; - png_uint_32 istop = row_info->rowbytes; - - for (i = 0; i < istop; i++) - { - *rp = (png_byte)(~(*rp)); - rp++; - } - } - else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && - row_info->bit_depth == 8) - { - png_bytep rp = row; - png_uint_32 i; - png_uint_32 istop = row_info->rowbytes; - - for (i = 0; i < istop; i+=2) - { - *rp = (png_byte)(~(*rp)); - rp+=2; - } - } - else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && - row_info->bit_depth == 16) - { - png_bytep rp = row; - png_uint_32 i; - png_uint_32 istop = row_info->rowbytes; - - for (i = 0; i < istop; i+=4) - { - *rp = (png_byte)(~(*rp)); - *(rp+1) = (png_byte)(~(*(rp+1))); - rp+=4; - } - } -} -#endif - -#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) -/* swaps byte order on 16 bit depth images */ -void /* PRIVATE */ -png_do_swap(png_row_infop row_info, png_bytep row) -{ - png_debug(1, "in png_do_swap\n"); - if ( -#if defined(PNG_USELESS_TESTS_SUPPORTED) - row != NULL && row_info != NULL && -#endif - row_info->bit_depth == 16) - { - png_bytep rp = row; - png_uint_32 i; - png_uint_32 istop= row_info->width * row_info->channels; - - for (i = 0; i < istop; i++, rp += 2) - { - png_byte t = *rp; - *rp = *(rp + 1); - *(rp + 1) = t; - } - } -} -#endif - -#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED) -static PNG_CONST png_byte onebppswaptable[256] = { - 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, - 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, - 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, - 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, - 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, - 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, - 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, - 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, - 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, - 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, - 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, - 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, - 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, - 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, - 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, - 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, - 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, - 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, - 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, - 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, - 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, - 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, - 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, - 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, - 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, - 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, - 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, - 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, - 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, - 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, - 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, - 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF -}; - -static PNG_CONST png_byte twobppswaptable[256] = { - 0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0, - 0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0, - 0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4, - 0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4, - 0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8, - 0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8, - 0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC, - 0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC, - 0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1, - 0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1, - 0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5, - 0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5, - 0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9, - 0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9, - 0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD, - 0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD, - 0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2, - 0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2, - 0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6, - 0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6, - 0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA, - 0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA, - 0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE, - 0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE, - 0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3, - 0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3, - 0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7, - 0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7, - 0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB, - 0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB, - 0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF, - 0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF -}; - -static PNG_CONST png_byte fourbppswaptable[256] = { - 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, - 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0, - 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71, - 0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1, - 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72, - 0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2, - 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73, - 0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3, - 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74, - 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4, - 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75, - 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5, - 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76, - 0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6, - 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77, - 0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7, - 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78, - 0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8, - 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79, - 0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9, - 0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A, - 0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA, - 0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B, - 0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB, - 0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C, - 0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC, - 0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D, - 0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD, - 0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E, - 0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE, - 0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F, - 0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF -}; - -/* swaps pixel packing order within bytes */ -void /* PRIVATE */ -png_do_packswap(png_row_infop row_info, png_bytep row) -{ - png_debug(1, "in png_do_packswap\n"); - if ( -#if defined(PNG_USELESS_TESTS_SUPPORTED) - row != NULL && row_info != NULL && -#endif - row_info->bit_depth < 8) - { - png_bytep rp, end, table; - - end = row + row_info->rowbytes; - - if (row_info->bit_depth == 1) - table = (png_bytep)onebppswaptable; - else if (row_info->bit_depth == 2) - table = (png_bytep)twobppswaptable; - else if (row_info->bit_depth == 4) - table = (png_bytep)fourbppswaptable; - else - return; - - for (rp = row; rp < end; rp++) - *rp = table[*rp]; - } -} -#endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */ - -#if defined(PNG_WRITE_FILLER_SUPPORTED) || \ - defined(PNG_READ_STRIP_ALPHA_SUPPORTED) -/* remove filler or alpha byte(s) */ -void /* PRIVATE */ -png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags) -{ - png_debug(1, "in png_do_strip_filler\n"); -#if defined(PNG_USELESS_TESTS_SUPPORTED) - if (row != NULL && row_info != NULL) -#endif - { - png_bytep sp=row; - png_bytep dp=row; - png_uint_32 row_width=row_info->width; - png_uint_32 i; - - if ((row_info->color_type == PNG_COLOR_TYPE_RGB || - (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA && - (flags & PNG_FLAG_STRIP_ALPHA))) && - row_info->channels == 4) - { - if (row_info->bit_depth == 8) - { - /* This converts from RGBX or RGBA to RGB */ - if (flags & PNG_FLAG_FILLER_AFTER) - { - dp+=3; sp+=4; - for (i = 1; i < row_width; i++) - { - *dp++ = *sp++; - *dp++ = *sp++; - *dp++ = *sp++; - sp++; - } - } - /* This converts from XRGB or ARGB to RGB */ - else - { - for (i = 0; i < row_width; i++) - { - sp++; - *dp++ = *sp++; - *dp++ = *sp++; - *dp++ = *sp++; - } - } - row_info->pixel_depth = 24; - row_info->rowbytes = row_width * 3; - } - else /* if (row_info->bit_depth == 16) */ - { - if (flags & PNG_FLAG_FILLER_AFTER) - { - /* This converts from RRGGBBXX or RRGGBBAA to RRGGBB */ - sp += 8; dp += 6; - for (i = 1; i < row_width; i++) - { - /* This could be (although png_memcpy is probably slower): - png_memcpy(dp, sp, 6); - sp += 8; - dp += 6; - */ - - *dp++ = *sp++; - *dp++ = *sp++; - *dp++ = *sp++; - *dp++ = *sp++; - *dp++ = *sp++; - *dp++ = *sp++; - sp += 2; - } - } - else - { - /* This converts from XXRRGGBB or AARRGGBB to RRGGBB */ - for (i = 0; i < row_width; i++) - { - /* This could be (although png_memcpy is probably slower): - png_memcpy(dp, sp, 6); - sp += 8; - dp += 6; - */ - - sp+=2; - *dp++ = *sp++; - *dp++ = *sp++; - *dp++ = *sp++; - *dp++ = *sp++; - *dp++ = *sp++; - *dp++ = *sp++; - } - } - row_info->pixel_depth = 48; - row_info->rowbytes = row_width * 6; - } - row_info->channels = 3; - } - else if ((row_info->color_type == PNG_COLOR_TYPE_GRAY || - (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && - (flags & PNG_FLAG_STRIP_ALPHA))) && - row_info->channels == 2) - { - if (row_info->bit_depth == 8) - { - /* This converts from GX or GA to G */ - if (flags & PNG_FLAG_FILLER_AFTER) - { - for (i = 0; i < row_width; i++) - { - *dp++ = *sp++; - sp++; - } - } - /* This converts from XG or AG to G */ - else - { - for (i = 0; i < row_width; i++) - { - sp++; - *dp++ = *sp++; - } - } - row_info->pixel_depth = 8; - row_info->rowbytes = row_width; - } - else /* if (row_info->bit_depth == 16) */ - { - if (flags & PNG_FLAG_FILLER_AFTER) - { - /* This converts from GGXX or GGAA to GG */ - sp += 4; dp += 2; - for (i = 1; i < row_width; i++) - { - *dp++ = *sp++; - *dp++ = *sp++; - sp += 2; - } - } - else - { - /* This converts from XXGG or AAGG to GG */ - for (i = 0; i < row_width; i++) - { - sp += 2; - *dp++ = *sp++; - *dp++ = *sp++; - } - } - row_info->pixel_depth = 16; - row_info->rowbytes = row_width * 2; - } - row_info->channels = 1; - } - if (flags & PNG_FLAG_STRIP_ALPHA) - row_info->color_type &= ~PNG_COLOR_MASK_ALPHA; - } -} -#endif - -#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) -/* swaps red and blue bytes within a pixel */ -void /* PRIVATE */ -png_do_bgr(png_row_infop row_info, png_bytep row) -{ - png_debug(1, "in png_do_bgr\n"); - if ( -#if defined(PNG_USELESS_TESTS_SUPPORTED) - row != NULL && row_info != NULL && -#endif - (row_info->color_type & PNG_COLOR_MASK_COLOR)) - { - png_uint_32 row_width = row_info->width; - if (row_info->bit_depth == 8) - { - if (row_info->color_type == PNG_COLOR_TYPE_RGB) - { - png_bytep rp; - png_uint_32 i; - - for (i = 0, rp = row; i < row_width; i++, rp += 3) - { - png_byte save = *rp; - *rp = *(rp + 2); - *(rp + 2) = save; - } - } - else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - { - png_bytep rp; - png_uint_32 i; - - for (i = 0, rp = row; i < row_width; i++, rp += 4) - { - png_byte save = *rp; - *rp = *(rp + 2); - *(rp + 2) = save; - } - } - } - else if (row_info->bit_depth == 16) - { - if (row_info->color_type == PNG_COLOR_TYPE_RGB) - { - png_bytep rp; - png_uint_32 i; - - for (i = 0, rp = row; i < row_width; i++, rp += 6) - { - png_byte save = *rp; - *rp = *(rp + 4); - *(rp + 4) = save; - save = *(rp + 1); - *(rp + 1) = *(rp + 5); - *(rp + 5) = save; - } - } - else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - { - png_bytep rp; - png_uint_32 i; - - for (i = 0, rp = row; i < row_width; i++, rp += 8) - { - png_byte save = *rp; - *rp = *(rp + 4); - *(rp + 4) = save; - save = *(rp + 1); - *(rp + 1) = *(rp + 5); - *(rp + 5) = save; - } - } - } - } -} -#endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */ - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_LEGACY_SUPPORTED) -void PNGAPI -png_set_user_transform_info(png_structp png_ptr, png_voidp - user_transform_ptr, int user_transform_depth, int user_transform_channels) -{ - png_debug(1, "in png_set_user_transform_info\n"); - if(png_ptr == NULL) return; -#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) - png_ptr->user_transform_ptr = user_transform_ptr; - png_ptr->user_transform_depth = (png_byte)user_transform_depth; - png_ptr->user_transform_channels = (png_byte)user_transform_channels; -#else - if(user_transform_ptr || user_transform_depth || user_transform_channels) - png_warning(png_ptr, - "This version of libpng does not support user transform info"); -#endif -} -#endif - -/* This function returns a pointer to the user_transform_ptr associated with - * the user transform functions. The application should free any memory - * associated with this pointer before png_write_destroy and png_read_destroy - * are called. - */ -png_voidp PNGAPI -png_get_user_transform_ptr(png_structp png_ptr) -{ -#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) - if (png_ptr == NULL) return (NULL); - return ((png_voidp)png_ptr->user_transform_ptr); -#else - return (NULL); -#endif -} -#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/uppdev/plugin/png/lib/pngvcrd.c b/uppdev/plugin/png/lib/pngvcrd.c deleted file mode 100644 index 54fef6097..000000000 --- a/uppdev/plugin/png/lib/pngvcrd.c +++ /dev/null @@ -1 +0,0 @@ -/* pnggvrd.c was removed from libpng-1.2.20. */ diff --git a/uppdev/plugin/png/lib/pngwio.c b/uppdev/plugin/png/lib/pngwio.c deleted file mode 100644 index 34da2b23e..000000000 --- a/uppdev/plugin/png/lib/pngwio.c +++ /dev/null @@ -1,234 +0,0 @@ - -/* pngwio.c - functions for data output - * - * Last changed in libpng 1.2.13 November 13, 2006 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2006 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This file provides a location for all output. Users who need - * special handling are expected to write functions that have the same - * arguments as these and perform similar functions, but that possibly - * use different output methods. Note that you shouldn't change these - * functions, but rather write replacement functions and then change - * them at run time with png_set_write_fn(...). - */ - -#define PNG_INTERNAL -#include "png.h" -#ifdef PNG_WRITE_SUPPORTED - -/* Write the data to whatever output you are using. The default routine - writes to a file pointer. Note that this routine sometimes gets called - with very small lengths, so you should implement some kind of simple - buffering if you are using unbuffered writes. This should never be asked - to write more than 64K on a 16 bit machine. */ - -void /* PRIVATE */ -png_write_data(png_structp png_ptr, png_bytep data, png_size_t length) -{ - if (png_ptr->write_data_fn != NULL ) - (*(png_ptr->write_data_fn))(png_ptr, data, length); - else - png_error(png_ptr, "Call to NULL write function"); -} - -#if !defined(PNG_NO_STDIO) -/* This is the function that does the actual writing of data. If you are - not writing to a standard C stream, you should create a replacement - write_data function and use it at run time with png_set_write_fn(), rather - than changing the library. */ -#ifndef USE_FAR_KEYWORD -void PNGAPI -png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) -{ - png_uint_32 check; - - if(png_ptr == NULL) return; -#if defined(_WIN32_WCE) - if ( !WriteFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) ) - check = 0; -#else - check = fwrite(data, 1, length, (png_FILE_p)(png_ptr->io_ptr)); -#endif - if (check != length) - png_error(png_ptr, "Write Error"); -} -#else -/* this is the model-independent version. Since the standard I/O library - can't handle far buffers in the medium and small models, we have to copy - the data. -*/ - -#define NEAR_BUF_SIZE 1024 -#define MIN(a,b) (a <= b ? a : b) - -void PNGAPI -png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) -{ - png_uint_32 check; - png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */ - png_FILE_p io_ptr; - - if(png_ptr == NULL) return; - /* Check if data really is near. If so, use usual code. */ - near_data = (png_byte *)CVT_PTR_NOCHECK(data); - io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); - if ((png_bytep)near_data == data) - { -#if defined(_WIN32_WCE) - if ( !WriteFile(io_ptr, near_data, length, &check, NULL) ) - check = 0; -#else - check = fwrite(near_data, 1, length, io_ptr); -#endif - } - else - { - png_byte buf[NEAR_BUF_SIZE]; - png_size_t written, remaining, err; - check = 0; - remaining = length; - do - { - written = MIN(NEAR_BUF_SIZE, remaining); - png_memcpy(buf, data, written); /* copy far buffer to near buffer */ -#if defined(_WIN32_WCE) - if ( !WriteFile(io_ptr, buf, written, &err, NULL) ) - err = 0; -#else - err = fwrite(buf, 1, written, io_ptr); -#endif - if (err != written) - break; - else - check += err; - data += written; - remaining -= written; - } - while (remaining != 0); - } - if (check != length) - png_error(png_ptr, "Write Error"); -} - -#endif -#endif - -/* This function is called to output any data pending writing (normally - to disk). After png_flush is called, there should be no data pending - writing in any buffers. */ -#if defined(PNG_WRITE_FLUSH_SUPPORTED) -void /* PRIVATE */ -png_flush(png_structp png_ptr) -{ - if (png_ptr->output_flush_fn != NULL) - (*(png_ptr->output_flush_fn))(png_ptr); -} - -#if !defined(PNG_NO_STDIO) -void PNGAPI -png_default_flush(png_structp png_ptr) -{ -#if !defined(_WIN32_WCE) - png_FILE_p io_ptr; -#endif - if(png_ptr == NULL) return; -#if !defined(_WIN32_WCE) - io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr)); - if (io_ptr != NULL) - fflush(io_ptr); -#endif -} -#endif -#endif - -/* This function allows the application to supply new output functions for - libpng if standard C streams aren't being used. - - This function takes as its arguments: - png_ptr - pointer to a png output data structure - io_ptr - pointer to user supplied structure containing info about - the output functions. May be NULL. - write_data_fn - pointer to a new output function that takes as its - arguments a pointer to a png_struct, a pointer to - data to be written, and a 32-bit unsigned int that is - the number of bytes to be written. The new write - function should call png_error(png_ptr, "Error msg") - to exit and output any fatal error messages. - flush_data_fn - pointer to a new flush function that takes as its - arguments a pointer to a png_struct. After a call to - the flush function, there should be no data in any buffers - or pending transmission. If the output method doesn't do - any buffering of ouput, a function prototype must still be - supplied although it doesn't have to do anything. If - PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile - time, output_flush_fn will be ignored, although it must be - supplied for compatibility. */ -void PNGAPI -png_set_write_fn(png_structp png_ptr, png_voidp io_ptr, - png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn) -{ - if(png_ptr == NULL) return; - png_ptr->io_ptr = io_ptr; - -#if !defined(PNG_NO_STDIO) - if (write_data_fn != NULL) - png_ptr->write_data_fn = write_data_fn; - else - png_ptr->write_data_fn = png_default_write_data; -#else - png_ptr->write_data_fn = write_data_fn; -#endif - -#if defined(PNG_WRITE_FLUSH_SUPPORTED) -#if !defined(PNG_NO_STDIO) - if (output_flush_fn != NULL) - png_ptr->output_flush_fn = output_flush_fn; - else - png_ptr->output_flush_fn = png_default_flush; -#else - png_ptr->output_flush_fn = output_flush_fn; -#endif -#endif /* PNG_WRITE_FLUSH_SUPPORTED */ - - /* It is an error to read while writing a png file */ - if (png_ptr->read_data_fn != NULL) - { - png_ptr->read_data_fn = NULL; - png_warning(png_ptr, - "Attempted to set both read_data_fn and write_data_fn in"); - png_warning(png_ptr, - "the same structure. Resetting read_data_fn to NULL."); - } -} - -#if defined(USE_FAR_KEYWORD) -#if defined(_MSC_VER) -void *png_far_to_near(png_structp png_ptr,png_voidp ptr, int check) -{ - void *near_ptr; - void FAR *far_ptr; - FP_OFF(near_ptr) = FP_OFF(ptr); - far_ptr = (void FAR *)near_ptr; - if(check != 0) - if(FP_SEG(ptr) != FP_SEG(far_ptr)) - png_error(png_ptr,"segment lost in conversion"); - return(near_ptr); -} -# else -void *png_far_to_near(png_structp png_ptr,png_voidp ptr, int check) -{ - void *near_ptr; - void FAR *far_ptr; - near_ptr = (void FAR *)ptr; - far_ptr = (void FAR *)near_ptr; - if(check != 0) - if(far_ptr != ptr) - png_error(png_ptr,"segment lost in conversion"); - return(near_ptr); -} -# endif -# endif -#endif /* PNG_WRITE_SUPPORTED */ diff --git a/uppdev/plugin/png/lib/pngwrite.c b/uppdev/plugin/png/lib/pngwrite.c deleted file mode 100644 index 8f9b537a5..000000000 --- a/uppdev/plugin/png/lib/pngwrite.c +++ /dev/null @@ -1,1514 +0,0 @@ - -/* pngwrite.c - general routines to write a PNG file - * - * Last changed in libpng 1.2.15 January 5, 2007 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2007 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - */ - -/* get internal access to png.h */ -#define PNG_INTERNAL -#include "png.h" -#ifdef PNG_WRITE_SUPPORTED - -/* Writes all the PNG information. This is the suggested way to use the - * library. If you have a new chunk to add, make a function to write it, - * and put it in the correct location here. If you want the chunk written - * after the image data, put it in png_write_end(). I strongly encourage - * you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing - * the chunk, as that will keep the code from breaking if you want to just - * write a plain PNG file. If you have long comments, I suggest writing - * them in png_write_end(), and compressing them. - */ -void PNGAPI -png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr) -{ - png_debug(1, "in png_write_info_before_PLTE\n"); - if (png_ptr == NULL || info_ptr == NULL) - return; - if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) - { - png_write_sig(png_ptr); /* write PNG signature */ -#if defined(PNG_MNG_FEATURES_SUPPORTED) - if((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)&&(png_ptr->mng_features_permitted)) - { - png_warning(png_ptr,"MNG features are not allowed in a PNG datastream"); - png_ptr->mng_features_permitted=0; - } -#endif - /* write IHDR information. */ - png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height, - info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type, - info_ptr->filter_type, -#if defined(PNG_WRITE_INTERLACING_SUPPORTED) - info_ptr->interlace_type); -#else - 0); -#endif - /* the rest of these check to see if the valid field has the appropriate - flag set, and if it does, writes the chunk. */ -#if defined(PNG_WRITE_gAMA_SUPPORTED) - if (info_ptr->valid & PNG_INFO_gAMA) - { -# ifdef PNG_FLOATING_POINT_SUPPORTED - png_write_gAMA(png_ptr, info_ptr->gamma); -#else -#ifdef PNG_FIXED_POINT_SUPPORTED - png_write_gAMA_fixed(png_ptr, info_ptr->int_gamma); -# endif -#endif - } -#endif -#if defined(PNG_WRITE_sRGB_SUPPORTED) - if (info_ptr->valid & PNG_INFO_sRGB) - png_write_sRGB(png_ptr, (int)info_ptr->srgb_intent); -#endif -#if defined(PNG_WRITE_iCCP_SUPPORTED) - if (info_ptr->valid & PNG_INFO_iCCP) - png_write_iCCP(png_ptr, info_ptr->iccp_name, PNG_COMPRESSION_TYPE_BASE, - info_ptr->iccp_profile, (int)info_ptr->iccp_proflen); -#endif -#if defined(PNG_WRITE_sBIT_SUPPORTED) - if (info_ptr->valid & PNG_INFO_sBIT) - png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type); -#endif -#if defined(PNG_WRITE_cHRM_SUPPORTED) - if (info_ptr->valid & PNG_INFO_cHRM) - { -#ifdef PNG_FLOATING_POINT_SUPPORTED - png_write_cHRM(png_ptr, - info_ptr->x_white, info_ptr->y_white, - info_ptr->x_red, info_ptr->y_red, - info_ptr->x_green, info_ptr->y_green, - info_ptr->x_blue, info_ptr->y_blue); -#else -# ifdef PNG_FIXED_POINT_SUPPORTED - png_write_cHRM_fixed(png_ptr, - info_ptr->int_x_white, info_ptr->int_y_white, - info_ptr->int_x_red, info_ptr->int_y_red, - info_ptr->int_x_green, info_ptr->int_y_green, - info_ptr->int_x_blue, info_ptr->int_y_blue); -# endif -#endif - } -#endif -#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) - if (info_ptr->unknown_chunks_num) - { - png_unknown_chunk *up; - - png_debug(5, "writing extra chunks\n"); - - for (up = info_ptr->unknown_chunks; - up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; - up++) - { - int keep=png_handle_as_unknown(png_ptr, up->name); - if (keep != PNG_HANDLE_CHUNK_NEVER && - up->location && !(up->location & PNG_HAVE_PLTE) && - !(up->location & PNG_HAVE_IDAT) && - ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || - (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) - { - png_write_chunk(png_ptr, up->name, up->data, up->size); - } - } - } -#endif - png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE; - } -} - -void PNGAPI -png_write_info(png_structp png_ptr, png_infop info_ptr) -{ -#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) - int i; -#endif - - png_debug(1, "in png_write_info\n"); - - if (png_ptr == NULL || info_ptr == NULL) - return; - - png_write_info_before_PLTE(png_ptr, info_ptr); - - if (info_ptr->valid & PNG_INFO_PLTE) - png_write_PLTE(png_ptr, info_ptr->palette, - (png_uint_32)info_ptr->num_palette); - else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - png_error(png_ptr, "Valid palette required for paletted images"); - -#if defined(PNG_WRITE_tRNS_SUPPORTED) - if (info_ptr->valid & PNG_INFO_tRNS) - { -#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) - /* invert the alpha channel (in tRNS) */ - if ((png_ptr->transformations & PNG_INVERT_ALPHA) && - info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - { - int j; - for (j=0; j<(int)info_ptr->num_trans; j++) - info_ptr->trans[j] = (png_byte)(255 - info_ptr->trans[j]); - } -#endif - png_write_tRNS(png_ptr, info_ptr->trans, &(info_ptr->trans_values), - info_ptr->num_trans, info_ptr->color_type); - } -#endif -#if defined(PNG_WRITE_bKGD_SUPPORTED) - if (info_ptr->valid & PNG_INFO_bKGD) - png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type); -#endif -#if defined(PNG_WRITE_hIST_SUPPORTED) - if (info_ptr->valid & PNG_INFO_hIST) - png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette); -#endif -#if defined(PNG_WRITE_oFFs_SUPPORTED) - if (info_ptr->valid & PNG_INFO_oFFs) - png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset, - info_ptr->offset_unit_type); -#endif -#if defined(PNG_WRITE_pCAL_SUPPORTED) - if (info_ptr->valid & PNG_INFO_pCAL) - png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0, - info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams, - info_ptr->pcal_units, info_ptr->pcal_params); -#endif -#if defined(PNG_WRITE_sCAL_SUPPORTED) - if (info_ptr->valid & PNG_INFO_sCAL) -#if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO) - png_write_sCAL(png_ptr, (int)info_ptr->scal_unit, - info_ptr->scal_pixel_width, info_ptr->scal_pixel_height); -#else -#ifdef PNG_FIXED_POINT_SUPPORTED - png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit, - info_ptr->scal_s_width, info_ptr->scal_s_height); -#else - png_warning(png_ptr, - "png_write_sCAL not supported; sCAL chunk not written."); -#endif -#endif -#endif -#if defined(PNG_WRITE_pHYs_SUPPORTED) - if (info_ptr->valid & PNG_INFO_pHYs) - png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit, - info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type); -#endif -#if defined(PNG_WRITE_tIME_SUPPORTED) - if (info_ptr->valid & PNG_INFO_tIME) - { - png_write_tIME(png_ptr, &(info_ptr->mod_time)); - png_ptr->mode |= PNG_WROTE_tIME; - } -#endif -#if defined(PNG_WRITE_sPLT_SUPPORTED) - if (info_ptr->valid & PNG_INFO_sPLT) - for (i = 0; i < (int)info_ptr->splt_palettes_num; i++) - png_write_sPLT(png_ptr, info_ptr->splt_palettes + i); -#endif -#if defined(PNG_WRITE_TEXT_SUPPORTED) - /* Check to see if we need to write text chunks */ - for (i = 0; i < info_ptr->num_text; i++) - { - png_debug2(2, "Writing header text chunk %d, type %d\n", i, - info_ptr->text[i].compression); - /* an internationalized chunk? */ - if (info_ptr->text[i].compression > 0) - { -#if defined(PNG_WRITE_iTXt_SUPPORTED) - /* write international chunk */ - png_write_iTXt(png_ptr, - info_ptr->text[i].compression, - info_ptr->text[i].key, - info_ptr->text[i].lang, - info_ptr->text[i].lang_key, - info_ptr->text[i].text); -#else - png_warning(png_ptr, "Unable to write international text"); -#endif - /* Mark this chunk as written */ - info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; - } - /* If we want a compressed text chunk */ - else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt) - { -#if defined(PNG_WRITE_zTXt_SUPPORTED) - /* write compressed chunk */ - png_write_zTXt(png_ptr, info_ptr->text[i].key, - info_ptr->text[i].text, 0, - info_ptr->text[i].compression); -#else - png_warning(png_ptr, "Unable to write compressed text"); -#endif - /* Mark this chunk as written */ - info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; - } - else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) - { -#if defined(PNG_WRITE_tEXt_SUPPORTED) - /* write uncompressed chunk */ - png_write_tEXt(png_ptr, info_ptr->text[i].key, - info_ptr->text[i].text, - 0); -#else - png_warning(png_ptr, "Unable to write uncompressed text"); -#endif - /* Mark this chunk as written */ - info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; - } - } -#endif -#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) - if (info_ptr->unknown_chunks_num) - { - png_unknown_chunk *up; - - png_debug(5, "writing extra chunks\n"); - - for (up = info_ptr->unknown_chunks; - up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; - up++) - { - int keep=png_handle_as_unknown(png_ptr, up->name); - if (keep != PNG_HANDLE_CHUNK_NEVER && - up->location && (up->location & PNG_HAVE_PLTE) && - !(up->location & PNG_HAVE_IDAT) && - ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || - (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) - { - png_write_chunk(png_ptr, up->name, up->data, up->size); - } - } - } -#endif -} - -/* Writes the end of the PNG file. If you don't want to write comments or - * time information, you can pass NULL for info. If you already wrote these - * in png_write_info(), do not write them again here. If you have long - * comments, I suggest writing them here, and compressing them. - */ -void PNGAPI -png_write_end(png_structp png_ptr, png_infop info_ptr) -{ - png_debug(1, "in png_write_end\n"); - if (png_ptr == NULL) - return; - if (!(png_ptr->mode & PNG_HAVE_IDAT)) - png_error(png_ptr, "No IDATs written into file"); - - /* see if user wants us to write information chunks */ - if (info_ptr != NULL) - { -#if defined(PNG_WRITE_TEXT_SUPPORTED) - int i; /* local index variable */ -#endif -#if defined(PNG_WRITE_tIME_SUPPORTED) - /* check to see if user has supplied a time chunk */ - if ((info_ptr->valid & PNG_INFO_tIME) && - !(png_ptr->mode & PNG_WROTE_tIME)) - png_write_tIME(png_ptr, &(info_ptr->mod_time)); -#endif -#if defined(PNG_WRITE_TEXT_SUPPORTED) - /* loop through comment chunks */ - for (i = 0; i < info_ptr->num_text; i++) - { - png_debug2(2, "Writing trailer text chunk %d, type %d\n", i, - info_ptr->text[i].compression); - /* an internationalized chunk? */ - if (info_ptr->text[i].compression > 0) - { -#if defined(PNG_WRITE_iTXt_SUPPORTED) - /* write international chunk */ - png_write_iTXt(png_ptr, - info_ptr->text[i].compression, - info_ptr->text[i].key, - info_ptr->text[i].lang, - info_ptr->text[i].lang_key, - info_ptr->text[i].text); -#else - png_warning(png_ptr, "Unable to write international text"); -#endif - /* Mark this chunk as written */ - info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; - } - else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt) - { -#if defined(PNG_WRITE_zTXt_SUPPORTED) - /* write compressed chunk */ - png_write_zTXt(png_ptr, info_ptr->text[i].key, - info_ptr->text[i].text, 0, - info_ptr->text[i].compression); -#else - png_warning(png_ptr, "Unable to write compressed text"); -#endif - /* Mark this chunk as written */ - info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; - } - else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) - { -#if defined(PNG_WRITE_tEXt_SUPPORTED) - /* write uncompressed chunk */ - png_write_tEXt(png_ptr, info_ptr->text[i].key, - info_ptr->text[i].text, 0); -#else - png_warning(png_ptr, "Unable to write uncompressed text"); -#endif - - /* Mark this chunk as written */ - info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; - } - } -#endif -#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) - if (info_ptr->unknown_chunks_num) - { - png_unknown_chunk *up; - - png_debug(5, "writing extra chunks\n"); - - for (up = info_ptr->unknown_chunks; - up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; - up++) - { - int keep=png_handle_as_unknown(png_ptr, up->name); - if (keep != PNG_HANDLE_CHUNK_NEVER && - up->location && (up->location & PNG_AFTER_IDAT) && - ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || - (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) - { - png_write_chunk(png_ptr, up->name, up->data, up->size); - } - } - } -#endif - } - - png_ptr->mode |= PNG_AFTER_IDAT; - - /* write end of PNG file */ - png_write_IEND(png_ptr); -} - -#if defined(PNG_WRITE_tIME_SUPPORTED) -#if !defined(_WIN32_WCE) -/* "time.h" functions are not supported on WindowsCE */ -void PNGAPI -png_convert_from_struct_tm(png_timep ptime, struct tm FAR * ttime) -{ - png_debug(1, "in png_convert_from_struct_tm\n"); - ptime->year = (png_uint_16)(1900 + ttime->tm_year); - ptime->month = (png_byte)(ttime->tm_mon + 1); - ptime->day = (png_byte)ttime->tm_mday; - ptime->hour = (png_byte)ttime->tm_hour; - ptime->minute = (png_byte)ttime->tm_min; - ptime->second = (png_byte)ttime->tm_sec; -} - -void PNGAPI -png_convert_from_time_t(png_timep ptime, time_t ttime) -{ - struct tm *tbuf; - - png_debug(1, "in png_convert_from_time_t\n"); - tbuf = gmtime(&ttime); - png_convert_from_struct_tm(ptime, tbuf); -} -#endif -#endif - -/* Initialize png_ptr structure, and allocate any memory needed */ -png_structp PNGAPI -png_create_write_struct(png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn) -{ -#ifdef PNG_USER_MEM_SUPPORTED - return (png_create_write_struct_2(user_png_ver, error_ptr, error_fn, - warn_fn, png_voidp_NULL, png_malloc_ptr_NULL, png_free_ptr_NULL)); -} - -/* Alternate initialize png_ptr structure, and allocate any memory needed */ -png_structp PNGAPI -png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, - png_malloc_ptr malloc_fn, png_free_ptr free_fn) -{ -#endif /* PNG_USER_MEM_SUPPORTED */ - png_structp png_ptr; -#ifdef PNG_SETJMP_SUPPORTED -#ifdef USE_FAR_KEYWORD - jmp_buf jmpbuf; -#endif -#endif - int i; - png_debug(1, "in png_create_write_struct\n"); -#ifdef PNG_USER_MEM_SUPPORTED - png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG, - (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr); -#else - png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); -#endif /* PNG_USER_MEM_SUPPORTED */ - if (png_ptr == NULL) - return (NULL); - - /* added at libpng-1.2.6 */ -#ifdef PNG_SET_USER_LIMITS_SUPPORTED - png_ptr->user_width_max=PNG_USER_WIDTH_MAX; - png_ptr->user_height_max=PNG_USER_HEIGHT_MAX; -#endif - -#ifdef PNG_SETJMP_SUPPORTED -#ifdef USE_FAR_KEYWORD - if (setjmp(jmpbuf)) -#else - if (setjmp(png_ptr->jmpbuf)) -#endif - { - png_free(png_ptr, png_ptr->zbuf); - png_ptr->zbuf=NULL; - png_destroy_struct(png_ptr); - return (NULL); - } -#ifdef USE_FAR_KEYWORD - png_memcpy(png_ptr->jmpbuf,jmpbuf,png_sizeof(jmp_buf)); -#endif -#endif - -#ifdef PNG_USER_MEM_SUPPORTED - png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn); -#endif /* PNG_USER_MEM_SUPPORTED */ - png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn); - - i=0; - do - { - if(user_png_ver[i] != png_libpng_ver[i]) - png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; - } while (png_libpng_ver[i++]); - - if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) - { - /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so - * we must recompile any applications that use any older library version. - * For versions after libpng 1.0, we will be compatible, so we need - * only check the first digit. - */ - if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || - (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) || - (user_png_ver[0] == '0' && user_png_ver[2] < '9')) - { -#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) - char msg[80]; - if (user_png_ver) - { - png_snprintf(msg, 80, - "Application was compiled with png.h from libpng-%.20s", - user_png_ver); - png_warning(png_ptr, msg); - } - png_snprintf(msg, 80, - "Application is running with png.c from libpng-%.20s", - png_libpng_ver); - png_warning(png_ptr, msg); -#endif -#ifdef PNG_ERROR_NUMBERS_SUPPORTED - png_ptr->flags=0; -#endif - png_error(png_ptr, - "Incompatible libpng version in application and library"); - } - } - - /* initialize zbuf - compression buffer */ - png_ptr->zbuf_size = PNG_ZBUF_SIZE; - png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, - (png_uint_32)png_ptr->zbuf_size); - - png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL, - png_flush_ptr_NULL); - -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT, - 1, png_doublep_NULL, png_doublep_NULL); -#endif - -#ifdef PNG_SETJMP_SUPPORTED -/* Applications that neglect to set up their own setjmp() and then encounter - a png_error() will longjmp here. Since the jmpbuf is then meaningless we - abort instead of returning. */ -#ifdef USE_FAR_KEYWORD - if (setjmp(jmpbuf)) - PNG_ABORT(); - png_memcpy(png_ptr->jmpbuf,jmpbuf,png_sizeof(jmp_buf)); -#else - if (setjmp(png_ptr->jmpbuf)) - PNG_ABORT(); -#endif -#endif - return (png_ptr); -} - -/* Initialize png_ptr structure, and allocate any memory needed */ -#if defined(PNG_1_0_X) || defined(PNG_1_2_X) -/* Deprecated. */ -#undef png_write_init -void PNGAPI -png_write_init(png_structp png_ptr) -{ - /* We only come here via pre-1.0.7-compiled applications */ - png_write_init_2(png_ptr, "1.0.6 or earlier", 0, 0); -} - -void PNGAPI -png_write_init_2(png_structp png_ptr, png_const_charp user_png_ver, - png_size_t png_struct_size, png_size_t png_info_size) -{ - /* We only come here via pre-1.0.12-compiled applications */ - if(png_ptr == NULL) return; -#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) - if(png_sizeof(png_struct) > png_struct_size || - png_sizeof(png_info) > png_info_size) - { - char msg[80]; - png_ptr->warning_fn=NULL; - if (user_png_ver) - { - png_snprintf(msg, 80, - "Application was compiled with png.h from libpng-%.20s", - user_png_ver); - png_warning(png_ptr, msg); - } - png_snprintf(msg, 80, - "Application is running with png.c from libpng-%.20s", - png_libpng_ver); - png_warning(png_ptr, msg); - } -#endif - if(png_sizeof(png_struct) > png_struct_size) - { - png_ptr->error_fn=NULL; -#ifdef PNG_ERROR_NUMBERS_SUPPORTED - png_ptr->flags=0; -#endif - png_error(png_ptr, - "The png struct allocated by the application for writing is too small."); - } - if(png_sizeof(png_info) > png_info_size) - { - png_ptr->error_fn=NULL; -#ifdef PNG_ERROR_NUMBERS_SUPPORTED - png_ptr->flags=0; -#endif - png_error(png_ptr, - "The info struct allocated by the application for writing is too small."); - } - png_write_init_3(&png_ptr, user_png_ver, png_struct_size); -} -#endif /* PNG_1_0_X || PNG_1_2_X */ - - -void PNGAPI -png_write_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver, - png_size_t png_struct_size) -{ - png_structp png_ptr=*ptr_ptr; -#ifdef PNG_SETJMP_SUPPORTED - jmp_buf tmp_jmp; /* to save current jump buffer */ -#endif - - int i = 0; - - if (png_ptr == NULL) - return; - - do - { - if (user_png_ver[i] != png_libpng_ver[i]) - { -#ifdef PNG_LEGACY_SUPPORTED - png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; -#else - png_ptr->warning_fn=NULL; - png_warning(png_ptr, - "Application uses deprecated png_write_init() and should be recompiled."); - break; -#endif - } - } while (png_libpng_ver[i++]); - - png_debug(1, "in png_write_init_3\n"); - -#ifdef PNG_SETJMP_SUPPORTED - /* save jump buffer and error functions */ - png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof (jmp_buf)); -#endif - - if (png_sizeof(png_struct) > png_struct_size) - { - png_destroy_struct(png_ptr); - png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); - *ptr_ptr = png_ptr; - } - - /* reset all variables to 0 */ - png_memset(png_ptr, 0, png_sizeof (png_struct)); - - /* added at libpng-1.2.6 */ -#ifdef PNG_SET_USER_LIMITS_SUPPORTED - png_ptr->user_width_max=PNG_USER_WIDTH_MAX; - png_ptr->user_height_max=PNG_USER_HEIGHT_MAX; -#endif - -#ifdef PNG_SETJMP_SUPPORTED - /* restore jump buffer */ - png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof (jmp_buf)); -#endif - - png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL, - png_flush_ptr_NULL); - - /* initialize zbuf - compression buffer */ - png_ptr->zbuf_size = PNG_ZBUF_SIZE; - png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, - (png_uint_32)png_ptr->zbuf_size); - -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT, - 1, png_doublep_NULL, png_doublep_NULL); -#endif -} - -/* Write a few rows of image data. If the image is interlaced, - * either you will have to write the 7 sub images, or, if you - * have called png_set_interlace_handling(), you will have to - * "write" the image seven times. - */ -void PNGAPI -png_write_rows(png_structp png_ptr, png_bytepp row, - png_uint_32 num_rows) -{ - png_uint_32 i; /* row counter */ - png_bytepp rp; /* row pointer */ - - png_debug(1, "in png_write_rows\n"); - - if (png_ptr == NULL) - return; - - /* loop through the rows */ - for (i = 0, rp = row; i < num_rows; i++, rp++) - { - png_write_row(png_ptr, *rp); - } -} - -/* Write the image. You only need to call this function once, even - * if you are writing an interlaced image. - */ -void PNGAPI -png_write_image(png_structp png_ptr, png_bytepp image) -{ - png_uint_32 i; /* row index */ - int pass, num_pass; /* pass variables */ - png_bytepp rp; /* points to current row */ - - if (png_ptr == NULL) - return; - - png_debug(1, "in png_write_image\n"); -#if defined(PNG_WRITE_INTERLACING_SUPPORTED) - /* intialize interlace handling. If image is not interlaced, - this will set pass to 1 */ - num_pass = png_set_interlace_handling(png_ptr); -#else - num_pass = 1; -#endif - /* loop through passes */ - for (pass = 0; pass < num_pass; pass++) - { - /* loop through image */ - for (i = 0, rp = image; i < png_ptr->height; i++, rp++) - { - png_write_row(png_ptr, *rp); - } - } -} - -/* called by user to write a row of image data */ -void PNGAPI -png_write_row(png_structp png_ptr, png_bytep row) -{ - if (png_ptr == NULL) - return; - png_debug2(1, "in png_write_row (row %ld, pass %d)\n", - png_ptr->row_number, png_ptr->pass); - - /* initialize transformations and other stuff if first time */ - if (png_ptr->row_number == 0 && png_ptr->pass == 0) - { - /* make sure we wrote the header info */ - if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) - png_error(png_ptr, - "png_write_info was never called before png_write_row."); - - /* check for transforms that have been set but were defined out */ -#if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED) - if (png_ptr->transformations & PNG_INVERT_MONO) - png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined."); -#endif -#if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED) - if (png_ptr->transformations & PNG_FILLER) - png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined."); -#endif -#if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && defined(PNG_READ_PACKSWAP_SUPPORTED) - if (png_ptr->transformations & PNG_PACKSWAP) - png_warning(png_ptr, "PNG_WRITE_PACKSWAP_SUPPORTED is not defined."); -#endif -#if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED) - if (png_ptr->transformations & PNG_PACK) - png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined."); -#endif -#if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED) - if (png_ptr->transformations & PNG_SHIFT) - png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined."); -#endif -#if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED) - if (png_ptr->transformations & PNG_BGR) - png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined."); -#endif -#if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED) - if (png_ptr->transformations & PNG_SWAP_BYTES) - png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined."); -#endif - - png_write_start_row(png_ptr); - } - -#if defined(PNG_WRITE_INTERLACING_SUPPORTED) - /* if interlaced and not interested in row, return */ - if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) - { - switch (png_ptr->pass) - { - case 0: - if (png_ptr->row_number & 0x07) - { - png_write_finish_row(png_ptr); - return; - } - break; - case 1: - if ((png_ptr->row_number & 0x07) || png_ptr->width < 5) - { - png_write_finish_row(png_ptr); - return; - } - break; - case 2: - if ((png_ptr->row_number & 0x07) != 4) - { - png_write_finish_row(png_ptr); - return; - } - break; - case 3: - if ((png_ptr->row_number & 0x03) || png_ptr->width < 3) - { - png_write_finish_row(png_ptr); - return; - } - break; - case 4: - if ((png_ptr->row_number & 0x03) != 2) - { - png_write_finish_row(png_ptr); - return; - } - break; - case 5: - if ((png_ptr->row_number & 0x01) || png_ptr->width < 2) - { - png_write_finish_row(png_ptr); - return; - } - break; - case 6: - if (!(png_ptr->row_number & 0x01)) - { - png_write_finish_row(png_ptr); - return; - } - break; - } - } -#endif - - /* set up row info for transformations */ - png_ptr->row_info.color_type = png_ptr->color_type; - png_ptr->row_info.width = png_ptr->usr_width; - png_ptr->row_info.channels = png_ptr->usr_channels; - png_ptr->row_info.bit_depth = png_ptr->usr_bit_depth; - png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth * - png_ptr->row_info.channels); - - png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, - png_ptr->row_info.width); - - png_debug1(3, "row_info->color_type = %d\n", png_ptr->row_info.color_type); - png_debug1(3, "row_info->width = %lu\n", png_ptr->row_info.width); - png_debug1(3, "row_info->channels = %d\n", png_ptr->row_info.channels); - png_debug1(3, "row_info->bit_depth = %d\n", png_ptr->row_info.bit_depth); - png_debug1(3, "row_info->pixel_depth = %d\n", png_ptr->row_info.pixel_depth); - png_debug1(3, "row_info->rowbytes = %lu\n", png_ptr->row_info.rowbytes); - - /* Copy user's row into buffer, leaving room for filter byte. */ - png_memcpy_check(png_ptr, png_ptr->row_buf + 1, row, - png_ptr->row_info.rowbytes); - -#if defined(PNG_WRITE_INTERLACING_SUPPORTED) - /* handle interlacing */ - if (png_ptr->interlaced && png_ptr->pass < 6 && - (png_ptr->transformations & PNG_INTERLACE)) - { - png_do_write_interlace(&(png_ptr->row_info), - png_ptr->row_buf + 1, png_ptr->pass); - /* this should always get caught above, but still ... */ - if (!(png_ptr->row_info.width)) - { - png_write_finish_row(png_ptr); - return; - } - } -#endif - - /* handle other transformations */ - if (png_ptr->transformations) - png_do_write_transformations(png_ptr); - -#if defined(PNG_MNG_FEATURES_SUPPORTED) - /* Write filter_method 64 (intrapixel differencing) only if - * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and - * 2. Libpng did not write a PNG signature (this filter_method is only - * used in PNG datastreams that are embedded in MNG datastreams) and - * 3. The application called png_permit_mng_features with a mask that - * included PNG_FLAG_MNG_FILTER_64 and - * 4. The filter_method is 64 and - * 5. The color_type is RGB or RGBA - */ - if((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && - (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) - { - /* Intrapixel differencing */ - png_do_write_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1); - } -#endif - - /* Find a filter if necessary, filter the row and write it out. */ - png_write_find_filter(png_ptr, &(png_ptr->row_info)); - - if (png_ptr->write_row_fn != NULL) - (*(png_ptr->write_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); -} - -#if defined(PNG_WRITE_FLUSH_SUPPORTED) -/* Set the automatic flush interval or 0 to turn flushing off */ -void PNGAPI -png_set_flush(png_structp png_ptr, int nrows) -{ - png_debug(1, "in png_set_flush\n"); - if (png_ptr == NULL) - return; - png_ptr->flush_dist = (nrows < 0 ? 0 : nrows); -} - -/* flush the current output buffers now */ -void PNGAPI -png_write_flush(png_structp png_ptr) -{ - int wrote_IDAT; - - png_debug(1, "in png_write_flush\n"); - if (png_ptr == NULL) - return; - /* We have already written out all of the data */ - if (png_ptr->row_number >= png_ptr->num_rows) - return; - - do - { - int ret; - - /* compress the data */ - ret = deflate(&png_ptr->zstream, Z_SYNC_FLUSH); - wrote_IDAT = 0; - - /* check for compression errors */ - if (ret != Z_OK) - { - if (png_ptr->zstream.msg != NULL) - png_error(png_ptr, png_ptr->zstream.msg); - else - png_error(png_ptr, "zlib error"); - } - - if (!(png_ptr->zstream.avail_out)) - { - /* write the IDAT and reset the zlib output buffer */ - png_write_IDAT(png_ptr, png_ptr->zbuf, - png_ptr->zbuf_size); - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - wrote_IDAT = 1; - } - } while(wrote_IDAT == 1); - - /* If there is any data left to be output, write it into a new IDAT */ - if (png_ptr->zbuf_size != png_ptr->zstream.avail_out) - { - /* write the IDAT and reset the zlib output buffer */ - png_write_IDAT(png_ptr, png_ptr->zbuf, - png_ptr->zbuf_size - png_ptr->zstream.avail_out); - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - } - png_ptr->flush_rows = 0; - png_flush(png_ptr); -} -#endif /* PNG_WRITE_FLUSH_SUPPORTED */ - -/* free all memory used by the write */ -void PNGAPI -png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr) -{ - png_structp png_ptr = NULL; - png_infop info_ptr = NULL; -#ifdef PNG_USER_MEM_SUPPORTED - png_free_ptr free_fn = NULL; - png_voidp mem_ptr = NULL; -#endif - - png_debug(1, "in png_destroy_write_struct\n"); - if (png_ptr_ptr != NULL) - { - png_ptr = *png_ptr_ptr; -#ifdef PNG_USER_MEM_SUPPORTED - free_fn = png_ptr->free_fn; - mem_ptr = png_ptr->mem_ptr; -#endif - } - - if (info_ptr_ptr != NULL) - info_ptr = *info_ptr_ptr; - - if (info_ptr != NULL) - { - png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); - -#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) - if (png_ptr->num_chunk_list) - { - png_free(png_ptr, png_ptr->chunk_list); - png_ptr->chunk_list=NULL; - png_ptr->num_chunk_list=0; - } -#endif - -#ifdef PNG_USER_MEM_SUPPORTED - png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn, - (png_voidp)mem_ptr); -#else - png_destroy_struct((png_voidp)info_ptr); -#endif - *info_ptr_ptr = NULL; - } - - if (png_ptr != NULL) - { - png_write_destroy(png_ptr); -#ifdef PNG_USER_MEM_SUPPORTED - png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn, - (png_voidp)mem_ptr); -#else - png_destroy_struct((png_voidp)png_ptr); -#endif - *png_ptr_ptr = NULL; - } -} - - -/* Free any memory used in png_ptr struct (old method) */ -void /* PRIVATE */ -png_write_destroy(png_structp png_ptr) -{ -#ifdef PNG_SETJMP_SUPPORTED - jmp_buf tmp_jmp; /* save jump buffer */ -#endif - png_error_ptr error_fn; - png_error_ptr warning_fn; - png_voidp error_ptr; -#ifdef PNG_USER_MEM_SUPPORTED - png_free_ptr free_fn; -#endif - - png_debug(1, "in png_write_destroy\n"); - /* free any memory zlib uses */ - deflateEnd(&png_ptr->zstream); - - /* free our memory. png_free checks NULL for us. */ - png_free(png_ptr, png_ptr->zbuf); - png_free(png_ptr, png_ptr->row_buf); - png_free(png_ptr, png_ptr->prev_row); - png_free(png_ptr, png_ptr->sub_row); - png_free(png_ptr, png_ptr->up_row); - png_free(png_ptr, png_ptr->avg_row); - png_free(png_ptr, png_ptr->paeth_row); - -#if defined(PNG_TIME_RFC1123_SUPPORTED) - png_free(png_ptr, png_ptr->time_buffer); -#endif - -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - png_free(png_ptr, png_ptr->prev_filters); - png_free(png_ptr, png_ptr->filter_weights); - png_free(png_ptr, png_ptr->inv_filter_weights); - png_free(png_ptr, png_ptr->filter_costs); - png_free(png_ptr, png_ptr->inv_filter_costs); -#endif - -#ifdef PNG_SETJMP_SUPPORTED - /* reset structure */ - png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof (jmp_buf)); -#endif - - error_fn = png_ptr->error_fn; - warning_fn = png_ptr->warning_fn; - error_ptr = png_ptr->error_ptr; -#ifdef PNG_USER_MEM_SUPPORTED - free_fn = png_ptr->free_fn; -#endif - - png_memset(png_ptr, 0, png_sizeof (png_struct)); - - png_ptr->error_fn = error_fn; - png_ptr->warning_fn = warning_fn; - png_ptr->error_ptr = error_ptr; -#ifdef PNG_USER_MEM_SUPPORTED - png_ptr->free_fn = free_fn; -#endif - -#ifdef PNG_SETJMP_SUPPORTED - png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof (jmp_buf)); -#endif -} - -/* Allow the application to select one or more row filters to use. */ -void PNGAPI -png_set_filter(png_structp png_ptr, int method, int filters) -{ - png_debug(1, "in png_set_filter\n"); - if (png_ptr == NULL) - return; -#if defined(PNG_MNG_FEATURES_SUPPORTED) - if((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && - (method == PNG_INTRAPIXEL_DIFFERENCING)) - method = PNG_FILTER_TYPE_BASE; -#endif - if (method == PNG_FILTER_TYPE_BASE) - { - switch (filters & (PNG_ALL_FILTERS | 0x07)) - { -#ifndef PNG_NO_WRITE_FILTER - case 5: - case 6: - case 7: png_warning(png_ptr, "Unknown row filter for method 0"); -#endif /* PNG_NO_WRITE_FILTER */ - case PNG_FILTER_VALUE_NONE: - png_ptr->do_filter=PNG_FILTER_NONE; break; -#ifndef PNG_NO_WRITE_FILTER - case PNG_FILTER_VALUE_SUB: - png_ptr->do_filter=PNG_FILTER_SUB; break; - case PNG_FILTER_VALUE_UP: - png_ptr->do_filter=PNG_FILTER_UP; break; - case PNG_FILTER_VALUE_AVG: - png_ptr->do_filter=PNG_FILTER_AVG; break; - case PNG_FILTER_VALUE_PAETH: - png_ptr->do_filter=PNG_FILTER_PAETH; break; - default: png_ptr->do_filter = (png_byte)filters; break; -#else - default: png_warning(png_ptr, "Unknown row filter for method 0"); -#endif /* PNG_NO_WRITE_FILTER */ - } - - /* If we have allocated the row_buf, this means we have already started - * with the image and we should have allocated all of the filter buffers - * that have been selected. If prev_row isn't already allocated, then - * it is too late to start using the filters that need it, since we - * will be missing the data in the previous row. If an application - * wants to start and stop using particular filters during compression, - * it should start out with all of the filters, and then add and - * remove them after the start of compression. - */ - if (png_ptr->row_buf != NULL) - { -#ifndef PNG_NO_WRITE_FILTER - if ((png_ptr->do_filter & PNG_FILTER_SUB) && png_ptr->sub_row == NULL) - { - png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, - (png_ptr->rowbytes + 1)); - png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; - } - - if ((png_ptr->do_filter & PNG_FILTER_UP) && png_ptr->up_row == NULL) - { - if (png_ptr->prev_row == NULL) - { - png_warning(png_ptr, "Can't add Up filter after starting"); - png_ptr->do_filter &= ~PNG_FILTER_UP; - } - else - { - png_ptr->up_row = (png_bytep)png_malloc(png_ptr, - (png_ptr->rowbytes + 1)); - png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; - } - } - - if ((png_ptr->do_filter & PNG_FILTER_AVG) && png_ptr->avg_row == NULL) - { - if (png_ptr->prev_row == NULL) - { - png_warning(png_ptr, "Can't add Average filter after starting"); - png_ptr->do_filter &= ~PNG_FILTER_AVG; - } - else - { - png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, - (png_ptr->rowbytes + 1)); - png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; - } - } - - if ((png_ptr->do_filter & PNG_FILTER_PAETH) && - png_ptr->paeth_row == NULL) - { - if (png_ptr->prev_row == NULL) - { - png_warning(png_ptr, "Can't add Paeth filter after starting"); - png_ptr->do_filter &= (png_byte)(~PNG_FILTER_PAETH); - } - else - { - png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr, - (png_ptr->rowbytes + 1)); - png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; - } - } - - if (png_ptr->do_filter == PNG_NO_FILTERS) -#endif /* PNG_NO_WRITE_FILTER */ - png_ptr->do_filter = PNG_FILTER_NONE; - } - } - else - png_error(png_ptr, "Unknown custom filter method"); -} - -/* This allows us to influence the way in which libpng chooses the "best" - * filter for the current scanline. While the "minimum-sum-of-absolute- - * differences metric is relatively fast and effective, there is some - * question as to whether it can be improved upon by trying to keep the - * filtered data going to zlib more consistent, hopefully resulting in - * better compression. - */ -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) /* GRR 970116 */ -void PNGAPI -png_set_filter_heuristics(png_structp png_ptr, int heuristic_method, - int num_weights, png_doublep filter_weights, - png_doublep filter_costs) -{ - int i; - - png_debug(1, "in png_set_filter_heuristics\n"); - if (png_ptr == NULL) - return; - if (heuristic_method >= PNG_FILTER_HEURISTIC_LAST) - { - png_warning(png_ptr, "Unknown filter heuristic method"); - return; - } - - if (heuristic_method == PNG_FILTER_HEURISTIC_DEFAULT) - { - heuristic_method = PNG_FILTER_HEURISTIC_UNWEIGHTED; - } - - if (num_weights < 0 || filter_weights == NULL || - heuristic_method == PNG_FILTER_HEURISTIC_UNWEIGHTED) - { - num_weights = 0; - } - - png_ptr->num_prev_filters = (png_byte)num_weights; - png_ptr->heuristic_method = (png_byte)heuristic_method; - - if (num_weights > 0) - { - if (png_ptr->prev_filters == NULL) - { - png_ptr->prev_filters = (png_bytep)png_malloc(png_ptr, - (png_uint_32)(png_sizeof(png_byte) * num_weights)); - - /* To make sure that the weighting starts out fairly */ - for (i = 0; i < num_weights; i++) - { - png_ptr->prev_filters[i] = 255; - } - } - - if (png_ptr->filter_weights == NULL) - { - png_ptr->filter_weights = (png_uint_16p)png_malloc(png_ptr, - (png_uint_32)(png_sizeof(png_uint_16) * num_weights)); - - png_ptr->inv_filter_weights = (png_uint_16p)png_malloc(png_ptr, - (png_uint_32)(png_sizeof(png_uint_16) * num_weights)); - for (i = 0; i < num_weights; i++) - { - png_ptr->inv_filter_weights[i] = - png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; - } - } - - for (i = 0; i < num_weights; i++) - { - if (filter_weights[i] < 0.0) - { - png_ptr->inv_filter_weights[i] = - png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; - } - else - { - png_ptr->inv_filter_weights[i] = - (png_uint_16)((double)PNG_WEIGHT_FACTOR*filter_weights[i]+0.5); - png_ptr->filter_weights[i] = - (png_uint_16)((double)PNG_WEIGHT_FACTOR/filter_weights[i]+0.5); - } - } - } - - /* If, in the future, there are other filter methods, this would - * need to be based on png_ptr->filter. - */ - if (png_ptr->filter_costs == NULL) - { - png_ptr->filter_costs = (png_uint_16p)png_malloc(png_ptr, - (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST)); - - png_ptr->inv_filter_costs = (png_uint_16p)png_malloc(png_ptr, - (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST)); - - for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) - { - png_ptr->inv_filter_costs[i] = - png_ptr->filter_costs[i] = PNG_COST_FACTOR; - } - } - - /* Here is where we set the relative costs of the different filters. We - * should take the desired compression level into account when setting - * the costs, so that Paeth, for instance, has a high relative cost at low - * compression levels, while it has a lower relative cost at higher - * compression settings. The filter types are in order of increasing - * relative cost, so it would be possible to do this with an algorithm. - */ - for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) - { - if (filter_costs == NULL || filter_costs[i] < 0.0) - { - png_ptr->inv_filter_costs[i] = - png_ptr->filter_costs[i] = PNG_COST_FACTOR; - } - else if (filter_costs[i] >= 1.0) - { - png_ptr->inv_filter_costs[i] = - (png_uint_16)((double)PNG_COST_FACTOR / filter_costs[i] + 0.5); - png_ptr->filter_costs[i] = - (png_uint_16)((double)PNG_COST_FACTOR * filter_costs[i] + 0.5); - } - } -} -#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ - -void PNGAPI -png_set_compression_level(png_structp png_ptr, int level) -{ - png_debug(1, "in png_set_compression_level\n"); - if (png_ptr == NULL) - return; - png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_LEVEL; - png_ptr->zlib_level = level; -} - -void PNGAPI -png_set_compression_mem_level(png_structp png_ptr, int mem_level) -{ - png_debug(1, "in png_set_compression_mem_level\n"); - if (png_ptr == NULL) - return; - png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL; - png_ptr->zlib_mem_level = mem_level; -} - -void PNGAPI -png_set_compression_strategy(png_structp png_ptr, int strategy) -{ - png_debug(1, "in png_set_compression_strategy\n"); - if (png_ptr == NULL) - return; - png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY; - png_ptr->zlib_strategy = strategy; -} - -void PNGAPI -png_set_compression_window_bits(png_structp png_ptr, int window_bits) -{ - if (png_ptr == NULL) - return; - if (window_bits > 15) - png_warning(png_ptr, "Only compression windows <= 32k supported by PNG"); - else if (window_bits < 8) - png_warning(png_ptr, "Only compression windows >= 256 supported by PNG"); -#ifndef WBITS_8_OK - /* avoid libpng bug with 256-byte windows */ - if (window_bits == 8) - { - png_warning(png_ptr, "Compression window is being reset to 512"); - window_bits=9; - } -#endif - png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS; - png_ptr->zlib_window_bits = window_bits; -} - -void PNGAPI -png_set_compression_method(png_structp png_ptr, int method) -{ - png_debug(1, "in png_set_compression_method\n"); - if (png_ptr == NULL) - return; - if (method != 8) - png_warning(png_ptr, "Only compression method 8 is supported by PNG"); - png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_METHOD; - png_ptr->zlib_method = method; -} - -void PNGAPI -png_set_write_status_fn(png_structp png_ptr, png_write_status_ptr write_row_fn) -{ - if (png_ptr == NULL) - return; - png_ptr->write_row_fn = write_row_fn; -} - -#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) -void PNGAPI -png_set_write_user_transform_fn(png_structp png_ptr, png_user_transform_ptr - write_user_transform_fn) -{ - png_debug(1, "in png_set_write_user_transform_fn\n"); - if (png_ptr == NULL) - return; - png_ptr->transformations |= PNG_USER_TRANSFORM; - png_ptr->write_user_transform_fn = write_user_transform_fn; -} -#endif - - -#if defined(PNG_INFO_IMAGE_SUPPORTED) -void PNGAPI -png_write_png(png_structp png_ptr, png_infop info_ptr, - int transforms, voidp params) -{ - if (png_ptr == NULL || info_ptr == NULL) - return; -#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) - /* invert the alpha channel from opacity to transparency */ - if (transforms & PNG_TRANSFORM_INVERT_ALPHA) - png_set_invert_alpha(png_ptr); -#endif - - /* Write the file header information. */ - png_write_info(png_ptr, info_ptr); - - /* ------ these transformations don't touch the info structure ------- */ - -#if defined(PNG_WRITE_INVERT_SUPPORTED) - /* invert monochrome pixels */ - if (transforms & PNG_TRANSFORM_INVERT_MONO) - png_set_invert_mono(png_ptr); -#endif - -#if defined(PNG_WRITE_SHIFT_SUPPORTED) - /* Shift the pixels up to a legal bit depth and fill in - * as appropriate to correctly scale the image. - */ - if ((transforms & PNG_TRANSFORM_SHIFT) - && (info_ptr->valid & PNG_INFO_sBIT)) - png_set_shift(png_ptr, &info_ptr->sig_bit); -#endif - -#if defined(PNG_WRITE_PACK_SUPPORTED) - /* pack pixels into bytes */ - if (transforms & PNG_TRANSFORM_PACKING) - png_set_packing(png_ptr); -#endif - -#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) - /* swap location of alpha bytes from ARGB to RGBA */ - if (transforms & PNG_TRANSFORM_SWAP_ALPHA) - png_set_swap_alpha(png_ptr); -#endif - -#if defined(PNG_WRITE_FILLER_SUPPORTED) - /* Get rid of filler (OR ALPHA) bytes, pack XRGB/RGBX/ARGB/RGBA into - * RGB (4 channels -> 3 channels). The second parameter is not used. - */ - if (transforms & PNG_TRANSFORM_STRIP_FILLER) - png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); -#endif - -#if defined(PNG_WRITE_BGR_SUPPORTED) - /* flip BGR pixels to RGB */ - if (transforms & PNG_TRANSFORM_BGR) - png_set_bgr(png_ptr); -#endif - -#if defined(PNG_WRITE_SWAP_SUPPORTED) - /* swap bytes of 16-bit files to most significant byte first */ - if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) - png_set_swap(png_ptr); -#endif - -#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) - /* swap bits of 1, 2, 4 bit packed pixel formats */ - if (transforms & PNG_TRANSFORM_PACKSWAP) - png_set_packswap(png_ptr); -#endif - - /* ----------------------- end of transformations ------------------- */ - - /* write the bits */ - if (info_ptr->valid & PNG_INFO_IDAT) - png_write_image(png_ptr, info_ptr->row_pointers); - - /* It is REQUIRED to call this to finish writing the rest of the file */ - png_write_end(png_ptr, info_ptr); - - transforms = transforms; /* quiet compiler warnings */ - params = params; -} -#endif -#endif /* PNG_WRITE_SUPPORTED */ diff --git a/uppdev/plugin/png/lib/pngwtran.c b/uppdev/plugin/png/lib/pngwtran.c deleted file mode 100644 index 19b29682c..000000000 --- a/uppdev/plugin/png/lib/pngwtran.c +++ /dev/null @@ -1,572 +0,0 @@ - -/* pngwtran.c - transforms the data in a row for PNG writers - * - * Last changed in libpng 1.2.9 April 14, 2006 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2006 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - */ - -#define PNG_INTERNAL -#include "png.h" -#ifdef PNG_WRITE_SUPPORTED - -/* Transform the data according to the user's wishes. The order of - * transformations is significant. - */ -void /* PRIVATE */ -png_do_write_transformations(png_structp png_ptr) -{ - png_debug(1, "in png_do_write_transformations\n"); - - if (png_ptr == NULL) - return; - -#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) - if (png_ptr->transformations & PNG_USER_TRANSFORM) - if(png_ptr->write_user_transform_fn != NULL) - (*(png_ptr->write_user_transform_fn)) /* user write transform function */ - (png_ptr, /* png_ptr */ - &(png_ptr->row_info), /* row_info: */ - /* png_uint_32 width; width of row */ - /* png_uint_32 rowbytes; number of bytes in row */ - /* png_byte color_type; color type of pixels */ - /* png_byte bit_depth; bit depth of samples */ - /* png_byte channels; number of channels (1-4) */ - /* png_byte pixel_depth; bits per pixel (depth*channels) */ - png_ptr->row_buf + 1); /* start of pixel data for row */ -#endif -#if defined(PNG_WRITE_FILLER_SUPPORTED) - if (png_ptr->transformations & PNG_FILLER) - png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, - png_ptr->flags); -#endif -#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) - if (png_ptr->transformations & PNG_PACKSWAP) - png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1); -#endif -#if defined(PNG_WRITE_PACK_SUPPORTED) - if (png_ptr->transformations & PNG_PACK) - png_do_pack(&(png_ptr->row_info), png_ptr->row_buf + 1, - (png_uint_32)png_ptr->bit_depth); -#endif -#if defined(PNG_WRITE_SWAP_SUPPORTED) - if (png_ptr->transformations & PNG_SWAP_BYTES) - png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1); -#endif -#if defined(PNG_WRITE_SHIFT_SUPPORTED) - if (png_ptr->transformations & PNG_SHIFT) - png_do_shift(&(png_ptr->row_info), png_ptr->row_buf + 1, - &(png_ptr->shift)); -#endif -#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) - if (png_ptr->transformations & PNG_SWAP_ALPHA) - png_do_write_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); -#endif -#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) - if (png_ptr->transformations & PNG_INVERT_ALPHA) - png_do_write_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); -#endif -#if defined(PNG_WRITE_BGR_SUPPORTED) - if (png_ptr->transformations & PNG_BGR) - png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1); -#endif -#if defined(PNG_WRITE_INVERT_SUPPORTED) - if (png_ptr->transformations & PNG_INVERT_MONO) - png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1); -#endif -} - -#if defined(PNG_WRITE_PACK_SUPPORTED) -/* Pack pixels into bytes. Pass the true bit depth in bit_depth. The - * row_info bit depth should be 8 (one pixel per byte). The channels - * should be 1 (this only happens on grayscale and paletted images). - */ -void /* PRIVATE */ -png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) -{ - png_debug(1, "in png_do_pack\n"); - if (row_info->bit_depth == 8 && -#if defined(PNG_USELESS_TESTS_SUPPORTED) - row != NULL && row_info != NULL && -#endif - row_info->channels == 1) - { - switch ((int)bit_depth) - { - case 1: - { - png_bytep sp, dp; - int mask, v; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - sp = row; - dp = row; - mask = 0x80; - v = 0; - - for (i = 0; i < row_width; i++) - { - if (*sp != 0) - v |= mask; - sp++; - if (mask > 1) - mask >>= 1; - else - { - mask = 0x80; - *dp = (png_byte)v; - dp++; - v = 0; - } - } - if (mask != 0x80) - *dp = (png_byte)v; - break; - } - case 2: - { - png_bytep sp, dp; - int shift, v; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - sp = row; - dp = row; - shift = 6; - v = 0; - for (i = 0; i < row_width; i++) - { - png_byte value; - - value = (png_byte)(*sp & 0x03); - v |= (value << shift); - if (shift == 0) - { - shift = 6; - *dp = (png_byte)v; - dp++; - v = 0; - } - else - shift -= 2; - sp++; - } - if (shift != 6) - *dp = (png_byte)v; - break; - } - case 4: - { - png_bytep sp, dp; - int shift, v; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - sp = row; - dp = row; - shift = 4; - v = 0; - for (i = 0; i < row_width; i++) - { - png_byte value; - - value = (png_byte)(*sp & 0x0f); - v |= (value << shift); - - if (shift == 0) - { - shift = 4; - *dp = (png_byte)v; - dp++; - v = 0; - } - else - shift -= 4; - - sp++; - } - if (shift != 4) - *dp = (png_byte)v; - break; - } - } - row_info->bit_depth = (png_byte)bit_depth; - row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels); - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, - row_info->width); - } -} -#endif - -#if defined(PNG_WRITE_SHIFT_SUPPORTED) -/* Shift pixel values to take advantage of whole range. Pass the - * true number of bits in bit_depth. The row should be packed - * according to row_info->bit_depth. Thus, if you had a row of - * bit depth 4, but the pixels only had values from 0 to 7, you - * would pass 3 as bit_depth, and this routine would translate the - * data to 0 to 15. - */ -void /* PRIVATE */ -png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth) -{ - png_debug(1, "in png_do_shift\n"); -#if defined(PNG_USELESS_TESTS_SUPPORTED) - if (row != NULL && row_info != NULL && -#else - if ( -#endif - row_info->color_type != PNG_COLOR_TYPE_PALETTE) - { - int shift_start[4], shift_dec[4]; - int channels = 0; - - if (row_info->color_type & PNG_COLOR_MASK_COLOR) - { - shift_start[channels] = row_info->bit_depth - bit_depth->red; - shift_dec[channels] = bit_depth->red; - channels++; - shift_start[channels] = row_info->bit_depth - bit_depth->green; - shift_dec[channels] = bit_depth->green; - channels++; - shift_start[channels] = row_info->bit_depth - bit_depth->blue; - shift_dec[channels] = bit_depth->blue; - channels++; - } - else - { - shift_start[channels] = row_info->bit_depth - bit_depth->gray; - shift_dec[channels] = bit_depth->gray; - channels++; - } - if (row_info->color_type & PNG_COLOR_MASK_ALPHA) - { - shift_start[channels] = row_info->bit_depth - bit_depth->alpha; - shift_dec[channels] = bit_depth->alpha; - channels++; - } - - /* with low row depths, could only be grayscale, so one channel */ - if (row_info->bit_depth < 8) - { - png_bytep bp = row; - png_uint_32 i; - png_byte mask; - png_uint_32 row_bytes = row_info->rowbytes; - - if (bit_depth->gray == 1 && row_info->bit_depth == 2) - mask = 0x55; - else if (row_info->bit_depth == 4 && bit_depth->gray == 3) - mask = 0x11; - else - mask = 0xff; - - for (i = 0; i < row_bytes; i++, bp++) - { - png_uint_16 v; - int j; - - v = *bp; - *bp = 0; - for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0]) - { - if (j > 0) - *bp |= (png_byte)((v << j) & 0xff); - else - *bp |= (png_byte)((v >> (-j)) & mask); - } - } - } - else if (row_info->bit_depth == 8) - { - png_bytep bp = row; - png_uint_32 i; - png_uint_32 istop = channels * row_info->width; - - for (i = 0; i < istop; i++, bp++) - { - - png_uint_16 v; - int j; - int c = (int)(i%channels); - - v = *bp; - *bp = 0; - for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) - { - if (j > 0) - *bp |= (png_byte)((v << j) & 0xff); - else - *bp |= (png_byte)((v >> (-j)) & 0xff); - } - } - } - else - { - png_bytep bp; - png_uint_32 i; - png_uint_32 istop = channels * row_info->width; - - for (bp = row, i = 0; i < istop; i++) - { - int c = (int)(i%channels); - png_uint_16 value, v; - int j; - - v = (png_uint_16)(((png_uint_16)(*bp) << 8) + *(bp + 1)); - value = 0; - for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) - { - if (j > 0) - value |= (png_uint_16)((v << j) & (png_uint_16)0xffff); - else - value |= (png_uint_16)((v >> (-j)) & (png_uint_16)0xffff); - } - *bp++ = (png_byte)(value >> 8); - *bp++ = (png_byte)(value & 0xff); - } - } - } -} -#endif - -#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) -void /* PRIVATE */ -png_do_write_swap_alpha(png_row_infop row_info, png_bytep row) -{ - png_debug(1, "in png_do_write_swap_alpha\n"); -#if defined(PNG_USELESS_TESTS_SUPPORTED) - if (row != NULL && row_info != NULL) -#endif - { - if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - { - /* This converts from ARGB to RGBA */ - if (row_info->bit_depth == 8) - { - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - for (i = 0, sp = dp = row; i < row_width; i++) - { - png_byte save = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = save; - } - } - /* This converts from AARRGGBB to RRGGBBAA */ - else - { - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - for (i = 0, sp = dp = row; i < row_width; i++) - { - png_byte save[2]; - save[0] = *(sp++); - save[1] = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = save[0]; - *(dp++) = save[1]; - } - } - } - else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - { - /* This converts from AG to GA */ - if (row_info->bit_depth == 8) - { - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - for (i = 0, sp = dp = row; i < row_width; i++) - { - png_byte save = *(sp++); - *(dp++) = *(sp++); - *(dp++) = save; - } - } - /* This converts from AAGG to GGAA */ - else - { - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - for (i = 0, sp = dp = row; i < row_width; i++) - { - png_byte save[2]; - save[0] = *(sp++); - save[1] = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = save[0]; - *(dp++) = save[1]; - } - } - } - } -} -#endif - -#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) -void /* PRIVATE */ -png_do_write_invert_alpha(png_row_infop row_info, png_bytep row) -{ - png_debug(1, "in png_do_write_invert_alpha\n"); -#if defined(PNG_USELESS_TESTS_SUPPORTED) - if (row != NULL && row_info != NULL) -#endif - { - if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - { - /* This inverts the alpha channel in RGBA */ - if (row_info->bit_depth == 8) - { - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - for (i = 0, sp = dp = row; i < row_width; i++) - { - /* does nothing - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - */ - sp+=3; dp = sp; - *(dp++) = (png_byte)(255 - *(sp++)); - } - } - /* This inverts the alpha channel in RRGGBBAA */ - else - { - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - for (i = 0, sp = dp = row; i < row_width; i++) - { - /* does nothing - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - */ - sp+=6; dp = sp; - *(dp++) = (png_byte)(255 - *(sp++)); - *(dp++) = (png_byte)(255 - *(sp++)); - } - } - } - else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - { - /* This inverts the alpha channel in GA */ - if (row_info->bit_depth == 8) - { - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - for (i = 0, sp = dp = row; i < row_width; i++) - { - *(dp++) = *(sp++); - *(dp++) = (png_byte)(255 - *(sp++)); - } - } - /* This inverts the alpha channel in GGAA */ - else - { - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - for (i = 0, sp = dp = row; i < row_width; i++) - { - /* does nothing - *(dp++) = *(sp++); - *(dp++) = *(sp++); - */ - sp+=2; dp = sp; - *(dp++) = (png_byte)(255 - *(sp++)); - *(dp++) = (png_byte)(255 - *(sp++)); - } - } - } - } -} -#endif - -#if defined(PNG_MNG_FEATURES_SUPPORTED) -/* undoes intrapixel differencing */ -void /* PRIVATE */ -png_do_write_intrapixel(png_row_infop row_info, png_bytep row) -{ - png_debug(1, "in png_do_write_intrapixel\n"); - if ( -#if defined(PNG_USELESS_TESTS_SUPPORTED) - row != NULL && row_info != NULL && -#endif - (row_info->color_type & PNG_COLOR_MASK_COLOR)) - { - int bytes_per_pixel; - png_uint_32 row_width = row_info->width; - if (row_info->bit_depth == 8) - { - png_bytep rp; - png_uint_32 i; - - if (row_info->color_type == PNG_COLOR_TYPE_RGB) - bytes_per_pixel = 3; - else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - bytes_per_pixel = 4; - else - return; - - for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) - { - *(rp) = (png_byte)((*rp - *(rp+1))&0xff); - *(rp+2) = (png_byte)((*(rp+2) - *(rp+1))&0xff); - } - } - else if (row_info->bit_depth == 16) - { - png_bytep rp; - png_uint_32 i; - - if (row_info->color_type == PNG_COLOR_TYPE_RGB) - bytes_per_pixel = 6; - else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - bytes_per_pixel = 8; - else - return; - - for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) - { - png_uint_32 s0 = (*(rp ) << 8) | *(rp+1); - png_uint_32 s1 = (*(rp+2) << 8) | *(rp+3); - png_uint_32 s2 = (*(rp+4) << 8) | *(rp+5); - png_uint_32 red = (png_uint_32)((s0-s1) & 0xffffL); - png_uint_32 blue = (png_uint_32)((s2-s1) & 0xffffL); - *(rp ) = (png_byte)((red >> 8) & 0xff); - *(rp+1) = (png_byte)(red & 0xff); - *(rp+4) = (png_byte)((blue >> 8) & 0xff); - *(rp+5) = (png_byte)(blue & 0xff); - } - } - } -} -#endif /* PNG_MNG_FEATURES_SUPPORTED */ -#endif /* PNG_WRITE_SUPPORTED */ diff --git a/uppdev/plugin/png/lib/pngwutil.c b/uppdev/plugin/png/lib/pngwutil.c deleted file mode 100644 index 352035d47..000000000 --- a/uppdev/plugin/png/lib/pngwutil.c +++ /dev/null @@ -1,2792 +0,0 @@ - -/* pngwutil.c - utilities to write a PNG file - * - * Last changed in libpng 1.2.20 Septhember 3, 2007 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2007 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - */ - -#define PNG_INTERNAL -#include "png.h" -#ifdef PNG_WRITE_SUPPORTED - -/* Place a 32-bit number into a buffer in PNG byte order. We work - * with unsigned numbers for convenience, although one supported - * ancillary chunk uses signed (two's complement) numbers. - */ -void PNGAPI -png_save_uint_32(png_bytep buf, png_uint_32 i) -{ - buf[0] = (png_byte)((i >> 24) & 0xff); - buf[1] = (png_byte)((i >> 16) & 0xff); - buf[2] = (png_byte)((i >> 8) & 0xff); - buf[3] = (png_byte)(i & 0xff); -} - -/* The png_save_int_32 function assumes integers are stored in two's - * complement format. If this isn't the case, then this routine needs to - * be modified to write data in two's complement format. - */ -void PNGAPI -png_save_int_32(png_bytep buf, png_int_32 i) -{ - buf[0] = (png_byte)((i >> 24) & 0xff); - buf[1] = (png_byte)((i >> 16) & 0xff); - buf[2] = (png_byte)((i >> 8) & 0xff); - buf[3] = (png_byte)(i & 0xff); -} - -/* Place a 16-bit number into a buffer in PNG byte order. - * The parameter is declared unsigned int, not png_uint_16, - * just to avoid potential problems on pre-ANSI C compilers. - */ -void PNGAPI -png_save_uint_16(png_bytep buf, unsigned int i) -{ - buf[0] = (png_byte)((i >> 8) & 0xff); - buf[1] = (png_byte)(i & 0xff); -} - -/* Write a PNG chunk all at once. The type is an array of ASCII characters - * representing the chunk name. The array must be at least 4 bytes in - * length, and does not need to be null terminated. To be safe, pass the - * pre-defined chunk names here, and if you need a new one, define it - * where the others are defined. The length is the length of the data. - * All the data must be present. If that is not possible, use the - * png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end() - * functions instead. - */ -void PNGAPI -png_write_chunk(png_structp png_ptr, png_bytep chunk_name, - png_bytep data, png_size_t length) -{ - if(png_ptr == NULL) return; - png_write_chunk_start(png_ptr, chunk_name, (png_uint_32)length); - png_write_chunk_data(png_ptr, data, length); - png_write_chunk_end(png_ptr); -} - -/* Write the start of a PNG chunk. The type is the chunk type. - * The total_length is the sum of the lengths of all the data you will be - * passing in png_write_chunk_data(). - */ -void PNGAPI -png_write_chunk_start(png_structp png_ptr, png_bytep chunk_name, - png_uint_32 length) -{ - png_byte buf[4]; - png_debug2(0, "Writing %s chunk (%lu bytes)\n", chunk_name, length); - if(png_ptr == NULL) return; - - /* write the length */ - png_save_uint_32(buf, length); - png_write_data(png_ptr, buf, (png_size_t)4); - - /* write the chunk name */ - png_write_data(png_ptr, chunk_name, (png_size_t)4); - /* reset the crc and run it over the chunk name */ - png_reset_crc(png_ptr); - png_calculate_crc(png_ptr, chunk_name, (png_size_t)4); -} - -/* Write the data of a PNG chunk started with png_write_chunk_start(). - * Note that multiple calls to this function are allowed, and that the - * sum of the lengths from these calls *must* add up to the total_length - * given to png_write_chunk_start(). - */ -void PNGAPI -png_write_chunk_data(png_structp png_ptr, png_bytep data, png_size_t length) -{ - /* write the data, and run the CRC over it */ - if(png_ptr == NULL) return; - if (data != NULL && length > 0) - { - png_calculate_crc(png_ptr, data, length); - png_write_data(png_ptr, data, length); - } -} - -/* Finish a chunk started with png_write_chunk_start(). */ -void PNGAPI -png_write_chunk_end(png_structp png_ptr) -{ - png_byte buf[4]; - - if(png_ptr == NULL) return; - - /* write the crc */ - png_save_uint_32(buf, png_ptr->crc); - - png_write_data(png_ptr, buf, (png_size_t)4); -} - -/* Simple function to write the signature. If we have already written - * the magic bytes of the signature, or more likely, the PNG stream is - * being embedded into another stream and doesn't need its own signature, - * we should call png_set_sig_bytes() to tell libpng how many of the - * bytes have already been written. - */ -void /* PRIVATE */ -png_write_sig(png_structp png_ptr) -{ - png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; - /* write the rest of the 8 byte signature */ - png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes], - (png_size_t)8 - png_ptr->sig_bytes); - if(png_ptr->sig_bytes < 3) - png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; -} - -#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_iCCP_SUPPORTED) -/* - * This pair of functions encapsulates the operation of (a) compressing a - * text string, and (b) issuing it later as a series of chunk data writes. - * The compression_state structure is shared context for these functions - * set up by the caller in order to make the whole mess thread-safe. - */ - -typedef struct -{ - char *input; /* the uncompressed input data */ - int input_len; /* its length */ - int num_output_ptr; /* number of output pointers used */ - int max_output_ptr; /* size of output_ptr */ - png_charpp output_ptr; /* array of pointers to output */ -} compression_state; - -/* compress given text into storage in the png_ptr structure */ -static int /* PRIVATE */ -png_text_compress(png_structp png_ptr, - png_charp text, png_size_t text_len, int compression, - compression_state *comp) -{ - int ret; - - comp->num_output_ptr = 0; - comp->max_output_ptr = 0; - comp->output_ptr = NULL; - comp->input = NULL; - comp->input_len = 0; - - /* we may just want to pass the text right through */ - if (compression == PNG_TEXT_COMPRESSION_NONE) - { - comp->input = text; - comp->input_len = text_len; - return((int)text_len); - } - - if (compression >= PNG_TEXT_COMPRESSION_LAST) - { -#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) - char msg[50]; - png_snprintf(msg, 50, "Unknown compression type %d", compression); - png_warning(png_ptr, msg); -#else - png_warning(png_ptr, "Unknown compression type"); -#endif - } - - /* We can't write the chunk until we find out how much data we have, - * which means we need to run the compressor first and save the - * output. This shouldn't be a problem, as the vast majority of - * comments should be reasonable, but we will set up an array of - * malloc'd pointers to be sure. - * - * If we knew the application was well behaved, we could simplify this - * greatly by assuming we can always malloc an output buffer large - * enough to hold the compressed text ((1001 * text_len / 1000) + 12) - * and malloc this directly. The only time this would be a bad idea is - * if we can't malloc more than 64K and we have 64K of random input - * data, or if the input string is incredibly large (although this - * wouldn't cause a failure, just a slowdown due to swapping). - */ - - /* set up the compression buffers */ - png_ptr->zstream.avail_in = (uInt)text_len; - png_ptr->zstream.next_in = (Bytef *)text; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - png_ptr->zstream.next_out = (Bytef *)png_ptr->zbuf; - - /* this is the same compression loop as in png_write_row() */ - do - { - /* compress the data */ - ret = deflate(&png_ptr->zstream, Z_NO_FLUSH); - if (ret != Z_OK) - { - /* error */ - if (png_ptr->zstream.msg != NULL) - png_error(png_ptr, png_ptr->zstream.msg); - else - png_error(png_ptr, "zlib error"); - } - /* check to see if we need more room */ - if (!(png_ptr->zstream.avail_out)) - { - /* make sure the output array has room */ - if (comp->num_output_ptr >= comp->max_output_ptr) - { - int old_max; - - old_max = comp->max_output_ptr; - comp->max_output_ptr = comp->num_output_ptr + 4; - if (comp->output_ptr != NULL) - { - png_charpp old_ptr; - - old_ptr = comp->output_ptr; - comp->output_ptr = (png_charpp)png_malloc(png_ptr, - (png_uint_32)(comp->max_output_ptr * - png_sizeof (png_charpp))); - png_memcpy(comp->output_ptr, old_ptr, old_max - * png_sizeof (png_charp)); - png_free(png_ptr, old_ptr); - } - else - comp->output_ptr = (png_charpp)png_malloc(png_ptr, - (png_uint_32)(comp->max_output_ptr * - png_sizeof (png_charp))); - } - - /* save the data */ - comp->output_ptr[comp->num_output_ptr] = (png_charp)png_malloc(png_ptr, - (png_uint_32)png_ptr->zbuf_size); - png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf, - png_ptr->zbuf_size); - comp->num_output_ptr++; - - /* and reset the buffer */ - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - png_ptr->zstream.next_out = png_ptr->zbuf; - } - /* continue until we don't have any more to compress */ - } while (png_ptr->zstream.avail_in); - - /* finish the compression */ - do - { - /* tell zlib we are finished */ - ret = deflate(&png_ptr->zstream, Z_FINISH); - - if (ret == Z_OK) - { - /* check to see if we need more room */ - if (!(png_ptr->zstream.avail_out)) - { - /* check to make sure our output array has room */ - if (comp->num_output_ptr >= comp->max_output_ptr) - { - int old_max; - - old_max = comp->max_output_ptr; - comp->max_output_ptr = comp->num_output_ptr + 4; - if (comp->output_ptr != NULL) - { - png_charpp old_ptr; - - old_ptr = comp->output_ptr; - /* This could be optimized to realloc() */ - comp->output_ptr = (png_charpp)png_malloc(png_ptr, - (png_uint_32)(comp->max_output_ptr * - png_sizeof (png_charpp))); - png_memcpy(comp->output_ptr, old_ptr, - old_max * png_sizeof (png_charp)); - png_free(png_ptr, old_ptr); - } - else - comp->output_ptr = (png_charpp)png_malloc(png_ptr, - (png_uint_32)(comp->max_output_ptr * - png_sizeof (png_charp))); - } - - /* save off the data */ - comp->output_ptr[comp->num_output_ptr] = - (png_charp)png_malloc(png_ptr, (png_uint_32)png_ptr->zbuf_size); - png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf, - png_ptr->zbuf_size); - comp->num_output_ptr++; - - /* and reset the buffer pointers */ - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - png_ptr->zstream.next_out = png_ptr->zbuf; - } - } - else if (ret != Z_STREAM_END) - { - /* we got an error */ - if (png_ptr->zstream.msg != NULL) - png_error(png_ptr, png_ptr->zstream.msg); - else - png_error(png_ptr, "zlib error"); - } - } while (ret != Z_STREAM_END); - - /* text length is number of buffers plus last buffer */ - text_len = png_ptr->zbuf_size * comp->num_output_ptr; - if (png_ptr->zstream.avail_out < png_ptr->zbuf_size) - text_len += png_ptr->zbuf_size - (png_size_t)png_ptr->zstream.avail_out; - - return((int)text_len); -} - -/* ship the compressed text out via chunk writes */ -static void /* PRIVATE */ -png_write_compressed_data_out(png_structp png_ptr, compression_state *comp) -{ - int i; - - /* handle the no-compression case */ - if (comp->input) - { - png_write_chunk_data(png_ptr, (png_bytep)comp->input, - (png_size_t)comp->input_len); - return; - } - - /* write saved output buffers, if any */ - for (i = 0; i < comp->num_output_ptr; i++) - { - png_write_chunk_data(png_ptr,(png_bytep)comp->output_ptr[i], - png_ptr->zbuf_size); - png_free(png_ptr, comp->output_ptr[i]); - comp->output_ptr[i]=NULL; - } - if (comp->max_output_ptr != 0) - png_free(png_ptr, comp->output_ptr); - comp->output_ptr=NULL; - /* write anything left in zbuf */ - if (png_ptr->zstream.avail_out < (png_uint_32)png_ptr->zbuf_size) - png_write_chunk_data(png_ptr, png_ptr->zbuf, - png_ptr->zbuf_size - png_ptr->zstream.avail_out); - - /* reset zlib for another zTXt/iTXt or image data */ - deflateReset(&png_ptr->zstream); - png_ptr->zstream.data_type = Z_BINARY; -} -#endif - -/* Write the IHDR chunk, and update the png_struct with the necessary - * information. Note that the rest of this code depends upon this - * information being correct. - */ -void /* PRIVATE */ -png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height, - int bit_depth, int color_type, int compression_type, int filter_type, - int interlace_type) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_IHDR; -#endif - png_byte buf[13]; /* buffer to store the IHDR info */ - - png_debug(1, "in png_write_IHDR\n"); - /* Check that we have valid input data from the application info */ - switch (color_type) - { - case PNG_COLOR_TYPE_GRAY: - switch (bit_depth) - { - case 1: - case 2: - case 4: - case 8: - case 16: png_ptr->channels = 1; break; - default: png_error(png_ptr,"Invalid bit depth for grayscale image"); - } - break; - case PNG_COLOR_TYPE_RGB: - if (bit_depth != 8 && bit_depth != 16) - png_error(png_ptr, "Invalid bit depth for RGB image"); - png_ptr->channels = 3; - break; - case PNG_COLOR_TYPE_PALETTE: - switch (bit_depth) - { - case 1: - case 2: - case 4: - case 8: png_ptr->channels = 1; break; - default: png_error(png_ptr, "Invalid bit depth for paletted image"); - } - break; - case PNG_COLOR_TYPE_GRAY_ALPHA: - if (bit_depth != 8 && bit_depth != 16) - png_error(png_ptr, "Invalid bit depth for grayscale+alpha image"); - png_ptr->channels = 2; - break; - case PNG_COLOR_TYPE_RGB_ALPHA: - if (bit_depth != 8 && bit_depth != 16) - png_error(png_ptr, "Invalid bit depth for RGBA image"); - png_ptr->channels = 4; - break; - default: - png_error(png_ptr, "Invalid image color type specified"); - } - - if (compression_type != PNG_COMPRESSION_TYPE_BASE) - { - png_warning(png_ptr, "Invalid compression type specified"); - compression_type = PNG_COMPRESSION_TYPE_BASE; - } - - /* Write filter_method 64 (intrapixel differencing) only if - * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and - * 2. Libpng did not write a PNG signature (this filter_method is only - * used in PNG datastreams that are embedded in MNG datastreams) and - * 3. The application called png_permit_mng_features with a mask that - * included PNG_FLAG_MNG_FILTER_64 and - * 4. The filter_method is 64 and - * 5. The color_type is RGB or RGBA - */ - if ( -#if defined(PNG_MNG_FEATURES_SUPPORTED) - !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && - ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) && - (color_type == PNG_COLOR_TYPE_RGB || - color_type == PNG_COLOR_TYPE_RGB_ALPHA) && - (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) && -#endif - filter_type != PNG_FILTER_TYPE_BASE) - { - png_warning(png_ptr, "Invalid filter type specified"); - filter_type = PNG_FILTER_TYPE_BASE; - } - -#ifdef PNG_WRITE_INTERLACING_SUPPORTED - if (interlace_type != PNG_INTERLACE_NONE && - interlace_type != PNG_INTERLACE_ADAM7) - { - png_warning(png_ptr, "Invalid interlace type specified"); - interlace_type = PNG_INTERLACE_ADAM7; - } -#else - interlace_type=PNG_INTERLACE_NONE; -#endif - - /* save off the relevent information */ - png_ptr->bit_depth = (png_byte)bit_depth; - png_ptr->color_type = (png_byte)color_type; - png_ptr->interlaced = (png_byte)interlace_type; -#if defined(PNG_MNG_FEATURES_SUPPORTED) - png_ptr->filter_type = (png_byte)filter_type; -#endif - png_ptr->compression_type = (png_byte)compression_type; - png_ptr->width = width; - png_ptr->height = height; - - png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels); - png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width); - /* set the usr info, so any transformations can modify it */ - png_ptr->usr_width = png_ptr->width; - png_ptr->usr_bit_depth = png_ptr->bit_depth; - png_ptr->usr_channels = png_ptr->channels; - - /* pack the header information into the buffer */ - png_save_uint_32(buf, width); - png_save_uint_32(buf + 4, height); - buf[8] = (png_byte)bit_depth; - buf[9] = (png_byte)color_type; - buf[10] = (png_byte)compression_type; - buf[11] = (png_byte)filter_type; - buf[12] = (png_byte)interlace_type; - - /* write the chunk */ - png_write_chunk(png_ptr, png_IHDR, buf, (png_size_t)13); - - /* initialize zlib with PNG info */ - png_ptr->zstream.zalloc = png_zalloc; - png_ptr->zstream.zfree = png_zfree; - png_ptr->zstream.opaque = (voidpf)png_ptr; - if (!(png_ptr->do_filter)) - { - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE || - png_ptr->bit_depth < 8) - png_ptr->do_filter = PNG_FILTER_NONE; - else - png_ptr->do_filter = PNG_ALL_FILTERS; - } - if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY)) - { - if (png_ptr->do_filter != PNG_FILTER_NONE) - png_ptr->zlib_strategy = Z_FILTERED; - else - png_ptr->zlib_strategy = Z_DEFAULT_STRATEGY; - } - if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_LEVEL)) - png_ptr->zlib_level = Z_DEFAULT_COMPRESSION; - if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL)) - png_ptr->zlib_mem_level = 8; - if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS)) - png_ptr->zlib_window_bits = 15; - if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_METHOD)) - png_ptr->zlib_method = 8; - if (deflateInit2(&png_ptr->zstream, png_ptr->zlib_level, - png_ptr->zlib_method, png_ptr->zlib_window_bits, - png_ptr->zlib_mem_level, png_ptr->zlib_strategy) != Z_OK) - png_error(png_ptr, "zlib failed to initialize compressor"); - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - /* libpng is not interested in zstream.data_type */ - /* set it to a predefined value, to avoid its evaluation inside zlib */ - png_ptr->zstream.data_type = Z_BINARY; - - png_ptr->mode = PNG_HAVE_IHDR; -} - -/* write the palette. We are careful not to trust png_color to be in the - * correct order for PNG, so people can redefine it to any convenient - * structure. - */ -void /* PRIVATE */ -png_write_PLTE(png_structp png_ptr, png_colorp palette, png_uint_32 num_pal) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_PLTE; -#endif - png_uint_32 i; - png_colorp pal_ptr; - png_byte buf[3]; - - png_debug(1, "in png_write_PLTE\n"); - if (( -#if defined(PNG_MNG_FEATURES_SUPPORTED) - !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) && -#endif - num_pal == 0) || num_pal > 256) - { - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - { - png_error(png_ptr, "Invalid number of colors in palette"); - } - else - { - png_warning(png_ptr, "Invalid number of colors in palette"); - return; - } - } - - if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR)) - { - png_warning(png_ptr, - "Ignoring request to write a PLTE chunk in grayscale PNG"); - return; - } - - png_ptr->num_palette = (png_uint_16)num_pal; - png_debug1(3, "num_palette = %d\n", png_ptr->num_palette); - - png_write_chunk_start(png_ptr, png_PLTE, num_pal * 3); -#ifndef PNG_NO_POINTER_INDEXING - for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++) - { - buf[0] = pal_ptr->red; - buf[1] = pal_ptr->green; - buf[2] = pal_ptr->blue; - png_write_chunk_data(png_ptr, buf, (png_size_t)3); - } -#else - /* This is a little slower but some buggy compilers need to do this instead */ - pal_ptr=palette; - for (i = 0; i < num_pal; i++) - { - buf[0] = pal_ptr[i].red; - buf[1] = pal_ptr[i].green; - buf[2] = pal_ptr[i].blue; - png_write_chunk_data(png_ptr, buf, (png_size_t)3); - } -#endif - png_write_chunk_end(png_ptr); - png_ptr->mode |= PNG_HAVE_PLTE; -} - -/* write an IDAT chunk */ -void /* PRIVATE */ -png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_IDAT; -#endif - png_debug(1, "in png_write_IDAT\n"); - - /* Optimize the CMF field in the zlib stream. */ - /* This hack of the zlib stream is compliant to the stream specification. */ - if (!(png_ptr->mode & PNG_HAVE_IDAT) && - png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE) - { - unsigned int z_cmf = data[0]; /* zlib compression method and flags */ - if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70) - { - /* Avoid memory underflows and multiplication overflows. */ - /* The conditions below are practically always satisfied; - however, they still must be checked. */ - if (length >= 2 && - png_ptr->height < 16384 && png_ptr->width < 16384) - { - png_uint_32 uncompressed_idat_size = png_ptr->height * - ((png_ptr->width * - png_ptr->channels * png_ptr->bit_depth + 15) >> 3); - unsigned int z_cinfo = z_cmf >> 4; - unsigned int half_z_window_size = 1 << (z_cinfo + 7); - while (uncompressed_idat_size <= half_z_window_size && - half_z_window_size >= 256) - { - z_cinfo--; - half_z_window_size >>= 1; - } - z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4); - if (data[0] != (png_byte)z_cmf) - { - data[0] = (png_byte)z_cmf; - data[1] &= 0xe0; - data[1] += (png_byte)(0x1f - ((z_cmf << 8) + data[1]) % 0x1f); - } - } - } - else - png_error(png_ptr, - "Invalid zlib compression method or flags in IDAT"); - } - - png_write_chunk(png_ptr, png_IDAT, data, length); - png_ptr->mode |= PNG_HAVE_IDAT; -} - -/* write an IEND chunk */ -void /* PRIVATE */ -png_write_IEND(png_structp png_ptr) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_IEND; -#endif - png_debug(1, "in png_write_IEND\n"); - png_write_chunk(png_ptr, png_IEND, png_bytep_NULL, - (png_size_t)0); - png_ptr->mode |= PNG_HAVE_IEND; -} - -#if defined(PNG_WRITE_gAMA_SUPPORTED) -/* write a gAMA chunk */ -#ifdef PNG_FLOATING_POINT_SUPPORTED -void /* PRIVATE */ -png_write_gAMA(png_structp png_ptr, double file_gamma) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_gAMA; -#endif - png_uint_32 igamma; - png_byte buf[4]; - - png_debug(1, "in png_write_gAMA\n"); - /* file_gamma is saved in 1/100,000ths */ - igamma = (png_uint_32)(file_gamma * 100000.0 + 0.5); - png_save_uint_32(buf, igamma); - png_write_chunk(png_ptr, png_gAMA, buf, (png_size_t)4); -} -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED -void /* PRIVATE */ -png_write_gAMA_fixed(png_structp png_ptr, png_fixed_point file_gamma) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_gAMA; -#endif - png_byte buf[4]; - - png_debug(1, "in png_write_gAMA\n"); - /* file_gamma is saved in 1/100,000ths */ - png_save_uint_32(buf, (png_uint_32)file_gamma); - png_write_chunk(png_ptr, png_gAMA, buf, (png_size_t)4); -} -#endif -#endif - -#if defined(PNG_WRITE_sRGB_SUPPORTED) -/* write a sRGB chunk */ -void /* PRIVATE */ -png_write_sRGB(png_structp png_ptr, int srgb_intent) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_sRGB; -#endif - png_byte buf[1]; - - png_debug(1, "in png_write_sRGB\n"); - if(srgb_intent >= PNG_sRGB_INTENT_LAST) - png_warning(png_ptr, - "Invalid sRGB rendering intent specified"); - buf[0]=(png_byte)srgb_intent; - png_write_chunk(png_ptr, png_sRGB, buf, (png_size_t)1); -} -#endif - -#if defined(PNG_WRITE_iCCP_SUPPORTED) -/* write an iCCP chunk */ -void /* PRIVATE */ -png_write_iCCP(png_structp png_ptr, png_charp name, int compression_type, - png_charp profile, int profile_len) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_iCCP; -#endif - png_size_t name_len; - png_charp new_name; - compression_state comp; - int embedded_profile_len = 0; - - png_debug(1, "in png_write_iCCP\n"); - - comp.num_output_ptr = 0; - comp.max_output_ptr = 0; - comp.output_ptr = NULL; - comp.input = NULL; - comp.input_len = 0; - - if (name == NULL || (name_len = png_check_keyword(png_ptr, name, - &new_name)) == 0) - { - png_warning(png_ptr, "Empty keyword in iCCP chunk"); - return; - } - - if (compression_type != PNG_COMPRESSION_TYPE_BASE) - png_warning(png_ptr, "Unknown compression type in iCCP chunk"); - - if (profile == NULL) - profile_len = 0; - - if (profile_len > 3) - embedded_profile_len = - ((*( (png_bytep)profile ))<<24) | - ((*( (png_bytep)profile+1))<<16) | - ((*( (png_bytep)profile+2))<< 8) | - ((*( (png_bytep)profile+3)) ); - - if (profile_len < embedded_profile_len) - { - png_warning(png_ptr, - "Embedded profile length too large in iCCP chunk"); - return; - } - - if (profile_len > embedded_profile_len) - { - png_warning(png_ptr, - "Truncating profile to actual length in iCCP chunk"); - profile_len = embedded_profile_len; - } - - if (profile_len) - profile_len = png_text_compress(png_ptr, profile, (png_size_t)profile_len, - PNG_COMPRESSION_TYPE_BASE, &comp); - - /* make sure we include the NULL after the name and the compression type */ - png_write_chunk_start(png_ptr, png_iCCP, - (png_uint_32)name_len+profile_len+2); - new_name[name_len+1]=0x00; - png_write_chunk_data(png_ptr, (png_bytep)new_name, name_len + 2); - - if (profile_len) - png_write_compressed_data_out(png_ptr, &comp); - - png_write_chunk_end(png_ptr); - png_free(png_ptr, new_name); -} -#endif - -#if defined(PNG_WRITE_sPLT_SUPPORTED) -/* write a sPLT chunk */ -void /* PRIVATE */ -png_write_sPLT(png_structp png_ptr, png_sPLT_tp spalette) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_sPLT; -#endif - png_size_t name_len; - png_charp new_name; - png_byte entrybuf[10]; - int entry_size = (spalette->depth == 8 ? 6 : 10); - int palette_size = entry_size * spalette->nentries; - png_sPLT_entryp ep; -#ifdef PNG_NO_POINTER_INDEXING - int i; -#endif - - png_debug(1, "in png_write_sPLT\n"); - if (spalette->name == NULL || (name_len = png_check_keyword(png_ptr, - spalette->name, &new_name))==0) - { - png_warning(png_ptr, "Empty keyword in sPLT chunk"); - return; - } - - /* make sure we include the NULL after the name */ - png_write_chunk_start(png_ptr, png_sPLT, - (png_uint_32)(name_len + 2 + palette_size)); - png_write_chunk_data(png_ptr, (png_bytep)new_name, name_len + 1); - png_write_chunk_data(png_ptr, (png_bytep)&spalette->depth, 1); - - /* loop through each palette entry, writing appropriately */ -#ifndef PNG_NO_POINTER_INDEXING - for (ep = spalette->entries; epentries+spalette->nentries; ep++) - { - if (spalette->depth == 8) - { - entrybuf[0] = (png_byte)ep->red; - entrybuf[1] = (png_byte)ep->green; - entrybuf[2] = (png_byte)ep->blue; - entrybuf[3] = (png_byte)ep->alpha; - png_save_uint_16(entrybuf + 4, ep->frequency); - } - else - { - png_save_uint_16(entrybuf + 0, ep->red); - png_save_uint_16(entrybuf + 2, ep->green); - png_save_uint_16(entrybuf + 4, ep->blue); - png_save_uint_16(entrybuf + 6, ep->alpha); - png_save_uint_16(entrybuf + 8, ep->frequency); - } - png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size); - } -#else - ep=spalette->entries; - for (i=0; i>spalette->nentries; i++) - { - if (spalette->depth == 8) - { - entrybuf[0] = (png_byte)ep[i].red; - entrybuf[1] = (png_byte)ep[i].green; - entrybuf[2] = (png_byte)ep[i].blue; - entrybuf[3] = (png_byte)ep[i].alpha; - png_save_uint_16(entrybuf + 4, ep[i].frequency); - } - else - { - png_save_uint_16(entrybuf + 0, ep[i].red); - png_save_uint_16(entrybuf + 2, ep[i].green); - png_save_uint_16(entrybuf + 4, ep[i].blue); - png_save_uint_16(entrybuf + 6, ep[i].alpha); - png_save_uint_16(entrybuf + 8, ep[i].frequency); - } - png_write_chunk_data(png_ptr, entrybuf, entry_size); - } -#endif - - png_write_chunk_end(png_ptr); - png_free(png_ptr, new_name); -} -#endif - -#if defined(PNG_WRITE_sBIT_SUPPORTED) -/* write the sBIT chunk */ -void /* PRIVATE */ -png_write_sBIT(png_structp png_ptr, png_color_8p sbit, int color_type) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_sBIT; -#endif - png_byte buf[4]; - png_size_t size; - - png_debug(1, "in png_write_sBIT\n"); - /* make sure we don't depend upon the order of PNG_COLOR_8 */ - if (color_type & PNG_COLOR_MASK_COLOR) - { - png_byte maxbits; - - maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 : - png_ptr->usr_bit_depth); - if (sbit->red == 0 || sbit->red > maxbits || - sbit->green == 0 || sbit->green > maxbits || - sbit->blue == 0 || sbit->blue > maxbits) - { - png_warning(png_ptr, "Invalid sBIT depth specified"); - return; - } - buf[0] = sbit->red; - buf[1] = sbit->green; - buf[2] = sbit->blue; - size = 3; - } - else - { - if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth) - { - png_warning(png_ptr, "Invalid sBIT depth specified"); - return; - } - buf[0] = sbit->gray; - size = 1; - } - - if (color_type & PNG_COLOR_MASK_ALPHA) - { - if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth) - { - png_warning(png_ptr, "Invalid sBIT depth specified"); - return; - } - buf[size++] = sbit->alpha; - } - - png_write_chunk(png_ptr, png_sBIT, buf, size); -} -#endif - -#if defined(PNG_WRITE_cHRM_SUPPORTED) -/* write the cHRM chunk */ -#ifdef PNG_FLOATING_POINT_SUPPORTED -void /* PRIVATE */ -png_write_cHRM(png_structp png_ptr, double white_x, double white_y, - double red_x, double red_y, double green_x, double green_y, - double blue_x, double blue_y) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_cHRM; -#endif - png_byte buf[32]; - png_uint_32 itemp; - - png_debug(1, "in png_write_cHRM\n"); - /* each value is saved in 1/100,000ths */ - if (white_x < 0 || white_x > 0.8 || white_y < 0 || white_y > 0.8 || - white_x + white_y > 1.0) - { - png_warning(png_ptr, "Invalid cHRM white point specified"); -#if !defined(PNG_NO_CONSOLE_IO) - fprintf(stderr,"white_x=%f, white_y=%f\n",white_x, white_y); -#endif - return; - } - itemp = (png_uint_32)(white_x * 100000.0 + 0.5); - png_save_uint_32(buf, itemp); - itemp = (png_uint_32)(white_y * 100000.0 + 0.5); - png_save_uint_32(buf + 4, itemp); - - if (red_x < 0 || red_y < 0 || red_x + red_y > 1.0) - { - png_warning(png_ptr, "Invalid cHRM red point specified"); - return; - } - itemp = (png_uint_32)(red_x * 100000.0 + 0.5); - png_save_uint_32(buf + 8, itemp); - itemp = (png_uint_32)(red_y * 100000.0 + 0.5); - png_save_uint_32(buf + 12, itemp); - - if (green_x < 0 || green_y < 0 || green_x + green_y > 1.0) - { - png_warning(png_ptr, "Invalid cHRM green point specified"); - return; - } - itemp = (png_uint_32)(green_x * 100000.0 + 0.5); - png_save_uint_32(buf + 16, itemp); - itemp = (png_uint_32)(green_y * 100000.0 + 0.5); - png_save_uint_32(buf + 20, itemp); - - if (blue_x < 0 || blue_y < 0 || blue_x + blue_y > 1.0) - { - png_warning(png_ptr, "Invalid cHRM blue point specified"); - return; - } - itemp = (png_uint_32)(blue_x * 100000.0 + 0.5); - png_save_uint_32(buf + 24, itemp); - itemp = (png_uint_32)(blue_y * 100000.0 + 0.5); - png_save_uint_32(buf + 28, itemp); - - png_write_chunk(png_ptr, png_cHRM, buf, (png_size_t)32); -} -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED -void /* PRIVATE */ -png_write_cHRM_fixed(png_structp png_ptr, png_fixed_point white_x, - png_fixed_point white_y, png_fixed_point red_x, png_fixed_point red_y, - png_fixed_point green_x, png_fixed_point green_y, png_fixed_point blue_x, - png_fixed_point blue_y) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_cHRM; -#endif - png_byte buf[32]; - - png_debug(1, "in png_write_cHRM\n"); - /* each value is saved in 1/100,000ths */ - if (white_x > 80000L || white_y > 80000L || white_x + white_y > 100000L) - { - png_warning(png_ptr, "Invalid fixed cHRM white point specified"); -#if !defined(PNG_NO_CONSOLE_IO) - fprintf(stderr,"white_x=%ld, white_y=%ld\n",white_x, white_y); -#endif - return; - } - png_save_uint_32(buf, (png_uint_32)white_x); - png_save_uint_32(buf + 4, (png_uint_32)white_y); - - if (red_x + red_y > 100000L) - { - png_warning(png_ptr, "Invalid cHRM fixed red point specified"); - return; - } - png_save_uint_32(buf + 8, (png_uint_32)red_x); - png_save_uint_32(buf + 12, (png_uint_32)red_y); - - if (green_x + green_y > 100000L) - { - png_warning(png_ptr, "Invalid fixed cHRM green point specified"); - return; - } - png_save_uint_32(buf + 16, (png_uint_32)green_x); - png_save_uint_32(buf + 20, (png_uint_32)green_y); - - if (blue_x + blue_y > 100000L) - { - png_warning(png_ptr, "Invalid fixed cHRM blue point specified"); - return; - } - png_save_uint_32(buf + 24, (png_uint_32)blue_x); - png_save_uint_32(buf + 28, (png_uint_32)blue_y); - - png_write_chunk(png_ptr, png_cHRM, buf, (png_size_t)32); -} -#endif -#endif - -#if defined(PNG_WRITE_tRNS_SUPPORTED) -/* write the tRNS chunk */ -void /* PRIVATE */ -png_write_tRNS(png_structp png_ptr, png_bytep trans, png_color_16p tran, - int num_trans, int color_type) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_tRNS; -#endif - png_byte buf[6]; - - png_debug(1, "in png_write_tRNS\n"); - if (color_type == PNG_COLOR_TYPE_PALETTE) - { - if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette) - { - png_warning(png_ptr,"Invalid number of transparent colors specified"); - return; - } - /* write the chunk out as it is */ - png_write_chunk(png_ptr, png_tRNS, trans, (png_size_t)num_trans); - } - else if (color_type == PNG_COLOR_TYPE_GRAY) - { - /* one 16 bit value */ - if(tran->gray >= (1 << png_ptr->bit_depth)) - { - png_warning(png_ptr, - "Ignoring attempt to write tRNS chunk out-of-range for bit_depth"); - return; - } - png_save_uint_16(buf, tran->gray); - png_write_chunk(png_ptr, png_tRNS, buf, (png_size_t)2); - } - else if (color_type == PNG_COLOR_TYPE_RGB) - { - /* three 16 bit values */ - png_save_uint_16(buf, tran->red); - png_save_uint_16(buf + 2, tran->green); - png_save_uint_16(buf + 4, tran->blue); - if(png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) - { - png_warning(png_ptr, - "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8"); - return; - } - png_write_chunk(png_ptr, png_tRNS, buf, (png_size_t)6); - } - else - { - png_warning(png_ptr, "Can't write tRNS with an alpha channel"); - } -} -#endif - -#if defined(PNG_WRITE_bKGD_SUPPORTED) -/* write the background chunk */ -void /* PRIVATE */ -png_write_bKGD(png_structp png_ptr, png_color_16p back, int color_type) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_bKGD; -#endif - png_byte buf[6]; - - png_debug(1, "in png_write_bKGD\n"); - if (color_type == PNG_COLOR_TYPE_PALETTE) - { - if ( -#if defined(PNG_MNG_FEATURES_SUPPORTED) - (png_ptr->num_palette || - (!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE))) && -#endif - back->index > png_ptr->num_palette) - { - png_warning(png_ptr, "Invalid background palette index"); - return; - } - buf[0] = back->index; - png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)1); - } - else if (color_type & PNG_COLOR_MASK_COLOR) - { - png_save_uint_16(buf, back->red); - png_save_uint_16(buf + 2, back->green); - png_save_uint_16(buf + 4, back->blue); - if(png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) - { - png_warning(png_ptr, - "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8"); - return; - } - png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)6); - } - else - { - if(back->gray >= (1 << png_ptr->bit_depth)) - { - png_warning(png_ptr, - "Ignoring attempt to write bKGD chunk out-of-range for bit_depth"); - return; - } - png_save_uint_16(buf, back->gray); - png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)2); - } -} -#endif - -#if defined(PNG_WRITE_hIST_SUPPORTED) -/* write the histogram */ -void /* PRIVATE */ -png_write_hIST(png_structp png_ptr, png_uint_16p hist, int num_hist) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_hIST; -#endif - int i; - png_byte buf[3]; - - png_debug(1, "in png_write_hIST\n"); - if (num_hist > (int)png_ptr->num_palette) - { - png_debug2(3, "num_hist = %d, num_palette = %d\n", num_hist, - png_ptr->num_palette); - png_warning(png_ptr, "Invalid number of histogram entries specified"); - return; - } - - png_write_chunk_start(png_ptr, png_hIST, (png_uint_32)(num_hist * 2)); - for (i = 0; i < num_hist; i++) - { - png_save_uint_16(buf, hist[i]); - png_write_chunk_data(png_ptr, buf, (png_size_t)2); - } - png_write_chunk_end(png_ptr); -} -#endif - -#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \ - defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) -/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification, - * and if invalid, correct the keyword rather than discarding the entire - * chunk. The PNG 1.0 specification requires keywords 1-79 characters in - * length, forbids leading or trailing whitespace, multiple internal spaces, - * and the non-break space (0x80) from ISO 8859-1. Returns keyword length. - * - * The new_key is allocated to hold the corrected keyword and must be freed - * by the calling routine. This avoids problems with trying to write to - * static keywords without having to have duplicate copies of the strings. - */ -png_size_t /* PRIVATE */ -png_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key) -{ - png_size_t key_len; - png_charp kp, dp; - int kflag; - int kwarn=0; - - png_debug(1, "in png_check_keyword\n"); - *new_key = NULL; - - if (key == NULL || (key_len = png_strlen(key)) == 0) - { - png_warning(png_ptr, "zero length keyword"); - return ((png_size_t)0); - } - - png_debug1(2, "Keyword to be checked is '%s'\n", key); - - *new_key = (png_charp)png_malloc_warn(png_ptr, (png_uint_32)(key_len + 2)); - if (*new_key == NULL) - { - png_warning(png_ptr, "Out of memory while procesing keyword"); - return ((png_size_t)0); - } - - /* Replace non-printing characters with a blank and print a warning */ - for (kp = key, dp = *new_key; *kp != '\0'; kp++, dp++) - { - if ((png_byte)*kp < 0x20 || - ((png_byte)*kp > 0x7E && (png_byte)*kp < 0xA1)) - { -#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) - char msg[40]; - - png_snprintf(msg, 40, - "invalid keyword character 0x%02X", (png_byte)*kp); - png_warning(png_ptr, msg); -#else - png_warning(png_ptr, "invalid character in keyword"); -#endif - *dp = ' '; - } - else - { - *dp = *kp; - } - } - *dp = '\0'; - - /* Remove any trailing white space. */ - kp = *new_key + key_len - 1; - if (*kp == ' ') - { - png_warning(png_ptr, "trailing spaces removed from keyword"); - - while (*kp == ' ') - { - *(kp--) = '\0'; - key_len--; - } - } - - /* Remove any leading white space. */ - kp = *new_key; - if (*kp == ' ') - { - png_warning(png_ptr, "leading spaces removed from keyword"); - - while (*kp == ' ') - { - kp++; - key_len--; - } - } - - png_debug1(2, "Checking for multiple internal spaces in '%s'\n", kp); - - /* Remove multiple internal spaces. */ - for (kflag = 0, dp = *new_key; *kp != '\0'; kp++) - { - if (*kp == ' ' && kflag == 0) - { - *(dp++) = *kp; - kflag = 1; - } - else if (*kp == ' ') - { - key_len--; - kwarn=1; - } - else - { - *(dp++) = *kp; - kflag = 0; - } - } - *dp = '\0'; - if(kwarn) - png_warning(png_ptr, "extra interior spaces removed from keyword"); - - if (key_len == 0) - { - png_free(png_ptr, *new_key); - *new_key=NULL; - png_warning(png_ptr, "Zero length keyword"); - } - - if (key_len > 79) - { - png_warning(png_ptr, "keyword length must be 1 - 79 characters"); - new_key[79] = '\0'; - key_len = 79; - } - - return (key_len); -} -#endif - -#if defined(PNG_WRITE_tEXt_SUPPORTED) -/* write a tEXt chunk */ -void /* PRIVATE */ -png_write_tEXt(png_structp png_ptr, png_charp key, png_charp text, - png_size_t text_len) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_tEXt; -#endif - png_size_t key_len; - png_charp new_key; - - png_debug(1, "in png_write_tEXt\n"); - if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0) - { - png_warning(png_ptr, "Empty keyword in tEXt chunk"); - return; - } - - if (text == NULL || *text == '\0') - text_len = 0; - else - text_len = png_strlen(text); - - /* make sure we include the 0 after the key */ - png_write_chunk_start(png_ptr, png_tEXt, (png_uint_32)key_len+text_len+1); - /* - * We leave it to the application to meet PNG-1.0 requirements on the - * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of - * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. - * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. - */ - png_write_chunk_data(png_ptr, (png_bytep)new_key, key_len + 1); - if (text_len) - png_write_chunk_data(png_ptr, (png_bytep)text, text_len); - - png_write_chunk_end(png_ptr); - png_free(png_ptr, new_key); -} -#endif - -#if defined(PNG_WRITE_zTXt_SUPPORTED) -/* write a compressed text chunk */ -void /* PRIVATE */ -png_write_zTXt(png_structp png_ptr, png_charp key, png_charp text, - png_size_t text_len, int compression) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_zTXt; -#endif - png_size_t key_len; - char buf[1]; - png_charp new_key; - compression_state comp; - - png_debug(1, "in png_write_zTXt\n"); - - comp.num_output_ptr = 0; - comp.max_output_ptr = 0; - comp.output_ptr = NULL; - comp.input = NULL; - comp.input_len = 0; - - if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0) - { - png_warning(png_ptr, "Empty keyword in zTXt chunk"); - return; - } - - if (text == NULL || *text == '\0' || compression==PNG_TEXT_COMPRESSION_NONE) - { - png_write_tEXt(png_ptr, new_key, text, (png_size_t)0); - png_free(png_ptr, new_key); - return; - } - - text_len = png_strlen(text); - - /* compute the compressed data; do it now for the length */ - text_len = png_text_compress(png_ptr, text, text_len, compression, - &comp); - - /* write start of chunk */ - png_write_chunk_start(png_ptr, png_zTXt, (png_uint_32) - (key_len+text_len+2)); - /* write key */ - png_write_chunk_data(png_ptr, (png_bytep)new_key, key_len + 1); - png_free(png_ptr, new_key); - - buf[0] = (png_byte)compression; - /* write compression */ - png_write_chunk_data(png_ptr, (png_bytep)buf, (png_size_t)1); - /* write the compressed data */ - png_write_compressed_data_out(png_ptr, &comp); - - /* close the chunk */ - png_write_chunk_end(png_ptr); -} -#endif - -#if defined(PNG_WRITE_iTXt_SUPPORTED) -/* write an iTXt chunk */ -void /* PRIVATE */ -png_write_iTXt(png_structp png_ptr, int compression, png_charp key, - png_charp lang, png_charp lang_key, png_charp text) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_iTXt; -#endif - png_size_t lang_len, key_len, lang_key_len, text_len; - png_charp new_lang, new_key; - png_byte cbuf[2]; - compression_state comp; - - png_debug(1, "in png_write_iTXt\n"); - - comp.num_output_ptr = 0; - comp.max_output_ptr = 0; - comp.output_ptr = NULL; - comp.input = NULL; - - if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0) - { - png_warning(png_ptr, "Empty keyword in iTXt chunk"); - return; - } - if (lang == NULL || (lang_len = png_check_keyword(png_ptr, lang, &new_lang))==0) - { - png_warning(png_ptr, "Empty language field in iTXt chunk"); - new_lang = NULL; - lang_len = 0; - } - - if (lang_key == NULL) - lang_key_len = 0; - else - lang_key_len = png_strlen(lang_key); - - if (text == NULL) - text_len = 0; - else - text_len = png_strlen(text); - - /* compute the compressed data; do it now for the length */ - text_len = png_text_compress(png_ptr, text, text_len, compression-2, - &comp); - - - /* make sure we include the compression flag, the compression byte, - * and the NULs after the key, lang, and lang_key parts */ - - png_write_chunk_start(png_ptr, png_iTXt, - (png_uint_32)( - 5 /* comp byte, comp flag, terminators for key, lang and lang_key */ - + key_len - + lang_len - + lang_key_len - + text_len)); - - /* - * We leave it to the application to meet PNG-1.0 requirements on the - * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of - * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. - * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. - */ - png_write_chunk_data(png_ptr, (png_bytep)new_key, key_len + 1); - - /* set the compression flag */ - if (compression == PNG_ITXT_COMPRESSION_NONE || \ - compression == PNG_TEXT_COMPRESSION_NONE) - cbuf[0] = 0; - else /* compression == PNG_ITXT_COMPRESSION_zTXt */ - cbuf[0] = 1; - /* set the compression method */ - cbuf[1] = 0; - png_write_chunk_data(png_ptr, cbuf, 2); - - cbuf[0] = 0; - png_write_chunk_data(png_ptr, (new_lang ? (png_bytep)new_lang : cbuf), lang_len + 1); - png_write_chunk_data(png_ptr, (lang_key ? (png_bytep)lang_key : cbuf), lang_key_len + 1); - png_write_compressed_data_out(png_ptr, &comp); - - png_write_chunk_end(png_ptr); - png_free(png_ptr, new_key); - if (new_lang) - png_free(png_ptr, new_lang); -} -#endif - -#if defined(PNG_WRITE_oFFs_SUPPORTED) -/* write the oFFs chunk */ -void /* PRIVATE */ -png_write_oFFs(png_structp png_ptr, png_int_32 x_offset, png_int_32 y_offset, - int unit_type) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_oFFs; -#endif - png_byte buf[9]; - - png_debug(1, "in png_write_oFFs\n"); - if (unit_type >= PNG_OFFSET_LAST) - png_warning(png_ptr, "Unrecognized unit type for oFFs chunk"); - - png_save_int_32(buf, x_offset); - png_save_int_32(buf + 4, y_offset); - buf[8] = (png_byte)unit_type; - - png_write_chunk(png_ptr, png_oFFs, buf, (png_size_t)9); -} -#endif -#if defined(PNG_WRITE_pCAL_SUPPORTED) -/* write the pCAL chunk (described in the PNG extensions document) */ -void /* PRIVATE */ -png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0, - png_int_32 X1, int type, int nparams, png_charp units, png_charpp params) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_pCAL; -#endif - png_size_t purpose_len, units_len, total_len; - png_uint_32p params_len; - png_byte buf[10]; - png_charp new_purpose; - int i; - - png_debug1(1, "in png_write_pCAL (%d parameters)\n", nparams); - if (type >= PNG_EQUATION_LAST) - png_warning(png_ptr, "Unrecognized equation type for pCAL chunk"); - - purpose_len = png_check_keyword(png_ptr, purpose, &new_purpose) + 1; - png_debug1(3, "pCAL purpose length = %d\n", (int)purpose_len); - units_len = png_strlen(units) + (nparams == 0 ? 0 : 1); - png_debug1(3, "pCAL units length = %d\n", (int)units_len); - total_len = purpose_len + units_len + 10; - - params_len = (png_uint_32p)png_malloc(png_ptr, (png_uint_32)(nparams - *png_sizeof(png_uint_32))); - - /* Find the length of each parameter, making sure we don't count the - null terminator for the last parameter. */ - for (i = 0; i < nparams; i++) - { - params_len[i] = png_strlen(params[i]) + (i == nparams - 1 ? 0 : 1); - png_debug2(3, "pCAL parameter %d length = %lu\n", i, params_len[i]); - total_len += (png_size_t)params_len[i]; - } - - png_debug1(3, "pCAL total length = %d\n", (int)total_len); - png_write_chunk_start(png_ptr, png_pCAL, (png_uint_32)total_len); - png_write_chunk_data(png_ptr, (png_bytep)new_purpose, purpose_len); - png_save_int_32(buf, X0); - png_save_int_32(buf + 4, X1); - buf[8] = (png_byte)type; - buf[9] = (png_byte)nparams; - png_write_chunk_data(png_ptr, buf, (png_size_t)10); - png_write_chunk_data(png_ptr, (png_bytep)units, (png_size_t)units_len); - - png_free(png_ptr, new_purpose); - - for (i = 0; i < nparams; i++) - { - png_write_chunk_data(png_ptr, (png_bytep)params[i], - (png_size_t)params_len[i]); - } - - png_free(png_ptr, params_len); - png_write_chunk_end(png_ptr); -} -#endif - -#if defined(PNG_WRITE_sCAL_SUPPORTED) -/* write the sCAL chunk */ -#if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO) -void /* PRIVATE */ -png_write_sCAL(png_structp png_ptr, int unit, double width, double height) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_sCAL; -#endif - char buf[64]; - png_size_t total_len; - - png_debug(1, "in png_write_sCAL\n"); - - buf[0] = (char)unit; -#if defined(_WIN32_WCE) -/* sprintf() function is not supported on WindowsCE */ - { - wchar_t wc_buf[32]; - size_t wc_len; - swprintf(wc_buf, TEXT("%12.12e"), width); - wc_len = wcslen(wc_buf); - WideCharToMultiByte(CP_ACP, 0, wc_buf, -1, buf + 1, wc_len, NULL, NULL); - total_len = wc_len + 2; - swprintf(wc_buf, TEXT("%12.12e"), height); - wc_len = wcslen(wc_buf); - WideCharToMultiByte(CP_ACP, 0, wc_buf, -1, buf + total_len, wc_len, - NULL, NULL); - total_len += wc_len; - } -#else - png_snprintf(buf + 1, 63, "%12.12e", width); - total_len = 1 + png_strlen(buf + 1) + 1; - png_snprintf(buf + total_len, 64-total_len, "%12.12e", height); - total_len += png_strlen(buf + total_len); -#endif - - png_debug1(3, "sCAL total length = %u\n", (unsigned int)total_len); - png_write_chunk(png_ptr, png_sCAL, (png_bytep)buf, total_len); -} -#else -#ifdef PNG_FIXED_POINT_SUPPORTED -void /* PRIVATE */ -png_write_sCAL_s(png_structp png_ptr, int unit, png_charp width, - png_charp height) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_sCAL; -#endif - png_byte buf[64]; - png_size_t wlen, hlen, total_len; - - png_debug(1, "in png_write_sCAL_s\n"); - - wlen = png_strlen(width); - hlen = png_strlen(height); - total_len = wlen + hlen + 2; - if (total_len > 64) - { - png_warning(png_ptr, "Can't write sCAL (buffer too small)"); - return; - } - - buf[0] = (png_byte)unit; - png_memcpy(buf + 1, width, wlen + 1); /* append the '\0' here */ - png_memcpy(buf + wlen + 2, height, hlen); /* do NOT append the '\0' here */ - - png_debug1(3, "sCAL total length = %u\n", (unsigned int)total_len); - png_write_chunk(png_ptr, png_sCAL, buf, total_len); -} -#endif -#endif -#endif - -#if defined(PNG_WRITE_pHYs_SUPPORTED) -/* write the pHYs chunk */ -void /* PRIVATE */ -png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit, - png_uint_32 y_pixels_per_unit, - int unit_type) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_pHYs; -#endif - png_byte buf[9]; - - png_debug(1, "in png_write_pHYs\n"); - if (unit_type >= PNG_RESOLUTION_LAST) - png_warning(png_ptr, "Unrecognized unit type for pHYs chunk"); - - png_save_uint_32(buf, x_pixels_per_unit); - png_save_uint_32(buf + 4, y_pixels_per_unit); - buf[8] = (png_byte)unit_type; - - png_write_chunk(png_ptr, png_pHYs, buf, (png_size_t)9); -} -#endif - -#if defined(PNG_WRITE_tIME_SUPPORTED) -/* Write the tIME chunk. Use either png_convert_from_struct_tm() - * or png_convert_from_time_t(), or fill in the structure yourself. - */ -void /* PRIVATE */ -png_write_tIME(png_structp png_ptr, png_timep mod_time) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_tIME; -#endif - png_byte buf[7]; - - png_debug(1, "in png_write_tIME\n"); - if (mod_time->month > 12 || mod_time->month < 1 || - mod_time->day > 31 || mod_time->day < 1 || - mod_time->hour > 23 || mod_time->second > 60) - { - png_warning(png_ptr, "Invalid time specified for tIME chunk"); - return; - } - - png_save_uint_16(buf, mod_time->year); - buf[2] = mod_time->month; - buf[3] = mod_time->day; - buf[4] = mod_time->hour; - buf[5] = mod_time->minute; - buf[6] = mod_time->second; - - png_write_chunk(png_ptr, png_tIME, buf, (png_size_t)7); -} -#endif - -/* initializes the row writing capability of libpng */ -void /* PRIVATE */ -png_write_start_row(png_structp png_ptr) -{ -#ifdef PNG_WRITE_INTERLACING_SUPPORTED -#ifdef PNG_USE_LOCAL_ARRAYS - /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - - /* start of interlace block */ - int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; - - /* offset to next interlace block */ - int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; - - /* start of interlace block in the y direction */ - int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; - - /* offset to next interlace block in the y direction */ - int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; -#endif -#endif - - png_size_t buf_size; - - png_debug(1, "in png_write_start_row\n"); - buf_size = (png_size_t)(PNG_ROWBYTES( - png_ptr->usr_channels*png_ptr->usr_bit_depth,png_ptr->width)+1); - - /* set up row buffer */ - png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, (png_uint_32)buf_size); - png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE; - -#ifndef PNG_NO_WRITE_FILTERING - /* set up filtering buffer, if using this filter */ - if (png_ptr->do_filter & PNG_FILTER_SUB) - { - png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, - (png_ptr->rowbytes + 1)); - png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; - } - - /* We only need to keep the previous row if we are using one of these. */ - if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH)) - { - /* set up previous row buffer */ - png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)buf_size); - png_memset(png_ptr->prev_row, 0, buf_size); - - if (png_ptr->do_filter & PNG_FILTER_UP) - { - png_ptr->up_row = (png_bytep)png_malloc(png_ptr, - (png_ptr->rowbytes + 1)); - png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; - } - - if (png_ptr->do_filter & PNG_FILTER_AVG) - { - png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, - (png_ptr->rowbytes + 1)); - png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; - } - - if (png_ptr->do_filter & PNG_FILTER_PAETH) - { - png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr, - (png_ptr->rowbytes + 1)); - png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; - } -#endif /* PNG_NO_WRITE_FILTERING */ - } - -#ifdef PNG_WRITE_INTERLACING_SUPPORTED - /* if interlaced, we need to set up width and height of pass */ - if (png_ptr->interlaced) - { - if (!(png_ptr->transformations & PNG_INTERLACE)) - { - png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - - png_pass_ystart[0]) / png_pass_yinc[0]; - png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 - - png_pass_start[0]) / png_pass_inc[0]; - } - else - { - png_ptr->num_rows = png_ptr->height; - png_ptr->usr_width = png_ptr->width; - } - } - else -#endif - { - png_ptr->num_rows = png_ptr->height; - png_ptr->usr_width = png_ptr->width; - } - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - png_ptr->zstream.next_out = png_ptr->zbuf; -} - -/* Internal use only. Called when finished processing a row of data. */ -void /* PRIVATE */ -png_write_finish_row(png_structp png_ptr) -{ -#ifdef PNG_WRITE_INTERLACING_SUPPORTED -#ifdef PNG_USE_LOCAL_ARRAYS - /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - - /* start of interlace block */ - int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; - - /* offset to next interlace block */ - int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; - - /* start of interlace block in the y direction */ - int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; - - /* offset to next interlace block in the y direction */ - int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; -#endif -#endif - - int ret; - - png_debug(1, "in png_write_finish_row\n"); - /* next row */ - png_ptr->row_number++; - - /* see if we are done */ - if (png_ptr->row_number < png_ptr->num_rows) - return; - -#ifdef PNG_WRITE_INTERLACING_SUPPORTED - /* if interlaced, go to next pass */ - if (png_ptr->interlaced) - { - png_ptr->row_number = 0; - if (png_ptr->transformations & PNG_INTERLACE) - { - png_ptr->pass++; - } - else - { - /* loop until we find a non-zero width or height pass */ - do - { - png_ptr->pass++; - if (png_ptr->pass >= 7) - break; - png_ptr->usr_width = (png_ptr->width + - png_pass_inc[png_ptr->pass] - 1 - - png_pass_start[png_ptr->pass]) / - png_pass_inc[png_ptr->pass]; - png_ptr->num_rows = (png_ptr->height + - png_pass_yinc[png_ptr->pass] - 1 - - png_pass_ystart[png_ptr->pass]) / - png_pass_yinc[png_ptr->pass]; - if (png_ptr->transformations & PNG_INTERLACE) - break; - } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0); - - } - - /* reset the row above the image for the next pass */ - if (png_ptr->pass < 7) - { - if (png_ptr->prev_row != NULL) - png_memset(png_ptr->prev_row, 0, - (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels* - png_ptr->usr_bit_depth,png_ptr->width))+1); - return; - } - } -#endif - - /* if we get here, we've just written the last row, so we need - to flush the compressor */ - do - { - /* tell the compressor we are done */ - ret = deflate(&png_ptr->zstream, Z_FINISH); - /* check for an error */ - if (ret == Z_OK) - { - /* check to see if we need more room */ - if (!(png_ptr->zstream.avail_out)) - { - png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - } - } - else if (ret != Z_STREAM_END) - { - if (png_ptr->zstream.msg != NULL) - png_error(png_ptr, png_ptr->zstream.msg); - else - png_error(png_ptr, "zlib error"); - } - } while (ret != Z_STREAM_END); - - /* write any extra space */ - if (png_ptr->zstream.avail_out < png_ptr->zbuf_size) - { - png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size - - png_ptr->zstream.avail_out); - } - - deflateReset(&png_ptr->zstream); - png_ptr->zstream.data_type = Z_BINARY; -} - -#if defined(PNG_WRITE_INTERLACING_SUPPORTED) -/* Pick out the correct pixels for the interlace pass. - * The basic idea here is to go through the row with a source - * pointer and a destination pointer (sp and dp), and copy the - * correct pixels for the pass. As the row gets compacted, - * sp will always be >= dp, so we should never overwrite anything. - * See the default: case for the easiest code to understand. - */ -void /* PRIVATE */ -png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - - /* start of interlace block */ - int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; - - /* offset to next interlace block */ - int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; -#endif - - png_debug(1, "in png_do_write_interlace\n"); - /* we don't have to do anything on the last pass (6) */ -#if defined(PNG_USELESS_TESTS_SUPPORTED) - if (row != NULL && row_info != NULL && pass < 6) -#else - if (pass < 6) -#endif - { - /* each pixel depth is handled separately */ - switch (row_info->pixel_depth) - { - case 1: - { - png_bytep sp; - png_bytep dp; - int shift; - int d; - int value; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - dp = row; - d = 0; - shift = 7; - for (i = png_pass_start[pass]; i < row_width; - i += png_pass_inc[pass]) - { - sp = row + (png_size_t)(i >> 3); - value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01; - d |= (value << shift); - - if (shift == 0) - { - shift = 7; - *dp++ = (png_byte)d; - d = 0; - } - else - shift--; - - } - if (shift != 7) - *dp = (png_byte)d; - break; - } - case 2: - { - png_bytep sp; - png_bytep dp; - int shift; - int d; - int value; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - dp = row; - shift = 6; - d = 0; - for (i = png_pass_start[pass]; i < row_width; - i += png_pass_inc[pass]) - { - sp = row + (png_size_t)(i >> 2); - value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03; - d |= (value << shift); - - if (shift == 0) - { - shift = 6; - *dp++ = (png_byte)d; - d = 0; - } - else - shift -= 2; - } - if (shift != 6) - *dp = (png_byte)d; - break; - } - case 4: - { - png_bytep sp; - png_bytep dp; - int shift; - int d; - int value; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - dp = row; - shift = 4; - d = 0; - for (i = png_pass_start[pass]; i < row_width; - i += png_pass_inc[pass]) - { - sp = row + (png_size_t)(i >> 1); - value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f; - d |= (value << shift); - - if (shift == 0) - { - shift = 4; - *dp++ = (png_byte)d; - d = 0; - } - else - shift -= 4; - } - if (shift != 4) - *dp = (png_byte)d; - break; - } - default: - { - png_bytep sp; - png_bytep dp; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - png_size_t pixel_bytes; - - /* start at the beginning */ - dp = row; - /* find out how many bytes each pixel takes up */ - pixel_bytes = (row_info->pixel_depth >> 3); - /* loop through the row, only looking at the pixels that - matter */ - for (i = png_pass_start[pass]; i < row_width; - i += png_pass_inc[pass]) - { - /* find out where the original pixel is */ - sp = row + (png_size_t)i * pixel_bytes; - /* move the pixel */ - if (dp != sp) - png_memcpy(dp, sp, pixel_bytes); - /* next pixel */ - dp += pixel_bytes; - } - break; - } - } - /* set new row width */ - row_info->width = (row_info->width + - png_pass_inc[pass] - 1 - - png_pass_start[pass]) / - png_pass_inc[pass]; - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, - row_info->width); - } -} -#endif - -/* This filters the row, chooses which filter to use, if it has not already - * been specified by the application, and then writes the row out with the - * chosen filter. - */ -#define PNG_MAXSUM (((png_uint_32)(-1)) >> 1) -#define PNG_HISHIFT 10 -#define PNG_LOMASK ((png_uint_32)0xffffL) -#define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT)) -void /* PRIVATE */ -png_write_find_filter(png_structp png_ptr, png_row_infop row_info) -{ - png_bytep best_row; -#ifndef PNG_NO_WRITE_FILTER - png_bytep prev_row, row_buf; - png_uint_32 mins, bpp; - png_byte filter_to_do = png_ptr->do_filter; - png_uint_32 row_bytes = row_info->rowbytes; -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - int num_p_filters = (int)png_ptr->num_prev_filters; -#endif - - png_debug(1, "in png_write_find_filter\n"); - /* find out how many bytes offset each pixel is */ - bpp = (row_info->pixel_depth + 7) >> 3; - - prev_row = png_ptr->prev_row; -#endif - best_row = png_ptr->row_buf; -#ifndef PNG_NO_WRITE_FILTER - row_buf = best_row; - mins = PNG_MAXSUM; - - /* The prediction method we use is to find which method provides the - * smallest value when summing the absolute values of the distances - * from zero, using anything >= 128 as negative numbers. This is known - * as the "minimum sum of absolute differences" heuristic. Other - * heuristics are the "weighted minimum sum of absolute differences" - * (experimental and can in theory improve compression), and the "zlib - * predictive" method (not implemented yet), which does test compressions - * of lines using different filter methods, and then chooses the - * (series of) filter(s) that give minimum compressed data size (VERY - * computationally expensive). - * - * GRR 980525: consider also - * (1) minimum sum of absolute differences from running average (i.e., - * keep running sum of non-absolute differences & count of bytes) - * [track dispersion, too? restart average if dispersion too large?] - * (1b) minimum sum of absolute differences from sliding average, probably - * with window size <= deflate window (usually 32K) - * (2) minimum sum of squared differences from zero or running average - * (i.e., ~ root-mean-square approach) - */ - - - /* We don't need to test the 'no filter' case if this is the only filter - * that has been chosen, as it doesn't actually do anything to the data. - */ - if ((filter_to_do & PNG_FILTER_NONE) && - filter_to_do != PNG_FILTER_NONE) - { - png_bytep rp; - png_uint_32 sum = 0; - png_uint_32 i; - int v; - - for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++) - { - v = *rp; - sum += (v < 128) ? v : 256 - v; - } - -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - png_uint_32 sumhi, sumlo; - int j; - sumlo = sum & PNG_LOMASK; - sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */ - - /* Reduce the sum if we match any of the previous rows */ - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) - { - sumlo = (sumlo * png_ptr->filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - sumhi = (sumhi * png_ptr->filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } - - /* Factor in the cost of this filter (this is here for completeness, - * but it makes no sense to have a "cost" for the NONE filter, as - * it has the minimum possible computational cost - none). - */ - sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> - PNG_COST_SHIFT; - sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> - PNG_COST_SHIFT; - - if (sumhi > PNG_HIMASK) - sum = PNG_MAXSUM; - else - sum = (sumhi << PNG_HISHIFT) + sumlo; - } -#endif - mins = sum; - } - - /* sub filter */ - if (filter_to_do == PNG_FILTER_SUB) - /* it's the only filter so no testing is needed */ - { - png_bytep rp, lp, dp; - png_uint_32 i; - for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; - i++, rp++, dp++) - { - *dp = *rp; - } - for (lp = row_buf + 1; i < row_bytes; - i++, rp++, lp++, dp++) - { - *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); - } - best_row = png_ptr->sub_row; - } - - else if (filter_to_do & PNG_FILTER_SUB) - { - png_bytep rp, dp, lp; - png_uint_32 sum = 0, lmins = mins; - png_uint_32 i; - int v; - -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - /* We temporarily increase the "minimum sum" by the factor we - * would reduce the sum of this filter, so that we can do the - * early exit comparison without scaling the sum each time. - */ - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int j; - png_uint_32 lmhi, lmlo; - lmlo = lmins & PNG_LOMASK; - lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; - - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) - { - lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } - - lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> - PNG_COST_SHIFT; - lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> - PNG_COST_SHIFT; - - if (lmhi > PNG_HIMASK) - lmins = PNG_MAXSUM; - else - lmins = (lmhi << PNG_HISHIFT) + lmlo; - } -#endif - - for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; - i++, rp++, dp++) - { - v = *dp = *rp; - - sum += (v < 128) ? v : 256 - v; - } - for (lp = row_buf + 1; i < row_bytes; - i++, rp++, lp++, dp++) - { - v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); - - sum += (v < 128) ? v : 256 - v; - - if (sum > lmins) /* We are already worse, don't continue. */ - break; - } - -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int j; - png_uint_32 sumhi, sumlo; - sumlo = sum & PNG_LOMASK; - sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; - - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) - { - sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } - - sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> - PNG_COST_SHIFT; - sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> - PNG_COST_SHIFT; - - if (sumhi > PNG_HIMASK) - sum = PNG_MAXSUM; - else - sum = (sumhi << PNG_HISHIFT) + sumlo; - } -#endif - - if (sum < mins) - { - mins = sum; - best_row = png_ptr->sub_row; - } - } - - /* up filter */ - if (filter_to_do == PNG_FILTER_UP) - { - png_bytep rp, dp, pp; - png_uint_32 i; - - for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, - pp = prev_row + 1; i < row_bytes; - i++, rp++, pp++, dp++) - { - *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff); - } - best_row = png_ptr->up_row; - } - - else if (filter_to_do & PNG_FILTER_UP) - { - png_bytep rp, dp, pp; - png_uint_32 sum = 0, lmins = mins; - png_uint_32 i; - int v; - - -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int j; - png_uint_32 lmhi, lmlo; - lmlo = lmins & PNG_LOMASK; - lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; - - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) - { - lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } - - lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> - PNG_COST_SHIFT; - lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> - PNG_COST_SHIFT; - - if (lmhi > PNG_HIMASK) - lmins = PNG_MAXSUM; - else - lmins = (lmhi << PNG_HISHIFT) + lmlo; - } -#endif - - for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, - pp = prev_row + 1; i < row_bytes; i++) - { - v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); - - sum += (v < 128) ? v : 256 - v; - - if (sum > lmins) /* We are already worse, don't continue. */ - break; - } - -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int j; - png_uint_32 sumhi, sumlo; - sumlo = sum & PNG_LOMASK; - sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; - - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) - { - sumlo = (sumlo * png_ptr->filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - sumhi = (sumhi * png_ptr->filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } - - sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> - PNG_COST_SHIFT; - sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> - PNG_COST_SHIFT; - - if (sumhi > PNG_HIMASK) - sum = PNG_MAXSUM; - else - sum = (sumhi << PNG_HISHIFT) + sumlo; - } -#endif - - if (sum < mins) - { - mins = sum; - best_row = png_ptr->up_row; - } - } - - /* avg filter */ - if (filter_to_do == PNG_FILTER_AVG) - { - png_bytep rp, dp, pp, lp; - png_uint_32 i; - for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, - pp = prev_row + 1; i < bpp; i++) - { - *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); - } - for (lp = row_buf + 1; i < row_bytes; i++) - { - *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) - & 0xff); - } - best_row = png_ptr->avg_row; - } - - else if (filter_to_do & PNG_FILTER_AVG) - { - png_bytep rp, dp, pp, lp; - png_uint_32 sum = 0, lmins = mins; - png_uint_32 i; - int v; - -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int j; - png_uint_32 lmhi, lmlo; - lmlo = lmins & PNG_LOMASK; - lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; - - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG) - { - lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } - - lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> - PNG_COST_SHIFT; - lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> - PNG_COST_SHIFT; - - if (lmhi > PNG_HIMASK) - lmins = PNG_MAXSUM; - else - lmins = (lmhi << PNG_HISHIFT) + lmlo; - } -#endif - - for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, - pp = prev_row + 1; i < bpp; i++) - { - v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); - - sum += (v < 128) ? v : 256 - v; - } - for (lp = row_buf + 1; i < row_bytes; i++) - { - v = *dp++ = - (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff); - - sum += (v < 128) ? v : 256 - v; - - if (sum > lmins) /* We are already worse, don't continue. */ - break; - } - -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int j; - png_uint_32 sumhi, sumlo; - sumlo = sum & PNG_LOMASK; - sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; - - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) - { - sumlo = (sumlo * png_ptr->filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - sumhi = (sumhi * png_ptr->filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } - - sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> - PNG_COST_SHIFT; - sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> - PNG_COST_SHIFT; - - if (sumhi > PNG_HIMASK) - sum = PNG_MAXSUM; - else - sum = (sumhi << PNG_HISHIFT) + sumlo; - } -#endif - - if (sum < mins) - { - mins = sum; - best_row = png_ptr->avg_row; - } - } - - /* Paeth filter */ - if (filter_to_do == PNG_FILTER_PAETH) - { - png_bytep rp, dp, pp, cp, lp; - png_uint_32 i; - for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, - pp = prev_row + 1; i < bpp; i++) - { - *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); - } - - for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) - { - int a, b, c, pa, pb, pc, p; - - b = *pp++; - c = *cp++; - a = *lp++; - - p = b - c; - pc = a - c; - -#ifdef PNG_USE_ABS - pa = abs(p); - pb = abs(pc); - pc = abs(p + pc); -#else - pa = p < 0 ? -p : p; - pb = pc < 0 ? -pc : pc; - pc = (p + pc) < 0 ? -(p + pc) : p + pc; -#endif - - p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; - - *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); - } - best_row = png_ptr->paeth_row; - } - - else if (filter_to_do & PNG_FILTER_PAETH) - { - png_bytep rp, dp, pp, cp, lp; - png_uint_32 sum = 0, lmins = mins; - png_uint_32 i; - int v; - -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int j; - png_uint_32 lmhi, lmlo; - lmlo = lmins & PNG_LOMASK; - lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; - - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) - { - lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } - - lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> - PNG_COST_SHIFT; - lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> - PNG_COST_SHIFT; - - if (lmhi > PNG_HIMASK) - lmins = PNG_MAXSUM; - else - lmins = (lmhi << PNG_HISHIFT) + lmlo; - } -#endif - - for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, - pp = prev_row + 1; i < bpp; i++) - { - v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); - - sum += (v < 128) ? v : 256 - v; - } - - for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) - { - int a, b, c, pa, pb, pc, p; - - b = *pp++; - c = *cp++; - a = *lp++; - -#ifndef PNG_SLOW_PAETH - p = b - c; - pc = a - c; -#ifdef PNG_USE_ABS - pa = abs(p); - pb = abs(pc); - pc = abs(p + pc); -#else - pa = p < 0 ? -p : p; - pb = pc < 0 ? -pc : pc; - pc = (p + pc) < 0 ? -(p + pc) : p + pc; -#endif - p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; -#else /* PNG_SLOW_PAETH */ - p = a + b - c; - pa = abs(p - a); - pb = abs(p - b); - pc = abs(p - c); - if (pa <= pb && pa <= pc) - p = a; - else if (pb <= pc) - p = b; - else - p = c; -#endif /* PNG_SLOW_PAETH */ - - v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); - - sum += (v < 128) ? v : 256 - v; - - if (sum > lmins) /* We are already worse, don't continue. */ - break; - } - -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int j; - png_uint_32 sumhi, sumlo; - sumlo = sum & PNG_LOMASK; - sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; - - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) - { - sumlo = (sumlo * png_ptr->filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - sumhi = (sumhi * png_ptr->filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } - - sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> - PNG_COST_SHIFT; - sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> - PNG_COST_SHIFT; - - if (sumhi > PNG_HIMASK) - sum = PNG_MAXSUM; - else - sum = (sumhi << PNG_HISHIFT) + sumlo; - } -#endif - - if (sum < mins) - { - best_row = png_ptr->paeth_row; - } - } -#endif /* PNG_NO_WRITE_FILTER */ - /* Do the actual writing of the filtered row data from the chosen filter. */ - - png_write_filtered_row(png_ptr, best_row); - -#ifndef PNG_NO_WRITE_FILTER -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - /* Save the type of filter we picked this time for future calculations */ - if (png_ptr->num_prev_filters > 0) - { - int j; - for (j = 1; j < num_p_filters; j++) - { - png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1]; - } - png_ptr->prev_filters[j] = best_row[0]; - } -#endif -#endif /* PNG_NO_WRITE_FILTER */ -} - - -/* Do the actual writing of a previously filtered row. */ -void /* PRIVATE */ -png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row) -{ - png_debug(1, "in png_write_filtered_row\n"); - png_debug1(2, "filter = %d\n", filtered_row[0]); - /* set up the zlib input buffer */ - - png_ptr->zstream.next_in = filtered_row; - png_ptr->zstream.avail_in = (uInt)png_ptr->row_info.rowbytes + 1; - /* repeat until we have compressed all the data */ - do - { - int ret; /* return of zlib */ - - /* compress the data */ - ret = deflate(&png_ptr->zstream, Z_NO_FLUSH); - /* check for compression errors */ - if (ret != Z_OK) - { - if (png_ptr->zstream.msg != NULL) - png_error(png_ptr, png_ptr->zstream.msg); - else - png_error(png_ptr, "zlib error"); - } - - /* see if it is time to write another IDAT */ - if (!(png_ptr->zstream.avail_out)) - { - /* write the IDAT and reset the zlib output buffer */ - png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - } - /* repeat until all data has been compressed */ - } while (png_ptr->zstream.avail_in); - - /* swap the current and previous rows */ - if (png_ptr->prev_row != NULL) - { - png_bytep tptr; - - tptr = png_ptr->prev_row; - png_ptr->prev_row = png_ptr->row_buf; - png_ptr->row_buf = tptr; - } - - /* finish row - updates counters and flushes zlib if last row */ - png_write_finish_row(png_ptr); - -#if defined(PNG_WRITE_FLUSH_SUPPORTED) - png_ptr->flush_rows++; - - if (png_ptr->flush_dist > 0 && - png_ptr->flush_rows >= png_ptr->flush_dist) - { - png_write_flush(png_ptr); - } -#endif -} -#endif /* PNG_WRITE_SUPPORTED */ diff --git a/uppdev/plugin/png/png.h b/uppdev/plugin/png/png.h deleted file mode 100644 index 059e4e039..000000000 --- a/uppdev/plugin/png/png.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef __nDraw_plugin_png__ -#define __nDraw_plugin_png__ - -#include - -NAMESPACE_UPP - -class PNGRaster : public StreamRaster { - class Data; - One data; - -public: - PNGRaster(); - ~PNGRaster(); - - virtual bool Create(); - virtual Size GetSize(); - virtual Info GetInfo(); - virtual Line GetLine(int line); - virtual const RGBA *GetPalette(); - virtual const RasterFormat *GetFormat(); - -private: - bool Init(); -}; - -class PNGEncoder : public StreamRasterEncoder { - class Data; - One data; - -public: - PNGEncoder(int bpp = 32, ImageKind kind = IMAGE_UNKNOWN, bool interlace = false); - ~PNGEncoder(); - - virtual int GetPaletteCount(); - virtual void Start(Size sz); - virtual void WriteLineRaw(const byte *data); - - PNGEncoder& Bpp(int b) { bpp = b; return *this; } - PNGEncoder& Interlace(int b = true) { interlace = b; return *this; } - -private: - int bpp; - ImageKind kind; - bool interlace; -}; - -END_UPP_NAMESPACE - -#endif diff --git a/uppdev/plugin/png/png.upp b/uppdev/plugin/png/png.upp deleted file mode 100644 index 803d5ab7d..000000000 --- a/uppdev/plugin/png/png.upp +++ /dev/null @@ -1,60 +0,0 @@ -description "PNG image file format U++ encapsulation\3770,128,128"; - -uses - Core, - Draw; - -library(!WIN32) png; - -options - -DPNG_NO_READ_SHIFT, - -DPNG_NO_READ_SWAP, - -DPNG_NO_READ_INVERT, - -DPNG_NO_READ_DITHER, - -DPNG_NO_READ_BACKGROUND, - -DPNG_NO_READ_GAMMA, - -DPNG_NO_READ_SWAP_ALPHA, - -DPNG_NO_READ_INVERT_ALPHA, - -DPNG_NO_READ_STRIP_ALPHA, - -DPNG_NO_READ_USER_TRANSFORM, - -DPNG_NO_READ_RGB_TO_GRAY, - -DPNG_NO_PROGRESSIVE_READ, - -DPNG_NO_READ_COMPOSITE_NODIV, - -DPNG_NO_MNG_FEATURES, - -DPNG_NO_READ_EMPTY_PLTE, - -DPNG_NO_WRITE_SHIFT, - -DPNG_NO_WRITE_PACK, - -DPNG_NO_WRITE_SWAP, - -DPNG_NO_WRITE_PACKSWAP, - -DPNG_NO_WRITE_INVERT, - -DPNG_NO_WRITE_FILLER, - -DPNG_NO_WRITE_SWAP_ALPHA, - -DPNG_NO_WRITE_INVERT_ALPHA, - -DPNG_NO_USER_TRANSFORM_PTR, - -DPNG_NO_WRITE_EMPTY_PLTE, - -DPNG_NO_EASY_ACCESS, - -DPNG_NO_READ_bKGD, - -DPNG_NO_READ_cHRM, - -DPNG_NO_READ_gAMA, - -DPNG_NO_READ_iCCP, - -DPNG_NO_READ_oFFs, - -DPNG_NO_READ_pCAL, - -DPNG_NO_READ_sCAL, - -DPNG_NO_READ_sBIT, - -DPNG_NO_READ_sPLT, - -DPNG_NO_READ_sRGB, - -DPNG_NO_READ_tIME, - -DPNG_NO_READ_zTXt, - -DPNG_NO_READ_OPT_PLTE, - -DPNG_NO_INFO_IMAGE; - -options(MSC8ARM) "-D_WIN32_WCE -DARM -D_ARM_ -DUNDER_CE -DUNICODE -D_UNICODE"; - -file - png.h, - pnglib.c, - pngupp.cpp, - pngreg.icpp, - Info readonly separator, - Copying; - diff --git a/uppdev/plugin/png/pnglib.c b/uppdev/plugin/png/pnglib.c deleted file mode 100644 index 85f270a40..000000000 --- a/uppdev/plugin/png/pnglib.c +++ /dev/null @@ -1,24 +0,0 @@ -#ifdef flagWIN32 - -#define PNG_NO_MMX_CODE -#define PNG_USE_GLOBAL_ARRAYS - -#include "lib/png.c" -#include "lib/pngerror.c" -#include "lib/pnggccrd.c" -#include "lib/pngget.c" -#include "lib/pngmem.c" -#include "lib/pngpread.c" -#include "lib/pngread.c" -#include "lib/pngrio.c" -#include "lib/pngrtran.c" -#include "lib/pngrutil.c" -#include "lib/pngset.c" -#include "lib/pngtrans.c" -#include "lib/pngvcrd.c" -#include "lib/pngwio.c" -#include "lib/pngwrite.c" -#include "lib/pngwtran.c" -#include "lib/pngwutil.c" - -#endif diff --git a/uppdev/plugin/png/pngreg.icpp b/uppdev/plugin/png/pngreg.icpp deleted file mode 100644 index dc1ef44e2..000000000 --- a/uppdev/plugin/png/pngreg.icpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "png.h" - -NAMESPACE_UPP - -INITBLOCK { - StreamRaster::Register(); -} - -END_UPP_NAMESPACE diff --git a/uppdev/plugin/png/pngupp.cpp b/uppdev/plugin/png/pngupp.cpp deleted file mode 100644 index d3366d4a7..000000000 --- a/uppdev/plugin/png/pngupp.cpp +++ /dev/null @@ -1,497 +0,0 @@ -#ifdef flagWIN32 -#include -#else -#include -#endif - -#include -#include "png.h" - -NAMESPACE_UPP - -#define LLOG(x) // LOG(x) - -static void png_read_stream(png_structp png_ptr, png_bytep buffer, png_size_t length) -{ - Stream& stream = *reinterpret_cast(png_get_io_ptr(png_ptr)); - if(!stream.GetAll(buffer, (int)length)) - png_error(png_ptr, "Error reading input file!"); -} - -static void png_write_stream(png_structp png_ptr, png_bytep buffer, png_size_t length) -{ - Stream& stream = *reinterpret_cast(png_get_io_ptr(png_ptr)); - stream.Put(buffer, (int)length); -} - -static void png_flush_stream(png_structp png_ptr) -{ - Stream& stream = *reinterpret_cast(png_get_io_ptr(png_ptr)); - stream.Flush(); -} - -static void png_user_error_fn(png_structp png_ptr, png_const_charp error_msg) -{ - LLOG("PNG error: " << error_msg); -} - -static void png_user_warning_fn(png_structp png_ptr, png_const_charp warning_msg) -{ - LLOG("png warning: " << warning_msg); -} - -NTL_MOVEABLE(png_color) - -static Size GetDotSize(Size pixel_size, png_uint_32 x_ppm, png_uint_32 y_ppm, int unit_type) -{ - if(unit_type != 1 || !x_ppm || !y_ppm) - return Size(0, 0); - static const double DOTS_PER_METER = 6e5 / 25.4; - return Size( - fround(pixel_size.cx * (DOTS_PER_METER / x_ppm)), - fround(pixel_size.cy * (DOTS_PER_METER / y_ppm))); -} - -class PNGRaster::Data { -public: - Data(); - ~Data(); - -public: - png_structp png_ptr; - png_infop info_ptr; - - Info info; - Size size; - RasterFormat fmt; - RGBA palette[256]; - int out_bpp; - int row_bytes; - Vector preimage; - Buffer row_pointers; - bool preload; - bool loaded; - bool strip16; - int next_row; - int64 soff; -}; - -PNGRaster::Data::Data() -{ - png_ptr = NULL; - info_ptr = NULL; -} - -PNGRaster::Data::~Data() -{ - png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); -} - -PNGRaster::PNGRaster() -{ -} - -PNGRaster::~PNGRaster() -{ -} - -bool PNGRaster::Init() -{ - if(!(data->png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, - NULL, png_user_error_fn, png_user_warning_fn))) - return false; - if (setjmp(png_jmpbuf(data->png_ptr))) - return false; - if(!(data->info_ptr = png_create_info_struct(data->png_ptr))) - return false; - png_set_read_fn(data->png_ptr, &GetStream(), png_read_stream); - png_read_info(data->png_ptr, data->info_ptr); - return true; -} - -bool PNGRaster::Create() -{ - data = new Data; - - data->soff = GetStream().GetPos(); - if(!Init()) { - data.Clear(); - return false; - } - if (setjmp(png_jmpbuf(data->png_ptr))) { - data.Clear(); - return false; - } - png_uint_32 width, height; - int bit_depth, color_type, interlace_type; - png_get_IHDR(data->png_ptr, data->info_ptr, &width, &height, &bit_depth, &color_type, - &interlace_type, NULL, NULL); - - if(height <= 0 || width <= 0) - return false; - data->size.cx = width; - data->size.cy = height; - - png_uint_32 x_ppm = 0, y_ppm = 0; - int unit_type = 0; - png_get_pHYs(data->png_ptr, data->info_ptr, &x_ppm, &y_ppm, &unit_type); - data->info.bpp = bit_depth; - data->info.colors = (bit_depth < 8 ? 1 << bit_depth : 0); - data->info.dots = GetDotSize(data->size, x_ppm, y_ppm, unit_type); - data->info.hotspot = Point(0, 0); - data->info.kind = IMAGE_OPAQUE; - - data->out_bpp = bit_depth; - - data->strip16 = (bit_depth > 8); - if(data->strip16) { - png_set_strip_16(data->png_ptr); - data->out_bpp = 8; - } - - if(color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_RGB_ALPHA) { - ASSERT(bit_depth >= 8); - data->out_bpp = 24; - png_set_bgr(data->png_ptr); - if(color_type == PNG_COLOR_TYPE_RGB_ALPHA) { - data->out_bpp = 32; - data->info.kind = IMAGE_ALPHA; - } - } - - png_bytep trans_colors = 0; - png_color_16p trans_values = 0; - int num_trans = 0; - - png_get_tRNS(data->png_ptr, data->info_ptr, &trans_colors, &num_trans, &trans_values); -// bool has_mask = (num_trans > 0); - -// AlphaArray im(width, height, out_bpp, 4, NULL, Vector(), has_mask ? 8 : 0, 4); -// im.SetDotSize(GetDotSize(im.GetSize(), x_ppm, y_ppm, unit_type)); -// ASSERT(im.GetRowBytes() >= png_get_rowbytes(png_ptr, info_ptr)); - -// if((color_type & PNG_COLOR_MASK_PALETTE) || !(color_type & PNG_COLOR_MASK_COLOR)) - Fill(data->palette, RGBAZero(), 256); - if(color_type & PNG_COLOR_MASK_PALETTE) { - png_colorp ppal = 0; - int pal_count = 0; - png_get_PLTE(data->png_ptr, data->info_ptr, &ppal, &pal_count); - pal_count = min(pal_count, 1 << min(bit_depth, 8)); - for(int i = 0; i < pal_count; i++) { - png_color c = ppal[i]; - RGBA rgba; - rgba.r = c.red; - rgba.g = c.green; - rgba.b = c.blue; - rgba.a = 255; - data->palette[i] = rgba; - } - if(trans_colors) { - data->info.kind = IMAGE_MASK; - for(int i = 0; i < num_trans; i++) - data->palette[(int)trans_colors[i]] = RGBAZero(); - } - - } - else if(!(color_type & PNG_COLOR_MASK_COLOR)) { // grayscale - int colors = 1 << min(bit_depth, 8); - for(int i = 0; i < colors; i++) { - int level = i * 255 / (colors - 1); - RGBA rgba; - rgba.r = rgba.g = rgba.b = (byte)level; - rgba.a = 255; - data->palette[i] = rgba; - } - if(trans_colors) { - data->info.kind = IMAGE_MASK; - for(int i = 0; i < num_trans; i++) - data->palette[(int)trans_colors[i]] = RGBAZero(); - } - } - -/* - if (setjmp(png_jmpbuf(png_ptr))) { - png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); - return out; - } -*/ - - data->row_bytes = png_get_rowbytes(data->png_ptr, data->info_ptr); - data->next_row = 0; - data->preload = (interlace_type != PNG_INTERLACE_NONE); - data->loaded = false; - switch(data->out_bpp) { - case 1: data->fmt.Set1mf(); break; - case 2: data->fmt.Set2mf(); break; - case 4: data->fmt.Set4mf(); break; - case 8: if(color_type & PNG_COLOR_MASK_ALPHA) data->fmt.Set8A(); else data->fmt.Set8(); break; - case 24: data->fmt.Set24le(0xFF0000, 0xFF00, 0xFF); break; - case 32: data->fmt.SetRGBAStraight(); break; - default: NEVER(); return false; // invalid bpp - } - - return true; -} - -Size PNGRaster::GetSize() -{ - return data ? data->size : Size(0, 0); -} - -Raster::Info PNGRaster::GetInfo() -{ - return data ? data->info : Raster::Info(); -} - -Raster::Line PNGRaster::GetLine(int line) -{ - ASSERT(data && line >= 0 && line < data->size.cy); - byte *scanline = new byte[data->row_bytes]; - if(setjmp(png_jmpbuf(data->png_ptr))) - return Raster::Line(scanline, this, true); - if(data->preload) { - delete[] scanline; - if(!data->loaded) { - data->loaded = true; - data->preimage.SetCount(data->row_bytes * data->size.cy); - data->row_pointers.Alloc(data->size.cy); - for(int i = 0; i < data->size.cy; i++) - data->row_pointers[i] = &data->preimage[i * data->row_bytes]; - png_read_image(data->png_ptr, data->row_pointers); - } - const byte *rowdata = &data->preimage[data->row_bytes * line]; - return Raster::Line(rowdata, this, false); - } - else { - if(line < data->next_row) { - png_destroy_read_struct(&data->png_ptr, &data->info_ptr, NULL); - GetStream().Seek(data->soff); - if(!Init()) { - NEVER(); - } - if(data->strip16) - png_set_strip_16(data->png_ptr); - if(data->out_bpp > 8) - png_set_bgr(data->png_ptr); - data->next_row = 0; - } - while(data->next_row < line) { - png_read_row(data->png_ptr, scanline, NULL); - data->next_row++; - } - png_read_row(data->png_ptr, scanline, NULL); - data->next_row++; - return Raster::Line(scanline, this, true); - } -} - -const RGBA *PNGRaster::GetPalette() -{ - ASSERT(data); - return data->palette; -} - -const RasterFormat *PNGRaster::GetFormat() -{ - ASSERT(data); - return &data->fmt; -} - -class PNGEncoder::Data { -public: - Data(RasterFormat& format); - ~Data(); - - void Start(Stream& stream, Size size, int bpp, ImageKind kind, bool interlace, const RGBA *palette); - void WriteLineRaw(const byte *data); - -private: - RasterFormat& format; - - ImageKind kind; - - png_structp png_ptr; - png_infop info_ptr; - bool interlace; - bool do_palette; - bool do_mask; - bool do_alpha; - - Vector imagebuf; - Vector rowbuf; - Size size; - int rowbytes; - int linebytes; - int passes; - - int line; -}; - -PNGEncoder::Data::Data(RasterFormat& format) -: format(format) -{ - png_ptr = NULL; - info_ptr = NULL; -} - -PNGEncoder::Data::~Data() -{ - png_destroy_write_struct(&png_ptr, &info_ptr); -} - -void PNGEncoder::Data::Start(Stream& stream, Size size_, int bpp, ImageKind kind_, bool interlace_, - const RGBA *imgpal) -{ - size = size_; - kind = kind_; - interlace = interlace_; - - png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, png_user_error_fn, png_user_warning_fn); - if(!png_ptr) { - stream.SetError(); - return; - } - - /* Allocate/initialize the image information data. REQUIRED */ - info_ptr = png_create_info_struct(png_ptr); - if(!info_ptr) { - stream.SetError(); - return; - } - -/* - if (setjmp(png_jmpbuf(png_ptr))) { - png_destroy_write_struct(&png_ptr, &info_ptr); - sptr -> SetError(); - return; - } -*/ - png_set_write_fn(png_ptr, (void *)&stream, png_write_stream, png_flush_stream); - - int color_type, bit_depth; - Vector palette; - - do_alpha = (kind != IMAGE_OPAQUE && bpp != 1); - do_mask = (do_alpha && kind == IMAGE_MASK); - do_palette = (bpp <= 8); - - if(do_palette) { - switch(bpp) { - case 1: format.Set1mf(); break; - case 2: format.Set2mf(); break; - case 4: format.Set4mf(); break; - default: NEVER(); - case 8: format.Set8(); break; - } - bit_depth = bpp; - color_type = PNG_COLOR_TYPE_PALETTE; - palette.SetCount(1 << bpp); - for(int i = 0; i < palette.GetCount(); i++) { - png_color& c = palette[i]; - c.red = imgpal[i].r; - c.green = imgpal[i].g; - c.blue = imgpal[i].b; - } - rowbytes = (size.cx * bpp + 31) >> 5 << 2; - } - else { - color_type = (do_alpha ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB); - bit_depth = 8; - if(do_alpha) { - format.Set32leStraight(0xFF << 16, 0xFF << 8, 0xFF, 0xFF << 24); - rowbytes = 4 * size.cx; - } - else { - format.Set24le(0xFF << 16, 0xFF << 8, 0xFF); - rowbytes = (3 * size.cx + 3) & -4; - } - } - - png_set_IHDR(png_ptr, info_ptr, size.cx, size.cy, bit_depth, color_type, - interlace ? PNG_INTERLACE_ADAM7 : PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); - - if(!palette.IsEmpty()) - png_set_PLTE(png_ptr, info_ptr, palette.Begin(), palette.GetCount()); - - byte transpal = (1 << bpp) - 1; - if(do_mask && do_palette) { - png_color_16 transrgb = { 0, 0, 0 }; - png_set_tRNS(png_ptr, info_ptr, &transpal, 1, &transrgb); - } - -// png_set_gAMA(png_ptr, info_ptr, gamma); - - /* Optionally write comments into the image */ -// text_ptr[0].key = "Title"; -// text_ptr[0].text = "Mona Lisa"; -// text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE; - #ifdef PNG_iTXt_SUPPORTED - text_ptr[0].lang = NULL; - #endif -// png_set_text(png_ptr, info_ptr, text_ptr, 1); - - /* other optional chunks like cHRM, bKGD, tRNS, tIME, oFFs, pHYs, */ - /* note that if sRGB is present the gAMA and cHRM chunks must be ignored - * on read and must be written in accordance with the sRGB profile */ - - /* Write the file header information. REQUIRED */ - png_write_info(png_ptr, info_ptr); - - png_set_bgr(png_ptr); - - passes = png_set_interlace_handling(png_ptr); - rowbuf.SetCount(rowbytes); - if(passes > 1) - imagebuf.SetCount(rowbytes * size.cy); - - line = 0; - linebytes = format.GetByteCount(size.cx); -} - -void PNGEncoder::Data::WriteLineRaw(const byte *s) -{ - byte *dest = (passes > 1 ? &imagebuf[line * rowbytes] : rowbuf.Begin()); - memcpy(dest, s, linebytes); - png_write_row(png_ptr, dest); - if(++line >= size.cy) { - for(int p = 1; p < passes; p++) - for(int y = 0; y < size.cy; y++) - png_write_row(png_ptr, &imagebuf[y * rowbytes]); - - /* You can write optional chunks like tEXt, zTXt, and tIME at the end - * as well. Shouldn't be necessary in 1.1.0 and up as all the public - * chunks are supported and you can use png_set_unknown_chunks() to - * register unknown chunks into the info structure to be written out. - */ - - png_write_end(png_ptr, info_ptr); - } -} - -PNGEncoder::PNGEncoder(int bpp_, ImageKind kind_, bool interlace_) -: bpp(bpp_), kind(kind_), interlace(interlace_) -{ -} - -PNGEncoder::~PNGEncoder() -{ -} - -int PNGEncoder::GetPaletteCount() -{ - return (bpp > 8 ? 0 : (1 << bpp) - (kind == IMAGE_OPAQUE || bpp == 1 ? 0 : 1)); -} - -void PNGEncoder::Start(Size sz) -{ - data = new Data(format); - data->Start(GetStream(), sz, bpp, kind, interlace, bpp > 8 ? NULL : GetPalette()); -} - -void PNGEncoder::WriteLineRaw(const byte *s) -{ - data->WriteLineRaw(s); -} - -END_UPP_NAMESPACE