diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index bac6f6005..8fae44990 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -2,7 +2,7 @@ include: - template: 'Workflows/Branch-Pipelines.gitlab-ci.yml' - project: 'freedesktop/ci-templates' - ref: '7811ba9814a3bad379377241c6c6b62d78b20eac' + ref: '98b1218f146a1ec96d65e3ce0041f9a6ec5cb5e6' file: '/templates/fedora.yml' # From https://gitlab.freedesktop.org/freedesktop/ci-templates/-/blob/master/src/gitlab-ci.tmpl @@ -15,20 +15,29 @@ workflow: variables: FDO_UPSTREAM_REPO: 'cairo/cairo' - FDO_DISTRIBUTION_VERSION: '38' - FDO_DISTRIBUTION_TAG: '2023-04-29.1' + FDO_DISTRIBUTION_VERSION: '40' + FDO_DISTRIBUTION_TAG: '2025-03-12-android.0' # TODO: should probably get its own image at some point instead of reusing the GStreamer one # See https://gitlab.freedesktop.org/gstreamer/gstreamer/-/blob/main/.gitlab-image-tags.yml for latest - WINDOWS_IMAGE: "registry.freedesktop.org/gstreamer/gstreamer/amd64/windows:2023-04-21.0-main" + # (This one is from the lastest stable branch since it's likely to stay around unchanged for longer) + WINDOWS_IMAGE: "registry.freedesktop.org/gstreamer/gstreamer/amd64/windows:2025-03-12.0-1.26" DEFAULT_MESON_ARGS: > --default-library=both + RUST_STABLE: "1.85.0" + RUSTUP_VERSION: "1.28.1" + + ANDROID_HOME: "/android/sdk" + ANDROID_NDK_HOME: "/android/ndk" + stages: - prep - build - test + - analysis + - deploy # Global CI policy: This can be used to configure global behaviour our our jobs default: @@ -60,13 +69,17 @@ fedora image: extends: - '.fdo.container-build@fedora' stage: 'prep' + tags: + - kvm variables: FDO_DISTRIBUTION_PACKAGES: > + binutils-gold meson ninja-build ccache gcc g++ + gperf zlib-devel expat-devel libpng-devel @@ -84,25 +97,92 @@ fedora image: systemd-devel systemd-udev expat-devel - autoconf - automake - make which - libtool diffutils xorg-x11-server-Xvfb dejavu-sans-fonts dejavu-sans-mono-fonts dejavu-serif-fonts google-noto-emoji-color-fonts + google-noto-sans-vf-fonts fonttools + unzip util-linux + poppler-utils + python3-pip + clang + clang-analyzer + clang-tools-extra + compiler-rt + libasan + libubsan + llvm + wget + FDO_DISTRIBUTION_EXEC: >- + bash .gitlab-ci/install-rust.sh --rustup-version ${RUSTUP_VERSION} \ + --stable ${RUST_STABLE} \ + --arch x86_64-unknown-linux-gnu && + bash .gitlab-ci/install-rust-tools.sh && + bash .gitlab-ci/install-grcov.sh && + bash .gitlab-ci/install-android-toolchain.sh $ANDROID_HOME $ANDROID_NDK_HOME && + rm -rf /root/.cargo /root/.cache # cleanup compilation dirs; binaries are installed now -.test fedora meson: +.build fedora: + extends: + - '.fdo.distribution-image@fedora' + - '.ccache_setup' + stage: 'build' + variables: + MESON_ARGS: > + ${DEFAULT_MESON_ARGS} + ${EXTRA_MESON_ARGS} + --werror + CFLAGS: '-Wno-error=deprecated-declarations' + script: + - meson setup ${MESON_ARGS} builddir + - meson compile -C builddir + + # Run test scripts + - mkdir builddir/src/.libs + - touch builddir/src/.libs/libfoo.so + # Run all the tests, except for the big test executable which + # gets run separately + - meson test -C builddir --no-suite=slow --print-errorlogs + + - meson install -C builddir + artifacts: + expire_in: "7 days" + when: "always" + paths: + - "*" + +fedora build shared: + extends: + - '.build fedora' + variables: + EXTRA_MESON_ARGS: '--default-library=shared' + +fedora build static: + extends: + - '.build fedora' + variables: + EXTRA_MESON_ARGS: '--default-library=static' + +fedora build clang: + extends: + - '.build fedora' + variables: + EXTRA_MESON_ARGS: '--default-library=shared' + script: + - export CC=clang + - meson setup ${MESON_ARGS} builddir + - meson compile -C builddir + +.test fedora: dependencies: - - 'fedora meson build' + - 'fedora build shared' needs: - - 'fedora meson build' + - 'fedora build shared' extends: - '.fdo.distribution-image@fedora' - '.ccache_setup' @@ -119,14 +199,14 @@ fedora image: - "builddir/test/**/*.cs" - "builddir/test/**/*.trace" -fedora meson build check-refs.sh: - extends: '.test fedora meson' +fedora build check-refs.sh: + extends: '.test fedora' script: # Check for duplicate reference images - ./test/check-refs.sh "$(pwd)/builddir/test/pdiff/perceptualdiff" -test fedora meson pdf: - extends: '.test fedora meson' +test fedora pdf: + extends: '.test fedora' script: - export CAIRO_TEST_IGNORE_pdf_argb32=$(tr '\n' ',' < .gitlab-ci/ignore-pdf-argb32.txt) - export CAIRO_TEST_IGNORE_pdf_rgb24=$(tr '\n' ',' < .gitlab-ci/ignore-pdf-rgb24.txt) @@ -134,8 +214,8 @@ test fedora meson pdf: - export srcdir=../../test - (cd builddir/test && xvfb-run ./cairo-test-suite) -test fedora meson ps2: - extends: '.test fedora meson' +test fedora ps2: + extends: '.test fedora' script: - export CAIRO_TEST_IGNORE_ps2_argb32=$(tr '\n' ',' < .gitlab-ci/ignore-ps2-argb32.txt) - export CAIRO_TEST_IGNORE_ps2_rgb24=$(tr '\n' ',' < .gitlab-ci/ignore-ps2-rgb24.txt) @@ -144,8 +224,8 @@ test fedora meson ps2: - export srcdir=../../test - (cd builddir/test && xvfb-run ./cairo-test-suite) -test fedora meson ps3: - extends: '.test fedora meson' +test fedora ps3: + extends: '.test fedora' script: - export CAIRO_TEST_IGNORE_ps3_argb32=$(tr '\n' ',' < .gitlab-ci/ignore-ps3-argb32.txt) - export CAIRO_TEST_IGNORE_ps3_rgb24=$(tr '\n' ',' < .gitlab-ci/ignore-ps3-rgb24.txt) @@ -154,8 +234,8 @@ test fedora meson ps3: - export srcdir=../../test - (cd builddir/test && xvfb-run ./cairo-test-suite) -test fedora meson script: - extends: '.test fedora meson' +test fedora script: + extends: '.test fedora' script: - export CAIRO_TEST_UGLY_HACK_TO_SOMETIMES_IGNORE_SCRIPT_XCB_HUGE_IMAGE_SHM=1 - export CAIRO_TEST_IGNORE_script_argb32=$(tr '\n' ',' < .gitlab-ci/ignore-script-argb32.txt) @@ -163,8 +243,8 @@ test fedora meson script: - export srcdir=../../test - (cd builddir/test && xvfb-run ./cairo-test-suite) -test fedora meson image: - extends: '.test fedora meson' +test fedora image: + extends: '.test fedora' script: - export CAIRO_TEST_IGNORE_image_argb32=$(tr '\n' ',' < .gitlab-ci/ignore-image-argb32.txt) - export CAIRO_TEST_IGNORE_image_rgb24=$(tr '\n' ',' < .gitlab-ci/ignore-image-rgb24.txt) @@ -173,8 +253,8 @@ test fedora meson image: - export srcdir=../../test - (cd builddir/test && xvfb-run ./cairo-test-suite) -test fedora meson recording: - extends: '.test fedora meson' +test fedora recording: + extends: '.test fedora' script: - export CAIRO_TEST_IGNORE_recording_argb32=$(tr '\n' ',' < .gitlab-ci/ignore-recording-argb32.txt) - export CAIRO_TEST_IGNORE_recording_rgb24=$(tr '\n' ',' < .gitlab-ci/ignore-recording-rgb24.txt) @@ -182,8 +262,8 @@ test fedora meson recording: - export srcdir=../../test - (cd builddir/test && xvfb-run ./cairo-test-suite) -test fedora meson svg: - extends: '.test fedora meson' +test fedora svg: + extends: '.test fedora' script: - export CAIRO_TEST_IGNORE_svg11_argb32=$(tr '\n' ',' < .gitlab-ci/ignore-svg11-argb32.txt) - export CAIRO_TEST_IGNORE_svg11_rgb24=$(tr '\n' ',' < .gitlab-ci/ignore-svg11-rgb24.txt) @@ -195,8 +275,8 @@ test fedora meson svg: - export srcdir=../../test - (cd builddir/test && xvfb-run ./cairo-test-suite) -test fedora meson xcb: - extends: '.test fedora meson' +test fedora xcb: + extends: '.test fedora' script: - export CAIRO_TEST_IGNORE_xcb_argb32=$(tr '\n' ',' < .gitlab-ci/ignore-xcb-argb32.txt) - export CAIRO_TEST_IGNORE_xcb_rgb24=$(tr '\n' ',' < .gitlab-ci/ignore-xcb-rgb24.txt) @@ -209,8 +289,8 @@ test fedora meson xcb: - export srcdir=../../test - (cd builddir/test && xvfb-run ./cairo-test-suite) -test fedora meson xlib: - extends: '.test fedora meson' +test fedora xlib: + extends: '.test fedora' script: - export CAIRO_TEST_IGNORE_xlib_argb32=$(tr '\n' ',' < .gitlab-ci/ignore-xlib-argb32.txt) - export CAIRO_TEST_IGNORE_xlib_rgb24=$(tr '\n' ',' < .gitlab-ci/ignore-xlib-rgb24.txt) @@ -221,39 +301,7 @@ test fedora meson xlib: - export srcdir=../../test - (cd builddir/test && xvfb-run ./cairo-test-suite) -fedora meson build: - extends: - - '.fdo.distribution-image@fedora' - - '.ccache_setup' - stage: 'build' - variables: - MESON_ARGS: > - ${DEFAULT_MESON_ARGS} - script: - - export CFLAGS="-Werror -Wno-error=deprecated-declarations" - - meson builddir ${MESON_ARGS} - - ninja -C builddir - - # Run test scripts - - mkdir builddir/src/.libs - - touch builddir/src/.libs/libfoo.so - # Run all the tests, except for the big test executable which - # gets run separately - - meson test -C builddir --no-suite=slow --print-errorlogs - - # TODO: These aren't set up as Meson tests yet - - (cd doc/public && bash "check-doc-syntax.sh") - # FIXME: The following line really needs gtk-doc to run first - - (cd doc/public && DOC_MODULE=cairo bash "check-doc-coverage.sh") - - - ninja -C builddir install - artifacts: - expire_in: "7 days" - when: "always" - paths: - - "*" - -meson mingw-32 build: +mingw-32 build: extends: - '.fdo.distribution-image@fedora' stage: 'build' @@ -264,7 +312,8 @@ meson mingw-32 build: script: - mkdir builddir - cd builddir - - mingw32-meson --default-library=both + # Test building with FreeType enabled and Fontconfig disabled + - mingw32-meson --default-library=both -Dfontconfig=disabled - ninja install artifacts: expire_in: "7 days" @@ -272,7 +321,7 @@ meson mingw-32 build: paths: - 'builddir/meson-logs/' -meson mingw-64 build: +mingw-64 build: extends: - '.fdo.distribution-image@fedora' stage: 'build' @@ -292,7 +341,7 @@ meson mingw-64 build: - 'builddir/meson-logs/' # Based on https://gitlab.freedesktop.org/gstreamer/gstreamer/-/blob/main/.gitlab-ci.yml (.build windows) -.build meson windows: +.build windows: image: $WINDOWS_IMAGE stage: 'build' tags: @@ -309,11 +358,8 @@ meson mingw-64 build: -Dzlib=enabled ${EXTRA_MESON_ARGS} before_script: - # Make sure meson is up to date, so we don't need to rebuild the image with each release - # FIXME: don't update meson version for now, since there seems to be a bug - # in newer meson versions (0.63.3 at the time of writing) where it can't - # find some hash file and then meson subprojects update fails) - # - pip3 install -U meson + # Make sure meson is up to date, latest fontconfig requires a newer Meson than what's on the image + - pip3 install -U meson script: # Make sure powershell exists on errors # https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_preference_variables?view=powershell-6 @@ -335,29 +381,35 @@ meson mingw-64 build: meson subprojects update --reset && meson build $env:MESON_ARGS && ninja -C build" + artifacts: + expire_in: "7 days" + when: "always" + paths: + - 'build/meson-logs/' -meson vs2019 shared amd64: - extends: '.build meson windows' +vs2019 shared amd64: + extends: '.build windows' variables: ARCH: 'amd64' EXTRA_MESON_ARGS: '--default-library=shared' -meson vs2019 static amd64: - extends: '.build meson windows' +vs2019 static amd64: + extends: '.build windows' variables: ARCH: 'amd64' EXTRA_MESON_ARGS: '--default-library=static' -meson vs2019 shared x86: - extends: '.build meson windows' +vs2019 shared x86: + extends: '.build windows' variables: ARCH: 'x86' EXTRA_MESON_ARGS: '--default-library=shared' -meson android arm64 fedora: +android arm64 fedora: # TODO: should probably build our own image here some day # See https://gitlab.freedesktop.org/gstreamer/gstreamer/container_registry/7689 for current images - image: 'registry.freedesktop.org/gstreamer/gstreamer/amd64/android-fedora:2020-10-22.0-master' + extends: + - '.fdo.distribution-image@fedora' stage: 'build' artifacts: name: "${CI_JOB_NAME}_${CI_COMMIT_SHA}" @@ -365,41 +417,14 @@ meson android arm64 fedora: when: 'always' paths: - "build/meson-logs/*.txt" - before_script: - - dnf install -y python3-pip gcc ninja-build gperf - - pip3 install --user meson script: - - export PATH="$HOME/.local/bin:$PATH" - - | - cat > android-cross-file.txt < + --buildtype=debug + script: + - meson setup ${MESON_ARGS} _scan_build . + - ninja -C _scan_build scan-build + artifacts: + name: "cairo-${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}" + when: always + paths: + - "_scan_build/meson-logs/scanbuild" + +coverage: + stage: 'analysis' + extends: + - '.fdo.distribution-image@fedora' + needs: + - job: 'fedora image' + artifacts: false + script: + - source ./.gitlab-ci/env.sh + - bash -x ./.gitlab-ci/build-with-coverage.sh + - bash -x ./.gitlab-ci/gen-coverage.sh + coverage: '/Coverage: \d+\.\d+/' + artifacts: + name: "cairo-${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}" + expire_in: 2 days + when: always + reports: + coverage_report: + coverage_format: cobertura + path: public/coverage.xml + paths: + - "_build/meson-logs" + - public + +pages: + stage: 'deploy' + needs: + - job: coverage + script: + - mkdir -p public + - cp .gitlab-ci/pages-index.html public/index.html + artifacts: + paths: + - public + expire_in: 1 day + rules: + # Restrict to the main branch so not every branch tries to deploy the web site + - if: ($CI_DEFAULT_BRANCH == $CI_COMMIT_BRANCH) diff --git a/.gitlab-ci/android-cross-file.txt b/.gitlab-ci/android-cross-file.txt new file mode 100644 index 000000000..e5df1e5a7 --- /dev/null +++ b/.gitlab-ci/android-cross-file.txt @@ -0,0 +1,22 @@ +[constants] +ndk_path = '/android/ndk' +ndk_bindir = ndk_path + '/toolchains/llvm/prebuilt/linux-x86_64/bin/' +toolchain = ndk_bindir + 'aarch64-linux-android' +api = '28' + +[host_machine] +system = 'android' +cpu_family = 'aarch64' +cpu = 'aarch64' +endian = 'little' + +[properties] +sys_root = ndk_path + '/sysroot' +c_ld = 'gold' +cpp_ld = 'gold' + +[binaries] +c = toolchain + api + '-clang' +cpp = toolchain + api + '-clang++' +ar = ndk_bindir + 'llvm-ar' +strip = ndk_bindir + 'llvm-strip' diff --git a/.gitlab-ci/build-with-coverage.sh b/.gitlab-ci/build-with-coverage.sh new file mode 100644 index 000000000..ed867986d --- /dev/null +++ b/.gitlab-ci/build-with-coverage.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +set -eux -o pipefail + +export CFLAGS="-coverage -ftest-coverage -fprofile-arcs" + +export CAIRO_TEST_IGNORE_image_argb32=$(tr '\n' ',' < .gitlab-ci/ignore-image-argb32.txt) +export CAIRO_TEST_IGNORE_image_rgb24=$(tr '\n' ',' < .gitlab-ci/ignore-image-rgb24.txt) +export CAIRO_TEST_IGNORE_image16_rgb24=$(tr '\n' ',' < .gitlab-ci/ignore-image16-rgb24.txt) +export CAIRO_TEST_TARGET=image,image16 + +meson setup --buildtype=debug _build . +meson compile -C _build + +export srcdir=../../test +cd _build/test +xvfb-run ./cairo-test-suite diff --git a/.gitlab-ci/env.sh b/.gitlab-ci/env.sh new file mode 100644 index 000000000..b5761529f --- /dev/null +++ b/.gitlab-ci/env.sh @@ -0,0 +1,2 @@ +export RUSTUP_HOME='/usr/local/rustup' +export PATH=$PATH:/usr/local/cargo/bin diff --git a/.gitlab-ci/gen-coverage.sh b/.gitlab-ci/gen-coverage.sh new file mode 100644 index 000000000..cfc78e240 --- /dev/null +++ b/.gitlab-ci/gen-coverage.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +set -eux -o pipefail + +mkdir -p public +grcov _build --source-dir ./ --prefix-dir ../ --output-type cobertura --branch --ignore-not-existing -o public/coverage.xml +grcov _build --source-dir ./ --prefix-dir ../ --output-type html --branch --ignore-not-existing -o public/coverage + +# Print "Coverage: 42.42" so .gitlab-ci.yml will pick it up with a regex +# +# We scrape this from the HTML report, not the JSON summary, because coverage.json +# uses no decimal places, just something like "42%". + +grep -Eo 'abbr title.* %' public/coverage/index.html | head -n 1 | grep -Eo '[0-9.]+ %' | grep -Eo '[0-9.]+' | awk '{ print "Coverage:", $1 }' diff --git a/.gitlab-ci/ignore-quartz-argb32.txt b/.gitlab-ci/ignore-quartz-argb32.txt index fb30f4bb0..806837e42 100644 --- a/.gitlab-ci/ignore-quartz-argb32.txt +++ b/.gitlab-ci/ignore-quartz-argb32.txt @@ -2,6 +2,7 @@ bug-361 bug-431 bug-image-compositor clip-operator +coverage-column-triangles coverage-rhombus culled-glyphs extended-blend-alpha diff --git a/.gitlab-ci/ignore-quartz-rgb24.txt b/.gitlab-ci/ignore-quartz-rgb24.txt index 92416e16b..9db477c35 100644 --- a/.gitlab-ci/ignore-quartz-rgb24.txt +++ b/.gitlab-ci/ignore-quartz-rgb24.txt @@ -10,6 +10,7 @@ bug-image-compositor bug-source-cu clip-device-offset clip-fill-rule-pixel-aligned +coverage-column-triangles coverage-rhombus culled-glyphs device-offset diff --git a/.gitlab-ci/install-android-toolchain.sh b/.gitlab-ci/install-android-toolchain.sh new file mode 100644 index 000000000..5b9fce8d2 --- /dev/null +++ b/.gitlab-ci/install-android-toolchain.sh @@ -0,0 +1,33 @@ +#! /bin/bash + +# Copied from gstreamer/cerbero +# https://gitlab.freedesktop.org/gstreamer/cerbero/-/blob/2a0f5829aa1b56e8d36ef36f9675845345d54542/ci/docker_android_setup.sh + +set -eux + +export ANDROID_HOME=$1 +export ANDROID_NDK_HOME=$2 + +mkdir -p /android/sources + +curl -o /android/sources/android-ndk.zip https://dl.google.com/android/repository/android-ndk-r25c-linux.zip +unzip /android/sources/android-ndk.zip -d ${ANDROID_NDK_HOME}/ +# remove the intermediate versioned directory +mv ${ANDROID_NDK_HOME}/*/* ${ANDROID_NDK_HOME}/ + +curl -o /android/sources/android-sdk-tools.zip https://dl.google.com/android/repository/commandlinetools-linux-9477386_latest.zip +unzip /android/sources/android-sdk-tools.zip -d ${ANDROID_HOME}/ +mkdir -p ${ANDROID_HOME}/licenses + +# Accept licenses. Values taken from: +# $ANDROID_HOME/tools/bin/sdkmanager --sdk_root=$ANDROID_HOME --licenses +# cd $ANDROID_HOME +# for f in licenses/*; do echo "echo \"$(cat $f | tr -d '\n')\" > \${ANDROID_HOME}/$f"; done +echo "601085b94cd77f0b54ff86406957099ebe79c4d6" > ${ANDROID_HOME}/licenses/android-googletv-license +echo "859f317696f67ef3d7f30a50a5560e7834b43903" > ${ANDROID_HOME}/licenses/android-sdk-arm-dbt-license +echo "24333f8a63b6825ea9c5514f83c2829b004d1fee" > ${ANDROID_HOME}/licenses/android-sdk-license +echo "84831b9409646a918e30573bab4c9c91346d8abd" > ${ANDROID_HOME}/licenses/android-sdk-preview-license +echo "33b6a2b64607f11b759f320ef9dff4ae5c47d97a" > ${ANDROID_HOME}/licenses/google-gdk-license +echo "e9acab5b5fbb560a72cfaecce8946896ff6aab9d" > ${ANDROID_HOME}/licenses/mips-android-sysimage-license + +rm -rf /android/sources diff --git a/.gitlab-ci/install-grcov.sh b/.gitlab-ci/install-grcov.sh new file mode 100644 index 000000000..43edaa73f --- /dev/null +++ b/.gitlab-ci/install-grcov.sh @@ -0,0 +1,8 @@ +source ./.gitlab-ci/env.sh + +set -eu +export CARGO_HOME='/usr/local/cargo' + +# Coverage tools +cargo install grcov +rustup component add llvm-tools-preview diff --git a/.gitlab-ci/install-rust-tools.sh b/.gitlab-ci/install-rust-tools.sh new file mode 100644 index 000000000..23e55f4d9 --- /dev/null +++ b/.gitlab-ci/install-rust-tools.sh @@ -0,0 +1,11 @@ +source ./.gitlab-ci/env.sh + +set -eu +export CARGO_HOME='/usr/local/cargo' + +rustup component add clippy +rustup component add rustfmt +# cargo install --force cargo-c +cargo install --version ^1.0 gitlab_clippy +cargo install --force cargo-deny +# cargo install --force cargo-outdated diff --git a/.gitlab-ci/install-rust.sh b/.gitlab-ci/install-rust.sh new file mode 100644 index 000000000..93cdb4abd --- /dev/null +++ b/.gitlab-ci/install-rust.sh @@ -0,0 +1,92 @@ +#!/bin/bash + +set -o errexit -o pipefail -o noclobber -o nounset + +source ./.gitlab-ci/env.sh + +export CARGO_HOME='/usr/local/cargo' + +PARSED=$(getopt --options '' --longoptions 'rustup-version:,stable:,minimum:,nightly,arch:' --name "$0" -- "$@") +if [ $? -ne 0 ]; then + echo 'Terminating...' >&2 + exit 1 +fi + +eval set -- "$PARSED" +unset PARSED + +RUSTUP_VERSION= +STABLE= +MINIMUM= +NIGHTLY= +ARCH= + +while true; do + case "$1" in + '--rustup-version') + RUSTUP_VERSION=$2 + shift 2 + ;; + + '--stable') + STABLE=$2 + shift 2 + ;; + + '--minimum') + MINIMUM=$2 + shift 2 + ;; + + '--nightly') + NIGHTLY=1 + shift 1 + ;; + + '--arch') + ARCH=$2 + shift 2 + ;; + + '--') + shift + break + ;; + + *) + echo "Programming error" + exit 3 + ;; + esac +done + +if [ -z "$RUSTUP_VERSION" ]; then + echo "missing --rustup-version argument" + exit 1 +fi + +if [ -z "$STABLE" ]; then + echo "missing --stable argument, please pass the stable version of rustc you want" + exit 1 +fi + +if [ -z "$ARCH" ]; then + echo "missing --arch argument, please pass an architecture triple like x86_64-unknown-linux-gnu" + exit 1 +fi + +RUSTUP_URL=https://static.rust-lang.org/rustup/archive/$RUSTUP_VERSION/$ARCH/rustup-init +wget $RUSTUP_URL + +chmod +x rustup-init +./rustup-init -y --no-modify-path --profile minimal --default-toolchain $STABLE +rm rustup-init +chmod -R a+w $RUSTUP_HOME $CARGO_HOME + +if [ -n "$MINIMUM" ]; then + rustup toolchain install $MINIMUM +fi + +if [ -n "$NIGHTLY" ]; then + rustup toolchain install nightly +fi diff --git a/.gitlab-ci/pages-index.html b/.gitlab-ci/pages-index.html new file mode 100644 index 000000000..9a6aba58a --- /dev/null +++ b/.gitlab-ci/pages-index.html @@ -0,0 +1,13 @@ + + + Cairo's development pages + + + +

Cairo's development pages

+ + + + diff --git a/BUGS b/BUGS index 452d52300..a2631e9f4 100644 --- a/BUGS +++ b/BUGS @@ -6,22 +6,22 @@ extra effort users put in to providing high-quality bug reports. There are two acceptable ways to report cairo bugs, and you can choose which you prefer: -1) Bugzilla bug tracking database: +1) Gitlab bug tracking database: You can use the following web interface to report new bugs, follow up on previous bug reports, and search for existing, known - bugs. Just use the "cairo" product: + bugs: - https://bugs.freedesktop.org + https://gitlab.freedesktop.org/cairo/cairo/-/issues It is necessary to go through a quick account creation process, (with email address verification), in order to be able to report - new bugs in bugzilla. We apologize for any inconvenience that might + new bugs in gitlab. We apologize for any inconvenience that might cause, and hope it won't prevent you from reporting bugs. 2) Cairo mailing list: - For people who cannot stand the bugzilla interface, you can just + For people who cannot stand the gitlab interface, you can just send an email to cairo mailing list (cairo@cairographics.org). The mailing list only allows posting from subscribers, so use the following page for subscription instructions: @@ -39,8 +39,8 @@ which you prefer: Which of the above you use to report bugs depends on your own preferences. Some people find just typing an email message much easier -than using the web-based forms on bugzilla. Others greatly prefer the -ability to check back on a specific bug entry in bugzilla without +than using the web-based forms on gitlab. Others greatly prefer the +ability to check back on a specific bug entry in gitlab without having to ask on the mailing list if an issue has been resolved. Regardless of which method you use, here are some general tips that @@ -48,9 +48,8 @@ will help you improve the quality of your bug report, (which will help in getting the bug fixed sooner): 1) Check to see if the bug has been reported already. It's pretty easy - to run a search or two against the cairo product in the - https://bugs.freedesktop.org bugzilla database. Another place to - look for known bugs is the cairo ROADMAP: + to run a search or two against the cairo product in the gitlab + database. Another place to look for known bugs is the cairo ROADMAP: https://cairographics.org/ROADMAP diff --git a/HACKING b/HACKING index bc97f5324..b771e5813 100644 --- a/HACKING +++ b/HACKING @@ -46,9 +46,9 @@ the -commit and -bugs lists. Bug Tracking System ------------------- -We use a standard bugzilla bug tracking system available at: +We use a standard gitlab bug tracking system available at: - https://bugs.freedesktop.org/ + https://gitlab.freedesktop.org/cairo/cairo/-/issues See file named BUGS for detailed information on reporting bugs. In short, for straight bug reports, it's best to report them there such that they diff --git a/NEWS b/NEWS index 29e4a0aa0..71bec9874 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,96 @@ +Release 1.18.4 (2025-03-08 Emmanuele Bassi ) +============================================================== + +A new stable release. + +The dependency on LZO has been made optional through a build time +configuration toggle. [!580] + +You can build Cairo against a Freetype installation that does not have the +FT_Color type. [#792] + +Cairo tests now build on Solaris 11.4 with GCC 14. [!599] + +The DirectWrite backend now builds on MINGW 11. [!600] + +Thanks to Luca Bacci, the DirectWrite backend now supports font +variations and proper glyph coverage. [#877, !602] + +Support for Windows 98 has been removed. The minimum requirement for +Windows is now Vista. + +Release 1.18.2 (2024-09-01 Emmanuele Bassi ) +============================================================== + +A new stable release. + +The malloc-stats code has been removed from the tests directory [#640]; the +canonical location for it is: https://github.com/behdad/malloc-stats + +Cairo now requires a version of pixman equal to, or newer than, 0.40. [!522] + +There have been multiple build fixes for newer versions of GCC [!525, !542]; +for MSVC [#808]; for Solaris [!540]; and on macOS 10.7 [#810]. + +PNG errors caused by loading malformed data are correctly propagated to +callers, so they can handle the case. [!524] + +Both stroke and fill colors are now set when showing glyphs on a PDF +surface. [#813] + +All the font options are copied when creating a fallback font object. [#819] + +When drawing text on macOS, Cairo now tries harder to select the appropriate +font name. [#811] + +Cairo now prefers the COLRv1 table inside a font, if one is available. [!537] + +Cairo requires a C11 toolchain when building. [!479] + +Release 1.18.0 (2023-09-20 Emmanuele Bassi ) +============================================================== + +The first stable cairo release in five years should be cause for celebration. + +All the API added in the 1.17 development cycle is now considered stable, and +will not change. + +Many thanks to all the contributors for this release. + +The cairo-sphinx tool has been removed; we could not find any instruction on +how to use it, and no user answered our call for help. If you were using +cairo-sphinx, please reach out to the cairo maintainers. + +Cairo now implements Type 3 color fonts for PDF. Thanks to Adrian Johnson for +his work on this feature. + +Khaled Hosny contributed multiple documentation fixes, to ensure that the +cairo API reference is up to date. Khaled also fixed multiple compiler +warnings generated when building cairo. + +The XML surface has been removed; it was disabled by default when building +cairo, and we could not find any downstream distributor that would enable +it. + +The Tee surface is now automatically enabled. Downstream distributors of +cairo have been enabling for years it in order to build Firefox. + +Fujii Hironori and Adrian Johnson fixed multiple issues with the DWrite +font backend. + +John Ralls improved the Quartz surface; mainly, Quartz surfaces now use +the main display ColorSpace, speeding up rendering operations. + +Cairo now hides all private symbols by default on every platform; the old +"slim" symbols hack to alias internally used symbols has been dropped, in +favor of using `-Bsymbolic-functions` with toolchains that support it. + +Uli Schlachter fixed multiple memory leaks in the code base and test suite, +and helped with many reviews and general maintenance. + +Marc Jeanmougin added new API to expose the Pixman dithering filter to cairo +patterns; this is currently implemented only for image surfaces. + Release 1.17.8 (2023-01-30 Emmanuele Bassi ) ============================================================== @@ -108,7 +201,7 @@ includes implementation of core functionality, performance optimizations, and stabilization. Subpixel positioning support allows improved glyph outlines with the -Freetype font backend. +FreeType font backend. For a complete log of changes, please see @@ -8223,7 +8316,7 @@ the PNG generation in the demos. These have now been resolved. 2003-10 ======= Graydon Hoare implemented the first real text -support using Freetype/fontconfig, (previous versions of cairo used +support using FreeType/fontconfig, (previous versions of cairo used Xft and could only draw text when using an X backend). 2003-09 diff --git a/README.md b/README.md index 025f8486d..85ea969d4 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,7 @@ What is cairo Cairo is a 2D graphics library with support for multiple output devices. Currently supported output targets include the X Window System (via both Xlib and XCB), quartz, win32, and image buffers, -as well as PDF, PostScript, and SVG file output. Experimental backends -include OpenGL. +as well as PDF, PostScript, and SVG file output. Cairo is designed to produce consistent output on all output media while taking advantage of display hardware acceleration when available @@ -127,7 +126,7 @@ system pixman. #### Windows backend -- Microsoft Windows 2000 or newer. +- Microsoft Windows Vista or newer. #### XCB backend @@ -146,7 +145,7 @@ system pixman. #### Windows GDI font backend -- Microsoft Windows 2000 or newer +- Microsoft Windows Vista or newer #### Windows DirectWrite font backend diff --git a/README.win32 b/README.win32 deleted file mode 100644 index ff962b72a..000000000 --- a/README.win32 +++ /dev/null @@ -1,66 +0,0 @@ -Building Cairo on Windows -========================= -There are two primary ways to build Cairo on Windows. You can use a -UNIX emulation based setup, such as Cygwin or MSYS, with the -conventional configure script shipped with Cairo releases. In this -configuration, you will build with GCC and (implicitly) libtool. In -the Cygwin case you end up with a DLL that depends on Cygwin and -should be used only from Cygwin applications. In the MSYS case you end -up with a "normal" Win32 DLL that can be used either from GCC- or -Microsoft Visual C++-compiled code. In theory, this technique is no -different than the ordinary build process for the Cairo library. In -practise there are lots of small details that can go wrong. - -The second way is to use a GNU-compatible make, but build using -Microsoft's Visual C++ compiler to produce native libraries. This is -the setup this README.win32 is written for. Also the DLL produced this -way is usable either from GCC- or MSVC-compiled code. - -Tools required -============== -You will need GNU make, version 3.80 or later. Earlier versions or -other modern make implementations may work, but are not guaranteed to. - -You will also need Microsoft Visual C++. Version 7 has been most -heavily tested, but other versions are likely to work fine. - -Libraries required -================== -Cairo requires a compatible version of the pixman library. Full build -instructions are beyond the scope of this document; however, using the -same tools, it should be possible to build pixman simply by entering -the pixman/src directory and typing: - - make -f Makefile.win32 CFG=release - -Depending on your feature set, you may also need zlib and libpng. - -Building -======== -There are a few files that you will need to edit. First, you must -determine which features will be built. Edit -build/Makefile.win32.features and set the features as desired. Note -that most features have external dependencies; specifically, -CAIRO_HAS_PNG_FUNCTIONS requires libpng to be present, and -CAIRO_HAS_PS_SURFACE and CAIRO_HAS_PDF_SURFACE both require zlib. - -To ensure that the compiler can find all dependencies, you may need to -edit build/Makefile.win32.common. In particular, ensure that -PIXMAN_CFLAGS contains a -I parameter pointing to the location of -your pixman header files and that PIXMAN_LIBS points to the actual -location of your pixman-1.lib file. You may also need to edit the -various occurrences of CAIRO_LIBS to point to other libraries -correctly. Note also that if you wish to link statically with zlib, -you should replace zdll.lib with zlib.lib. - -Finally, from the top Cairo directory, type: - - make -f Makefile.win32 CFG=release - -If this command succeeds, you will end up with src/release/cairo.dll. -To successfully use Cairo from your own programs, you will probably -want to move this file to some central location. You will also -probably want to copy the Cairo header files. These should be placed -in a cairo subdirectory (for instance, c:/code/common/include/cairo). -The exact set to copy depends on your features and is reported to you -at the end of the build. diff --git a/boilerplate/cairo-boilerplate-quartz.c b/boilerplate/cairo-boilerplate-quartz.c index 1a1417c75..dd2452c0a 100644 --- a/boilerplate/cairo-boilerplate-quartz.c +++ b/boilerplate/cairo-boilerplate-quartz.c @@ -28,6 +28,40 @@ #include +#include + +#ifndef RTLD_DEFAULT +#define RTLD_DEFAULT ((void *) 0) +#endif + +/* + * macOS Private functions + */ +typedef enum { + kCGContextTypeUnknown, + kCGContextTypePDF, + kCGContextTypePostScript, + kCGContextTypeWindow, + kCGContextTypeBitmap, + kCGContextTypeGL, + kCGContextTypeDisplayList, + kCGContextTypeKSeparation, + kCGContextTypeIOSurface, + kCGContextTypeCount +} CGContextType; + + +static unsigned int (*CGContextGetTypePtr) (CGContextRef) = NULL; +static void +quartz_ensure_symbols (void) +{ + static cairo_bool_t symbol_lookup_done = FALSE; + if (!symbol_lookup_done) { + CGContextGetTypePtr = dlsym (RTLD_DEFAULT, "CGContextGetType"); + symbol_lookup_done = TRUE; + } +} + static cairo_surface_t * _cairo_boilerplate_quartz_create_surface (const char *name, cairo_content_t content, @@ -47,6 +81,48 @@ _cairo_boilerplate_quartz_create_surface (const char *name, return cairo_quartz_surface_create (format, width, height); } +static bool +cg_context_is_bitmap (CGContextRef context) +{ + quartz_ensure_symbols (); + + if (likely (CGContextGetTypePtr)) { + return CGContextGetTypePtr (context) == kCGContextTypeBitmap; + } + + return CGBitmapContextGetBitsPerPixel (context) != 0; +} + +static cairo_status_t +_cairo_boilerplate_quartz_surface_to_png (cairo_surface_t *surface, + const char *dest) +{ + CGContextRef context = cairo_quartz_surface_get_cg_context (surface); + if (!context || !cg_context_is_bitmap (context)) { + return CAIRO_STATUS_SURFACE_TYPE_MISMATCH; + } + + CGImageRef image = CGBitmapContextCreateImage (context); + CFStringRef png_utti = CFSTR("public.png"); + CFStringRef path; + CFURLRef url; + + CGImageDestinationRef image_dest; + + path = CFStringCreateWithCString (NULL, dest, kCFStringEncodingUTF8); + url = CFURLCreateWithFileSystemPath (NULL, path, kCFURLPOSIXPathStyle, FALSE); + image_dest = CGImageDestinationCreateWithURL (url, png_utti, 1, NULL); + + CGImageDestinationAddImage (image_dest, image, NULL); + CGImageDestinationFinalize (image_dest); + + CFRelease (url); + CFRelease (path); + + CGImageRelease (image); + return CAIRO_STATUS_SUCCESS; +} + static const cairo_boilerplate_target_t targets[] = { { "quartz", "quartz", NULL, NULL, @@ -56,7 +132,7 @@ static const cairo_boilerplate_target_t targets[] = { cairo_surface_create_similar, NULL, NULL, _cairo_boilerplate_get_image_surface, - _cairo_quartz_surface_to_png, + _cairo_boilerplate_quartz_surface_to_png, NULL, NULL, NULL, TRUE, FALSE, FALSE }, @@ -68,7 +144,7 @@ static const cairo_boilerplate_target_t targets[] = { cairo_surface_create_similar, NULL, NULL, _cairo_boilerplate_get_image_surface, - _cairo_quartz_surface_to_png, + _cairo_boilerplate_quartz_surface_to_png, NULL, NULL, NULL, FALSE, FALSE, FALSE }, diff --git a/boilerplate/cairo-boilerplate-win32-printing.c b/boilerplate/cairo-boilerplate-win32-printing.c index e8fcdcef5..9177480fc 100644 --- a/boilerplate/cairo-boilerplate-win32-printing.c +++ b/boilerplate/cairo-boilerplate-win32-printing.c @@ -36,51 +36,6 @@ #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 - -static 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), - (LPWSTR) &lpMsgBuf, - 0, NULL)) { - fprintf (stderr, "%s: Unknown GDI error", context); - } else { - fprintf (stderr, "%s: %S", context, (wchar_t *)lpMsgBuf); - - LocalFree (lpMsgBuf); - } - - fflush (stderr); - - /* 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_STATUS_NO_MEMORY; -} - static cairo_user_data_key_t win32_closure_key; typedef struct _win32_target_closure { @@ -174,7 +129,7 @@ create_printer_dc (win32_target_closure_t *ptc) xform.eDx = 0; xform.eDy = printable_height - ptc->height*y_dpi/72.0; if (!SetWorldTransform (ptc->dc, &xform)) { - _cairo_win32_print_gdi_error ("cairo-boilerplate-win32-printing:SetWorldTransform"); + fprintf (stderr, "%s:%s\n", "cairo-boilerplate-win32-printing", "SetWorldTransform"); return; } diff --git a/boilerplate/cairo-boilerplate.h b/boilerplate/cairo-boilerplate.h index 736534eaf..4ecf575da 100644 --- a/boilerplate/cairo-boilerplate.h +++ b/boilerplate/cairo-boilerplate.h @@ -73,7 +73,7 @@ #define CAIRO_BOILERPLATE_DEBUG(x) #endif -#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4) +#if defined (__GNUC__) #ifdef __MINGW32__ #define CAIRO_BOILERPLATE_PRINTF_FORMAT(fmt_index, va_index) \ __attribute__((__format__(__MINGW_PRINTF_FORMAT, fmt_index, va_index))) diff --git a/boilerplate/check-link.c b/boilerplate/check-link.c deleted file mode 100644 index 688339a95..000000000 --- a/boilerplate/check-link.c +++ /dev/null @@ -1,17 +0,0 @@ -#include -#include - -int -main (void) -{ - printf ("Check linking to the just built cairo boilerplate library\n"); - if (cairo_boilerplate_version () == CAIRO_VERSION) { - return 0; - } else { - fprintf (stderr, - "Error: linked to cairo boilerplate version %s instead of %s\n", - cairo_boilerplate_version_string (), - CAIRO_VERSION_STRING); - return 1; - } -} diff --git a/boilerplate/meson.build b/boilerplate/meson.build index 450eabf3e..544bfcc09 100644 --- a/boilerplate/meson.build +++ b/boilerplate/meson.build @@ -28,6 +28,7 @@ cairo_boilerplate_constructors = custom_target('cairo-boilerplate-constructors.c libcairoboilerplate = static_library('cairoboilerplate', cairo_boilerplate_sources + [cairo_boilerplate_constructors], include_directories: [incbase], dependencies: deps + [libcairo_dep], + c_args: ['-DCAIRO_COMPILATION'], install: false, build_by_default: false, ) diff --git a/doc/public/cairo-docs.xml b/doc/public/cairo-docs.xml index cc7c9aa04..6bfbddf64 100644 --- a/doc/public/cairo-docs.xml +++ b/doc/public/cairo-docs.xml @@ -48,6 +48,7 @@ + Utilities @@ -56,53 +57,53 @@ - + Index - + - + Index of new symbols in 1.0 - - + + Index of new symbols in 1.2 - - + + Index of new symbols in 1.4 - - + + Index of new symbols in 1.6 - - + + Index of new symbols in 1.8 - - + + Index of new symbols in 1.10 - - + + Index of new symbols in 1.12 - - + + Index of new symbols in 1.14 - - + + Index of new symbols in 1.16 - - + + Index of new symbols in 1.18 - - + + diff --git a/doc/public/cairo-overrides.txt b/doc/public/cairo-overrides.txt index e69de29bb..dd8084492 100644 --- a/doc/public/cairo-overrides.txt +++ b/doc/public/cairo-overrides.txt @@ -0,0 +1,124 @@ + +CAIRO_HAS_FT_FONT +#define CAIRO_HAS_FT_FONT + + + +CAIRO_HAS_FC_FONT +#define CAIRO_HAS_FC_FONT + + + +CAIRO_HAS_PNG_FUNCTIONS +#define CAIRO_HAS_PNG_FUNCTIONS + + + +CAIRO_HAS_SVG_SURFACE +#define CAIRO_HAS_SVG_SURFACE + + + +CAIRO_HAS_PDF_SURFACE +#define CAIRO_HAS_PDF_SURFACE + + + +CAIRO_HAS_PS_SURFACE +#define CAIRO_HAS_PS_SURFACE + + + +CAIRO_HAS_SCRIPT_SURFACE +#define CAIRO_HAS_SCRIPT_SURFACE + + + +CAIRO_HAS_XLIB_SURFACE +#define CAIRO_HAS_XLIB_SURFACE + + + +CAIRO_HAS_XLIB_XRENDER_SURFACE +#define CAIRO_HAS_XLIB_XRENDER_SURFACE + + + +CAIRO_HAS_XCB_SURFACE +#define CAIRO_HAS_XCB_SURFACE + + + +CAIRO_HAS_XLIB_XCB_FUNCTIONS +#define CAIRO_HAS_XLIB_XCB_FUNCTIONS + + + +CAIRO_HAS_XCB_SHM_FUNCTIONS +#define CAIRO_HAS_XCB_SHM_FUNCTIONS + + + +CAIRO_HAS_QUARTZ_SURFACE +#define CAIRO_HAS_QUARTZ_SURFACE + + + +CAIRO_HAS_QUARTZ_IMAGE_SURFACE +#define CAIRO_HAS_QUARTZ_IMAGE_SURFACE + + + +CAIRO_HAS_QUARTZ_FONT +#define CAIRO_HAS_QUARTZ_FONT + + + +CAIRO_HAS_WIN32_SURFACE +#define CAIRO_HAS_WIN32_SURFACE + + + +CAIRO_HAS_WIN32_FONT +#define CAIRO_HAS_WIN32_FONT + + + +CAIRO_HAS_DWRITE_FONT +#define CAIRO_HAS_DWRITE_FONT + + + +CAIRO_HAS_GOBJECT_FUNCTIONS +#define CAIRO_HAS_GOBJECT_FUNCTIONS + + + +CAIRO_HAS_IMAGE_SURFACE +#define CAIRO_HAS_IMAGE_SURFACE + + + +CAIRO_HAS_USER_FONT +#define CAIRO_HAS_USER_FONT + + + +CAIRO_HAS_MIME_SURFACE +#define CAIRO_HAS_MIME_SURFACE + + + +CAIRO_HAS_RECORDING_SURFACE +#define CAIRO_HAS_RECORDING_SURFACE + + + +CAIRO_HAS_OBSERVER_SURFACE +#define CAIRO_HAS_OBSERVER_SURFACE + + + +CAIRO_HAS_TEE_SURFACE +#define CAIRO_HAS_TEE_SURFACE + diff --git a/doc/public/cairo-sections.txt b/doc/public/cairo-sections.txt index 5f53fc49c..52bbbb231 100644 --- a/doc/public/cairo-sections.txt +++ b/doc/public/cairo-sections.txt @@ -163,6 +163,7 @@ to_win32_surface
cairo-quartz CAIRO_HAS_QUARTZ_SURFACE +CAIRO_HAS_QUARTZ_IMAGE_SURFACE cairo_quartz_surface_create cairo_quartz_surface_create_for_cg_context cairo_quartz_surface_get_cg_context @@ -173,6 +174,7 @@ cairo_quartz_image_surface_get_image
cairo-xlib CAIRO_HAS_XLIB_SURFACE +CAIRO_HAS_XLIB_XCB_FUNCTIONS cairo_xlib_surface_create cairo_xlib_surface_create_for_bitmap cairo_xlib_surface_set_size @@ -407,6 +409,9 @@ cairo_pattern_get_type cairo_pattern_get_reference_count cairo_pattern_set_user_data cairo_pattern_get_user_data +cairo_dither_t +cairo_pattern_set_dither +cairo_pattern_get_dither
@@ -433,6 +438,8 @@ cairo_raster_source_finish_func_t cairo-tag CAIRO_TAG_DEST CAIRO_TAG_LINK +CAIRO_TAG_CONTENT +CAIRO_TAG_CONTENT_REF cairo_tag_begin cairo_tag_end
@@ -757,6 +764,7 @@ cairo_get_status_string cairo_status_string CAIRO_FONT_TYPE_ATSUI cairo_atsui_font_face_create_for_atsu_font_id +CAIRO_HAS_GOBJECT_FUNCTIONS
@@ -772,3 +780,12 @@ cairo_script_surface_create cairo_script_surface_create_for_target cairo_script_write_comment
+ +
+cairo-tee +CAIRO_HAS_TEE_SURFACE +cairo_tee_surface_create +cairo_tee_surface_add +cairo_tee_surface_index +cairo_tee_surface_remove +
diff --git a/meson-cc-tests/atomic-ops-c11.c b/meson-cc-tests/atomic-ops-c11.c new file mode 100644 index 000000000..4d60e998f --- /dev/null +++ b/meson-cc-tests/atomic-ops-c11.c @@ -0,0 +1,12 @@ +#include +#include + +/* We require lock free atomics for int and pointers as cairo assumes + * an int* can be cast to cairo_atomic_int_t* + */ +_Static_assert (ATOMIC_INT_LOCK_FREE == 2, "Lock free atomics not supported"); +_Static_assert (ATOMIC_POINTER_LOCK_FREE == 2, "Lock free atomics not supported"); + +int atomic_add(atomic_int *i) { return atomic_fetch_add_explicit(i, 1, memory_order_seq_cst); } +int atomic_cmpxchg(atomic_int *i, int j, int k) { return atomic_compare_exchange_strong_explicit (i, &j, k, memory_order_seq_cst, memory_order_seq_cst); } +int main(void) { return 0; } diff --git a/meson-cc-tests/ft_has_color.c b/meson-cc-tests/ft_has_color.c deleted file mode 100644 index daeed7f35..000000000 --- a/meson-cc-tests/ft_has_color.c +++ /dev/null @@ -1,7 +0,0 @@ -#include -#include FT_FREETYPE_H - -int main(void) { - FT_Long has_color = FT_HAS_COLOR(((FT_Face)NULL)); - return 0; -} diff --git a/meson.build b/meson.build index c4fcd675b..6dafaad6e 100644 --- a/meson.build +++ b/meson.build @@ -1,12 +1,15 @@ -project('cairo', 'c', 'cpp', - meson_version: '>= 0.56.0', +project('cairo', 'c', + meson_version: '>= 1.3.0', version: run_command(find_program('version.py'), check: true).stdout().strip(), - default_options: ['warning_level=2'], + default_options: ['c_std=gnu11,c11', + 'cpp_std=gnu++11,c++11', + 'warning_level=2'], ) -freetype_required_version = '>= 9.7.3' -freetype_colrv1_required_version = '>= 25.0.19' -fontconfig_required_version = '>= 2.2.95' +freetype_required_version = '>= 23.0.17' # Release version 2.10 +freetype_colrv1_required_version = '>= 25.0.19' # Release version 2.13 +fontconfig_required_version = '>= 2.13.0' +libpng_required_version = '>= 1.4.0' xrender_required_version = '>= 0.6' xcb_required_version = '>= 1.6' xcb_render_required_version = '>= 1.6' @@ -73,7 +76,7 @@ if cc.get_id() != 'msvc' endif supported_cflags = cc.get_supported_arguments(cflags) - add_project_arguments(supported_cflags, language: 'c') + add_project_arguments(supported_cflags, language: ['c', 'cpp']) # We only wish to enable attribute(warn_unused_result) if we can prevent # gcc from generating thousands of warnings about the misapplication of the @@ -92,20 +95,13 @@ if cc.get_id() == 'msvc' add_project_arguments('/wd4244', '/wd4146', # Don't warn about double -> float truncation '/wd4305', - language : 'c') + # Don't warn about _cairo_status -> _cairo_int_status conversion + '/wd5286', + language : ['c', 'cpp']) + add_project_arguments('-D_CRT_SECURE_NO_WARNINGS', language : ['c', 'cpp']) endif -add_project_arguments('-D_GNU_SOURCE', language: 'c') - -# Make sure source directory hasn't been configured with autotools -fs = import('fs') -if fs.exists('config.h') or fs.exists('src/cairo-features.h') or fs.exists('src/cairo-supported-features.h') - error(''' - The source directory '@0@' appears to contain - autotools configuration artifacts. This can cause difficult to - debug build problems. Please clean it up and then re-run meson. - '''.format(meson.source_root())) -endif +add_project_arguments('-D_GNU_SOURCE', language: ['c', 'cpp']) pkgmod = import('pkgconfig') python3 = import('python').find_installation() @@ -145,6 +141,8 @@ check_headers = [ ['xlocale.h'], ['sys/ioctl.h'], ['intsafe.h'], + ['alloca.h'], + ['termios.h'], ] check_types = [ @@ -185,6 +183,10 @@ test_deps = [] internal_deps = [] extra_link_args = [] +extra_link_args += cc.get_supported_link_arguments([ + '-Wl,-Bsymbolic-functions', +]) + if host_machine.endian() == 'big' conf.set('WORDS_BIGENDIAN', 1) endif @@ -201,7 +203,7 @@ else endif endif -lzo_dep = dependency('lzo2', required: false) +lzo_dep = dependency('lzo2', required: get_option('lzo')) if lzo_dep.found() conf.set('HAVE_LZO', 1) endif @@ -238,6 +240,7 @@ endif png_dep = dependency('libpng', required: get_option('png'), + version: libpng_required_version, fallback: ['libpng', 'libpng_dep'] ) if png_dep.found() @@ -263,12 +266,10 @@ if png_dep.found() endif endif -# Don't build fontconfig as a subproject on Windows unless -# explicitly requested +# Disable fontconfig by default on platforms where it is optional fontconfig_option = get_option('fontconfig') -if host_machine.system() == 'windows' and not fontconfig_option.enabled() - fontconfig_option = false -endif +fontconfig_required = host_machine.system() not in ['windows', 'darwin'] +fontconfig_option = fontconfig_option.disable_auto_if(not fontconfig_required) fontconfig_dep = dependency('fontconfig', required: fontconfig_option, @@ -301,8 +302,13 @@ endif ttx = find_program('ttx', required: false) +# Disable FreeType by default on platforms where it is optional +freetype_option = get_option('freetype') +freetype_required = host_machine.system() not in ['windows', 'darwin'] +freetype_option = freetype_option.disable_auto_if(not freetype_required) + freetype_dep = dependency('freetype2', - required: get_option('freetype'), + required: freetype_option, version: freetype_required_version, fallback: ['freetype2', 'freetype_dep'], ) @@ -310,32 +316,20 @@ if freetype_dep.found() feature_conf.set('CAIRO_HAS_FT_FONT', 1) built_features += [{ 'name': 'cairo-ft', - 'description': 'Freetype font backend', + 'description': 'FreeType font backend', 'deps': [freetype_dep], # cairo-ft.h includes fontconfig.h so it needs its cflags 'compile-deps': [fontconfig_dep.partial_dependency(compile_args: true, includes: true)], }] - ft_check_funcs = [ - 'FT_Get_X11_Font_Format', - 'FT_GlyphSlot_Embolden', - 'FT_GlyphSlot_Oblique', - 'FT_Load_Sfnt_Table', - 'FT_Library_SetLcdFilter', - 'FT_Get_Var_Design_Coordinates', - 'FT_Done_MM_Var', - 'FT_Palette_Select', - ] - if freetype_dep.type_name() == 'internal' - foreach func : ft_check_funcs - conf.set('HAVE_@0@'.format(func.to_upper()), 1) - endforeach + if freetype_dep.version().version_compare(freetype_colrv1_required_version) + conf.set('HAVE_FT_SVG_DOCUMENT', 1) + conf.set('HAVE_FT_LOAD_NO_SVG', 1) + conf.set('HAVE_FT_COLR_V1', 1) + endif internal_deps += [freetype_dep] else - if not cc.links(files('meson-cc-tests/ft_has_color.c'), dependencies: freetype_dep, name: 'FT has color') - conf.set('FT_HAS_COLOR', '(0)') - endif if png_dep.found() and \ cc.has_type('FT_SVG_Document', dependencies: freetype_dep, prefix: '#include ') conf.set('HAVE_FT_SVG_DOCUMENT', 1) @@ -343,11 +337,13 @@ if freetype_dep.found() conf.set('CAIRO_CAN_TEST_TTX_FONT', 1) endif endif + if cc.has_define('FT_LOAD_NO_SVG', dependencies: freetype_dep, prefix: '#include ') + conf.set('HAVE_FT_LOAD_NO_SVG', 1) + endif if freetype_dep.version().version_compare(freetype_colrv1_required_version) and \ cc.has_function('FT_Get_Color_Glyph_Paint', dependencies: freetype_dep) conf.set('HAVE_FT_COLR_V1', 1) endif - check_funcs += ft_check_funcs deps += [freetype_dep] endif endif @@ -372,7 +368,7 @@ if x11_dep.found() and xext_dep.found() # Can skip the run check by providing the result in a cross file or # native file as bool property value. - prop = meson.get_external_property('ipc_rmid_deferred_release', 'auto') + prop = meson.get_external_property('ipc_rmid_deferred_release', meson.is_cross_build() ? 'false' : 'auto') # We don't know the type of prop (bool, string) but need to differentiate # between a set value (bool) or the fallback value (string), so convert to # a string and check the string value. @@ -492,6 +488,8 @@ if host_machine.system() == 'darwin' and not get_option('quartz').disabled() endif if host_machine.system() == 'windows' + add_languages('cpp', native: false) + add_project_arguments('-DWIN32_LEAN_AND_MEAN', '-DNOMINMAX', language: ['c', 'cpp']) win32_extra_deps = [ @@ -541,7 +539,7 @@ if host_machine.system() == 'windows' add_project_arguments('-DWINVER=_WIN32_WINNT_WIN10', '-D_WIN32_WINNT=_WIN32_WINNT_WIN10', '-DNTDDI_VERSION=NTDDI_WIN10_RS3', language: ['c', 'cpp']) else - add_project_arguments('-DWINVER=_WIN32_WINNT_WIN2K', '-D_WIN32_WINNT=_WIN32_WINNT_WIN2K', language: ['c', 'cpp']) + add_project_arguments('-DWINVER=_WIN32_WINNT_VISTA', '-D_WIN32_WINNT=_WIN32_WINNT_VISTA', language: ['c', 'cpp']) endif endif @@ -636,12 +634,15 @@ if feature_conf.get('CAIRO_HAS_SVG_SURFACE', 0) == 1 endif pixman_dep = dependency('pixman-1', - version: '>= 0.36.0', + version: '>= 0.40.0', fallback: ['pixman', 'idep_pixman'], ) if pixman_dep.found() feature_conf.set('CAIRO_HAS_IMAGE_SURFACE', 1) conf.set('HAS_PIXMAN_GLYPHS', 1) + if pixman_dep.version().version_compare('>= 0.42.3') + conf.set('HAS_PIXMAN_r8g8b8_sRGB', 1) + endif if pixman_dep.type_name() == 'internal' internal_deps += [pixman_dep] else @@ -734,14 +735,22 @@ endforeach extra_link_args += pthread_link_args -if cc.links(files('meson-cc-tests/atomic-ops-cxx11.c'), name: 'Atomic ops: cxx11') - conf.set('HAVE_CXX11_ATOMIC_PRIMITIVES', 1) -elif cc.links(files('meson-cc-tests/atomic-ops-gcc-legacy.c'), name: 'Atomic ops: gcc legacy') - conf.set('HAVE_GCC_LEGACY_ATOMICS', 1) -elif cc.has_header('atomic_ops.h') - conf.set('HAVE_LIB_ATOMIC_OPS', 1) -elif cc.has_header('libkern/OSAtomic.h') - conf.set('HAVE_OS_ATOMIC_OPS', 1) +# Atomics are an optional feature in C11. Also need to check that C11 atomics are lock free. +# On Windows we use the Interlocked family of functions +if host_machine.system() != 'windows' + if cc.links(files('meson-cc-tests/atomic-ops-c11.c'), name: 'Atomic ops: c11') + conf.set('HAVE_C11_ATOMIC_PRIMITIVES', 1) + elif cc.links(files('meson-cc-tests/atomic-ops-cxx11.c'), name: 'Atomic ops: cxx11') + conf.set('HAVE_CXX11_ATOMIC_PRIMITIVES', 1) + elif cc.links(files('meson-cc-tests/atomic-ops-gcc-legacy.c'), name: 'Atomic ops: gcc legacy') + conf.set('HAVE_GCC_LEGACY_ATOMICS', 1) + elif cc.has_header('atomic_ops.h') + conf.set('HAVE_LIB_ATOMIC_OPS', 1) + elif cc.has_header('libkern/OSAtomic.h') + conf.set('HAVE_OS_ATOMIC_OPS', 1) + else + warning('Atomic ops not supported.') + endif endif test_mkdir_c_args = [] @@ -765,7 +774,7 @@ if not ['x86', 'x86_64'].contains(host_machine.cpu_family()) conf.set('ATOMIC_OP_NEEDS_MEMORY_BARRIER', 1) endif -have_ld_preload = ['linux', 'freebsd', 'darwin', 'dragonfly'].contains(host_machine.system()) +have_ld_preload = ['linux', 'freebsd', 'darwin', 'dragonfly', 'sunos'].contains(host_machine.system()) if have_ld_preload and zlib_dep.found() and conf.get('CAIRO_HAS_REAL_PTHREAD', 0) == 1 and conf.get('CAIRO_HAS_DLSYM', 0) == 1 conf.set('CAIRO_HAS_TRACE', 1) diff --git a/meson_options.txt b/meson.options similarity index 91% rename from meson_options.txt rename to meson.options index 5b96940dd..8aa6814bb 100644 --- a/meson_options.txt +++ b/meson.options @@ -6,7 +6,7 @@ option('freetype', type : 'feature', value : 'auto') # Cairo surface backends option('png', type : 'feature', value : 'auto') # png and svg surfaces option('quartz', type : 'feature', value : 'auto') -option('tee', type : 'feature', value : 'disabled') +option('tee', type : 'feature', value : 'auto') option('xcb', type : 'feature', value : 'auto') option('xlib', type : 'feature', value : 'auto') option('xlib-xcb', type : 'feature', value : 'disabled') @@ -16,6 +16,7 @@ option('zlib', type : 'feature', value : 'auto') # script, ps, pdf, xml surfaces option('tests', type : 'feature', value : 'auto') # Util deps +option('lzo', type : 'feature', value : 'auto') option('gtk2-utils', type : 'feature', value : 'disabled') # Misc deps diff --git a/perf/cairo-perf-print.c b/perf/cairo-perf-print.c index ab1440f55..e9c493fa3 100644 --- a/perf/cairo-perf-print.c +++ b/perf/cairo-perf-print.c @@ -43,6 +43,9 @@ #if USE_TERMINAL_SIZE #include #include +#if HAVE_TERMIOS_H +#include +#endif #endif static void diff --git a/src/cairo-analysis-surface.c b/src/cairo-analysis-surface.c index 6889be38f..f6099c41b 100644 --- a/src/cairo-analysis-surface.c +++ b/src/cairo-analysis-surface.c @@ -123,7 +123,7 @@ attach_proxy (cairo_surface_t *source, { struct proxy *proxy; - proxy = _cairo_malloc (sizeof (*proxy)); + proxy = _cairo_calloc (sizeof (*proxy)); if (unlikely (proxy == NULL)) return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY); @@ -953,7 +953,7 @@ _cairo_analysis_surface_create (cairo_surface_t *target, if (unlikely (status)) return _cairo_surface_create_in_error (status); - surface = _cairo_malloc (sizeof (cairo_analysis_surface_t)); + surface = _cairo_calloc (sizeof (cairo_analysis_surface_t)); if (unlikely (surface == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); @@ -1213,7 +1213,7 @@ _cairo_null_surface_create (cairo_content_t content) { cairo_surface_t *surface; - surface = _cairo_malloc (sizeof (cairo_surface_t)); + surface = _cairo_calloc (sizeof (cairo_surface_t)); if (unlikely (surface == NULL)) { return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); } diff --git a/src/cairo-arc.c b/src/cairo-arc.c index 1c891d1a0..010b9c1a7 100644 --- a/src/cairo-arc.c +++ b/src/cairo-arc.c @@ -188,6 +188,9 @@ _cairo_arc_in_direction (cairo_t *cr, if (cairo_status (cr)) return; + if (! ISFINITE (angle_max) || ! ISFINITE (angle_min)) + return; + assert (angle_max >= angle_min); if (angle_max - angle_min > 2 * M_PI * MAX_FULL_CIRCLES) { diff --git a/src/cairo-array.c b/src/cairo-array.c index 064b63f29..a4a4f8c84 100644 --- a/src/cairo-array.c +++ b/src/cairo-array.c @@ -40,7 +40,7 @@ #include "cairo-array-private.h" #include "cairo-error-private.h" -/** +/*< private > * _cairo_array_init: * * Initialize a new #cairo_array_t object to store objects each of size @@ -63,7 +63,7 @@ _cairo_array_init (cairo_array_t *array, unsigned int element_size) array->elements = NULL; } -/** +/*< private > * _cairo_array_fini: * @array: A #cairo_array_t * @@ -77,7 +77,7 @@ _cairo_array_fini (cairo_array_t *array) free (array->elements); } -/** +/*< private > * _cairo_array_grow_by: * @array: a #cairo_array_t * @@ -125,7 +125,7 @@ _cairo_array_grow_by (cairo_array_t *array, unsigned int additional) return CAIRO_STATUS_SUCCESS; } -/** +/*< private > * _cairo_array_truncate: * @array: a #cairo_array_t * @@ -140,7 +140,7 @@ _cairo_array_truncate (cairo_array_t *array, unsigned int num_elements) array->num_elements = num_elements; } -/** +/*< private > * _cairo_array_index: * @array: a #cairo_array_t * @@ -149,7 +149,7 @@ _cairo_array_truncate (cairo_array_t *array, unsigned int num_elements) * pointer may be used for further direct indexing with []. For * example: * - * + * |[ * cairo_array_t array; * double *values; * @@ -159,7 +159,7 @@ _cairo_array_truncate (cairo_array_t *array, unsigned int num_elements) * values = _cairo_array_index (&array, 0); * for (i = 0; i < _cairo_array_num_elements (&array); i++) * ... use values[i] here ... - * + * ]| * * Returns: A pointer to the object stored at @index. **/ @@ -185,7 +185,7 @@ _cairo_array_index (cairo_array_t *array, unsigned int index) return array->elements + (size_t)index * array->element_size; } -/** +/*< private > * _cairo_array_index_const: * @array: a #cairo_array_t * @@ -194,7 +194,7 @@ _cairo_array_index (cairo_array_t *array, unsigned int index) * pointer may be used for further direct indexing with []. For * example: * - * + * |[ * struct foo { * int a; * cairo_list_t list; @@ -107,7 +107,7 @@ * printf("%d\n", pos->a); * cairo_list_del (pos); * } - * + * ]| **/ #define cairo_list_foreach_entry_safe(pos, n, type, head, member) \ for (pos = cairo_list_entry ((head)->next, type, member),\ @@ -115,7 +115,7 @@ &pos->member != (head); \ pos = n, n = cairo_list_entry (n->member.next, type, member)) -/** +/*< private > * cairo_list_foreach_entry: * @pos: a variable of type T * to use as a loop variable. * @type: the type of the entry struct @@ -129,7 +129,7 @@ &pos->member != (head); \ pos = cairo_list_entry(pos->member.prev, type, member)) -/** +/*< private > * cairo_list_foreach_entry_safe: * @pos: a variable of type T * to use as a loop variable. * @n: a variable of type T * that point to the next item after @pos. @@ -175,7 +175,7 @@ cairo_list_validate_is_empty (const cairo_list_t *head) #define cairo_list_validate_is_empty(head) #endif -/** +/*< private > * cairo_list_init: * @entry: list entry to initialize * @@ -200,7 +200,7 @@ __cairo_list_add (cairo_list_t *entry, prev->next = entry; } -/** +/*< private > * cairo_list_add: * @entry: new entry * @head: linked list head @@ -216,7 +216,7 @@ cairo_list_add (cairo_list_t *entry, cairo_list_t *head) cairo_list_validate (head); } -/** +/*< private > * cairo_list_add_tail: * @entry: new entry * @head: linked list head @@ -245,7 +245,7 @@ _cairo_list_del (cairo_list_t *entry) __cairo_list_del (entry->prev, entry->next); } -/** +/*< private > * cairo_list_del: * @entry: entry to remove * @@ -258,7 +258,7 @@ cairo_list_del (cairo_list_t *entry) cairo_list_init (entry); } -/** +/*< private > * cairo_list_move: * @entry: entry to move * @head: linked list to move @entry to @@ -274,7 +274,7 @@ cairo_list_move (cairo_list_t *entry, cairo_list_t *head) cairo_list_validate (head); } -/** +/*< private > * cairo_list_move_tail: * @entry: entry tp move * @head: linked list to move @entry to @@ -290,7 +290,7 @@ cairo_list_move_tail (cairo_list_t *entry, cairo_list_t *head) cairo_list_validate (head); } -/** +/*< private > * cairo_list_move_list: * @old: List to move * @new: List to move to. Should be empty, @@ -304,7 +304,7 @@ cairo_list_move_list (cairo_list_t *old, cairo_list_t *new) cairo_list_init (old); } -/** +/*< private > * cairo_list_is_first: * @entry: entry to check * @head: linked list @@ -319,7 +319,7 @@ cairo_list_is_first (const cairo_list_t *entry, return entry->prev == head; } -/** +/*< private > * cairo_list_is_last: * @entry: entry to check * @head: linked list @@ -334,7 +334,7 @@ cairo_list_is_last (const cairo_list_t *entry, return entry->next == head; } -/** +/*< private > * cairo_list_is_empty: * @head: linked list * @@ -347,7 +347,7 @@ cairo_list_is_empty (const cairo_list_t *head) return head->next == head; } -/** +/*< private > * cairo_list_is_singular: * @head: linked list * diff --git a/src/cairo-malloc-private.h b/src/cairo-malloc-private.h index 0de52a561..b850c475c 100644 --- a/src/cairo-malloc-private.h +++ b/src/cairo-malloc-private.h @@ -62,6 +62,22 @@ #define _cairo_malloc(size) \ ((size) != 0 ? malloc(size) : NULL) +/** + * _cairo_calloc: + * @size: size of each element + * + * Allocates @size memory using calloc(). Behaves much like + * calloc(), except that only one parameter is required. + * The memory should be freed using free(). + * calloc 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 calloc() failure or overflow. + **/ + +#define _cairo_calloc(size) \ + ((size) != 0 ? calloc(1,size) : NULL) + /** * _cairo_malloc_ab: * @a: number of elements to allocate @@ -89,6 +105,31 @@ _cairo_malloc_ab(size_t a, size_t size) return _cairo_malloc(c); } +/** + * _cairo_calloc_ab: + * @a: number of elements to allocate + * @size: size of each element + * + * Allocates @a*@size memory using _cairo_calloc(), taking care to not + * overflow when doing the multiplication. + * + * @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 calloc() failure or overflow. + **/ + +static cairo_always_inline void * +_cairo_calloc_ab(size_t a, size_t size) +{ + size_t c; + if (_cairo_mul_size_t_overflow (a, size, &c)) + return NULL; + + return _cairo_calloc(c); +} + /** * _cairo_realloc_ab: * @ptr: original pointer to block of memory to be resized diff --git a/src/cairo-matrix.c b/src/cairo-matrix.c index e8fd097ae..f2be48b74 100644 --- a/src/cairo-matrix.c +++ b/src/cairo-matrix.c @@ -85,7 +85,6 @@ cairo_matrix_init_identity (cairo_matrix_t *matrix) 0, 1, 0, 0); } -slim_hidden_def(cairo_matrix_init_identity); /** * cairo_matrix_init: @@ -118,7 +117,6 @@ cairo_matrix_init (cairo_matrix_t *matrix, matrix->xy = xy; matrix->yy = yy; matrix->x0 = x0; matrix->y0 = y0; } -slim_hidden_def(cairo_matrix_init); /** * _cairo_matrix_get_affine: @@ -178,7 +176,6 @@ cairo_matrix_init_translate (cairo_matrix_t *matrix, 0, 1, tx, ty); } -slim_hidden_def(cairo_matrix_init_translate); /** * cairo_matrix_translate: @@ -202,7 +199,6 @@ cairo_matrix_translate (cairo_matrix_t *matrix, double tx, double ty) cairo_matrix_multiply (matrix, &tmp, matrix); } -slim_hidden_def (cairo_matrix_translate); /** * cairo_matrix_init_scale: @@ -224,7 +220,6 @@ cairo_matrix_init_scale (cairo_matrix_t *matrix, 0, sy, 0, 0); } -slim_hidden_def(cairo_matrix_init_scale); /** * cairo_matrix_scale: @@ -247,7 +242,6 @@ cairo_matrix_scale (cairo_matrix_t *matrix, double sx, double sy) cairo_matrix_multiply (matrix, &tmp, matrix); } -slim_hidden_def(cairo_matrix_scale); /** * cairo_matrix_init_rotate: @@ -277,7 +271,6 @@ cairo_matrix_init_rotate (cairo_matrix_t *matrix, -s, c, 0, 0); } -slim_hidden_def(cairo_matrix_init_rotate); /** * cairo_matrix_rotate: @@ -304,7 +297,6 @@ cairo_matrix_rotate (cairo_matrix_t *matrix, double radians) cairo_matrix_multiply (matrix, &tmp, matrix); } -slim_hidden_def (cairo_matrix_rotate); /** * cairo_matrix_multiply: @@ -344,7 +336,6 @@ cairo_matrix_multiply (cairo_matrix_t *result, const cairo_matrix_t *a, const ca *result = r; } -slim_hidden_def(cairo_matrix_multiply); void _cairo_matrix_multiply (cairo_matrix_t *r, @@ -390,7 +381,6 @@ cairo_matrix_transform_distance (const cairo_matrix_t *matrix, double *dx, doubl *dx = new_x; *dy = new_y; } -slim_hidden_def(cairo_matrix_transform_distance); /** * cairo_matrix_transform_point: @@ -410,7 +400,6 @@ cairo_matrix_transform_point (const cairo_matrix_t *matrix, double *x, double *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, @@ -621,7 +610,6 @@ cairo_matrix_invert (cairo_matrix_t *matrix) return CAIRO_STATUS_SUCCESS; } -slim_hidden_def(cairo_matrix_invert); cairo_bool_t _cairo_matrix_is_invertible (const cairo_matrix_t *matrix) diff --git a/src/cairo-mempool.c b/src/cairo-mempool.c index dd4756261..6cebaf123 100644 --- a/src/cairo-mempool.c +++ b/src/cairo-mempool.c @@ -305,7 +305,7 @@ _cairo_mempool_init (cairo_mempool_t *pool, pool->max_free_bits = -1; num_blocks = bytes >> min_bits; - pool->blocks = calloc (num_blocks, sizeof (struct _cairo_memblock)); + pool->blocks = _cairo_calloc_ab (num_blocks, sizeof (struct _cairo_memblock)); if (pool->blocks == NULL) return _cairo_error (CAIRO_STATUS_NO_MEMORY); diff --git a/src/cairo-misc.c b/src/cairo-misc.c index 6f6f9937e..59cf76fc9 100644 --- a/src/cairo-misc.c +++ b/src/cairo-misc.c @@ -48,6 +48,9 @@ #ifdef HAVE_XLOCALE_H #include #endif +#if HAVE_FCNTL_H +#include +#endif COMPILE_TIME_ASSERT ((int)CAIRO_STATUS_LAST_STATUS < (int)CAIRO_INT_STATUS_UNSUPPORTED); COMPILE_TIME_ASSERT (CAIRO_INT_STATUS_LAST_STATUS <= 127); @@ -184,7 +187,6 @@ cairo_status_to_string (cairo_status_t status) } } - /** * cairo_glyph_allocate: * @num_glyphs: number of glyphs to allocate @@ -213,7 +215,6 @@ cairo_glyph_allocate (int num_glyphs) return _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t)); } -slim_hidden_def (cairo_glyph_allocate); /** * cairo_glyph_free: @@ -233,7 +234,6 @@ cairo_glyph_free (cairo_glyph_t *glyphs) { free (glyphs); } -slim_hidden_def (cairo_glyph_free); /** * cairo_text_cluster_allocate: @@ -263,7 +263,6 @@ cairo_text_cluster_allocate (int num_clusters) return _cairo_malloc_ab (num_clusters, sizeof (cairo_text_cluster_t)); } -slim_hidden_def (cairo_text_cluster_allocate); /** * cairo_text_cluster_free: @@ -283,8 +282,6 @@ cairo_text_cluster_free (cairo_text_cluster_t *clusters) { free (clusters); } -slim_hidden_def (cairo_text_cluster_free); - /* Private stuff */ @@ -809,12 +806,12 @@ get_C_locale (void) locale_t C; retry: - C = (locale_t) _cairo_atomic_ptr_get ((void **) &C_locale); + C = (locale_t) _cairo_atomic_ptr_get ((cairo_atomic_intptr_t *) &C_locale); if (unlikely (!C)) { C = newlocale (LC_ALL_MASK, "C", NULL); - if (!_cairo_atomic_ptr_cmpxchg ((void **) &C_locale, NULL, C)) { + if (!_cairo_atomic_ptr_cmpxchg ((cairo_atomic_intptr_t *) &C_locale, NULL, C)) { freelocale (C_locale); goto retry; } @@ -962,14 +959,40 @@ _cairo_fopen (const char *filename, const char *mode, FILE **file_out) return status; } - result = _wfopen(filename_w, mode_w); + result = _wfopen (filename_w, mode_w); free (filename_w); free (mode_w); #else /* Use fopen directly */ + +#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 7) + /* Glibc 2.7 supports the "e" mode flag that opens the file with O_CLOEXEC. + * this avoid the race condition in the fcntl fallback below. */ + + char new_mode[20]; + snprintf (new_mode, sizeof (new_mode), "%s%s", mode, "e"); + result = fopen (filename, new_mode); + +#else /* fopen "e" not available */ + result = fopen (filename, mode); -#endif + +#if defined(HAVE_FCNTL_H) && defined(FD_CLOEXEC) + /* Manually set CLOEXEC */ + if (result != NULL) { + int fd = fileno (result); + if (fd != -1) { + int flags = fcntl (fd, F_GETFD); + if (flags >= 0) + flags = fcntl (fd, F_SETFD, flags | FD_CLOEXEC); + } + } +#endif /* defined(HAVE_FCNTL_H) && defined(FD_CLOEXEC) */ + +#endif /* fopen "e" not available */ + +#endif /* !_WIN32 */ *file_out = result; @@ -977,18 +1000,15 @@ _cairo_fopen (const char *filename, const char *mode, FILE **file_out) } #ifdef _WIN32 - #include #include -#if !_WIN32_WCE /* tmpfile() replacement for Windows. * * On Windows tmpfile() creates the file in the root directory. This - * may fail due to insufficient privileges. However, this isn't a - * problem on Windows CE so we don't use it there. + * may fail due to insufficient privileges. */ -FILE * +static FILE * _cairo_win32_tmpfile (void) { DWORD path_len; @@ -1002,7 +1022,7 @@ _cairo_win32_tmpfile (void) if (path_len <= 0 || path_len >= MAX_PATH) return NULL; - if (GetTempFileNameW (path_name, L"ps_", 0, file_name) == 0) + if (GetTempFileNameW (path_name, L"cairo_", 0, file_name) == 0) return NULL; handle = CreateFileW (file_name, @@ -1031,10 +1051,60 @@ _cairo_win32_tmpfile (void) return fp; } -#endif /* !_WIN32_WCE */ - #endif /* _WIN32 */ +/** + * _cairo_tmpfile: + * + * Exactly like the C library function. On platforms that support + * O_CLOEXEC, the file will be opened with this flag. On Windows, the + * file is opened in the temp directory instead of the root directory. + * + * Return value: a file handle or NULL on error. + **/ +FILE * +_cairo_tmpfile (void) +{ +#ifdef _WIN32 + return _cairo_win32_tmpfile (); +#else /* !_WIN32 */ + int fd; + FILE *file; + int flags; + +#ifdef O_TMPFILE + fd = open(P_tmpdir, + O_TMPFILE | O_EXCL | O_RDWR | O_NOATIME | O_CLOEXEC, + 0600); + if (fd == -1 && errno == ENOENT) { + fd = open("/tmp", + O_TMPFILE | O_EXCL | O_RDWR | O_NOATIME | O_CLOEXEC, + 0600); + } + if (fd != -1) + return fdopen (fd, "wb+"); + + /* Fallback */ +#endif /* O_TMPFILE */ + + file = tmpfile(); + +#if defined(HAVE_FCNTL_H) && defined(FD_CLOEXEC) + /* Manually set CLOEXEC */ + if (file != NULL) { + fd = fileno(file); + if (fd != -1) { + flags = fcntl(fd, F_GETFD); + if (flags >= 0 && !(flags & FD_CLOEXEC)) + fcntl(fd, F_SETFD, flags | FD_CLOEXEC); + } + } +#endif /* defined(HAVE_FCNTL_H) && defined(FD_CLOEXEC) */ + + return file; +#endif /* !_WIN32 */ +} + typedef struct _cairo_intern_string { cairo_hash_entry_t hash_entry; int len; diff --git a/src/cairo-mono-scan-converter.c b/src/cairo-mono-scan-converter.c index 32ddfcc51..e7c8ddb1e 100644 --- a/src/cairo-mono-scan-converter.c +++ b/src/cairo-mono-scan-converter.c @@ -562,7 +562,7 @@ _cairo_mono_scan_converter_create (int xmin, cairo_mono_scan_converter_t *self; cairo_status_t status; - self = _cairo_malloc (sizeof(struct _cairo_mono_scan_converter)); + self = _cairo_calloc (sizeof(struct _cairo_mono_scan_converter)); if (unlikely (self == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto bail_nomem; diff --git a/src/cairo-mutex-list-private.h b/src/cairo-mutex-list-private.h index af5cc0517..48f74f2c3 100644 --- a/src/cairo-mutex-list-private.h +++ b/src/cairo-mutex-list-private.h @@ -53,7 +53,6 @@ CAIRO_MUTEX_DECLARE (_cairo_ft_unscaled_font_map_mutex) #if CAIRO_HAS_WIN32_FONT CAIRO_MUTEX_DECLARE (_cairo_win32_font_face_mutex) -CAIRO_MUTEX_DECLARE (_cairo_win32_font_dc_mutex) #endif #if CAIRO_HAS_XLIB_SURFACE diff --git a/src/cairo-mutex-private.h b/src/cairo-mutex-private.h index 65732a180..6b3eb0365 100644 --- a/src/cairo-mutex-private.h +++ b/src/cairo-mutex-private.h @@ -53,9 +53,15 @@ 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 + +#if HAS_ATOMIC_OPS + cairo_private extern cairo_atomic_int_t _cairo_mutex_initialized; +#else cairo_private extern int _cairo_mutex_initialized; #endif +#endif + /* Finally, extern the static mutexes and undef */ #define CAIRO_MUTEX_DECLARE(mutex) cairo_private extern cairo_mutex_t mutex; diff --git a/src/cairo-mutex.c b/src/cairo-mutex.c index 5b6debeca..89acad525 100644 --- a/src/cairo-mutex.c +++ b/src/cairo-mutex.c @@ -51,7 +51,11 @@ # define _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VALUE _CAIRO_MUTEX_INITIALIZED # endif +#if HAS_ATOMIC_OPS +cairo_atomic_int_t _cairo_mutex_initialized = _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VALUE; +#else int _cairo_mutex_initialized = _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VALUE; +#endif # undef _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VALUE diff --git a/src/cairo-output-stream.c b/src/cairo-output-stream.c index 7305b52ca..799a73e04 100644 --- a/src/cairo-output-stream.c +++ b/src/cairo-output-stream.c @@ -148,7 +148,7 @@ _cairo_output_stream_create (cairo_write_func_t write_func, { cairo_output_stream_with_closure_t *stream; - stream = _cairo_malloc (sizeof (cairo_output_stream_with_closure_t)); + stream = _cairo_calloc (sizeof (cairo_output_stream_with_closure_t)); if (unlikely (stream == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_output_stream_t *) &_cairo_output_stream_nil; @@ -174,7 +174,7 @@ _cairo_output_stream_create_in_error (cairo_status_t status) if (status == CAIRO_STATUS_WRITE_ERROR) return (cairo_output_stream_t *) &_cairo_output_stream_nil_write_error; - stream = _cairo_malloc (sizeof (cairo_output_stream_t)); + stream = _cairo_calloc (sizeof (cairo_output_stream_t)); if (unlikely (stream == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_output_stream_t *) &_cairo_output_stream_nil; @@ -655,7 +655,7 @@ _cairo_output_stream_create_for_file (FILE *file) return (cairo_output_stream_t *) &_cairo_output_stream_nil_write_error; } - stream = _cairo_malloc (sizeof *stream); + stream = _cairo_calloc (sizeof *stream); if (unlikely (stream == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_output_stream_t *) &_cairo_output_stream_nil; @@ -694,7 +694,7 @@ _cairo_output_stream_create_for_filename (const char *filename) } } - stream = _cairo_malloc (sizeof *stream); + stream = _cairo_calloc (sizeof *stream); if (unlikely (stream == NULL)) { fclose (file); _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); @@ -738,7 +738,7 @@ _cairo_memory_stream_create (void) { memory_stream_t *stream; - stream = _cairo_malloc (sizeof *stream); + stream = _cairo_calloc (sizeof *stream); if (unlikely (stream == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_output_stream_t *) &_cairo_output_stream_nil; @@ -765,7 +765,7 @@ _cairo_memory_stream_destroy (cairo_output_stream_t *abstract_stream, stream = (memory_stream_t *) abstract_stream; *length_out = _cairo_array_num_elements (&stream->array); - *data_out = _cairo_malloc (*length_out); + *data_out = _cairo_calloc (*length_out); if (unlikely (*data_out == NULL)) { status = _cairo_output_stream_destroy (abstract_stream); assert (status == CAIRO_STATUS_SUCCESS); @@ -812,7 +812,7 @@ _cairo_null_stream_create (void) { cairo_output_stream_t *stream; - stream = _cairo_malloc (sizeof *stream); + stream = _cairo_calloc (sizeof *stream); if (unlikely (stream == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_output_stream_t *) &_cairo_output_stream_nil; diff --git a/src/cairo-paginated-surface.c b/src/cairo-paginated-surface.c index ac24745e3..ff05ecd51 100644 --- a/src/cairo-paginated-surface.c +++ b/src/cairo-paginated-surface.c @@ -99,7 +99,7 @@ _cairo_paginated_surface_create (cairo_surface_t *target, cairo_paginated_surface_t *surface; cairo_status_t status; - surface = _cairo_malloc (sizeof (cairo_paginated_surface_t)); + surface = _cairo_calloc (sizeof (cairo_paginated_surface_t)); if (unlikely (surface == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto FAIL; diff --git a/src/cairo-path-fixed.c b/src/cairo-path-fixed.c index fc146f3b3..ca759447e 100644 --- a/src/cairo-path-fixed.c +++ b/src/cairo-path-fixed.c @@ -325,7 +325,7 @@ _cairo_path_fixed_create (void) { cairo_path_fixed_t *path; - path = _cairo_malloc (sizeof (cairo_path_fixed_t)); + path = _cairo_calloc (sizeof (cairo_path_fixed_t)); if (!path) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return NULL; diff --git a/src/cairo-path-stroke.c b/src/cairo-path-stroke.c index 9ebeb6cd3..60f647eb7 100644 --- a/src/cairo-path-stroke.c +++ b/src/cairo-path-stroke.c @@ -162,6 +162,10 @@ _cairo_stroker_init (cairo_stroker_t *stroker, stroker->has_first_face = FALSE; stroker->has_initial_sub_path = FALSE; + /* Coverity complains these may be unitialized. */ + memset (&stroker->current_face, 0, sizeof (cairo_stroke_face_t)); + memset (&stroker->first_face, 0, sizeof (cairo_stroke_face_t)); + _cairo_stroker_dash_init (&stroker->dash, stroke_style); stroker->add_external_edge = NULL; diff --git a/src/cairo-path.c b/src/cairo-path.c index 566e86f5a..6f7a9cef0 100644 --- a/src/cairo-path.c +++ b/src/cairo-path.c @@ -294,7 +294,7 @@ _cairo_path_create_in_error (cairo_status_t status) if (status == CAIRO_STATUS_NO_MEMORY) return (cairo_path_t*) &_cairo_path_nil; - path = _cairo_malloc (sizeof (cairo_path_t)); + path = _cairo_calloc (sizeof (cairo_path_t)); if (unlikely (path == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_path_t*) &_cairo_path_nil; @@ -314,7 +314,7 @@ _cairo_path_create_internal (cairo_path_fixed_t *path_fixed, { cairo_path_t *path; - path = _cairo_malloc (sizeof (cairo_path_t)); + path = _cairo_calloc (sizeof (cairo_path_t)); if (unlikely (path == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_path_t*) &_cairo_path_nil; @@ -372,7 +372,6 @@ cairo_path_destroy (cairo_path_t *path) free (path); } -slim_hidden_def (cairo_path_destroy); /** * _cairo_path_create: diff --git a/src/cairo-pattern-private.h b/src/cairo-pattern-private.h index d061b39c4..0e69d0177 100644 --- a/src/cairo-pattern-private.h +++ b/src/cairo-pattern-private.h @@ -52,6 +52,7 @@ enum { CAIRO_PATTERN_NOTIFY_FILTER = 0x2, CAIRO_PATTERN_NOTIFY_EXTEND = 0x4, CAIRO_PATTERN_NOTIFY_OPACITY = 0x9, + CAIRO_PATTERN_NOTIFY_DITHER = 0x12, }; struct _cairo_pattern_observer { @@ -73,6 +74,7 @@ struct _cairo_pattern { cairo_extend_t extend; cairo_bool_t has_component_alpha; cairo_bool_t is_foreground_marker; + cairo_dither_t dither; cairo_matrix_t matrix; double opacity; diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c index 2c0ba31f8..4d713e6c6 100644 --- a/src/cairo-pattern.c +++ b/src/cairo-pattern.c @@ -63,6 +63,14 @@ * functions. **/ +/** + * CAIRO_HAS_MIME_SURFACE: + * + * Unused symbol, always defined. + * + * Since: 1.12 + **/ + static freed_pool_t freed_pattern_pool[5]; static const cairo_solid_pattern_t _cairo_pattern_nil = { @@ -77,6 +85,7 @@ static const cairo_solid_pattern_t _cairo_pattern_nil = { CAIRO_EXTEND_GRADIENT_DEFAULT, /* extend */ FALSE, /* has component alpha */ FALSE, /* is_foreground_marker */ + CAIRO_DITHER_DEFAULT, /* dither */ { 1., 0., 0., 1., 0., 0., }, /* matrix */ 1.0 /* opacity */ } @@ -94,6 +103,7 @@ static const cairo_solid_pattern_t _cairo_pattern_nil_null_pointer = { CAIRO_EXTEND_GRADIENT_DEFAULT, /* extend */ FALSE, /* has component alpha */ FALSE, /* is_foreground_marker */ + CAIRO_DITHER_DEFAULT, /* dither */ { 1., 0., 0., 1., 0., 0., }, /* matrix */ 1.0 /* opacity */ } @@ -111,6 +121,7 @@ const cairo_solid_pattern_t _cairo_pattern_black = { CAIRO_EXTEND_REPEAT, /* extend */ FALSE, /* has component alpha */ FALSE, /* is_foreground_marker */ + CAIRO_DITHER_DEFAULT, /* dither */ { 1., 0., 0., 1., 0., 0., }, /* matrix */ 1.0 /* opacity */ }, @@ -129,6 +140,7 @@ const cairo_solid_pattern_t _cairo_pattern_clear = { CAIRO_EXTEND_REPEAT, /* extend */ FALSE, /* has component alpha */ FALSE, /* is_foreground_marker */ + CAIRO_DITHER_DEFAULT, /* dither */ { 1., 0., 0., 1., 0., 0., }, /* matrix */ 1.0 /* opacity */ }, @@ -147,6 +159,7 @@ const cairo_solid_pattern_t _cairo_pattern_white = { CAIRO_EXTEND_REPEAT, /* extend */ FALSE, /* has component alpha */ FALSE, /* is_foreground_marker */ + CAIRO_DITHER_DEFAULT, /* dither */ { 1., 0., 0., 1., 0., 0., }, /* matrix */ 1.0 /* opacity */ }, @@ -240,6 +253,8 @@ _cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type) pattern->has_component_alpha = FALSE; pattern->is_foreground_marker = FALSE; + pattern->dither = CAIRO_DITHER_DEFAULT; + cairo_matrix_init_identity (&pattern->matrix); cairo_list_init (&pattern->observers); @@ -611,7 +626,7 @@ _cairo_pattern_create_solid (const cairo_color_t *color) _freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_SOLID]); if (unlikely (pattern == NULL)) { /* None cached, need to create a new pattern. */ - pattern = _cairo_malloc (sizeof (cairo_solid_pattern_t)); + pattern = _cairo_calloc (sizeof (cairo_solid_pattern_t)); if (unlikely (pattern == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_pattern_t *) &_cairo_pattern_nil; @@ -676,7 +691,6 @@ cairo_pattern_create_rgb (double red, double green, double blue) { return cairo_pattern_create_rgba (red, green, blue, 1.0); } -slim_hidden_def (cairo_pattern_create_rgb); /** * cairo_pattern_create_rgba: @@ -720,7 +734,6 @@ cairo_pattern_create_rgba (double red, double green, double blue, return _cairo_pattern_create_solid (&color); } -slim_hidden_def (cairo_pattern_create_rgba); /** * cairo_pattern_create_for_surface: @@ -755,7 +768,7 @@ cairo_pattern_create_for_surface (cairo_surface_t *surface) pattern = _freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_SURFACE]); if (unlikely (pattern == NULL)) { - pattern = _cairo_malloc (sizeof (cairo_surface_pattern_t)); + pattern = _cairo_calloc (sizeof (cairo_surface_pattern_t)); if (unlikely (pattern == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_pattern_t *)&_cairo_pattern_nil.base; @@ -769,7 +782,6 @@ cairo_pattern_create_for_surface (cairo_surface_t *surface) return &pattern->base; } -slim_hidden_def (cairo_pattern_create_for_surface); /** * cairo_pattern_create_linear: @@ -807,7 +819,7 @@ cairo_pattern_create_linear (double x0, double y0, double x1, double y1) pattern = _freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_LINEAR]); if (unlikely (pattern == NULL)) { - pattern = _cairo_malloc (sizeof (cairo_linear_pattern_t)); + pattern = _cairo_calloc (sizeof (cairo_linear_pattern_t)); if (unlikely (pattern == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_pattern_t *) &_cairo_pattern_nil.base; @@ -821,7 +833,6 @@ cairo_pattern_create_linear (double x0, double y0, double x1, double y1) return &pattern->base.base; } -slim_hidden_def (cairo_pattern_create_linear); /** * cairo_pattern_create_radial: @@ -862,7 +873,7 @@ cairo_pattern_create_radial (double cx0, double cy0, double radius0, pattern = _freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_RADIAL]); if (unlikely (pattern == NULL)) { - pattern = _cairo_malloc (sizeof (cairo_radial_pattern_t)); + pattern = _cairo_calloc (sizeof (cairo_radial_pattern_t)); if (unlikely (pattern == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_pattern_t *) &_cairo_pattern_nil.base; @@ -876,7 +887,6 @@ cairo_pattern_create_radial (double cx0, double cy0, double radius0, return &pattern->base.base; } -slim_hidden_def (cairo_pattern_create_radial); /* This order is specified in the diagram in the documentation for * cairo_pattern_create_mesh() */ @@ -1041,7 +1051,7 @@ cairo_pattern_create_mesh (void) pattern = _freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_MESH]); if (unlikely (pattern == NULL)) { - pattern = _cairo_malloc (sizeof (cairo_mesh_pattern_t)); + pattern = _cairo_calloc (sizeof (cairo_mesh_pattern_t)); if (unlikely (pattern == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_pattern_t *) &_cairo_pattern_nil.base; @@ -1057,7 +1067,6 @@ cairo_pattern_create_mesh (void) return &pattern->base; } -slim_hidden_def (cairo_pattern_create_mesh); /** * cairo_pattern_reference: @@ -1087,7 +1096,6 @@ cairo_pattern_reference (cairo_pattern_t *pattern) return pattern; } -slim_hidden_def (cairo_pattern_reference); /** * cairo_pattern_get_type: @@ -1105,7 +1113,6 @@ cairo_pattern_get_type (cairo_pattern_t *pattern) { return pattern->type; } -slim_hidden_def (cairo_pattern_get_type); /** * cairo_pattern_status: @@ -1159,7 +1166,6 @@ cairo_pattern_destroy (cairo_pattern_t *pattern) else free (pattern); } -slim_hidden_def (cairo_pattern_destroy); /** * cairo_pattern_get_reference_count: @@ -1293,7 +1299,6 @@ cairo_mesh_pattern_begin_patch (cairo_pattern_t *pattern) for (i = 0; i < 4; i++) mesh->has_color[i] = FALSE; } -slim_hidden_def (cairo_mesh_pattern_begin_patch); static void _calc_control_point (cairo_mesh_patch_t *patch, int control_point) @@ -1410,7 +1415,6 @@ cairo_mesh_pattern_end_patch (cairo_pattern_t *pattern) mesh->current_patch = NULL; } -slim_hidden_def (cairo_mesh_pattern_end_patch); /** * cairo_mesh_pattern_curve_to: @@ -1500,7 +1504,6 @@ cairo_mesh_pattern_curve_to (cairo_pattern_t *pattern, mesh->current_patch->points[i][j].y = y3; } } -slim_hidden_def (cairo_mesh_pattern_curve_to); /** * cairo_mesh_pattern_line_to: @@ -1571,7 +1574,6 @@ cairo_mesh_pattern_line_to (cairo_pattern_t *pattern, (last_point.y + 2 * y) * (1. / 3), x, y); } -slim_hidden_def (cairo_mesh_pattern_line_to); /** * cairo_mesh_pattern_move_to: @@ -1621,7 +1623,6 @@ cairo_mesh_pattern_move_to (cairo_pattern_t *pattern, mesh->current_patch->points[0][0].x = x; mesh->current_patch->points[0][0].y = y; } -slim_hidden_def (cairo_mesh_pattern_move_to); /** * cairo_mesh_pattern_set_control_point: @@ -1840,7 +1841,6 @@ cairo_mesh_pattern_set_corner_color_rgba (cairo_pattern_t *pattern, _cairo_mesh_pattern_set_corner_color (mesh, corner_num, red, green, blue, alpha); } -slim_hidden_def (cairo_mesh_pattern_set_corner_color_rgba); static void _cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern, @@ -1984,7 +1984,6 @@ cairo_pattern_add_color_stop_rgba (cairo_pattern_t *pattern, _cairo_pattern_add_color_stop ((cairo_gradient_pattern_t *) pattern, offset, red, green, blue, alpha); } -slim_hidden_def (cairo_pattern_add_color_stop_rgba); /** * cairo_pattern_set_matrix: @@ -2041,7 +2040,6 @@ cairo_pattern_set_matrix (cairo_pattern_t *pattern, if (unlikely (status)) status = _cairo_pattern_set_error (pattern, status); } -slim_hidden_def (cairo_pattern_set_matrix); /** * cairo_pattern_get_matrix: @@ -2107,6 +2105,45 @@ cairo_pattern_get_filter (cairo_pattern_t *pattern) return pattern->filter; } +/** + * cairo_pattern_get_dither: + * @pattern: a #cairo_pattern_t + * + * Gets the current dithering mode, as set by + * cairo_pattern_set_dither(). + * + * Return value: the current dithering mode. + * + * Since: 1.18 + **/ +cairo_dither_t +cairo_pattern_get_dither (cairo_pattern_t *pattern) +{ + return pattern->dither; +} + +/** + * cairo_pattern_set_dither: + * @pattern: a #cairo_pattern_t + * @dither: a #cairo_dither_t describing the new dithering mode + * + * Set the dithering 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, only pixman is supported. + * + * Since: 1.18 + **/ +void +cairo_pattern_set_dither (cairo_pattern_t *pattern, cairo_dither_t dither) +{ + if (pattern->status) + return; + + pattern->dither = dither; + _cairo_pattern_notify_observers (pattern, CAIRO_PATTERN_NOTIFY_DITHER); + +} + /** * cairo_pattern_set_extend: * @pattern: a #cairo_pattern_t @@ -2131,7 +2168,6 @@ cairo_pattern_set_extend (cairo_pattern_t *pattern, cairo_extend_t extend) pattern->extend = extend; _cairo_pattern_notify_observers (pattern, CAIRO_PATTERN_NOTIFY_EXTEND); } -slim_hidden_def (cairo_pattern_set_extend); /** * cairo_pattern_get_extend: @@ -2150,7 +2186,6 @@ cairo_pattern_get_extend (cairo_pattern_t *pattern) { return pattern->extend; } -slim_hidden_def (cairo_pattern_get_extend); void _cairo_pattern_pretransform (cairo_pattern_t *pattern, @@ -2714,7 +2749,6 @@ _cairo_gradient_pattern_interpolate (const cairo_gradient_pattern_t *gradient, #undef lerp } - /** * _cairo_gradient_pattern_fit_to_range: * @@ -2767,6 +2801,12 @@ _cairo_gradient_pattern_fit_to_range (const cairo_gradient_pattern_t *gradient, dim = MAX (dim, fabs (radial->cd1.center.y - radial->cd2.center.y)); dim = MAX (dim, fabs (radial->cd1.radius - radial->cd2.radius)); } + dim = MAX (dim, fabs (gradient->base.matrix.xx)); + dim = MAX (dim, fabs (gradient->base.matrix.xy)); + dim = MAX (dim, fabs (gradient->base.matrix.x0)); + dim = MAX (dim, fabs (gradient->base.matrix.yx)); + dim = MAX (dim, fabs (gradient->base.matrix.yy)); + dim = MAX (dim, fabs (gradient->base.matrix.y0)); if (unlikely (dim > max_value)) { cairo_matrix_t scale; @@ -4213,7 +4253,6 @@ cairo_pattern_get_rgba (cairo_pattern_t *pattern, return CAIRO_STATUS_SUCCESS; } -slim_hidden_def (cairo_pattern_get_rgba); /** * cairo_pattern_get_surface: @@ -4463,7 +4502,6 @@ cairo_mesh_pattern_get_patch_count (cairo_pattern_t *pattern, return CAIRO_STATUS_SUCCESS; } -slim_hidden_def (cairo_mesh_pattern_get_patch_count); /** * cairo_mesh_pattern_get_path: @@ -4509,12 +4547,12 @@ cairo_mesh_pattern_get_path (cairo_pattern_t *pattern, patch = _cairo_array_index_const (&mesh->patches, patch_num); - path = _cairo_malloc (sizeof (cairo_path_t)); + path = _cairo_calloc (sizeof (cairo_path_t)); if (path == NULL) return _cairo_path_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); path->num_data = 18; - path->data = _cairo_malloc_ab (path->num_data, + path->data = _cairo_calloc_ab (path->num_data, sizeof (cairo_path_data_t)); if (path->data == NULL) { free (path); @@ -4551,7 +4589,6 @@ cairo_mesh_pattern_get_path (cairo_pattern_t *pattern, return path; } -slim_hidden_def (cairo_mesh_pattern_get_path); /** * cairo_mesh_pattern_get_corner_color_rgba: @@ -4621,7 +4658,6 @@ cairo_mesh_pattern_get_corner_color_rgba (cairo_pattern_t *pattern, return CAIRO_STATUS_SUCCESS; } -slim_hidden_def (cairo_mesh_pattern_get_corner_color_rgba); /** * cairo_mesh_pattern_get_control_point: @@ -4686,7 +4722,6 @@ cairo_mesh_pattern_get_control_point (cairo_pattern_t *pattern, return CAIRO_STATUS_SUCCESS; } -slim_hidden_def (cairo_mesh_pattern_get_control_point); void _cairo_pattern_reset_static_data (void) diff --git a/src/cairo-pdf-interchange.c b/src/cairo-pdf-interchange.c index 2f97b081c..720ce0d53 100644 --- a/src/cairo-pdf-interchange.c +++ b/src/cairo-pdf-interchange.c @@ -52,6 +52,7 @@ #include "cairo-array-private.h" #include "cairo-error-private.h" #include "cairo-output-stream-private.h" +#include "cairo-recording-surface-inline.h" #include "cairo-recording-surface-private.h" #include "cairo-surface-snapshot-inline.h" @@ -159,7 +160,7 @@ command_list_push_group (cairo_pdf_surface_t *surface, cairo_pdf_recording_surface_commands_t recording_commands; cairo_int_status_t status = CAIRO_STATUS_SUCCESS; - group = _cairo_malloc (sizeof(cairo_pdf_command_list_t)); + group = _cairo_calloc (sizeof(cairo_pdf_command_list_t)); _cairo_array_init (&group->commands, sizeof(cairo_pdf_command_t)); group->parent = ic->current_commands; @@ -373,7 +374,7 @@ add_tree_node (cairo_pdf_surface_t *surface, cairo_pdf_struct_tree_node_t *node; cairo_int_status_t status = CAIRO_STATUS_SUCCESS; - node = _cairo_malloc (sizeof(cairo_pdf_struct_tree_node_t)); + node = _cairo_calloc (sizeof(cairo_pdf_struct_tree_node_t)); if (unlikely (node == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -483,7 +484,7 @@ add_annotation (cairo_pdf_surface_t *surface, cairo_pdf_interchange_t *ic = &surface->interchange; cairo_pdf_annotation_t *annot; - annot = _cairo_malloc (sizeof (cairo_pdf_annotation_t)); + annot = _cairo_calloc (sizeof (cairo_pdf_annotation_t)); if (unlikely (annot == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -767,13 +768,11 @@ static cairo_int_status_t cairo_pdf_interchange_write_dest (cairo_pdf_surface_t *surface, cairo_link_attrs_t *link_attrs) { - cairo_int_status_t status; + cairo_int_status_t status = CAIRO_STATUS_SUCCESS; cairo_pdf_interchange_t *ic = &surface->interchange; - cairo_pdf_forward_link_t *link; - cairo_pdf_resource_t link_res; /* If the dest is known, emit an explicit dest */ - if (link_attrs->dest) { + if (link_attrs->link_type == TAG_LINK_DEST_AND_URI || link_attrs->link_type == TAG_LINK_DEST) { cairo_pdf_named_dest_t key; cairo_pdf_named_dest_t *named_dest; @@ -796,53 +795,56 @@ cairo_pdf_interchange_write_dest (cairo_pdf_surface_t *surface, if (named_dest->attrs.y_valid) y = named_dest->attrs.y; - _cairo_output_stream_printf (surface->object_stream.stream, " /Dest "); - status = cairo_pdf_interchange_write_explicit_dest (surface, - named_dest->page, - TRUE, - x, y); + if (named_dest->attrs.internal) { + _cairo_output_stream_printf (surface->object_stream.stream, " /Dest "); + status = cairo_pdf_interchange_write_explicit_dest (surface, + named_dest->page, + TRUE, + x, y); + } else { + char *name = NULL; + + status = _cairo_utf8_to_pdf_string (named_dest->attrs.name, &name); + if (unlikely (status)) + return status; + + _cairo_output_stream_printf (surface->object_stream.stream, " /Dest %s\n", + name); + free (name); + } return status; } - } - - /* If the page is known, emit an explicit dest */ - if (!link_attrs->dest) { - if (link_attrs->page < 1) - return _cairo_tag_error ("Link attribute: \"page=%d\" page must be >= 1", link_attrs->page); - - if (link_attrs->page <= (int)_cairo_array_num_elements (&surface->pages)) { - _cairo_output_stream_printf (surface->object_stream.stream, " /Dest "); - return cairo_pdf_interchange_write_explicit_dest (surface, - link_attrs->page, - link_attrs->has_pos, - link_attrs->pos.x, - link_attrs->pos.y); + /* name does not exist */ + if (link_attrs->link_type == TAG_LINK_DEST_AND_URI) { + /* Don't emit anything. The caller will fallback to emitting a URI destination. */ + return CAIRO_INT_STATUS_NOTHING_TO_DO; } + + /* Mising destination. Emit a "do nothing" dest that points to the same page and position. */ + _cairo_tag_warning ("Link to dest=\"%s\" not found", link_attrs->dest); + _cairo_output_stream_printf (surface->object_stream.stream, " /Dest "); + status = cairo_pdf_interchange_write_explicit_dest (surface, + link_attrs->link_page, + FALSE, + 0, 0); + return status; } - /* Link refers to a future or unknown page. Use an indirect object - * and write the link at the end of the document */ + /* link_attrs->link_type == TAG_LINK_PAGE */ - link = _cairo_malloc (sizeof (cairo_pdf_forward_link_t)); - if (unlikely (link == NULL)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); + if (link_attrs->page < 1) + return _cairo_tag_error ("Link attribute: \"page=%d\" page must be >= 1", link_attrs->page); - link_res = _cairo_pdf_surface_new_object (surface); - if (link_res.id == 0) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); + if (link_attrs->page > (int)_cairo_array_num_elements (&surface->pages)) + return _cairo_tag_error ("Link attribute: \"page=%d\" page exceeds page count (%d)", + link_attrs->page, _cairo_array_num_elements (&surface->pages)); - _cairo_output_stream_printf (surface->object_stream.stream, - " /Dest %d 0 R\n", - link_res.id); - - link->res = link_res; - link->dest = link_attrs->dest ? strdup (link_attrs->dest) : NULL; - link->page = link_attrs->page; - link->has_pos = link_attrs->has_pos; - link->pos = link_attrs->pos; - status = _cairo_array_append (&surface->forward_links, link); - - return status; + _cairo_output_stream_printf (surface->object_stream.stream, " /Dest "); + return cairo_pdf_interchange_write_explicit_dest (surface, + link_attrs->page, + link_attrs->has_pos, + link_attrs->pos.x, + link_attrs->pos.y); } static cairo_int_status_t @@ -917,12 +919,20 @@ cairo_pdf_interchange_write_link_action (cairo_pdf_surface_t *surface, cairo_int_status_t status; char *dest = NULL; - if (link_attrs->link_type == TAG_LINK_DEST) { + if (link_attrs->link_type == TAG_LINK_DEST_AND_URI || + link_attrs->link_type == TAG_LINK_DEST || + link_attrs->link_type == TAG_LINK_PAGE) + { status = cairo_pdf_interchange_write_dest (surface, link_attrs); - if (unlikely (status)) + if (status != CAIRO_INT_STATUS_NOTHING_TO_DO) return status; - } else if (link_attrs->link_type == TAG_LINK_URI) { + /* CAIRO_INT_STATUS_NOTHING_TO_DO means that the link type is TAG_LINK_DEST_AND_URI + * and the DEST is missing. Fall through to writing a URI link below. + */ + } + + if (link_attrs->link_type == TAG_LINK_URI || link_attrs->link_type == TAG_LINK_DEST_AND_URI) { status = _cairo_utf8_to_pdf_string (link_attrs->uri, &dest); if (unlikely (status)) return status; @@ -1459,67 +1469,6 @@ strcmp_null (const char *s1, const char *s2) return FALSE; } -static cairo_int_status_t -cairo_pdf_interchange_write_forward_links (cairo_pdf_surface_t *surface) -{ - int num_elems, i; - cairo_pdf_forward_link_t *link; - cairo_int_status_t status; - cairo_pdf_named_dest_t key; - cairo_pdf_named_dest_t *named_dest; - cairo_pdf_interchange_t *ic = &surface->interchange; - - num_elems = _cairo_array_num_elements (&surface->forward_links); - for (i = 0; i < num_elems; i++) { - link = _cairo_array_index (&surface->forward_links, i); - if (link->page > (int)_cairo_array_num_elements (&surface->pages)) - return _cairo_tag_error ("Link attribute: \"page=%d\" page exceeds page count (%d)", - link->page, _cairo_array_num_elements (&surface->pages)); - - - status = _cairo_pdf_surface_object_begin (surface, link->res); - if (unlikely (status)) - return status; - - if (link->dest) { - key.attrs.name = link->dest; - init_named_dest_key (&key); - named_dest = _cairo_hash_table_lookup (ic->named_dests, &key.base); - if (named_dest) { - double x = 0; - double y = 0; - - if (named_dest->extents.valid) { - x = named_dest->extents.extents.x; - y = named_dest->extents.extents.y; - } - - if (named_dest->attrs.x_valid) - x = named_dest->attrs.x; - - if (named_dest->attrs.y_valid) - y = named_dest->attrs.y; - - status = cairo_pdf_interchange_write_explicit_dest (surface, - named_dest->page, - TRUE, - x, y); - } else { - return _cairo_tag_error ("Link to dest=\"%s\" not found", link->dest); - } - } else { - cairo_pdf_interchange_write_explicit_dest (surface, - link->page, - link->has_pos, - link->pos.x, - link->pos.y); - } - _cairo_pdf_surface_object_end (surface); - } - - return CAIRO_STATUS_SUCCESS; -} - static cairo_int_status_t cairo_pdf_interchange_write_page_labels (cairo_pdf_surface_t *surface) { @@ -1634,7 +1583,7 @@ _cairo_pdf_interchange_write_document_dests (cairo_pdf_surface_t *surface) return CAIRO_STATUS_SUCCESS; } - ic->sorted_dests = calloc (ic->num_dests, sizeof (cairo_pdf_named_dest_t *)); + ic->sorted_dests = _cairo_calloc_ab (ic->num_dests, sizeof (cairo_pdf_named_dest_t *)); if (unlikely (ic->sorted_dests == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -1657,6 +1606,7 @@ _cairo_pdf_interchange_write_document_dests (cairo_pdf_surface_t *surface) cairo_pdf_named_dest_t *dest = ic->sorted_dests[i]; double x = 0; double y = 0; + char *name = NULL; if (dest->attrs.internal) continue; @@ -1672,13 +1622,19 @@ _cairo_pdf_interchange_write_document_dests (cairo_pdf_surface_t *surface) if (dest->attrs.y_valid) y = dest->attrs.y; + status = _cairo_utf8_to_pdf_string (dest->attrs.name, &name); + if (unlikely (status)) + return status; + page_info = _cairo_array_index (&surface->pages, dest->page - 1); _cairo_output_stream_printf (surface->object_stream.stream, - " (%s) [%d 0 R /XYZ %f %f 0]\n", - dest->attrs.name, + " %s [%d 0 R /XYZ %f %f 0]\n", + name, page_info->page_res.id, x, page_info->height - y); + free (name); + } _cairo_output_stream_printf (surface->object_stream.stream, " ]\n" @@ -1810,7 +1766,7 @@ _cairo_pdf_interchange_begin_structure_tag (cairo_pdf_surface_t *surface, return status; /* Add to command_id to node map. */ - command_entry = _cairo_malloc (sizeof(cairo_pdf_command_entry_t)); + command_entry = _cairo_calloc (sizeof(cairo_pdf_command_entry_t)); command_entry->recording_id = ic->recording_id; command_entry->command_id = ic->command_id; command_entry->node = ic->current_analyze_node; @@ -1826,7 +1782,7 @@ _cairo_pdf_interchange_begin_structure_tag (cairo_pdf_surface_t *surface, } if (ic->current_analyze_node->type == PDF_NODE_CONTENT) { - cairo_pdf_content_tag_t *content = _cairo_malloc (sizeof(cairo_pdf_content_tag_t)); + cairo_pdf_content_tag_t *content = _cairo_calloc (sizeof(cairo_pdf_content_tag_t)); content->node = ic->current_analyze_node; _cairo_pdf_content_tag_init_key (content); status = _cairo_hash_table_insert (ic->content_tag_map, &content->base); @@ -1882,7 +1838,7 @@ _cairo_pdf_interchange_begin_dest_tag (cairo_pdf_surface_t *surface, cairo_int_status_t status = CAIRO_STATUS_SUCCESS; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { - dest = calloc (1, sizeof (cairo_pdf_named_dest_t)); + dest = _cairo_calloc (sizeof (cairo_pdf_named_dest_t)); if (unlikely (dest == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -2003,6 +1959,8 @@ _cairo_pdf_interchange_tag_end (cairo_pdf_surface_t *surface, } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_RENDER) { status = _cairo_tag_stack_pop (&ic->render_tag_stack, name, &elem); + } else { + ASSERT_NOT_REACHED; } if (unlikely (status)) return status; @@ -2035,14 +1993,22 @@ _cairo_pdf_interchange_command_id (cairo_pdf_surface_t *surface, if (surface->paginated_mode == CAIRO_PAGINATED_MODE_RENDER && ic->current_render_node) { /* TODO If the group does not have tags we don't need to close the current tag. */ if (command_list_is_group (surface, command_id)) { + /* A "Do /xnnn" can not be inside a tag (since the + * XObject may also contain tags). Close the tag. + */ if (ic->marked_content_open) { status = _cairo_pdf_operators_tag_end (&surface->pdf_operators); ic->marked_content_open = FALSE; } - if (command_list_has_content (surface, command_id, NULL)) { + /* If there is any more content after this and we are + * inside a tag (current node is not the root node), + * ensure that the next command will open the tag. + */ + if (command_list_has_content (surface, command_id, NULL) && ic->current_render_node->parent) { ic->render_next_command_has_content = TRUE; } } else if (ic->render_next_command_has_content) { + /* After a "Do /xnnn" operation, if there is more content, open the tag. */ add_mcid_to_node (surface, ic->current_render_node, ic->command_id, &mcid); status = _cairo_pdf_operators_tag_begin (&surface->pdf_operators, ic->current_render_node->name, mcid); @@ -2071,7 +2037,9 @@ _cairo_pdf_interchange_struct_tree_requires_recording_surface ( if (_cairo_surface_is_snapshot (recording_surface)) free_me = recording_surface = _cairo_surface_snapshot_get_target (recording_surface); - if (_cairo_recording_surface_has_tags (recording_surface)) { + if (_cairo_surface_is_recording (recording_surface) && + _cairo_recording_surface_has_tags (recording_surface)) + { /* Check if tags are to be ignored in this source */ switch (source_type) { case CAIRO_ANALYSIS_SOURCE_PAINT: @@ -2416,10 +2384,6 @@ _cairo_pdf_interchange_write_document_objects (cairo_pdf_surface_t *surface) if (unlikely (status)) return status; - status = cairo_pdf_interchange_write_forward_links (surface); - if (unlikely (status)) - return status; - status = cairo_pdf_interchange_write_names_dict (surface); if (unlikely (status)) return status; @@ -2477,7 +2441,7 @@ _cairo_pdf_interchange_init (cairo_pdf_surface_t *surface) _cairo_tag_stack_init (&ic->analysis_tag_stack); _cairo_tag_stack_init (&ic->render_tag_stack); - ic->struct_root = calloc (1, sizeof(cairo_pdf_struct_tree_node_t)); + ic->struct_root = _cairo_calloc (sizeof(cairo_pdf_struct_tree_node_t)); if (unlikely (ic->struct_root == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -2521,7 +2485,7 @@ _cairo_pdf_interchange_init (cairo_pdf_surface_t *surface) ic->mcid_order = 0; _cairo_array_init (&ic->outline, sizeof(cairo_pdf_outline_entry_t *)); - outline_root = calloc (1, sizeof(cairo_pdf_outline_entry_t)); + outline_root = _cairo_calloc (sizeof(cairo_pdf_outline_entry_t)); if (unlikely (outline_root == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -2635,7 +2599,7 @@ _cairo_pdf_interchange_add_outline (cairo_pdf_surface_t *surface, if (parent_id < 0 || parent_id >= (int)_cairo_array_num_elements (&ic->outline)) return CAIRO_STATUS_SUCCESS; - outline = _cairo_malloc (sizeof(cairo_pdf_outline_entry_t)); + outline = _cairo_calloc (sizeof(cairo_pdf_outline_entry_t)); if (unlikely (outline == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -2869,8 +2833,10 @@ _cairo_pdf_interchange_set_custom_metadata (cairo_pdf_surface_t *surface, if (value && strlen(value)) { new_data.name = strdup (name); status = _cairo_utf8_to_pdf_string (value, &s); - if (unlikely (status)) + if (unlikely (status)) { + free (new_data.name); return status; + } new_data.value = s; status = _cairo_array_append (&ic->custom_metadata, &new_data); } diff --git a/src/cairo-pdf-operators.c b/src/cairo-pdf-operators.c index 176f45b48..7bed41310 100644 --- a/src/cairo-pdf-operators.c +++ b/src/cairo-pdf-operators.c @@ -359,7 +359,7 @@ _word_wrap_stream_create (cairo_output_stream_t *output, cairo_bool_t ps, int ma if (output->status) return _cairo_output_stream_create_in_error (output->status); - stream = _cairo_malloc (sizeof (word_wrap_stream_t)); + stream = _cairo_calloc (sizeof (word_wrap_stream_t)); if (unlikely (stream == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_output_stream_t *) &_cairo_output_stream_nil; diff --git a/src/cairo-pdf-surface-private.h b/src/cairo-pdf-surface-private.h index 13ccc5001..bf1d39456 100644 --- a/src/cairo-pdf-surface-private.h +++ b/src/cairo-pdf-surface-private.h @@ -266,14 +266,6 @@ typedef struct _cairo_pdf_outline_entry { int count; } cairo_pdf_outline_entry_t; -typedef struct _cairo_pdf_forward_link { - cairo_pdf_resource_t res; - char *dest; - int page; - cairo_bool_t has_pos; - cairo_point_double_t pos; -} cairo_pdf_forward_link_t; - struct docinfo { char *title; char *author; @@ -468,7 +460,6 @@ struct _cairo_pdf_surface { cairo_pdf_interchange_t interchange; int page_parent_tree; /* -1 if not used */ cairo_array_t page_annots; - cairo_array_t forward_links; cairo_bool_t tagged; char *current_page_label; cairo_array_t page_labels; diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c index 459f90a8f..3e734c759 100644 --- a/src/cairo-pdf-surface.c +++ b/src/cairo-pdf-surface.c @@ -52,6 +52,7 @@ #include "cairo-composite-rectangles-private.h" #include "cairo-default-context-private.h" #include "cairo-error-private.h" +#include "cairo-user-font-private.h" #include "cairo-image-surface-inline.h" #include "cairo-image-info-private.h" #include "cairo-recording-surface-inline.h" @@ -446,7 +447,7 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output, cairo_pdf_surface_t *surface; cairo_status_t status, status_ignored; - surface = _cairo_malloc (sizeof (cairo_pdf_surface_t)); + surface = _cairo_calloc (sizeof (cairo_pdf_surface_t)); if (unlikely (surface == NULL)) { /* destroy stream on behalf of caller */ status = _cairo_output_stream_destroy (output); @@ -554,7 +555,6 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output, surface->page_parent_tree = -1; _cairo_array_init (&surface->page_annots, sizeof (cairo_pdf_resource_t)); - _cairo_array_init (&surface->forward_links, sizeof (cairo_pdf_forward_link_t)); surface->tagged = FALSE; surface->current_page_label = NULL; _cairo_array_init (&surface->page_labels, sizeof (char *)); @@ -1402,7 +1402,7 @@ _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)); + group = _cairo_calloc (sizeof (cairo_pdf_smask_group_t)); if (unlikely (group == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return NULL; @@ -1766,7 +1766,7 @@ _cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t *surface, unique_id_length = 0; } - surface_entry = _cairo_malloc (sizeof (cairo_pdf_source_surface_entry_t)); + surface_entry = _cairo_calloc (sizeof (cairo_pdf_source_surface_entry_t)); if (surface_entry == NULL) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto fail1; @@ -2534,6 +2534,7 @@ _cairo_pdf_surface_open_content_stream (cairo_pdf_surface_t *surface, _cairo_pdf_surface_open_stream (surface, resource, surface->compress_streams, + "%s", str); free (str); free (data); @@ -2698,16 +2699,18 @@ _cairo_pdf_surface_finish (void *abstract_surface) status = _cairo_pdf_surface_open_object_stream (surface); if (unlikely (status)) - return status; + goto CLEANUP; /* Emit unbounded surfaces */ - _cairo_pdf_surface_write_patterns_and_smask_groups (surface, TRUE); + status = _cairo_pdf_surface_write_patterns_and_smask_groups (surface, TRUE); + if (unlikely (status)) + goto CLEANUP; _cairo_pdf_surface_clear (surface, TRUE); - status = surface->base.status; - if (status == CAIRO_STATUS_SUCCESS) - status = _cairo_pdf_surface_emit_font_subsets (surface); + status = _cairo_pdf_surface_emit_font_subsets (surface); + if (unlikely (status)) + goto CLEANUP; /* Emit any new patterns or surfaces created by the Type 3 font subset. */ _cairo_pdf_surface_write_patterns_and_smask_groups (surface, TRUE); @@ -2716,27 +2719,29 @@ _cairo_pdf_surface_finish (void *abstract_surface) status = _cairo_pdf_surface_write_pages (surface); if (unlikely (status)) - return status; + goto CLEANUP; status = _cairo_pdf_interchange_write_document_objects (surface); if (unlikely (status)) - return status; + goto CLEANUP; status = _cairo_pdf_surface_write_page_dicts (surface); if (unlikely (status)) - return status; + goto CLEANUP; catalog = _cairo_pdf_surface_new_object (surface); - if (catalog.id == 0) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); + if (catalog.id == 0) { + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + goto CLEANUP; + } status = _cairo_pdf_surface_write_catalog (surface, catalog); if (unlikely (status)) - return status; + goto CLEANUP; status = _cairo_pdf_surface_close_object_stream (surface); if (unlikely (status)) - return status; + goto CLEANUP; if (!surface->debug && surface->pdf_version >= CAIRO_PDF_VERSION_1_5) { @@ -2822,7 +2827,6 @@ _cairo_pdf_surface_finish (void *abstract_surface) _cairo_array_fini (&surface->fonts); _cairo_array_fini (&surface->knockout_group); _cairo_array_fini (&surface->page_annots); - _cairo_array_fini (&surface->forward_links); _cairo_hash_table_foreach (surface->color_glyphs, _cairo_pdf_color_glyph_pluck, @@ -9296,6 +9300,13 @@ _cairo_pdf_surface_show_text_glyphs (void *abstract_surface, if (unlikely (status)) goto cleanup; + /* User-fonts can use strokes; reset the stroke pattern as well. */ + if (_cairo_font_face_is_user(scaled_font->font_face)) { + status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, TRUE); + if (unlikely (status)) + goto cleanup; + } + /* 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 @@ -9386,7 +9397,7 @@ _cairo_pdf_surface_supports_color_glyph (void *abstract_surface if (glyph_entry) return glyph_entry->supported; - glyph_entry = _cairo_malloc (sizeof (cairo_pdf_color_glyph_t)); + glyph_entry = _cairo_calloc (sizeof (cairo_pdf_color_glyph_t)); if (glyph_entry == NULL) { status = _cairo_surface_set_error (&surface->base, _cairo_error (CAIRO_STATUS_NO_MEMORY)); diff --git a/src/cairo-pixman-private.h b/src/cairo-pixman-private.h index d705025c8..d187b79f6 100644 --- a/src/cairo-pixman-private.h +++ b/src/cairo-pixman-private.h @@ -42,10 +42,4 @@ #include -#if PIXMAN_VERSION < PIXMAN_VERSION_ENCODE(0,22,0) -#define pixman_image_composite32 pixman_image_composite -#define pixman_image_get_component_alpha(i) 0 -#define pixman_image_set_component_alpha(i, x) do { } while (0) -#endif - #endif diff --git a/src/cairo-png.c b/src/cairo-png.c index 5b9c58447..287f70545 100644 --- a/src/cairo-png.c +++ b/src/cairo-png.c @@ -569,7 +569,6 @@ cairo_surface_write_to_png_stream (cairo_surface_t *surface, 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) @@ -731,13 +730,8 @@ read_png (struct png_read_closure_t *png_closure) png_set_palette_to_rgb (png); /* expand gray bit depth if needed */ - if (color_type == PNG_COLOR_TYPE_GRAY) { -#if PNG_LIBPNG_VER >= 10209 + if (color_type == PNG_COLOR_TYPE_GRAY) 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)) @@ -987,4 +981,3 @@ cairo_image_surface_create_from_png_stream (cairo_read_func_t read_func, return read_png (&png_closure); } -slim_hidden_def (cairo_image_surface_create_from_png_stream); diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index 381b4cf75..5421c39c9 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -1065,7 +1065,7 @@ _cairo_ps_surface_get_page_media (cairo_ps_surface_t *surface) } } - page = _cairo_malloc (sizeof (cairo_page_media_t)); + page = _cairo_calloc (sizeof (cairo_page_media_t)); if (unlikely (page == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return NULL; @@ -1101,7 +1101,7 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream, cairo_status_t status, status_ignored; cairo_ps_surface_t *surface; - surface = _cairo_malloc (sizeof (cairo_ps_surface_t)); + surface = _cairo_calloc (sizeof (cairo_ps_surface_t)); if (unlikely (surface == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto CLEANUP; @@ -1115,7 +1115,7 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream, surface->final_stream = stream; - surface->tmpfile = tmpfile (); + surface->tmpfile = _cairo_tmpfile (); if (surface->tmpfile == NULL) { switch (errno) { case ENOMEM: @@ -2351,7 +2351,7 @@ _base85_strings_stream_create (cairo_output_stream_t *output) { string_array_stream_t *stream; - stream = _cairo_malloc (sizeof (string_array_stream_t)); + stream = _cairo_calloc (sizeof (string_array_stream_t)); if (unlikely (stream == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_output_stream_t *) &_cairo_output_stream_nil; @@ -2381,7 +2381,7 @@ _base85_wrap_stream_create (cairo_output_stream_t *output) { string_array_stream_t *stream; - stream = _cairo_malloc (sizeof (string_array_stream_t)); + stream = _cairo_calloc (sizeof (string_array_stream_t)); if (unlikely (stream == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_output_stream_t *) &_cairo_output_stream_nil; @@ -3507,13 +3507,13 @@ _cairo_ps_surface_use_form (cairo_ps_surface_t *surface, if (surface->ps_level == CAIRO_PS_LEVEL_3) max_size = MAX_L3_FORM_DATA; else - max_size = MAX_L3_FORM_DATA; + max_size = MAX_L2_FORM_DATA; /* Don't add any more Forms if we exceed the form memory limit */ if (surface->total_form_size + params->approx_size > max_size) return CAIRO_INT_STATUS_UNSUPPORTED; - surface->total_form_size += params->approx_size > max_size; + surface->total_form_size += params->approx_size; unique_id = _cairo_malloc (source_key.unique_id_length); if (unique_id == NULL) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -3521,7 +3521,7 @@ _cairo_ps_surface_use_form (cairo_ps_surface_t *surface, unique_id_length = source_key.unique_id_length; memcpy (unique_id, source_key.unique_id, unique_id_length); - source_entry = calloc (sizeof (cairo_ps_form_t), 1); + source_entry = _cairo_calloc (sizeof (cairo_ps_form_t)); if (source_entry == NULL) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto fail; diff --git a/src/cairo-quartz-font.c b/src/cairo-quartz-font.c index 1e7531356..b1a6fd7f5 100644 --- a/src/cairo-quartz-font.c +++ b/src/cairo-quartz-font.c @@ -51,6 +51,7 @@ * @Short_Description: Font support via Core Text on Apple operating systems. * @See_Also: #cairo_font_face_t * + * Provide support for font faces via Core Text. **/ /** @@ -76,10 +77,10 @@ static const CGFloat font_scale = 1.0; #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080 #define FONT_ORIENTATION_HORIZONTAL kCTFontHorizontalOrientation -#define FONT_COLOR_GLYPHS kCTFontTraitColorGlyphs +#define FONT_COLOR_GLYPHS kCTFontColorGlyphsTrait #else #define FONT_ORIENTATION_HORIZONTAL kCTFontOrientationHorizontal -#define FONT_COLOR_GLYPHS kCTFontColorGlyphsTrait +#define FONT_COLOR_GLYPHS kCTFontTraitColorGlyphs #endif static void @@ -164,6 +165,17 @@ _cairo_quartz_font_face_create_for_toy (cairo_toy_font_face_t *toy_face, cgFont = CGFontCreateWithFontName (FontName); CFRelease (FontName); + if (!cgFont) { + /* Attempt to create font by replacing hyphens for spaces in font name. */ + for (size_t i = 0; i < strlen (full_name); i++) { + if (full_name[i] == '-') + full_name[i] = ' '; + } + FontName = CFStringCreateWithCString (NULL, full_name, kCFStringEncodingASCII); + cgFont = CGFontCreateWithFontName (FontName); + CFRelease (FontName); + } + if (cgFont) break; } @@ -249,7 +261,7 @@ _cairo_quartz_font_face_scaled_font_create (void *abstract_face, CTFontRef ctFont; CGRect bbox; - font = _cairo_malloc (sizeof(cairo_quartz_scaled_font_t)); + font = _cairo_calloc (sizeof(cairo_quartz_scaled_font_t)); if (font == NULL) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -306,7 +318,7 @@ static inline cairo_quartz_font_face_t* _cairo_quartz_font_face_create () { cairo_quartz_font_face_t *font_face = - _cairo_malloc (sizeof (cairo_quartz_font_face_t)); + _cairo_calloc (sizeof (cairo_quartz_font_face_t)); if (!font_face) { cairo_status_t ignore_status; diff --git a/src/cairo-quartz-image-surface.c b/src/cairo-quartz-image-surface.c index d09f5b5bc..4f9bc2118 100644 --- a/src/cairo-quartz-image-surface.c +++ b/src/cairo-quartz-image-surface.c @@ -49,6 +49,15 @@ #define SURFACE_ERROR_INVALID_SIZE (_cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_INVALID_SIZE))) #define SURFACE_ERROR_INVALID_FORMAT (_cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_INVALID_FORMAT))) +/** + * CAIRO_HAS_QUARTZ_IMAGE_SURFACE: + * + * Defined if the Quartz image surface backend is available. + * This macro can be used to conditionally compile backend-specific code. + * + * Since: 1.10 + **/ + static cairo_surface_t * _cairo_quartz_image_surface_create_similar (void *asurface, cairo_content_t content, @@ -283,7 +292,7 @@ cairo_quartz_image_surface_create (cairo_surface_t *surface) if (format != CAIRO_FORMAT_ARGB32 && format != CAIRO_FORMAT_RGB24) return SURFACE_ERROR_INVALID_FORMAT; - qisurf = _cairo_malloc (sizeof(cairo_quartz_image_surface_t)); + qisurf = _cairo_calloc (sizeof(cairo_quartz_image_surface_t)); if (qisurf == NULL) return SURFACE_ERROR_NO_MEMORY; @@ -326,7 +335,7 @@ cairo_quartz_image_surface_create (cairo_surface_t *surface) * or %NULL if the quartz surface is not an image surface. * * Since: 1.6 - */ + **/ cairo_surface_t * cairo_quartz_image_surface_get_image (cairo_surface_t *surface) { diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c index 6da1b6ffa..0a5c72f0d 100644 --- a/src/cairo-quartz-surface.c +++ b/src/cairo-quartz-surface.c @@ -851,7 +851,7 @@ _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (cairo_quartz_surface_t if (unlikely (status)) return status; - info = _cairo_malloc (sizeof (SurfacePatternDrawInfo)); + info = _cairo_calloc (sizeof (SurfacePatternDrawInfo)); if (unlikely (!info)) { CGImageRelease (image); @@ -2136,7 +2136,7 @@ _cairo_quartz_surface_create_internal (CGContextRef cgContext, cairo_quartz_surface_t *surface; /* Init the base surface */ - surface = _cairo_malloc (sizeof (cairo_quartz_surface_t)); + surface = _cairo_calloc (sizeof (cairo_quartz_surface_t)); if (unlikely (surface == NULL)) return (cairo_quartz_surface_t*) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); @@ -2386,7 +2386,7 @@ _cairo_quartz_snapshot_create (cairo_surface_t *surface) ! _cairo_quartz_is_cgcontext_bitmap_context (((cairo_quartz_surface_t*)surface)->cgContext)) return NULL; - snapshot = _cairo_malloc (sizeof (cairo_quartz_snapshot_t)); + snapshot = _cairo_calloc (sizeof (cairo_quartz_snapshot_t)); if (unlikely (surface == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); diff --git a/src/cairo-raster-source-pattern.c b/src/cairo-raster-source-pattern.c index 64520feae..0ae3b946a 100644 --- a/src/cairo-raster-source-pattern.c +++ b/src/cairo-raster-source-pattern.c @@ -168,7 +168,7 @@ cairo_pattern_create_raster_source (void *user_data, if (! CAIRO_CONTENT_VALID (content)) return _cairo_pattern_create_in_error (CAIRO_STATUS_INVALID_CONTENT); - pattern = calloc (1, sizeof (*pattern)); + pattern = _cairo_calloc (sizeof (*pattern)); if (unlikely (pattern == NULL)) return _cairo_pattern_create_in_error (CAIRO_STATUS_NO_MEMORY); diff --git a/src/cairo-recording-surface-private.h b/src/cairo-recording-surface-private.h index acace4ec8..2ee414e7d 100644 --- a/src/cairo-recording-surface-private.h +++ b/src/cairo-recording-surface-private.h @@ -183,8 +183,6 @@ typedef struct _cairo_recording_region_array { cairo_list_t link; } cairo_recording_regions_array_t; -slim_hidden_proto (cairo_recording_surface_create); - cairo_private cairo_int_status_t _cairo_recording_surface_get_path (cairo_surface_t *surface, cairo_path_fixed_t *path); diff --git a/src/cairo-recording-surface.c b/src/cairo-recording-surface.c index 5735c7ca3..6add3a218 100644 --- a/src/cairo-recording-surface.c +++ b/src/cairo-recording-surface.c @@ -168,7 +168,7 @@ static int bbtree_left_or_right (struct bbtree *bbt, static struct bbtree * bbtree_new (const cairo_box_t *box, cairo_command_header_t *chain) { - struct bbtree *bbt = _cairo_malloc (sizeof (*bbt)); + struct bbtree *bbt = _cairo_calloc (sizeof (*bbt)); if (bbt == NULL) return NULL; bbt->extents = *box; @@ -399,7 +399,7 @@ cairo_recording_surface_create (cairo_content_t content, { cairo_recording_surface_t *surface; - surface = _cairo_malloc (sizeof (cairo_recording_surface_t)); + surface = _cairo_calloc (sizeof (cairo_recording_surface_t)); if (unlikely (surface == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); @@ -445,7 +445,6 @@ cairo_recording_surface_create (cairo_content_t content, return &surface->base; } -slim_hidden_def (cairo_recording_surface_create); static cairo_surface_t * _cairo_recording_surface_create_similar (void *abstract_surface, @@ -481,7 +480,7 @@ _cairo_recording_surface_region_array_destroy (cairo_recording_surface_t * cairo_recording_region_element_t *region_elements; int i, num_elements; - num_elements = surface->commands.num_elements; + num_elements = MIN(surface->commands.num_elements, _cairo_array_num_elements(®ion_array->regions)); elements = _cairo_array_index (&surface->commands, 0); region_elements = _cairo_array_index (®ion_array->regions, 0); for (i = 0; i < num_elements; i++) { @@ -654,7 +653,7 @@ attach_proxy (cairo_surface_t *source, { struct proxy *proxy; - proxy = _cairo_malloc (sizeof (*proxy)); + proxy = _cairo_calloc (sizeof (*proxy)); if (unlikely (proxy == NULL)) return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY); @@ -823,7 +822,7 @@ _cairo_recording_surface_paint (void *abstract_surface, if (unlikely (status)) return status; - command = _cairo_malloc (sizeof (cairo_command_paint_t)); + command = _cairo_calloc (sizeof (cairo_command_paint_t)); if (unlikely (command == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto CLEANUP_COMPOSITE; @@ -879,7 +878,7 @@ _cairo_recording_surface_mask (void *abstract_surface, if (unlikely (status)) return status; - command = _cairo_malloc (sizeof (cairo_command_mask_t)); + command = _cairo_calloc (sizeof (cairo_command_mask_t)); if (unlikely (command == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto CLEANUP_COMPOSITE; @@ -947,7 +946,7 @@ _cairo_recording_surface_stroke (void *abstract_surface, if (unlikely (status)) return status; - command = _cairo_malloc (sizeof (cairo_command_stroke_t)); + command = _cairo_calloc (sizeof (cairo_command_stroke_t)); if (unlikely (command == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto CLEANUP_COMPOSITE; @@ -1023,7 +1022,7 @@ _cairo_recording_surface_fill (void *abstract_surface, if (unlikely (status)) return status; - command = _cairo_malloc (sizeof (cairo_command_fill_t)); + command = _cairo_calloc (sizeof (cairo_command_fill_t)); if (unlikely (command == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto CLEANUP_COMPOSITE; @@ -1105,7 +1104,7 @@ _cairo_recording_surface_show_text_glyphs (void *abstract_surface, if (unlikely (status)) return status; - command = _cairo_malloc (sizeof (cairo_command_show_text_glyphs_t)); + command = _cairo_calloc (sizeof (cairo_command_show_text_glyphs_t)); if (unlikely (command == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto CLEANUP_COMPOSITE; @@ -1155,6 +1154,10 @@ _cairo_recording_surface_show_text_glyphs (void *abstract_surface, command->cluster_flags = cluster_flags; + status = scaled_font->status; + if (unlikely (status)) + goto CLEANUP_ARRAYS; + command->scaled_font = cairo_scaled_font_reference (scaled_font); status = _cairo_recording_surface_commit (surface, &command->header); @@ -1194,7 +1197,7 @@ _cairo_recording_surface_tag (void *abstract_surface, surface->has_tags = TRUE; - command = calloc (1, sizeof (cairo_command_tag_t)); + command = _cairo_calloc (sizeof (cairo_command_tag_t)); if (unlikely (command == NULL)) { return _cairo_error (CAIRO_STATUS_NO_MEMORY); } @@ -1268,7 +1271,7 @@ _cairo_recording_surface_copy__paint (cairo_recording_surface_t *surface, cairo_command_paint_t *command; cairo_status_t status; - command = _cairo_malloc (sizeof (*command)); + command = _cairo_calloc (sizeof (*command)); if (unlikely (command == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto err; @@ -1302,7 +1305,7 @@ _cairo_recording_surface_copy__mask (cairo_recording_surface_t *surface, cairo_command_mask_t *command; cairo_status_t status; - command = _cairo_malloc (sizeof (*command)); + command = _cairo_calloc (sizeof (*command)); if (unlikely (command == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto err; @@ -1343,7 +1346,7 @@ _cairo_recording_surface_copy__stroke (cairo_recording_surface_t *surface, cairo_command_stroke_t *command; cairo_status_t status; - command = _cairo_malloc (sizeof (*command)); + command = _cairo_calloc (sizeof (*command)); if (unlikely (command == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto err; @@ -1395,7 +1398,7 @@ _cairo_recording_surface_copy__fill (cairo_recording_surface_t *surface, cairo_command_fill_t *command; cairo_status_t status; - command = _cairo_malloc (sizeof (*command)); + command = _cairo_calloc (sizeof (*command)); if (unlikely (command == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto err; @@ -1439,7 +1442,7 @@ _cairo_recording_surface_copy__glyphs (cairo_recording_surface_t *surface, cairo_command_show_text_glyphs_t *command; cairo_status_t status; - command = _cairo_malloc (sizeof (*command)); + command = _cairo_calloc (sizeof (*command)); if (unlikely (command == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto err; @@ -1517,7 +1520,7 @@ _cairo_recording_surface_copy__tag (cairo_recording_surface_t *surface, cairo_command_tag_t *command; cairo_status_t status; - command = calloc (1, sizeof (*command)); + command = _cairo_calloc (sizeof (*command)); if (unlikely (command == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto err; @@ -1624,7 +1627,7 @@ _cairo_recording_surface_snapshot (void *abstract_other) cairo_recording_surface_t *surface; cairo_status_t status; - surface = _cairo_malloc (sizeof (cairo_recording_surface_t)); + surface = _cairo_calloc (sizeof (cairo_recording_surface_t)); if (unlikely (surface == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); @@ -1732,7 +1735,7 @@ _cairo_recording_surface_regions_allocate_unique_id (void) unique_id = 1; return unique_id; #else - cairo_atomic_int_t old, id; + int old, id; do { old = _cairo_atomic_uint_get (&unique_id); @@ -1773,7 +1776,7 @@ _cairo_recording_surface_region_array_attach (cairo_surface_t *abstract_surface, assert (_cairo_surface_is_recording (abstract_surface)); - region_array = _cairo_malloc (sizeof (cairo_recording_regions_array_t)); + region_array = _cairo_calloc (sizeof (cairo_recording_regions_array_t)); if (region_array == NULL) { *id = 0; return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -2673,7 +2676,6 @@ DONE: if (height) *height = _cairo_fixed_to_double (bbox.p2.y - bbox.p1.y); } -slim_hidden_def (cairo_recording_surface_ink_extents); cairo_status_t _cairo_recording_surface_get_bbox (cairo_recording_surface_t *surface, diff --git a/src/cairo-reference-count-private.h b/src/cairo-reference-count-private.h index 75fdf3538..f19125c61 100644 --- a/src/cairo-reference-count-private.h +++ b/src/cairo-reference-count-private.h @@ -52,7 +52,7 @@ typedef struct { #define CAIRO_REFERENCE_COUNT_GET_VALUE(RC) _cairo_atomic_int_get (&(RC)->ref_count) -#define CAIRO_REFERENCE_COUNT_INVALID_VALUE ((cairo_atomic_int_t) -1) +#define CAIRO_REFERENCE_COUNT_INVALID_VALUE ((int) -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) diff --git a/src/cairo-region.c b/src/cairo-region.c index d38f50d92..610747294 100644 --- a/src/cairo-region.c +++ b/src/cairo-region.c @@ -202,7 +202,7 @@ cairo_region_create (void) { cairo_region_t *region; - region = _cairo_malloc (sizeof (cairo_region_t)); + region = _cairo_calloc (sizeof (cairo_region_t)); if (region == NULL) return (cairo_region_t *) &_cairo_region_nil; @@ -213,7 +213,6 @@ cairo_region_create (void) return region; } -slim_hidden_def (cairo_region_create); /** * cairo_region_create_rectangles: @@ -239,7 +238,7 @@ cairo_region_create_rectangles (const cairo_rectangle_int_t *rects, cairo_region_t *region; int i; - region = _cairo_malloc (sizeof (cairo_region_t)); + region = _cairo_calloc (sizeof (cairo_region_t)); if (unlikely (region == NULL)) return _cairo_region_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); @@ -281,14 +280,13 @@ cairo_region_create_rectangles (const cairo_rectangle_int_t *rects, return region; } -slim_hidden_def (cairo_region_create_rectangles); cairo_region_t * _cairo_region_create_from_boxes (const cairo_box_t *boxes, int count) { cairo_region_t *region; - region = _cairo_malloc (sizeof (cairo_region_t)); + region = _cairo_calloc (sizeof (cairo_region_t)); if (unlikely (region == NULL)) return _cairo_region_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); @@ -334,7 +332,7 @@ cairo_region_create_rectangle (const cairo_rectangle_int_t *rectangle) { cairo_region_t *region; - region = _cairo_malloc (sizeof (cairo_region_t)); + region = _cairo_calloc (sizeof (cairo_region_t)); if (unlikely (region == NULL)) return (cairo_region_t *) &_cairo_region_nil; @@ -347,7 +345,6 @@ cairo_region_create_rectangle (const cairo_rectangle_int_t *rectangle) return region; } -slim_hidden_def (cairo_region_create_rectangle); /** * cairo_region_copy: @@ -384,7 +381,6 @@ cairo_region_copy (const cairo_region_t *original) return copy; } -slim_hidden_def (cairo_region_copy); /** * cairo_region_reference: @@ -409,7 +405,6 @@ cairo_region_reference (cairo_region_t *region) _cairo_reference_count_inc (®ion->ref_count); return region; } -slim_hidden_def (cairo_region_reference); /** * cairo_region_destroy: @@ -435,7 +430,6 @@ cairo_region_destroy (cairo_region_t *region) _cairo_region_fini (region); free (region); } -slim_hidden_def (cairo_region_destroy); /** * cairo_region_num_rectangles: @@ -455,7 +449,6 @@ cairo_region_num_rectangles (const cairo_region_t *region) return pixman_region32_n_rects (CONST_CAST ®ion->rgn); } -slim_hidden_def (cairo_region_num_rectangles); /** * cairo_region_get_rectangle: @@ -487,7 +480,6 @@ cairo_region_get_rectangle (const cairo_region_t *region, rectangle->width = pbox->x2 - pbox->x1; rectangle->height = pbox->y2 - pbox->y1; } -slim_hidden_def (cairo_region_get_rectangle); /** * cairo_region_get_extents: @@ -517,7 +509,6 @@ cairo_region_get_extents (const cairo_region_t *region, extents->width = pextents->x2 - pextents->x1; extents->height = pextents->y2 - pextents->y1; } -slim_hidden_def (cairo_region_get_extents); /** * cairo_region_status: @@ -535,7 +526,6 @@ cairo_region_status (const cairo_region_t *region) { return region->status; } -slim_hidden_def (cairo_region_status); /** * cairo_region_subtract: @@ -566,7 +556,6 @@ cairo_region_subtract (cairo_region_t *dst, const cairo_region_t *other) return CAIRO_STATUS_SUCCESS; } -slim_hidden_def (cairo_region_subtract); /** * cairo_region_subtract_rectangle: @@ -600,7 +589,6 @@ cairo_region_subtract_rectangle (cairo_region_t *dst, return status; } -slim_hidden_def (cairo_region_subtract_rectangle); /** * cairo_region_intersect: @@ -627,7 +615,6 @@ cairo_region_intersect (cairo_region_t *dst, const cairo_region_t *other) return CAIRO_STATUS_SUCCESS; } -slim_hidden_def (cairo_region_intersect); /** * cairo_region_intersect_rectangle: @@ -662,7 +649,6 @@ cairo_region_intersect_rectangle (cairo_region_t *dst, return status; } -slim_hidden_def (cairo_region_intersect_rectangle); /** * cairo_region_union: @@ -690,7 +676,6 @@ cairo_region_union (cairo_region_t *dst, return CAIRO_STATUS_SUCCESS; } -slim_hidden_def (cairo_region_union); /** * cairo_region_union_rectangle: @@ -724,7 +709,6 @@ cairo_region_union_rectangle (cairo_region_t *dst, return status; } -slim_hidden_def (cairo_region_union_rectangle); /** * cairo_region_xor: @@ -763,7 +747,6 @@ cairo_region_xor (cairo_region_t *dst, const cairo_region_t *other) return status; } -slim_hidden_def (cairo_region_xor); /** * cairo_region_xor_rectangle: @@ -804,7 +787,6 @@ cairo_region_xor_rectangle (cairo_region_t *dst, return status; } -slim_hidden_def (cairo_region_xor_rectangle); /** * cairo_region_is_empty: @@ -824,7 +806,6 @@ cairo_region_is_empty (const cairo_region_t *region) return ! pixman_region32_not_empty (CONST_CAST ®ion->rgn); } -slim_hidden_def (cairo_region_is_empty); /** * cairo_region_translate: @@ -845,7 +826,6 @@ cairo_region_translate (cairo_region_t *region, pixman_region32_translate (®ion->rgn, dx, dy); } -slim_hidden_def (cairo_region_translate); /** * cairo_region_contains_rectangle: @@ -886,7 +866,6 @@ cairo_region_contains_rectangle (const cairo_region_t *region, case PIXMAN_REGION_PART: return CAIRO_REGION_OVERLAP_PART; } } -slim_hidden_def (cairo_region_contains_rectangle); /** * cairo_region_contains_point: @@ -911,7 +890,6 @@ cairo_region_contains_point (const cairo_region_t *region, return pixman_region32_contains_point (CONST_CAST ®ion->rgn, x, y, &box); } -slim_hidden_def (cairo_region_contains_point); /** * cairo_region_equal: @@ -942,4 +920,3 @@ cairo_region_equal (const cairo_region_t *a, return pixman_region32_equal (CONST_CAST &a->rgn, CONST_CAST &b->rgn); } -slim_hidden_def (cairo_region_equal); diff --git a/src/cairo-scaled-font-subsets.c b/src/cairo-scaled-font-subsets.c index 2a9e8144c..f15f819a0 100644 --- a/src/cairo-scaled-font-subsets.c +++ b/src/cairo-scaled-font-subsets.c @@ -166,7 +166,7 @@ _cairo_sub_font_glyph_create (unsigned long scaled_font_glyph_index, { cairo_sub_font_glyph_t *sub_font_glyph; - sub_font_glyph = _cairo_malloc (sizeof (cairo_sub_font_glyph_t)); + sub_font_glyph = _cairo_calloc (sizeof (cairo_sub_font_glyph_t)); if (unlikely (sub_font_glyph == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return NULL; @@ -276,7 +276,7 @@ _cairo_sub_font_create (cairo_scaled_font_subsets_t *parent, cairo_sub_font_t *sub_font; int i; - sub_font = _cairo_malloc (sizeof (cairo_sub_font_t)); + sub_font = _cairo_calloc (sizeof (cairo_sub_font_t)); if (unlikely (sub_font == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -430,7 +430,7 @@ _cairo_sub_font_glyph_map_to_unicode (cairo_sub_font_glyph_t *sub_font_glyph, 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) + strncmp (utf8, sub_font_glyph->utf8, utf8_len) == 0) { /* Requested utf8 mapping matches the existing mapping */ *is_mapped = TRUE; @@ -749,7 +749,7 @@ _cairo_scaled_font_subsets_create_internal (cairo_subsets_type_t type) { cairo_scaled_font_subsets_t *subsets; - subsets = _cairo_malloc (sizeof (cairo_scaled_font_subsets_t)); + subsets = _cairo_calloc (sizeof (cairo_scaled_font_subsets_t)); if (unlikely (subsets == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return NULL; @@ -922,6 +922,7 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets, font_face = cairo_scaled_font_get_font_face (scaled_font); cairo_matrix_init_identity (&identity); _cairo_font_options_init_default (&font_options); + cairo_scaled_font_get_font_options (scaled_font, &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, @@ -1205,7 +1206,7 @@ _cairo_string_init_key (cairo_string_entry_t *key, char *s) static cairo_status_t create_string_entry (char *s, cairo_string_entry_t **entry) { - *entry = _cairo_malloc (sizeof (cairo_string_entry_t)); + *entry = _cairo_calloc (sizeof (cairo_string_entry_t)); if (unlikely (*entry == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -1237,7 +1238,7 @@ _cairo_scaled_font_subset_create_glyph_names (cairo_scaled_font_subset_t *subset if (unlikely (names == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); - subset->glyph_names = calloc (subset->num_glyphs, sizeof (char *)); + subset->glyph_names = _cairo_calloc_ab (subset->num_glyphs, sizeof (char *)); if (unlikely (subset->glyph_names == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto CLEANUP_HASH; diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c index 75640f723..82a4447f5 100755 --- a/src/cairo-scaled-font.c +++ b/src/cairo-scaled-font.c @@ -336,7 +336,6 @@ 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. @@ -379,7 +378,7 @@ _cairo_scaled_font_map_lock (void) CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex); if (cairo_scaled_font_map == NULL) { - cairo_scaled_font_map = _cairo_malloc (sizeof (cairo_scaled_font_map_t)); + cairo_scaled_font_map = _cairo_calloc (sizeof (cairo_scaled_font_map_t)); if (unlikely (cairo_scaled_font_map == NULL)) goto CLEANUP_MUTEX_LOCK; @@ -520,7 +519,7 @@ _cairo_scaled_font_register_placeholder_and_unlock_font_map (cairo_scaled_font_t if (unlikely (status)) return status; - placeholder_scaled_font = _cairo_malloc (sizeof (cairo_scaled_font_t)); + placeholder_scaled_font = _cairo_calloc (sizeof (cairo_scaled_font_t)); if (unlikely (placeholder_scaled_font == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -679,6 +678,12 @@ _cairo_scaled_font_init_key (cairo_scaled_font_t *scaled_font, _cairo_scaled_font_compute_hash (scaled_font); } +static void +_cairo_scaled_font_fini_key (cairo_scaled_font_t *scaled_font) +{ + _cairo_font_options_fini (&scaled_font->options); +} + static cairo_bool_t _cairo_scaled_font_keys_equal (const void *abstract_key_a, const void *abstract_key_b) @@ -915,6 +920,7 @@ _cairo_scaled_font_fini_internal (cairo_scaled_font_t *scaled_font) _cairo_scaled_font_reset_cache (scaled_font); _cairo_hash_table_destroy (scaled_font->glyphs); + _cairo_font_options_fini (&scaled_font->options); cairo_font_face_destroy (scaled_font->font_face); cairo_font_face_destroy (scaled_font->original_font_face); @@ -1106,6 +1112,7 @@ cairo_scaled_font_create (cairo_font_face_t *font_face, * just wait until it's done, then retry */ _cairo_scaled_font_placeholder_wait_for_creation_to_finish (scaled_font); } + _cairo_scaled_font_fini_key (&key); if (scaled_font != NULL) { /* If the original reference count is 0, then this font must have @@ -1239,7 +1246,6 @@ cairo_scaled_font_create (cairo_font_face_t *font_face, 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]; @@ -1257,7 +1263,7 @@ _cairo_scaled_font_create_in_error (cairo_status_t status) CAIRO_MUTEX_LOCK (_cairo_scaled_font_error_mutex); scaled_font = _cairo_scaled_font_nil_objects[status]; if (unlikely (scaled_font == NULL)) { - scaled_font = _cairo_malloc (sizeof (cairo_scaled_font_t)); + scaled_font = _cairo_calloc (sizeof (cairo_scaled_font_t)); if (unlikely (scaled_font == NULL)) { CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_error_mutex); _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); @@ -1325,7 +1331,6 @@ cairo_scaled_font_reference (cairo_scaled_font_t *scaled_font) return scaled_font; } -slim_hidden_def (cairo_scaled_font_reference); /** * cairo_scaled_font_destroy: @@ -1409,7 +1414,6 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font) free (lru); } } -slim_hidden_def (cairo_scaled_font_destroy); /** * cairo_scaled_font_get_reference_count: @@ -1453,7 +1457,6 @@ cairo_scaled_font_get_user_data (cairo_scaled_font_t *scaled_font, return _cairo_user_data_array_get_data (&scaled_font->user_data, key); } -slim_hidden_def (cairo_scaled_font_get_user_data); /** * cairo_scaled_font_set_user_data: @@ -1485,7 +1488,6 @@ cairo_scaled_font_set_user_data (cairo_scaled_font_t *scaled_font, return _cairo_user_data_array_set_data (&scaled_font->user_data, key, user_data, destroy); } -slim_hidden_def (cairo_scaled_font_set_user_data); /* Public font API follows. */ @@ -1513,7 +1515,6 @@ cairo_scaled_font_extents (cairo_scaled_font_t *scaled_font, *extents = scaled_font->extents; } -slim_hidden_def (cairo_scaled_font_extents); /** * cairo_scaled_font_text_extents: @@ -1713,7 +1714,6 @@ ZERO_EXTENTS: extents->x_advance = 0.0; extents->y_advance = 0.0; } -slim_hidden_def (cairo_scaled_font_glyph_extents); #define GLYPH_LUT_SIZE 64 static cairo_status_t @@ -2180,7 +2180,6 @@ cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font, return status; } -slim_hidden_def (cairo_scaled_font_text_to_glyphs); static inline cairo_bool_t _range_contains_glyph (const cairo_box_t *extents, @@ -2662,7 +2661,7 @@ _cairo_scaled_glyph_set_path (cairo_scaled_glyph_t *scaled_glyph, * glyph, or NULL if foreground color not required. * * Sets the surface that was used to record the glyph. - */ + **/ void _cairo_scaled_glyph_set_recording_surface (cairo_scaled_glyph_t *scaled_glyph, cairo_scaled_font_t *scaled_font, @@ -2695,7 +2694,7 @@ _cairo_scaled_glyph_set_recording_surface (cairo_scaled_glyph_t *scaled_glyph, * used when rendering the surface color. * * Sets the color surface of the glyph. - */ + **/ void _cairo_scaled_glyph_set_color_surface (cairo_scaled_glyph_t *scaled_glyph, cairo_scaled_font_t *scaled_font, @@ -2760,7 +2759,7 @@ _cairo_scaled_font_allocate_glyph (cairo_scaled_font_t *scaled_font, } } - page = _cairo_malloc (sizeof (cairo_scaled_glyph_page_t)); + page = _cairo_calloc (sizeof (cairo_scaled_glyph_page_t)); if (unlikely (page == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -2991,7 +2990,6 @@ _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 @@ -3017,7 +3015,6 @@ cairo_scaled_font_get_font_face (cairo_scaled_font_t *scaled_font) return scaled_font->font_face; } -slim_hidden_def (cairo_scaled_font_get_font_face); /** * cairo_scaled_font_get_font_matrix: @@ -3040,7 +3037,6 @@ cairo_scaled_font_get_font_matrix (cairo_scaled_font_t *scaled_font, *font_matrix = scaled_font->font_matrix; } -slim_hidden_def (cairo_scaled_font_get_font_matrix); /** * cairo_scaled_font_get_ctm: @@ -3065,7 +3061,6 @@ cairo_scaled_font_get_ctm (cairo_scaled_font_t *scaled_font, *ctm = scaled_font->ctm; } -slim_hidden_def (cairo_scaled_font_get_ctm); /** * cairo_scaled_font_get_scale_matrix: @@ -3116,7 +3111,6 @@ cairo_scaled_font_get_font_options (cairo_scaled_font_t *scaled_font, _cairo_font_options_fini (options); _cairo_font_options_init_copy (options, &scaled_font->options); } -slim_hidden_def (cairo_scaled_font_get_font_options); cairo_bool_t _cairo_scaled_font_has_color_glyphs (cairo_scaled_font_t *scaled_font) diff --git a/src/cairo-script-private.h b/src/cairo-script-private.h index 5b506f500..989401244 100644 --- a/src/cairo-script-private.h +++ b/src/cairo-script-private.h @@ -52,8 +52,6 @@ cairo_private void _cairo_script_context_attach_snapshots (cairo_device_t *device, cairo_bool_t enable); -slim_hidden_proto (cairo_script_surface_create); - CAIRO_END_DECLS #endif /* CAIRO_SCRIPT_PRIVATE_H */ diff --git a/src/cairo-script-surface.c b/src/cairo-script-surface.c index c3f1b05bb..6d25acd38 100644 --- a/src/cairo-script-surface.c +++ b/src/cairo-script-surface.c @@ -264,7 +264,7 @@ _bitmap_next_id (struct _bitmap *b, } while (b != NULL); assert (prev != NULL); - bb = _cairo_malloc (sizeof (struct _bitmap)); + bb = _cairo_calloc (sizeof (struct _bitmap)); if (unlikely (bb == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -370,6 +370,21 @@ _filter_to_string (cairo_filter_t filter) return names[filter]; } +static const char * +_dither_to_string (cairo_dither_t dither) +{ + static const char *names[] = { + "DITHER_DEFAULT", /* CAIRO_FILTER_FAST */ + "DITHER_NONE", /* CAIRO_FILTER_GOOD */ + "DITHER_FAST", /* CAIRO_FILTER_BEST */ + "DITHER_GOOD", /* CAIRO_FILTER_NEAREST */ + "DITHER_BEST", /* CAIRO_FILTER_BILINEAR */ + }; + assert (dither < ARRAY_LENGTH (names)); + return names[dither]; +} + + static const char * _fill_rule_to_string (cairo_fill_rule_t rule) { @@ -1129,7 +1144,7 @@ attach_snapshot (cairo_script_context_t *ctx, if (! ctx->attach_snapshots) return; - surface = _cairo_malloc (sizeof (*surface)); + surface = _cairo_calloc (sizeof (*surface)); if (unlikely (surface == NULL)) return; @@ -1731,6 +1746,17 @@ _emit_pattern (cairo_script_surface_t *surface, " //%s set-filter\n ", _filter_to_string (pattern->filter)); } + /* XXX need to discriminate the user explicitly setting the default */ + if (pattern->dither != CAIRO_DITHER_DEFAULT) { + if (need_newline) { + _cairo_output_stream_puts (ctx->stream, "\n "); + need_newline = FALSE; + } + + _cairo_output_stream_printf (ctx->stream, + " //%s set-dither\n ", + _dither_to_string (pattern->dither)); + } if (! is_default_extend ){ if (need_newline) { _cairo_output_stream_puts (ctx->stream, "\n "); @@ -2204,6 +2230,7 @@ _cairo_script_surface_finish (void *abstract_surface) _cairo_pattern_fini (&surface->cr.current_source.base); _cairo_path_fixed_fini (&surface->cr.current_path); + _cairo_font_options_fini (&surface->cr.current_font_options); _cairo_surface_clipper_reset (&surface->clipper); status = cairo_device_acquire (&ctx->base); @@ -2231,7 +2258,7 @@ _cairo_script_surface_finish (void *abstract_surface) } cairo_list_del (&surface->operand.link); } else { - struct deferred_finish *link = _cairo_malloc (sizeof (*link)); + struct deferred_finish *link = _cairo_calloc (sizeof (*link)); if (link == NULL) { status2 = _cairo_error (CAIRO_STATUS_NO_MEMORY); if (status == CAIRO_STATUS_SUCCESS) @@ -2965,7 +2992,7 @@ _emit_scaled_font_init (cairo_script_surface_t *surface, cairo_script_font_t *font_private; cairo_int_status_t status; - font_private = _cairo_malloc (sizeof (cairo_script_font_t)); + font_private = _cairo_calloc (sizeof (cairo_script_font_t)); if (unlikely (font_private == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -3701,7 +3728,7 @@ _cairo_script_surface_create_internal (cairo_script_context_t *ctx, if (unlikely (ctx == NULL)) return (cairo_script_surface_t *) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NULL_POINTER)); - surface = _cairo_malloc (sizeof (cairo_script_surface_t)); + surface = _cairo_calloc (sizeof (cairo_script_surface_t)); if (unlikely (surface == NULL)) return (cairo_script_surface_t *) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); @@ -3750,7 +3777,7 @@ _cairo_script_context_create_internal (cairo_output_stream_t *stream) { cairo_script_context_t *ctx; - ctx = _cairo_malloc (sizeof (cairo_script_context_t)); + ctx = _cairo_calloc (sizeof (cairo_script_context_t)); if (unlikely (ctx == NULL)) return _cairo_device_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); @@ -3963,7 +3990,6 @@ cairo_script_surface_create (cairo_device_t *script, content, extents, NULL)->base; } -slim_hidden_def (cairo_script_surface_create); /** * cairo_script_surface_create_for_target: diff --git a/src/cairo-surface-observer.c b/src/cairo-surface-observer.c index bf29d4219..9ff21fc27 100644 --- a/src/cairo-surface-observer.c +++ b/src/cairo-surface-observer.c @@ -60,8 +60,17 @@ * @Short_Description: Observing other surfaces * @See_Also: #cairo_surface_t * - * A surface that exists solely to watch another is doing. - */ + * A surface that exists solely to watch what another surface is doing. + **/ + +/** + * CAIRO_HAS_OBSERVER_SURFACE: + * + * Defined if the observer surface backend is available. + * This macro can be used to conditionally compile backend-specific code. + * + * Since: 1.12 + **/ static const cairo_surface_backend_t _cairo_surface_observer_backend; @@ -357,7 +366,7 @@ _cairo_device_create_observer_internal (cairo_device_t *target, cairo_device_observer_t *device; cairo_status_t status; - device = _cairo_malloc (sizeof (cairo_device_observer_t)); + device = _cairo_calloc (sizeof (cairo_device_observer_t)); if (unlikely (device == NULL)) return _cairo_device_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); @@ -388,7 +397,7 @@ _cairo_surface_create_observer_internal (cairo_device_t *device, cairo_surface_observer_t *surface; cairo_status_t status; - surface = _cairo_malloc (sizeof (cairo_surface_observer_t)); + surface = _cairo_calloc (sizeof (cairo_surface_observer_t)); if (unlikely (surface == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); @@ -1382,8 +1391,8 @@ static const cairo_surface_backend_t _cairo_surface_observer_backend = { * the process it will log operations and times, which are fast, which are * slow, which are frequent, etc. * - * The @mode parameter can be set to either CAIRO_SURFACE_OBSERVER_NORMAL - * or CAIRO_SURFACE_OBSERVER_RECORD_OPERATIONS, to control whether or not + * The @mode parameter can be set to either %CAIRO_SURFACE_OBSERVER_NORMAL + * or %CAIRO_SURFACE_OBSERVER_RECORD_OPERATIONS, to control whether or not * the internal observer should record operations. * * Return value: a pointer to the newly allocated surface. The caller @@ -1427,7 +1436,7 @@ _cairo_surface_observer_add_callback (cairo_list_t *head, { struct callback_list *cb; - cb = _cairo_malloc (sizeof (*cb)); + cb = _cairo_calloc (sizeof (*cb)); if (unlikely (cb == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -1438,6 +1447,18 @@ _cairo_surface_observer_add_callback (cairo_list_t *head, return CAIRO_STATUS_SUCCESS; } +/** + * cairo_surface_observer_add_paint_callback: + * @abstract_surface: a #cairo_surface_observer_t + * @func: callback function for paint operations + * @data: closure to pass to the callback + * + * Adds a callback for paint operations on the observed surface. + * + * Returns: the status of the surface + * + * Since: 1.12 + **/ cairo_status_t cairo_surface_observer_add_paint_callback (cairo_surface_t *abstract_surface, cairo_surface_observer_callback_t func, @@ -1456,6 +1477,18 @@ cairo_surface_observer_add_paint_callback (cairo_surface_t *abstract_surface, func, data); } +/** + * cairo_surface_observer_add_mask_callback: + * @abstract_surface: a #cairo_surface_observer_t + * @func: callback function for mask operations + * @data: closure to pass to the callback + * + * Adds a callback for mask operations on the observed surface. + * + * Returns: the status of the surface + * + * Since: 1.12 + **/ cairo_status_t cairo_surface_observer_add_mask_callback (cairo_surface_t *abstract_surface, cairo_surface_observer_callback_t func, @@ -1474,6 +1507,18 @@ cairo_surface_observer_add_mask_callback (cairo_surface_t *abstract_surface, func, data); } +/** + * cairo_surface_observer_add_fill_callback: + * @abstract_surface: a #cairo_surface_observer_t + * @func: callback function for fill operations + * @data: closure to pass to the callback + * + * Adds a callback for fill operations on the observed surface. + * + * Returns: the status of the surface + * + * Since: 1.12 + **/ cairo_status_t cairo_surface_observer_add_fill_callback (cairo_surface_t *abstract_surface, cairo_surface_observer_callback_t func, @@ -1492,6 +1537,18 @@ cairo_surface_observer_add_fill_callback (cairo_surface_t *abstract_surface, func, data); } +/** + * cairo_surface_observer_add_stroke_callback: + * @abstract_surface: a #cairo_surface_observer_t + * @func: callback function for stroke operations + * @data: closure to pass to the callback + * + * Adds a callback for stroke operations on the observed surface. + * + * Returns: the status of the surface + * + * Since: 1.12 + **/ cairo_status_t cairo_surface_observer_add_stroke_callback (cairo_surface_t *abstract_surface, cairo_surface_observer_callback_t func, @@ -1510,6 +1567,18 @@ cairo_surface_observer_add_stroke_callback (cairo_surface_t *abstract_surface, func, data); } +/** + * cairo_surface_observer_add_glyphs_callback: + * @abstract_surface: a #cairo_surface_observer_t + * @func: callback function for glyph operations + * @data: closure to pass to the callback + * + * Adds a callback for glyph operations on the observed surface. + * + * Returns: the status of the surface + * + * Since: 1.10 + **/ cairo_status_t cairo_surface_observer_add_glyphs_callback (cairo_surface_t *abstract_surface, cairo_surface_observer_callback_t func, @@ -1528,6 +1597,18 @@ cairo_surface_observer_add_glyphs_callback (cairo_surface_t *abstract_surface, func, data); } +/** + * cairo_surface_observer_add_flush_callback: + * @abstract_surface: a #cairo_surface_observer_t + * @func: callback for flush operations + * @data: closure to pass to the callback + * + * Adds a callback for flush operations on the observed surface. + * + * Returns: the status of the surface + * + * Since: 1.10 + **/ cairo_status_t cairo_surface_observer_add_flush_callback (cairo_surface_t *abstract_surface, cairo_surface_observer_callback_t func, @@ -1546,6 +1627,18 @@ cairo_surface_observer_add_flush_callback (cairo_surface_t *abstract_surface, func, data); } +/** + * cairo_surface_observer_add_finish_callback: + * @abstract_surface: a #cairo_surface_observer_t + * @func: callback function for the finish operation + * @data: closure to pass to the callback + * + * Adds a callback for finish operations on the observed surface. + * + * Returns: the status of the surface + * + * Since: 1.10 + **/ cairo_status_t cairo_surface_observer_add_finish_callback (cairo_surface_t *abstract_surface, cairo_surface_observer_callback_t func, @@ -1966,6 +2059,18 @@ _cairo_observation_print (cairo_output_stream_t *stream, cairo_device_destroy (script); } +/** + * cairo_surface_observer_print: + * @abstract_surface: a #cairo_surface_observer_t + * @write_func: callback for writing on a stream + * @closure: data to pass to @write_func + * + * Prints the observer log using the given callback. + * + * Returns: the status of the print operation + * + * Since: 1.12 + **/ cairo_status_t cairo_surface_observer_print (cairo_surface_t *abstract_surface, cairo_write_func_t write_func, @@ -1987,6 +2092,16 @@ cairo_surface_observer_print (cairo_surface_t *abstract_surface, return _cairo_output_stream_destroy (stream); } +/** + * cairo_surface_observer_elapsed: + * @abstract_surface: a #cairo_surface_observer_t + * + * Returns the total observation time. + * + * Returns: the elapsed time, in nanoseconds + * + * Since: 1.12 + **/ double cairo_surface_observer_elapsed (cairo_surface_t *abstract_surface) { @@ -2002,6 +2117,18 @@ cairo_surface_observer_elapsed (cairo_surface_t *abstract_surface) return _cairo_time_to_ns (_cairo_observation_total_elapsed (&surface->log)); } +/** + * cairo_device_observer_print: + * @abstract_device: the observed #cairo_device_t + * @write_func: the write function + * @closure: data to pass to the @write_func + * + * Prints the device log using the given function. + * + * Returns: the status after the operation + * + * Since: 1.12 + **/ cairo_status_t cairo_device_observer_print (cairo_device_t *abstract_device, cairo_write_func_t write_func, @@ -2023,6 +2150,16 @@ cairo_device_observer_print (cairo_device_t *abstract_device, return _cairo_output_stream_destroy (stream); } +/** + * cairo_device_observer_elapsed: + * @abstract_device: the observed #cairo_device_t + * + * Returns the total elapsed time of the observation. + * + * Returns: the elapsed time, in nanoseconds. + * + * Since: 1.12 + **/ double cairo_device_observer_elapsed (cairo_device_t *abstract_device) { @@ -2038,6 +2175,16 @@ cairo_device_observer_elapsed (cairo_device_t *abstract_device) return _cairo_time_to_ns (_cairo_observation_total_elapsed (&device->log)); } +/** + * cairo_device_observer_paint_elapsed: + * @abstract_device: the observed #cairo_device_t + * + * Returns the elapsed time of the paint operations. + * + * Returns: the elapsed time, in nanoseconds. + * + * Since: 1.12 + **/ double cairo_device_observer_paint_elapsed (cairo_device_t *abstract_device) { @@ -2053,6 +2200,16 @@ cairo_device_observer_paint_elapsed (cairo_device_t *abstract_device) return _cairo_time_to_ns (device->log.paint.elapsed); } +/** + * cairo_device_observer_mask_elapsed: + * @abstract_device: the observed #cairo_device_t + * + * Returns the elapsed time of the mask operations. + * + * Returns: the elapsed time, in nanoseconds + * + * Since: 1.12 + **/ double cairo_device_observer_mask_elapsed (cairo_device_t *abstract_device) { @@ -2068,6 +2225,16 @@ cairo_device_observer_mask_elapsed (cairo_device_t *abstract_device) return _cairo_time_to_ns (device->log.mask.elapsed); } +/** + * cairo_device_observer_fill_elapsed: + * @abstract_device: the observed #cairo_device_t + * + * Returns the elapsed time of the fill operations. + * + * Returns: the elapsed time, in nanoseconds. + * + * Since: 1.12 + **/ double cairo_device_observer_fill_elapsed (cairo_device_t *abstract_device) { @@ -2083,6 +2250,16 @@ cairo_device_observer_fill_elapsed (cairo_device_t *abstract_device) return _cairo_time_to_ns (device->log.fill.elapsed); } +/** + * cairo_device_observer_stroke_elapsed: + * @abstract_device: the observed #cairo_device_t + * + * Returns the elapsed time of the stroke operations. + * + * Returns: the elapsed time, in nanoseconds. + * + * Since: 1.12 + **/ double cairo_device_observer_stroke_elapsed (cairo_device_t *abstract_device) { @@ -2098,6 +2275,16 @@ cairo_device_observer_stroke_elapsed (cairo_device_t *abstract_device) return _cairo_time_to_ns (device->log.stroke.elapsed); } +/** + * cairo_device_observer_glyphs_elapsed: + * @abstract_device: the observed #cairo_device_t + * + * Returns the elapsed time of the glyph operations. + * + * Returns: the elapsed time, in nanoseconds. + * + * Since: 1.12 + **/ double cairo_device_observer_glyphs_elapsed (cairo_device_t *abstract_device) { diff --git a/src/cairo-surface-snapshot.c b/src/cairo-surface-snapshot.c index b2908f6bc..dd4a25364 100644 --- a/src/cairo-surface-snapshot.c +++ b/src/cairo-surface-snapshot.c @@ -101,7 +101,7 @@ _cairo_surface_snapshot_acquire_source_image (void *abstract_ struct snapshot_extra *extra; cairo_status_t status; - extra = _cairo_malloc (sizeof (*extra)); + extra = _cairo_calloc (sizeof (*extra)); if (unlikely (extra == NULL)) { *extra_out = NULL; return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -263,7 +263,7 @@ _cairo_surface_snapshot (cairo_surface_t *surface) if (snapshot != NULL) return cairo_surface_reference (&snapshot->base); - snapshot = _cairo_malloc (sizeof (cairo_surface_snapshot_t)); + snapshot = _cairo_calloc (sizeof (cairo_surface_snapshot_t)); if (unlikely (snapshot == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_FINISHED)); diff --git a/src/cairo-surface-subsurface.c b/src/cairo-surface-subsurface.c index b2a10e9bc..9818c7296 100644 --- a/src/cairo-surface-subsurface.c +++ b/src/cairo-surface-subsurface.c @@ -462,7 +462,7 @@ cairo_surface_create_for_rectangle (cairo_surface_t *target, if (unlikely (target->finished)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_FINISHED)); - surface = _cairo_malloc (sizeof (cairo_surface_subsurface_t)); + surface = _cairo_calloc (sizeof (cairo_surface_subsurface_t)); if (unlikely (surface == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); @@ -522,7 +522,7 @@ _cairo_surface_create_for_rectangle_int (cairo_surface_t *target, assert (target->backend->type != CAIRO_SURFACE_TYPE_SUBSURFACE); - surface = _cairo_malloc (sizeof (cairo_surface_subsurface_t)); + surface = _cairo_calloc (sizeof (cairo_surface_subsurface_t)); if (unlikely (surface == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); diff --git a/src/cairo-surface.c b/src/cairo-surface.c index f1292e0bb..86c1837b9 100644 --- a/src/cairo-surface.c +++ b/src/cairo-surface.c @@ -127,13 +127,18 @@ const cairo_surface_t name = { \ NULL, /* snapshot_detach */ \ { NULL, NULL }, /* snapshots */ \ { NULL, NULL }, /* snapshot */ \ - { CAIRO_ANTIALIAS_DEFAULT, /* antialias */ \ + { /* font options begin */\ + CAIRO_ANTIALIAS_DEFAULT, /* antialias */ \ CAIRO_SUBPIXEL_ORDER_DEFAULT, /* subpixel_order */ \ CAIRO_LCD_FILTER_DEFAULT, /* lcd_filter */ \ CAIRO_HINT_STYLE_DEFAULT, /* hint_style */ \ CAIRO_HINT_METRICS_DEFAULT, /* hint_metrics */ \ - CAIRO_ROUND_GLYPH_POS_DEFAULT /* round_glyph_positions */ \ - }, /* font_options */ \ + CAIRO_ROUND_GLYPH_POS_DEFAULT, /* round_glyph_positions */ \ + NULL, /* variations */ \ + CAIRO_COLOR_MODE_DEFAULT, /* color mode */ \ + CAIRO_COLOR_PALETTE_DEFAULT, /* color palette */ \ + NULL, 0, /* custom palette */ \ + }, /* font_options end */ \ NULL, /* foreground_source */ \ FALSE, /* foreground_used */ \ } @@ -154,6 +159,7 @@ static DEFINE_NIL_SURFACE(CAIRO_STATUS_INVALID_STRIDE, _cairo_surface_nil_invali static DEFINE_NIL_SURFACE(CAIRO_STATUS_INVALID_SIZE, _cairo_surface_nil_invalid_size); static DEFINE_NIL_SURFACE(CAIRO_STATUS_DEVICE_TYPE_MISMATCH, _cairo_surface_nil_device_type_mismatch); static DEFINE_NIL_SURFACE(CAIRO_STATUS_DEVICE_ERROR, _cairo_surface_nil_device_error); +static DEFINE_NIL_SURFACE(CAIRO_STATUS_PNG_ERROR, _cairo_surface_nil_png_error); static DEFINE_NIL_SURFACE(CAIRO_INT_STATUS_UNSUPPORTED, _cairo_surface_nil_unsupported); static DEFINE_NIL_SURFACE(CAIRO_INT_STATUS_NOTHING_TO_DO, _cairo_surface_nil_nothing_to_do); @@ -260,7 +266,6 @@ cairo_surface_status (cairo_surface_t *surface) { return surface->status; } -slim_hidden_def (cairo_surface_status); static unsigned int _cairo_surface_allocate_unique_id (void) @@ -272,7 +277,7 @@ _cairo_surface_allocate_unique_id (void) unique_id = 1; return unique_id; #else - cairo_atomic_int_t old, id; + int old, id; do { old = _cairo_atomic_uint_get (&unique_id); @@ -454,6 +459,7 @@ _cairo_surface_copy_similar_properties (cairo_surface_t *surface, cairo_surface_get_font_options (other, &options); _cairo_surface_set_font_options (surface, &options); + _cairo_font_options_fini (&options); } cairo_surface_set_fallback_resolution (surface, @@ -605,7 +611,6 @@ cairo_surface_create_similar_image (cairo_surface_t *other, return image; } -slim_hidden_def (cairo_surface_create_similar_image); /** * _cairo_surface_map_to_image: @@ -937,7 +942,6 @@ cairo_surface_reference (cairo_surface_t *surface) return surface; } -slim_hidden_def (cairo_surface_reference); /** * cairo_surface_destroy: @@ -986,6 +990,9 @@ cairo_surface_destroy (cairo_surface_t *surface) if (surface->owns_device) cairo_device_destroy (surface->device); + if (surface->has_font_options) + _cairo_font_options_fini (&surface->font_options); + assert (surface->snapshot_of == NULL); assert (! _cairo_surface_has_snapshots (surface)); /* paranoid check that nobody took a reference whilst finishing */ @@ -993,7 +1000,6 @@ cairo_surface_destroy (cairo_surface_t *surface) free (surface); } -slim_hidden_def(cairo_surface_destroy); /** * cairo_surface_get_reference_count: @@ -1087,7 +1093,6 @@ cairo_surface_finish (cairo_surface_t *surface) cairo_surface_destroy (surface); } -slim_hidden_def (cairo_surface_finish); /** * _cairo_surface_release_device_reference: @@ -1215,7 +1220,6 @@ cairo_surface_get_mime_data (cairo_surface_t *surface, } } } -slim_hidden_def (cairo_surface_get_mime_data); static void _cairo_mime_data_destroy (void *ptr) @@ -1445,7 +1449,7 @@ cairo_surface_set_mime_data (cairo_surface_t *surface, return _cairo_surface_set_error (surface, status); if (data != NULL) { - mime_data = _cairo_malloc (sizeof (cairo_mime_data_t)); + mime_data = _cairo_calloc (sizeof (cairo_mime_data_t)); if (unlikely (mime_data == NULL)) return _cairo_surface_set_error (surface, _cairo_error (CAIRO_STATUS_NO_MEMORY)); @@ -1472,7 +1476,6 @@ cairo_surface_set_mime_data (cairo_surface_t *surface, return CAIRO_STATUS_SUCCESS; } -slim_hidden_def (cairo_surface_set_mime_data); /** * cairo_surface_supports_mime_type: @@ -1512,7 +1515,6 @@ cairo_surface_supports_mime_type (cairo_surface_t *surface, return FALSE; } -slim_hidden_def (cairo_surface_supports_mime_type); static void _cairo_mime_data_reference (const void *key, void *elt, void *closure) @@ -1624,7 +1626,6 @@ cairo_surface_get_font_options (cairo_surface_t *surface, _cairo_font_options_init_copy (options, &surface->font_options); } -slim_hidden_def (cairo_surface_get_font_options); cairo_status_t _cairo_surface_flush (cairo_surface_t *surface, unsigned flags) @@ -1666,7 +1667,6 @@ cairo_surface_flush (cairo_surface_t *surface) if (unlikely (status)) _cairo_surface_set_error (surface, status); } -slim_hidden_def (cairo_surface_flush); /** * cairo_surface_mark_dirty: @@ -1695,7 +1695,6 @@ cairo_surface_mark_dirty (cairo_surface_t *surface) extents.x, extents.y, extents.width, extents.height); } -slim_hidden_def (cairo_surface_mark_dirty); /** * cairo_surface_mark_dirty_rectangle: @@ -1769,7 +1768,6 @@ cairo_surface_mark_dirty_rectangle (cairo_surface_t *surface, _cairo_surface_set_error (surface, status); } } -slim_hidden_def (cairo_surface_mark_dirty_rectangle); /** * cairo_surface_set_device_scale: @@ -1825,7 +1823,6 @@ cairo_surface_set_device_scale (cairo_surface_t *surface, _cairo_observers_notify (&surface->device_transform_observers, surface); } -slim_hidden_def (cairo_surface_set_device_scale); /** * cairo_surface_get_device_scale: @@ -1848,7 +1845,6 @@ cairo_surface_get_device_scale (cairo_surface_t *surface, if (y_scale) *y_scale = surface->device_transform.yy; } -slim_hidden_def (cairo_surface_get_device_scale); /** * cairo_surface_set_device_offset: @@ -1903,7 +1899,6 @@ cairo_surface_set_device_offset (cairo_surface_t *surface, _cairo_observers_notify (&surface->device_transform_observers, surface); } -slim_hidden_def (cairo_surface_set_device_offset); /** * cairo_surface_get_device_offset: @@ -1926,7 +1921,6 @@ cairo_surface_get_device_offset (cairo_surface_t *surface, if (y_offset) *y_offset = surface->device_transform.y0; } -slim_hidden_def (cairo_surface_get_device_offset); /** * cairo_surface_set_fallback_resolution: @@ -1995,7 +1989,6 @@ cairo_surface_set_fallback_resolution (cairo_surface_t *surface, 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: @@ -2503,7 +2496,6 @@ cairo_surface_copy_page (cairo_surface_t *surface) _cairo_surface_set_error (surface, surface->backend->copy_page (surface)); } -slim_hidden_def (cairo_surface_copy_page); /** * cairo_surface_show_page: @@ -2542,7 +2534,6 @@ cairo_surface_show_page (cairo_surface_t *surface) _cairo_surface_set_error (surface, surface->backend->show_page (surface)); } -slim_hidden_def (cairo_surface_show_page); /** * _cairo_surface_get_extents: @@ -2633,7 +2624,6 @@ cairo_surface_has_show_text_glyphs (cairo_surface_t *surface) else return surface->backend->show_text_glyphs != NULL; } -slim_hidden_def (cairo_surface_has_show_text_glyphs); #define GLYPH_CACHE_SIZE 64 @@ -3144,6 +3134,8 @@ _cairo_surface_create_in_error (cairo_status_t status) return (cairo_surface_t *) &_cairo_surface_nil_device_type_mismatch; case CAIRO_STATUS_DEVICE_ERROR: return (cairo_surface_t *) &_cairo_surface_nil_device_error; + case CAIRO_STATUS_PNG_ERROR: + return (cairo_surface_t *) &_cairo_surface_nil_png_error; case CAIRO_STATUS_SUCCESS: case CAIRO_STATUS_LAST_STATUS: ASSERT_NOT_REACHED; @@ -3172,7 +3164,6 @@ _cairo_surface_create_in_error (cairo_status_t status) case CAIRO_STATUS_INVALID_MESH_CONSTRUCTION: case CAIRO_STATUS_DEVICE_FINISHED: case CAIRO_STATUS_JBIG2_GLOBAL_MISSING: - case CAIRO_STATUS_PNG_ERROR: case CAIRO_STATUS_FREETYPE_ERROR: case CAIRO_STATUS_WIN32_GDI_ERROR: case CAIRO_INT_STATUS_DWRITE_ERROR: diff --git a/src/cairo-svg-glyph-render.c b/src/cairo-svg-glyph-render.c index cac8a7a73..d0448bbda 100644 --- a/src/cairo-svg-glyph-render.c +++ b/src/cairo-svg-glyph-render.c @@ -1028,7 +1028,7 @@ create_element (tag_type_t type, char *tag) cairo_svg_element_t *elem; cairo_status_t status; - elem = _cairo_malloc (sizeof (cairo_svg_element_t)); + elem = _cairo_calloc (sizeof (cairo_svg_element_t)); if (unlikely (elem == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); return NULL; @@ -1767,6 +1767,7 @@ _read_png_from_base64 (void *closure, unsigned char *data, unsigned int length) } if (length > 0 && decode->buf_pos < 0) { n = 0; + val = 0; while (*decode->data && n < 4) { c = *decode->data++; if (c >='A' && c <='Z') { @@ -2589,7 +2590,7 @@ init_graphics_state (cairo_svg_glyph_render_t *svg_render) { cairo_svg_graphics_state_t *gs; - gs = _cairo_malloc (sizeof (cairo_svg_graphics_state_t)); + gs = _cairo_calloc (sizeof (cairo_svg_graphics_state_t)); get_paint (svg_render, "black", &gs->fill); get_paint (svg_render, "none", &gs->stroke); gs->color.type = FOREGROUND; @@ -2881,7 +2882,7 @@ save_graphics_state (cairo_svg_glyph_render_t *svg_render) cairo_save (svg_render->cr); - gs = _cairo_malloc (sizeof (cairo_svg_graphics_state_t)); + gs = _cairo_calloc (sizeof (cairo_svg_graphics_state_t)); gs->fill = svg_render->graphics_state->fill; gs->stroke = svg_render->graphics_state->stroke; gs->color = svg_render->graphics_state->color; @@ -3102,7 +3103,7 @@ _cairo_render_svg_glyph (const char *svg_document, { cairo_status_t status = CAIRO_STATUS_SUCCESS; - cairo_svg_glyph_render_t *svg_render = _cairo_malloc (sizeof (cairo_svg_glyph_render_t)); + cairo_svg_glyph_render_t *svg_render = _cairo_calloc (sizeof (cairo_svg_glyph_render_t)); if (unlikely (svg_render == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -3208,7 +3209,7 @@ _cairo_render_svg_glyph (const char *svg_document, * @debug_level: 0 - quiet, 1 - print errors, 2 - print warnings, 3 - info * @return TRUE on success, ie no errors, FALSE if error **/ -cairo_bool_t +cairo_public cairo_bool_t _cairo_debug_svg_render (cairo_t *cr, const char *svg_document, const char *element, diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c index b7212a547..249f46f53 100644 --- a/src/cairo-svg-surface.c +++ b/src/cairo-svg-surface.c @@ -940,7 +940,7 @@ _cairo_svg_surface_add_source_surface (cairo_svg_surface_t *surface, unique_id_length = 0; } - cairo_svg_source_surface_t *source_surface_entry = malloc (sizeof (cairo_svg_source_surface_t)); + cairo_svg_source_surface_t *source_surface_entry = _cairo_calloc (sizeof (cairo_svg_source_surface_t)); if (source_surface_entry == NULL) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto fail; @@ -1060,7 +1060,7 @@ _cairo_svg_surface_create_for_document (cairo_svg_document_t *document, cairo_surface_t *paginated; cairo_status_t status; - surface = _cairo_malloc (sizeof (cairo_svg_surface_t)); + surface = _cairo_calloc (sizeof (cairo_svg_surface_t)); if (unlikely (surface == NULL)) { return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); } @@ -1459,7 +1459,7 @@ _cairo_svg_document_emit_bitmap_glyph_data (cairo_svg_document_t *document, } _cairo_svg_stream_printf (&document->xml_node_glyphs, "/>\n"); - cairo_svg_paint_t *paint_entry = malloc (sizeof (cairo_svg_paint_t)); + cairo_svg_paint_t *paint_entry = _cairo_calloc (sizeof (cairo_svg_paint_t)); if (paint_entry == NULL) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto cleanup; @@ -2392,7 +2392,7 @@ _cairo_svg_surface_emit_composite_recording_pattern (cairo_svg_stream_t *output, } if (source_surface->transitive_paint_used) { - cairo_svg_paint_t *paint_entry = malloc (sizeof (cairo_svg_paint_t)); + cairo_svg_paint_t *paint_entry = _cairo_calloc (sizeof (cairo_svg_paint_t)); if (paint_entry == NULL) { return _cairo_error (CAIRO_STATUS_NO_MEMORY); } @@ -4175,7 +4175,7 @@ _cairo_svg_document_create (cairo_output_stream_t *output_stream, return output_stream->status; } - document = _cairo_malloc (sizeof (cairo_svg_document_t)); + document = _cairo_calloc (sizeof (cairo_svg_document_t)); if (unlikely (document == NULL)) { return _cairo_error (CAIRO_STATUS_NO_MEMORY); } @@ -4316,7 +4316,7 @@ _cairo_svg_document_finish (cairo_svg_document_t *document) } if (surface->transitive_paint_used) { - cairo_svg_paint_t *paint_entry = malloc (sizeof (cairo_svg_paint_t)); + cairo_svg_paint_t *paint_entry = _cairo_calloc (sizeof (cairo_svg_paint_t)); if (paint_entry == NULL) { return _cairo_error (CAIRO_STATUS_NO_MEMORY); } diff --git a/src/cairo-tag-attributes-private.h b/src/cairo-tag-attributes-private.h index 1b770aef9..5853f9a0d 100644 --- a/src/cairo-tag-attributes-private.h +++ b/src/cairo-tag-attributes-private.h @@ -47,6 +47,8 @@ typedef enum { TAG_LINK_DEST, TAG_LINK_URI, TAG_LINK_FILE, + TAG_LINK_PAGE, + TAG_LINK_DEST_AND_URI, } cairo_tag_link_type_t; typedef struct _cairo_content_attrs { diff --git a/src/cairo-tag-attributes.c b/src/cairo-tag-attributes.c index 4fde1b5b8..70ccd674f 100644 --- a/src/cairo-tag-attributes.c +++ b/src/cairo-tag-attributes.c @@ -432,7 +432,7 @@ parse_attributes (const char *attributes, const attribute_spec_t *attrib_def, ca goto fail1; } - attrib = calloc (1, sizeof (attribute_t)); + attrib = _cairo_calloc (sizeof (attribute_t)); if (unlikely (attrib == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto fail1; @@ -655,25 +655,30 @@ _cairo_tag_parse_link_attributes (const char *attributes, cairo_link_attrs_t *li } } - if (link_attrs->uri) { - link_attrs->link_type = TAG_LINK_URI; - if (link_attrs->dest || link_attrs->page || link_attrs->has_pos || link_attrs->file) - invalid_combination = TRUE; - - } else if (link_attrs->file) { + if (link_attrs->file) { link_attrs->link_type = TAG_LINK_FILE; if (link_attrs->uri) invalid_combination = TRUE; else if (link_attrs->dest && (link_attrs->page || link_attrs->has_pos)) invalid_combination = TRUE; + } else if (link_attrs->uri && link_attrs->dest) { + link_attrs->link_type = TAG_LINK_DEST_AND_URI; + if (link_attrs->page || link_attrs->has_pos || link_attrs->file) + invalid_combination = TRUE; + + } else if (link_attrs->uri) { + link_attrs->link_type = TAG_LINK_URI; + if (link_attrs->dest || link_attrs->page || link_attrs->has_pos || link_attrs->file) + invalid_combination = TRUE; + } else if (link_attrs->dest) { link_attrs->link_type = TAG_LINK_DEST; if (link_attrs->uri || link_attrs->page || link_attrs->has_pos) invalid_combination = TRUE; } else if (link_attrs->page) { - link_attrs->link_type = TAG_LINK_DEST; + link_attrs->link_type = TAG_LINK_PAGE; if (link_attrs->uri || link_attrs->dest) invalid_combination = TRUE; diff --git a/src/cairo-tag-stack-private.h b/src/cairo-tag-stack-private.h index 49145bf1d..b3878ddb2 100644 --- a/src/cairo-tag-stack-private.h +++ b/src/cairo-tag-stack-private.h @@ -116,4 +116,7 @@ _cairo_tag_get_type (const char *name); cairo_private cairo_status_t _cairo_tag_error (const char *fmt, ...) CAIRO_PRINTF_FORMAT (1, 2); +cairo_private void +_cairo_tag_warning (const char *fmt, ...) CAIRO_PRINTF_FORMAT (1, 2); + #endif /* CAIRO_TAG_STACK_PRIVATE_H */ diff --git a/src/cairo-tag-stack.c b/src/cairo-tag-stack.c index f182b508b..0d32f4fab 100644 --- a/src/cairo-tag-stack.c +++ b/src/cairo-tag-stack.c @@ -198,7 +198,7 @@ _cairo_tag_stack_push (cairo_tag_stack_t *stack, } } - elem = _cairo_malloc (sizeof(cairo_tag_stack_elem_t)); + elem = _cairo_calloc (sizeof(cairo_tag_stack_elem_t)); if (unlikely (elem == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -331,3 +331,17 @@ _cairo_tag_error (const char *fmt, ...) } return _cairo_error (CAIRO_STATUS_TAG_ERROR); } + +void +_cairo_tag_warning (const char *fmt, ...) +{ + va_list ap; + + if (getenv ("CAIRO_DEBUG_TAG") != NULL) { + printf ("TAG WARNING: "); + va_start (ap, fmt); + vprintf (fmt, ap); + va_end (ap); + printf ("\n"); + } +} diff --git a/src/cairo-tee-surface.c b/src/cairo-tee-surface.c index 1d075a29c..173991290 100644 --- a/src/cairo-tee-surface.c +++ b/src/cairo-tee-surface.c @@ -35,8 +35,22 @@ * Chris Wilson */ -/* This surface supports redirecting all its input to multiple surfaces. - */ +/** + * SECTION:cairo-tee + * @Title: Tee surface + * @Short_Description: Redirect input to multiple surfaces + * @See_Also: #cairo_surface_t + * + * The "tee" surface supports redirecting all its input to multiple surfaces. + **/ + +/** + * CAIRO_HAS_TEE_SURFACE: + * + * Defined if the tee surface backend is available. + * + * Since: 1.10 + **/ #include "cairoint.h" @@ -52,13 +66,10 @@ typedef struct _cairo_tee_surface { cairo_surface_t base; - cairo_surface_wrapper_t master; - cairo_array_t slaves; + cairo_surface_wrapper_t primary; + cairo_array_t replicas; } cairo_tee_surface_t; -slim_hidden_proto (cairo_tee_surface_create); -slim_hidden_proto (cairo_tee_surface_add); - static cairo_surface_t * _cairo_tee_surface_create_similar (void *abstract_surface, cairo_content_t content, @@ -69,21 +80,21 @@ _cairo_tee_surface_create_similar (void *abstract_surface, cairo_tee_surface_t *other = abstract_surface; cairo_surface_t *similar; cairo_surface_t *surface; - cairo_surface_wrapper_t *slaves; - int n, num_slaves; + cairo_surface_wrapper_t *replicas; + int n, num_replicas; - similar = _cairo_surface_wrapper_create_similar (&other->master, + similar = _cairo_surface_wrapper_create_similar (&other->primary, content, width, height); surface = cairo_tee_surface_create (similar); cairo_surface_destroy (similar); if (unlikely (surface->status)) return surface; - num_slaves = _cairo_array_num_elements (&other->slaves); - slaves = _cairo_array_index (&other->slaves, 0); - for (n = 0; n < num_slaves; n++) { + num_replicas = _cairo_array_num_elements (&other->replicas); + replicas = _cairo_array_index (&other->replicas, 0); + for (n = 0; n < num_replicas; n++) { - similar = _cairo_surface_wrapper_create_similar (&slaves[n], + similar = _cairo_surface_wrapper_create_similar (&replicas[n], content, width, height); cairo_tee_surface_add (surface, similar); @@ -103,17 +114,17 @@ static cairo_status_t _cairo_tee_surface_finish (void *abstract_surface) { cairo_tee_surface_t *surface = abstract_surface; - cairo_surface_wrapper_t *slaves; - int n, num_slaves; + cairo_surface_wrapper_t *replicas; + int n, num_replicas; - _cairo_surface_wrapper_fini (&surface->master); + _cairo_surface_wrapper_fini (&surface->primary); - num_slaves = _cairo_array_num_elements (&surface->slaves); - slaves = _cairo_array_index (&surface->slaves, 0); - for (n = 0; n < num_slaves; n++) - _cairo_surface_wrapper_fini (&slaves[n]); + num_replicas = _cairo_array_num_elements (&surface->replicas); + replicas = _cairo_array_index (&surface->replicas, 0); + for (n = 0; n < num_replicas; n++) + _cairo_surface_wrapper_fini (&replicas[n]); - _cairo_array_fini (&surface->slaves); + _cairo_array_fini (&surface->replicas); return CAIRO_STATUS_SUCCESS; } @@ -123,7 +134,7 @@ _cairo_tee_surface_source (void *abstract_surface, cairo_rectangle_int_t *extents) { cairo_tee_surface_t *surface = abstract_surface; - return _cairo_surface_get_source (surface->master.target, extents); + return _cairo_surface_get_source (surface->primary.target, extents); } static cairo_status_t @@ -132,26 +143,26 @@ _cairo_tee_surface_acquire_source_image (void *abstract_surface, void **image_extra) { cairo_tee_surface_t *surface = abstract_surface; - cairo_surface_wrapper_t *slaves; - int num_slaves, n; + cairo_surface_wrapper_t *replicas; + int num_replicas, n; /* we prefer to use a real image surface if available */ - if (_cairo_surface_is_image (surface->master.target)) { - return _cairo_surface_wrapper_acquire_source_image (&surface->master, + if (_cairo_surface_is_image (surface->primary.target)) { + return _cairo_surface_wrapper_acquire_source_image (&surface->primary, image_out, image_extra); } - num_slaves = _cairo_array_num_elements (&surface->slaves); - slaves = _cairo_array_index (&surface->slaves, 0); - for (n = 0; n < num_slaves; n++) { - if (_cairo_surface_is_image (slaves[n].target)) { - return _cairo_surface_wrapper_acquire_source_image (&slaves[n], + num_replicas = _cairo_array_num_elements (&surface->replicas); + replicas = _cairo_array_index (&surface->replicas, 0); + for (n = 0; n < num_replicas; n++) { + if (_cairo_surface_is_image (replicas[n].target)) { + return _cairo_surface_wrapper_acquire_source_image (&replicas[n], image_out, image_extra); } } - return _cairo_surface_wrapper_acquire_source_image (&surface->master, + return _cairo_surface_wrapper_acquire_source_image (&surface->primary, image_out, image_extra); } @@ -162,7 +173,7 @@ _cairo_tee_surface_release_source_image (void *abstract_surface, { cairo_tee_surface_t *surface = abstract_surface; - _cairo_surface_wrapper_release_source_image (&surface->master, + _cairo_surface_wrapper_release_source_image (&surface->primary, image, image_extra); } @@ -170,21 +181,21 @@ static cairo_surface_t * _cairo_tee_surface_snapshot (void *abstract_surface) { cairo_tee_surface_t *surface = abstract_surface; - cairo_surface_wrapper_t *slaves; - int num_slaves, n; + cairo_surface_wrapper_t *replicas; + int num_replicas, n; /* we prefer to use a recording surface for our snapshots */ - if (_cairo_surface_is_recording (surface->master.target)) - return _cairo_surface_wrapper_snapshot (&surface->master); + if (_cairo_surface_is_recording (surface->primary.target)) + return _cairo_surface_wrapper_snapshot (&surface->primary); - num_slaves = _cairo_array_num_elements (&surface->slaves); - slaves = _cairo_array_index (&surface->slaves, 0); - for (n = 0; n < num_slaves; n++) { - if (_cairo_surface_is_recording (slaves[n].target)) - return _cairo_surface_wrapper_snapshot (&slaves[n]); + num_replicas = _cairo_array_num_elements (&surface->replicas); + replicas = _cairo_array_index (&surface->replicas, 0); + for (n = 0; n < num_replicas; n++) { + if (_cairo_surface_is_recording (replicas[n].target)) + return _cairo_surface_wrapper_snapshot (&replicas[n]); } - return _cairo_surface_wrapper_snapshot (&surface->master); + return _cairo_surface_wrapper_snapshot (&surface->primary); } static cairo_bool_t @@ -193,7 +204,7 @@ _cairo_tee_surface_get_extents (void *abstract_surface, { cairo_tee_surface_t *surface = abstract_surface; - return _cairo_surface_wrapper_get_extents (&surface->master, rectangle); + return _cairo_surface_wrapper_get_extents (&surface->primary, rectangle); } static void @@ -202,7 +213,7 @@ _cairo_tee_surface_get_font_options (void *abstract_surface, { cairo_tee_surface_t *surface = abstract_surface; - _cairo_surface_wrapper_get_font_options (&surface->master, options); + _cairo_surface_wrapper_get_font_options (&surface->primary, options); } static cairo_int_status_t @@ -212,19 +223,19 @@ _cairo_tee_surface_paint (void *abstract_surface, const cairo_clip_t *clip) { cairo_tee_surface_t *surface = abstract_surface; - cairo_surface_wrapper_t *slaves; - int n, num_slaves; + cairo_surface_wrapper_t *replicas; + int n, num_replicas; cairo_int_status_t status; - num_slaves = _cairo_array_num_elements (&surface->slaves); - slaves = _cairo_array_index (&surface->slaves, 0); - for (n = 0; n < num_slaves; n++) { - status = _cairo_surface_wrapper_paint (&slaves[n], op, source, 0, clip); + num_replicas = _cairo_array_num_elements (&surface->replicas); + replicas = _cairo_array_index (&surface->replicas, 0); + for (n = 0; n < num_replicas; n++) { + status = _cairo_surface_wrapper_paint (&replicas[n], op, source, 0, clip); if (unlikely (status)) return status; } - return _cairo_surface_wrapper_paint (&surface->master, op, source, 0, clip); + return _cairo_surface_wrapper_paint (&surface->primary, op, source, 0, clip); } static cairo_int_status_t @@ -235,14 +246,14 @@ _cairo_tee_surface_mask (void *abstract_surface, const cairo_clip_t *clip) { cairo_tee_surface_t *surface = abstract_surface; - cairo_surface_wrapper_t *slaves; + cairo_surface_wrapper_t *replicas; cairo_int_status_t status; - int n, num_slaves; + int n, num_replicas; - num_slaves = _cairo_array_num_elements (&surface->slaves); - slaves = _cairo_array_index (&surface->slaves, 0); - for (n = 0; n < num_slaves; n++) { - status = _cairo_surface_wrapper_mask (&slaves[n], + num_replicas = _cairo_array_num_elements (&surface->replicas); + replicas = _cairo_array_index (&surface->replicas, 0); + for (n = 0; n < num_replicas; n++) { + status = _cairo_surface_wrapper_mask (&replicas[n], op, source, 0, mask, 0, clip); @@ -250,7 +261,7 @@ _cairo_tee_surface_mask (void *abstract_surface, return status; } - return _cairo_surface_wrapper_mask (&surface->master, + return _cairo_surface_wrapper_mask (&surface->primary, op, source, 0, mask, 0, clip); @@ -269,14 +280,14 @@ _cairo_tee_surface_stroke (void *abstract_surface, const cairo_clip_t *clip) { cairo_tee_surface_t *surface = abstract_surface; - cairo_surface_wrapper_t *slaves; + cairo_surface_wrapper_t *replicas; cairo_int_status_t status; - int n, num_slaves; + int n, num_replicas; - num_slaves = _cairo_array_num_elements (&surface->slaves); - slaves = _cairo_array_index (&surface->slaves, 0); - for (n = 0; n < num_slaves; n++) { - status = _cairo_surface_wrapper_stroke (&slaves[n], + num_replicas = _cairo_array_num_elements (&surface->replicas); + replicas = _cairo_array_index (&surface->replicas, 0); + for (n = 0; n < num_replicas; n++) { + status = _cairo_surface_wrapper_stroke (&replicas[n], op, source, 0, path, style, ctm, ctm_inverse, @@ -286,7 +297,7 @@ _cairo_tee_surface_stroke (void *abstract_surface, return status; } - return _cairo_surface_wrapper_stroke (&surface->master, + return _cairo_surface_wrapper_stroke (&surface->primary, op, source, 0, path, style, ctm, ctm_inverse, @@ -305,14 +316,14 @@ _cairo_tee_surface_fill (void *abstract_surface, const cairo_clip_t *clip) { cairo_tee_surface_t *surface = abstract_surface; - cairo_surface_wrapper_t *slaves; + cairo_surface_wrapper_t *replicas; cairo_int_status_t status; - int n, num_slaves; + int n, num_replicas; - num_slaves = _cairo_array_num_elements (&surface->slaves); - slaves = _cairo_array_index (&surface->slaves, 0); - for (n = 0; n < num_slaves; n++) { - status = _cairo_surface_wrapper_fill (&slaves[n], + num_replicas = _cairo_array_num_elements (&surface->replicas); + replicas = _cairo_array_index (&surface->replicas, 0); + for (n = 0; n < num_replicas; n++) { + status = _cairo_surface_wrapper_fill (&replicas[n], op, source, 0, path, fill_rule, tolerance, antialias, @@ -321,7 +332,7 @@ _cairo_tee_surface_fill (void *abstract_surface, return status; } - return _cairo_surface_wrapper_fill (&surface->master, + return _cairo_surface_wrapper_fill (&surface->primary, op, source, 0, path, fill_rule, tolerance, antialias, @@ -349,9 +360,9 @@ _cairo_tee_surface_show_text_glyphs (void *abstract_surface, const cairo_clip_t *clip) { cairo_tee_surface_t *surface = abstract_surface; - cairo_surface_wrapper_t *slaves; + cairo_surface_wrapper_t *replicas; cairo_int_status_t status; - int n, num_slaves; + int n, num_replicas; cairo_glyph_t *glyphs_copy; /* XXX: This copying is ugly. */ @@ -359,11 +370,11 @@ _cairo_tee_surface_show_text_glyphs (void *abstract_surface, if (unlikely (glyphs_copy == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); - num_slaves = _cairo_array_num_elements (&surface->slaves); - slaves = _cairo_array_index (&surface->slaves, 0); - for (n = 0; n < num_slaves; n++) { + num_replicas = _cairo_array_num_elements (&surface->replicas); + replicas = _cairo_array_index (&surface->replicas, 0); + for (n = 0; n < num_replicas; n++) { memcpy (glyphs_copy, glyphs, sizeof (cairo_glyph_t) * num_glyphs); - status = _cairo_surface_wrapper_show_text_glyphs (&slaves[n], op, + status = _cairo_surface_wrapper_show_text_glyphs (&replicas[n], op, source, 0, utf8, utf8_len, glyphs_copy, num_glyphs, @@ -376,7 +387,7 @@ _cairo_tee_surface_show_text_glyphs (void *abstract_surface, } memcpy (glyphs_copy, glyphs, sizeof (cairo_glyph_t) * num_glyphs); - status = _cairo_surface_wrapper_show_text_glyphs (&surface->master, op, + status = _cairo_surface_wrapper_show_text_glyphs (&surface->primary, op, source, 0, utf8, utf8_len, glyphs_copy, num_glyphs, @@ -423,38 +434,63 @@ static const cairo_surface_backend_t cairo_tee_surface_backend = { _cairo_tee_surface_show_text_glyphs }; +/** + * cairo_tee_surface_create: + * @primary: the primary #cairo_surface_t + * + * Creates a new "tee" surface. + * + * The @primary surface is used when querying surface options, like + * font options and extents. + * + * Operations performed on the tee surface will be replayed on any + * surface added to it. + * + * Returns: the newly created surface + * + * Since: 1.10 + **/ cairo_surface_t * -cairo_tee_surface_create (cairo_surface_t *master) +cairo_tee_surface_create (cairo_surface_t *primary) { cairo_tee_surface_t *surface; - if (unlikely (master->status)) - return _cairo_surface_create_in_error (master->status); + if (unlikely (primary->status)) + return _cairo_surface_create_in_error (primary->status); - surface = _cairo_malloc (sizeof (cairo_tee_surface_t)); + surface = _cairo_calloc (sizeof (cairo_tee_surface_t)); if (unlikely (surface == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); _cairo_surface_init (&surface->base, &cairo_tee_surface_backend, - master->device, - master->content, + primary->device, + primary->content, TRUE); /* is_vector */ - _cairo_surface_wrapper_init (&surface->master, master); + _cairo_surface_wrapper_init (&surface->primary, primary); - _cairo_array_init (&surface->slaves, sizeof (cairo_surface_wrapper_t)); + _cairo_array_init (&surface->replicas, sizeof (cairo_surface_wrapper_t)); return &surface->base; } -slim_hidden_def (cairo_tee_surface_create); +/** + * cairo_tee_surface_add: + * @abstract_surface: a #cairo_tee_surface_t + * @target: the surface to add + * + * Adds a new target surface to the list of replicas of a + * tee surface. + * + * Since: 1.10 + **/ void cairo_tee_surface_add (cairo_surface_t *abstract_surface, cairo_surface_t *target) { cairo_tee_surface_t *surface; - cairo_surface_wrapper_t slave; + cairo_surface_wrapper_t replica; cairo_status_t status; if (unlikely (abstract_surface->status)) @@ -478,22 +514,31 @@ cairo_tee_surface_add (cairo_surface_t *abstract_surface, surface = (cairo_tee_surface_t *) abstract_surface; - _cairo_surface_wrapper_init (&slave, target); - status = _cairo_array_append (&surface->slaves, &slave); + _cairo_surface_wrapper_init (&replica, target); + status = _cairo_array_append (&surface->replicas, &replica); if (unlikely (status)) { - _cairo_surface_wrapper_fini (&slave); + _cairo_surface_wrapper_fini (&replica); status = _cairo_surface_set_error (&surface->base, status); } } -slim_hidden_def (cairo_tee_surface_add); +/** + * cairo_tee_surface_remove: + * @abstract_surface: a #cairo_tee_surface_t + * @target: the surface to remove + * + * Removes the given surface from the list of replicas of a + * tee surface. + * + * Since: 1.10 + **/ void cairo_tee_surface_remove (cairo_surface_t *abstract_surface, cairo_surface_t *target) { cairo_tee_surface_t *surface; - cairo_surface_wrapper_t *slaves; - int n, num_slaves; + cairo_surface_wrapper_t *replicas; + int n, num_replicas; if (unlikely (abstract_surface->status)) return; @@ -510,31 +555,45 @@ cairo_tee_surface_remove (cairo_surface_t *abstract_surface, } surface = (cairo_tee_surface_t *) abstract_surface; - if (target == surface->master.target) { + if (target == surface->primary.target) { _cairo_surface_set_error (abstract_surface, _cairo_error (CAIRO_STATUS_INVALID_INDEX)); return; } - num_slaves = _cairo_array_num_elements (&surface->slaves); - slaves = _cairo_array_index (&surface->slaves, 0); - for (n = 0; n < num_slaves; n++) { - if (slaves[n].target == target) + num_replicas = _cairo_array_num_elements (&surface->replicas); + replicas = _cairo_array_index (&surface->replicas, 0); + for (n = 0; n < num_replicas; n++) { + if (replicas[n].target == target) break; } - if (n == num_slaves) { + if (n == num_replicas) { _cairo_surface_set_error (abstract_surface, _cairo_error (CAIRO_STATUS_INVALID_INDEX)); return; } - _cairo_surface_wrapper_fini (&slaves[n]); - for (n++; n < num_slaves; n++) - slaves[n-1] = slaves[n]; - surface->slaves.num_elements--; /* XXX: cairo_array_remove()? */ + _cairo_surface_wrapper_fini (&replicas[n]); + for (n++; n < num_replicas; n++) + replicas[n-1] = replicas[n]; + surface->replicas.num_elements--; /* XXX: cairo_array_remove()? */ } +/** + * cairo_tee_surface_index: + * @abstract_surface: a #cairo_tee_surface_t + * @index: the index of the replica to retrieve + * + * Retrieves the replica surface at the given index. + * + * The primary surface used to create the #cairo_tee_surface_t is + * always set at the zero index. + * + * Returns: the surface at the given index + * + * Since: 1.10 + **/ cairo_surface_t * cairo_tee_surface_index (cairo_surface_t *abstract_surface, unsigned int index) @@ -551,16 +610,16 @@ cairo_tee_surface_index (cairo_surface_t *abstract_surface, surface = (cairo_tee_surface_t *) abstract_surface; if (index == 0) { - return surface->master.target; + return surface->primary.target; } else { - cairo_surface_wrapper_t *slave; + cairo_surface_wrapper_t *replica; index--; - if (index >= _cairo_array_num_elements (&surface->slaves)) + if (index >= _cairo_array_num_elements (&surface->replicas)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_INDEX)); - slave = _cairo_array_index (&surface->slaves, index); - return slave->target; + replica = _cairo_array_index (&surface->replicas, index); + return replica->target; } } diff --git a/src/cairo-tee.h b/src/cairo-tee.h index 9125a3a4a..58264ffff 100644 --- a/src/cairo-tee.h +++ b/src/cairo-tee.h @@ -43,18 +43,18 @@ CAIRO_BEGIN_DECLS cairo_public cairo_surface_t * -cairo_tee_surface_create (cairo_surface_t *master); +cairo_tee_surface_create (cairo_surface_t *primary); cairo_public void -cairo_tee_surface_add (cairo_surface_t *surface, +cairo_tee_surface_add (cairo_surface_t *abstract_surface, cairo_surface_t *target); cairo_public void -cairo_tee_surface_remove (cairo_surface_t *surface, +cairo_tee_surface_remove (cairo_surface_t *abstract_surface, cairo_surface_t *target); cairo_public cairo_surface_t * -cairo_tee_surface_index (cairo_surface_t *surface, +cairo_tee_surface_index (cairo_surface_t *abstract_surface, unsigned int index); CAIRO_END_DECLS diff --git a/src/cairo-tor-scan-converter.c b/src/cairo-tor-scan-converter.c index e8142d5bc..f29359ce4 100644 --- a/src/cairo-tor-scan-converter.c +++ b/src/cairo-tor-scan-converter.c @@ -1872,7 +1872,7 @@ _cairo_tor_scan_converter_create (int xmin, cairo_tor_scan_converter_t *self; cairo_status_t status; - self = _cairo_malloc (sizeof(struct _cairo_tor_scan_converter)); + self = _cairo_calloc (sizeof(struct _cairo_tor_scan_converter)); if (unlikely (self == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto bail_nomem; diff --git a/src/cairo-tor22-scan-converter.c b/src/cairo-tor22-scan-converter.c index 1e71a35b4..bbdc02f3a 100644 --- a/src/cairo-tor22-scan-converter.c +++ b/src/cairo-tor22-scan-converter.c @@ -1675,7 +1675,7 @@ _cairo_tor22_scan_converter_create (int xmin, cairo_tor22_scan_converter_t *self; cairo_status_t status; - self = _cairo_malloc (sizeof(struct _cairo_tor22_scan_converter)); + self = _cairo_calloc (sizeof(struct _cairo_tor22_scan_converter)); if (unlikely (self == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto bail_nomem; diff --git a/src/cairo-toy-font-face.c b/src/cairo-toy-font-face.c index c27eebefc..211723c41 100644 --- a/src/cairo-toy-font-face.c +++ b/src/cairo-toy-font-face.c @@ -312,7 +312,7 @@ cairo_toy_font_face_create (const char *family, } /* Otherwise create it and insert into hash table. */ - font_face = _cairo_malloc (sizeof (cairo_toy_font_face_t)); + font_face = _cairo_calloc (sizeof (cairo_toy_font_face_t)); if (unlikely (font_face == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto UNWIND_HASH_TABLE_LOCK; @@ -340,7 +340,6 @@ cairo_toy_font_face_create (const char *family, UNWIND: return (cairo_font_face_t*) &_cairo_font_face_nil; } -slim_hidden_def (cairo_toy_font_face_create); static cairo_bool_t _cairo_toy_font_face_destroy (void *abstract_face) @@ -469,7 +468,6 @@ cairo_toy_font_face_get_slant (cairo_font_face_t *font_face) } return toy_font_face->slant; } -slim_hidden_def (cairo_toy_font_face_get_slant); /** * cairo_toy_font_face_get_weight: @@ -496,7 +494,6 @@ cairo_toy_font_face_get_weight (cairo_font_face_t *font_face) } 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, diff --git a/src/cairo-truetype-subset.c b/src/cairo-truetype-subset.c index 78c7dd5ec..a8551117c 100644 --- a/src/cairo-truetype-subset.c +++ b/src/cairo-truetype-subset.c @@ -194,7 +194,7 @@ _cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset, if (unlikely (status)) return status; - font = _cairo_malloc (sizeof (cairo_truetype_font_t)); + font = _cairo_calloc (sizeof (cairo_truetype_font_t)); if (unlikely (font == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -212,14 +212,14 @@ _cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset, /* Add 2: +1 case font does not contain .notdef, and +1 because an extra * entry is required to contain the end location of the last glyph. */ - font->glyphs = calloc (font->base.num_glyphs_in_face + 2, sizeof (subset_glyph_t)); + font->glyphs = _cairo_calloc_ab (font->base.num_glyphs_in_face + 2, sizeof (subset_glyph_t)); if (unlikely (font->glyphs == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto fail1; } /* Add 1 in case font does not contain .notdef */ - font->parent_to_subset = calloc (font->base.num_glyphs_in_face + 1, sizeof (int)); + font->parent_to_subset = _cairo_calloc_ab (font->base.num_glyphs_in_face + 1, sizeof (int)); if (unlikely (font->parent_to_subset == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto fail2; @@ -259,7 +259,7 @@ _cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset, } /* Add 1 in case font does not contain .notdef */ - font->widths = calloc (font->base.num_glyphs_in_face + 1, sizeof (int)); + font->widths = _cairo_calloc_ab (font->base.num_glyphs_in_face + 1, sizeof (int)); if (unlikely (font->widths == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto fail4; @@ -1181,8 +1181,8 @@ cairo_truetype_subset_init_internal (cairo_truetype_subset_t *truetype_subse /* 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); + truetype_subset->widths = _cairo_calloc_ab (font->scaled_font_subset->num_glyphs, + sizeof (double)); if (unlikely (truetype_subset->widths == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto fail3; @@ -1317,8 +1317,10 @@ _cairo_truetype_reverse_cmap (cairo_scaled_font_t *scaled_font, /* 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; + if (size < (8 + 4*num_segments)*sizeof(uint16_t)) { + status = CAIRO_INT_STATUS_UNSUPPORTED; + goto fail; + } end_code = map->endCount; start_code = &(end_code[num_segments + 1]); @@ -1355,8 +1357,10 @@ _cairo_truetype_reverse_cmap (cairo_scaled_font_t *scaled_font, int j; if (range_size > 0) { - if ((char*)glyph_ids + 2*range_size > (char*)map + size) - return CAIRO_INT_STATUS_UNSUPPORTED; + if ((char*)glyph_ids + 2*range_size > (char*)map + size) { + status = CAIRO_INT_STATUS_UNSUPPORTED; + goto fail; + } for (j = 0; j < range_size; j++) { if (glyph_ids[j] == g_id_be) { diff --git a/src/cairo-type1-fallback.c b/src/cairo-type1-fallback.c index 3a44c4666..d0bbc62f0 100644 --- a/src/cairo-type1-fallback.c +++ b/src/cairo-type1-fallback.c @@ -88,11 +88,11 @@ cairo_type1_font_create (cairo_scaled_font_subset_t *scaled_font_subset, cairo_font_options_t font_options; cairo_status_t status; - font = calloc (1, sizeof (cairo_type1_font_t)); + font = _cairo_calloc (sizeof (cairo_type1_font_t)); if (unlikely (font == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); - font->widths = calloc (scaled_font_subset->num_glyphs, sizeof (int)); + font->widths = _cairo_calloc_ab (scaled_font_subset->num_glyphs, sizeof (int)); if (unlikely (font->widths == NULL)) { free (font); return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -107,6 +107,7 @@ cairo_type1_font_create (cairo_scaled_font_subset_t *scaled_font_subset, cairo_matrix_init_identity (&ctm); _cairo_font_options_init_default (&font_options); + cairo_scaled_font_get_font_options (scaled_font_subset->scaled_font, &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); @@ -746,7 +747,8 @@ _cairo_type1_fallback_init_internal (cairo_type1_subset_t *type1_subset, goto fail1; } - type1_subset->widths = calloc (sizeof (double), font->scaled_font_subset->num_glyphs); + type1_subset->widths = _cairo_calloc_ab (font->scaled_font_subset->num_glyphs, + sizeof (double)); if (unlikely (type1_subset->widths == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto fail2; @@ -840,7 +842,7 @@ _cairo_type2_charstrings_init (cairo_type2_charstrings_t *type2_subset, _cairo_array_init (&type2_subset->charstrings, sizeof (cairo_array_t)); - type2_subset->widths = calloc (sizeof (int), font->scaled_font_subset->num_glyphs); + type2_subset->widths = _cairo_calloc_ab (font->scaled_font_subset->num_glyphs, sizeof (int)); if (unlikely (type2_subset->widths == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto fail1; diff --git a/src/cairo-type1-subset.c b/src/cairo-type1-subset.c index 0166f7a78..5c3766e3a 100644 --- a/src/cairo-type1-subset.c +++ b/src/cairo-type1-subset.c @@ -167,7 +167,8 @@ _cairo_type1_font_subset_init (cairo_type1_font_subset_t *font, _cairo_array_init (&font->glyphs_array, sizeof (glyph_data_t)); _cairo_array_init (&font->glyph_names_array, sizeof (char *)); - font->scaled_subset_index_to_glyphs = calloc (scaled_font_subset->num_glyphs, sizeof font->scaled_subset_index_to_glyphs[0]); + font->scaled_subset_index_to_glyphs = _cairo_calloc_ab (scaled_font_subset->num_glyphs, + sizeof font->scaled_subset_index_to_glyphs[0]); if (unlikely (font->scaled_subset_index_to_glyphs == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -404,7 +405,7 @@ cairo_type1_font_subset_get_bbox (cairo_type1_font_subset_t *font) if (yy == 0.0) return CAIRO_INT_STATUS_UNSUPPORTED; - /* Freetype uses 1/yy to get units per EM */ + /* FreeType uses 1/yy to get units per EM */ font->base.units_per_em = 1.0/yy; /* If the FontMatrix is not a uniform scale the metrics we extract @@ -1085,6 +1086,9 @@ cairo_type1_font_for_each_subr (cairo_type1_font_subset_t *font, /* Skip binary data and | or NP token. */ p = skip_token (subr_string + subr_length, cleartext_end); + if (p == NULL) + return CAIRO_INT_STATUS_UNSUPPORTED; + while (p < cleartext_end && _cairo_isspace(*p)) p++; @@ -1248,6 +1252,9 @@ cairo_type1_font_subset_for_each_glyph (cairo_type1_font_subset_t *font, /* Skip binary data and |- or ND token. */ p = skip_token (charstring + charstring_length, dict_end); + if (p == NULL) + return CAIRO_INT_STATUS_UNSUPPORTED; + while (p < dict_end && _cairo_isspace(*p)) p++; @@ -1349,7 +1356,7 @@ cairo_type1_font_subset_write_private_dict (cairo_type1_font_subset_t *font, if (font->num_subrs <= 0) return CAIRO_INT_STATUS_UNSUPPORTED; - font->subrs = calloc (font->num_subrs, sizeof (font->subrs[0])); + font->subrs = _cairo_calloc_ab (font->num_subrs, sizeof (font->subrs[0])); if (unlikely (font->subrs == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -1404,7 +1411,8 @@ skip_subrs: font->glyphs = _cairo_array_index (&font->glyphs_array, 0); font->glyph_names = _cairo_array_index (&font->glyph_names_array, 0); font->base.num_glyphs = _cairo_array_num_elements (&font->glyphs_array); - font->type1_subset_index_to_glyphs = calloc (font->base.num_glyphs, sizeof font->type1_subset_index_to_glyphs[0]); + font->type1_subset_index_to_glyphs = _cairo_calloc_ab (font->base.num_glyphs, + sizeof font->type1_subset_index_to_glyphs[0]); if (unlikely (font->type1_subset_index_to_glyphs == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -1776,7 +1784,7 @@ _cairo_type1_subset_init (cairo_type1_subset_t *type1_subset, if (unlikely (type1_subset->base_font == NULL)) goto fail1; - type1_subset->widths = calloc (sizeof (double), scaled_font_subset->num_glyphs); + type1_subset->widths = _cairo_calloc_ab (scaled_font_subset->num_glyphs, sizeof (double)); if (unlikely (type1_subset->widths == NULL)) goto fail2; diff --git a/src/cairo-type3-glyph-surface.c b/src/cairo-type3-glyph-surface.c index 53c029493..bb77756a1 100644 --- a/src/cairo-type3-glyph-surface.c +++ b/src/cairo-type3-glyph-surface.c @@ -82,7 +82,7 @@ _cairo_type3_glyph_surface_create (cairo_scaled_font_t *scaled_font, if (unlikely (stream != NULL && stream->status)) return _cairo_surface_create_in_error (stream->status); - surface = _cairo_malloc (sizeof (cairo_type3_glyph_surface_t)); + surface = _cairo_calloc (sizeof (cairo_type3_glyph_surface_t)); if (unlikely (surface == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); diff --git a/src/cairo-user-font.c b/src/cairo-user-font.c index ee11d864c..56525d5c1 100644 --- a/src/cairo-user-font.c +++ b/src/cairo-user-font.c @@ -573,7 +573,7 @@ _cairo_user_font_face_scaled_font_create (void *abstract_ font_face->immutable = TRUE; - user_scaled_font = _cairo_malloc (sizeof (cairo_user_scaled_font_t)); + user_scaled_font = _cairo_calloc (sizeof (cairo_user_scaled_font_t)); if (unlikely (user_scaled_font == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -720,7 +720,7 @@ cairo_user_font_face_create (void) { cairo_user_font_face_t *font_face; - font_face = _cairo_malloc (sizeof (cairo_user_font_face_t)); + font_face = _cairo_calloc (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; @@ -734,7 +734,6 @@ cairo_user_font_face_create (void) return &font_face->base; } -slim_hidden_def(cairo_user_font_face_create); /* User-font method setters */ @@ -775,7 +774,6 @@ cairo_user_font_face_set_init_func (cairo_font_face_t *font_fac } 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_color_glyph_func: @@ -826,7 +824,6 @@ cairo_user_font_face_set_render_color_glyph_func (cairo_font_face_t user_font_face->scaled_font_methods.render_color_glyph = render_glyph_func; user_font_face->has_color = render_glyph_func ? TRUE : FALSE; } -slim_hidden_def(cairo_user_font_face_set_render_color_glyph_func); /** * cairo_user_font_face_set_render_glyph_func: @@ -876,7 +873,6 @@ cairo_user_font_face_set_render_glyph_func (cairo_font_face_t } 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: @@ -950,7 +946,6 @@ cairo_user_font_face_set_unicode_to_glyph_func (cairo_font_face_t } 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 */ diff --git a/src/cairo-version.c b/src/cairo-version.c index 943e1cde0..0b0d2123c 100644 --- a/src/cairo-version.c +++ b/src/cairo-version.c @@ -252,4 +252,3 @@ cairo_version_string (void) { return CAIRO_VERSION_STRING; } -slim_hidden_def (cairo_version_string); diff --git a/src/cairo-version.h b/src/cairo-version.h index 3ac065f68..ef38594ca 100644 --- a/src/cairo-version.h +++ b/src/cairo-version.h @@ -2,7 +2,7 @@ #define CAIRO_VERSION_H #define CAIRO_VERSION_MAJOR 1 -#define CAIRO_VERSION_MINOR 17 -#define CAIRO_VERSION_MICRO 9 +#define CAIRO_VERSION_MINOR 18 +#define CAIRO_VERSION_MICRO 5 #endif diff --git a/src/cairo-xcb-connection-shm.c b/src/cairo-xcb-connection-shm.c index 140a73cd0..fda75cfa7 100644 --- a/src/cairo-xcb-connection-shm.c +++ b/src/cairo-xcb-connection-shm.c @@ -93,13 +93,13 @@ _cairo_xcb_connection_shm_get_image (cairo_xcb_connection_t *connection, XCB_IMAGE_FORMAT_Z_PIXMAP, shmseg, offset), NULL); - free (reply); if (!reply) { /* an error here should be impossible */ return _cairo_error (CAIRO_STATUS_READ_ERROR); } + free (reply); return CAIRO_STATUS_SUCCESS; } diff --git a/src/cairo-xcb-connection.c b/src/cairo-xcb-connection.c index 2c58cca70..016ca1c0c 100644 --- a/src/cairo-xcb-connection.c +++ b/src/cairo-xcb-connection.c @@ -111,7 +111,7 @@ _cairo_xcb_connection_find_visual_formats (cairo_xcb_connection_t *connection, cairo_xcb_xrender_format_t *f; cairo_status_t status; - f = _cairo_malloc (sizeof (cairo_xcb_xrender_format_t)); + f = _cairo_calloc (sizeof (cairo_xcb_xrender_format_t)); if (unlikely (f == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -177,7 +177,7 @@ _cairo_xcb_connection_parse_xrender_formats (cairo_xcb_connection_t *connection, if (! _cairo_hash_table_lookup (connection->xrender_formats, &key)) { cairo_xcb_xrender_format_t *f; - f = _cairo_malloc (sizeof (cairo_xcb_xrender_format_t)); + f = _cairo_calloc (sizeof (cairo_xcb_xrender_format_t)); if (unlikely (f == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -239,7 +239,7 @@ _cairo_xcb_connection_parse_xrender_formats (cairo_xcb_connection_t *connection, /* * We require support for depth 1, 8, 24 and 32 pixmaps */ -#define DEPTH_MASK(d) (1 << ((d) - 1)) +#define DEPTH_MASK(d) ((uint32_t)(1) << ((d) - 1)) #define REQUIRED_DEPTHS (DEPTH_MASK(1) | \ DEPTH_MASK(8) | \ DEPTH_MASK(24) | \ @@ -629,7 +629,7 @@ _cairo_xcb_connection_get (xcb_connection_t *xcb_connection) } } - connection = _cairo_malloc (sizeof (cairo_xcb_connection_t)); + connection = _cairo_calloc (sizeof (cairo_xcb_connection_t)); if (unlikely (connection == NULL)) goto unlock; @@ -686,7 +686,8 @@ _cairo_xcb_connection_get (xcb_connection_t *xcb_connection) connection->root = xcb_get_setup (xcb_connection); connection->render = NULL; - connection->subpixel_orders = calloc (connection->root->roots_len, sizeof(*connection->subpixel_orders)); + connection->subpixel_orders = _cairo_calloc_ab (connection->root->roots_len, + sizeof(*connection->subpixel_orders)); if (unlikely (connection->subpixel_orders == NULL)) { CAIRO_MUTEX_UNLOCK (connection->device.mutex); _cairo_xcb_connection_destroy (connection); @@ -896,9 +897,6 @@ cairo_xcb_device_debug_cap_xrender_version (cairo_device_t *device, connection->flags &= ~CAIRO_XCB_RENDER_HAS_GRADIENTS; } } -#if CAIRO_HAS_XLIB_XCB_FUNCTIONS -slim_hidden_def (cairo_xcb_device_debug_cap_xrender_version); -#endif /** * cairo_xcb_device_debug_set_precision: @@ -926,9 +924,6 @@ cairo_xcb_device_debug_set_precision (cairo_device_t *device, ((cairo_xcb_connection_t *) device)->force_precision = precision; } -#if CAIRO_HAS_XLIB_XCB_FUNCTIONS -slim_hidden_def (cairo_xcb_device_debug_set_precision); -#endif /** * cairo_xcb_device_debug_get_precision: @@ -955,6 +950,3 @@ cairo_xcb_device_debug_get_precision (cairo_device_t *device) return ((cairo_xcb_connection_t *) device)->force_precision; } -#if CAIRO_HAS_XLIB_XCB_FUNCTIONS -slim_hidden_def (cairo_xcb_device_debug_get_precision); -#endif diff --git a/src/cairo-xcb-private.h b/src/cairo-xcb-private.h index 009f0820a..95805f8a9 100644 --- a/src/cairo-xcb-private.h +++ b/src/cairo-xcb-private.h @@ -765,16 +765,6 @@ _cairo_xcb_connection_render_create_conical_gradient (cairo_xcb_connection_t uint32_t num_stops, xcb_render_fixed_t *stops, xcb_render_color_t *colors); -#if CAIRO_HAS_XLIB_XCB_FUNCTIONS -slim_hidden_proto (cairo_xcb_surface_create); -slim_hidden_proto (cairo_xcb_surface_create_for_bitmap); -slim_hidden_proto (cairo_xcb_surface_create_with_xrender_format); -slim_hidden_proto (cairo_xcb_surface_set_size); -slim_hidden_proto (cairo_xcb_surface_set_drawable); -slim_hidden_proto (cairo_xcb_device_debug_get_precision); -slim_hidden_proto_no_warn (cairo_xcb_device_debug_set_precision); -slim_hidden_proto_no_warn (cairo_xcb_device_debug_cap_xrender_version); -#endif cairo_private void _cairo_xcb_resources_get (cairo_xcb_screen_t *screen, diff --git a/src/cairo-xcb-screen.c b/src/cairo-xcb-screen.c index f443eec29..0ed880d66 100644 --- a/src/cairo-xcb-screen.c +++ b/src/cairo-xcb-screen.c @@ -249,7 +249,7 @@ _cairo_xcb_screen_get (xcb_connection_t *xcb_connection, } } - screen = _cairo_malloc (sizeof (cairo_xcb_screen_t)); + screen = _cairo_calloc (sizeof (cairo_xcb_screen_t)); if (unlikely (screen == NULL)) goto unlock; diff --git a/src/cairo-xcb-shm.c b/src/cairo-xcb-shm.c index 763778ab2..4037eaa72 100644 --- a/src/cairo-xcb-shm.c +++ b/src/cairo-xcb-shm.c @@ -36,6 +36,15 @@ #include "cairoint.h" +/** + * CAIRO_HAS_XCB_SHM_FUNCTIONS: + * + * Defined if Cairo has SHM functions for XCB. + * This macro can be used to conditionally compile backend-specific code. + * + * Since: 1.10 + **/ + #if CAIRO_HAS_XCB_SHM_FUNCTIONS #include "cairo-xcb-private.h" @@ -209,7 +218,7 @@ _cairo_xcb_connection_allocate_shm_info (cairo_xcb_connection_t *connection, return _cairo_error (CAIRO_STATUS_NO_MEMORY); } - pool = _cairo_malloc (sizeof (cairo_xcb_shm_mem_pool_t)); + pool = _cairo_calloc (sizeof (cairo_xcb_shm_mem_pool_t)); if (unlikely (pool == NULL)) { CAIRO_MUTEX_UNLOCK (connection->shm_mutex); return _cairo_error (CAIRO_STATUS_NO_MEMORY); diff --git a/src/cairo-xcb-surface-core.c b/src/cairo-xcb-surface-core.c index f9f12f04b..660e6d05a 100644 --- a/src/cairo-xcb-surface-core.c +++ b/src/cairo-xcb-surface-core.c @@ -85,7 +85,7 @@ _cairo_xcb_pixmap_create (cairo_xcb_surface_t *target, { cairo_xcb_pixmap_t *surface; - surface = _cairo_malloc (sizeof (cairo_xcb_pixmap_t)); + surface = _cairo_calloc (sizeof (cairo_xcb_pixmap_t)); if (unlikely (surface == NULL)) return (cairo_xcb_pixmap_t *) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); @@ -119,7 +119,7 @@ _cairo_xcb_pixmap_copy (cairo_xcb_surface_t *target) { cairo_xcb_pixmap_t *surface; - surface = _cairo_malloc (sizeof (cairo_xcb_pixmap_t)); + surface = _cairo_calloc (sizeof (cairo_xcb_pixmap_t)); if (unlikely (surface == NULL)) return (cairo_xcb_pixmap_t *) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); diff --git a/src/cairo-xcb-surface-render.c b/src/cairo-xcb-surface-render.c index ab3d6881f..2777c3cda 100644 --- a/src/cairo-xcb-surface-render.c +++ b/src/cairo-xcb-surface-render.c @@ -114,7 +114,7 @@ _cairo_xcb_picture_create (cairo_xcb_screen_t *screen, { cairo_xcb_picture_t *surface; - surface = _cairo_malloc (sizeof (cairo_xcb_picture_t)); + surface = _cairo_calloc (sizeof (cairo_xcb_picture_t)); if (unlikely (surface == NULL)) return (cairo_xcb_picture_t *) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); @@ -4136,7 +4136,7 @@ _cairo_xcb_font_create (cairo_xcb_connection_t *connection, cairo_xcb_font_t *priv; int i; - priv = _cairo_malloc (sizeof (cairo_xcb_font_t)); + priv = _cairo_calloc (sizeof (cairo_xcb_font_t)); if (unlikely (priv == NULL)) return NULL; @@ -4329,7 +4329,7 @@ _cairo_xcb_glyph_fini (cairo_scaled_glyph_private_t *glyph_private, } if (to_free == NULL) { - to_free = _cairo_malloc (sizeof (cairo_xcb_font_glyphset_free_glyphs_t)); + to_free = _cairo_calloc (sizeof (cairo_xcb_font_glyphset_free_glyphs_t)); if (unlikely (to_free == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return; /* XXX cannot propagate failure */ @@ -4356,7 +4356,7 @@ _cairo_xcb_glyph_attach (cairo_xcb_connection_t *c, { cairo_xcb_glyph_private_t *priv; - priv = _cairo_malloc (sizeof (*priv)); + priv = _cairo_calloc (sizeof (*priv)); if (unlikely (priv == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c index de020d8a0..302d3fbe0 100644 --- a/src/cairo-xcb-surface.c +++ b/src/cairo-xcb-surface.c @@ -50,12 +50,6 @@ #include "cairo-surface-backend-private.h" #include "cairo-compositor-private.h" -#if CAIRO_HAS_XLIB_XCB_FUNCTIONS -slim_hidden_proto (cairo_xcb_surface_create); -slim_hidden_proto (cairo_xcb_surface_create_for_bitmap); -slim_hidden_proto (cairo_xcb_surface_create_with_xrender_format); -#endif - /** * SECTION:cairo-xcb * @Title: XCB Surfaces @@ -1075,7 +1069,7 @@ _cairo_xcb_surface_create_internal (cairo_xcb_screen_t *screen, { cairo_xcb_surface_t *surface; - surface = _cairo_malloc (sizeof (cairo_xcb_surface_t)); + surface = _cairo_calloc (sizeof (cairo_xcb_surface_t)); if (unlikely (surface == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); @@ -1236,9 +1230,6 @@ cairo_xcb_surface_create (xcb_connection_t *connection, xrender_format, width, height); } -#if CAIRO_HAS_XLIB_XCB_FUNCTIONS -slim_hidden_def (cairo_xcb_surface_create); -#endif /** * cairo_xcb_surface_create_for_bitmap: @@ -1287,9 +1278,6 @@ cairo_xcb_surface_create_for_bitmap (xcb_connection_t *connection, cairo_xcb_screen->connection->standard_formats[CAIRO_FORMAT_A1], width, height); } -#if CAIRO_HAS_XLIB_XCB_FUNCTIONS -slim_hidden_def (cairo_xcb_surface_create_for_bitmap); -#endif /** * cairo_xcb_surface_create_with_xrender_format: @@ -1379,9 +1367,6 @@ cairo_xcb_surface_create_with_xrender_format (xcb_connection_t *connection, format->id, width, height); } -#if CAIRO_HAS_XLIB_XCB_FUNCTIONS -slim_hidden_def (cairo_xcb_surface_create_with_xrender_format); -#endif /* This does the necessary fixup when a surface's drawable or size changed. */ static void @@ -1451,9 +1436,6 @@ cairo_xcb_surface_set_size (cairo_surface_t *abstract_surface, surface->width = width; surface->height = height; } -#if CAIRO_HAS_XLIB_XCB_FUNCTIONS -slim_hidden_def (cairo_xcb_surface_set_size); -#endif /** * cairo_xcb_surface_set_drawable: @@ -1526,6 +1508,3 @@ cairo_xcb_surface_set_drawable (cairo_surface_t *abstract_surface, surface->width = width; surface->height = height; } -#if CAIRO_HAS_XLIB_XCB_FUNCTIONS -slim_hidden_def (cairo_xcb_surface_set_drawable); -#endif diff --git a/src/cairo-xlib-display.c b/src/cairo-xlib-display.c index 108897e92..8b2ffe8e1 100644 --- a/src/cairo-xlib-display.c +++ b/src/cairo-xlib-display.c @@ -207,7 +207,7 @@ _cairo_xlib_device_create (Display *dpy) } } - display = _cairo_malloc (sizeof (cairo_xlib_display_t)); + display = _cairo_calloc (sizeof (cairo_xlib_display_t)); if (unlikely (display == NULL)) { device = _cairo_device_create_in_error (CAIRO_STATUS_NO_MEMORY); goto UNLOCK; diff --git a/src/cairo-xlib-private.h b/src/cairo-xlib-private.h index 8e338aea6..e8900030b 100644 --- a/src/cairo-xlib-private.h +++ b/src/cairo-xlib-private.h @@ -83,7 +83,7 @@ struct _cairo_xlib_display { int render_major; int render_minor; - XRenderPictFormat *cached_xrender_formats[CAIRO_FORMAT_RGB30 + 1]; + XRenderPictFormat *cached_xrender_formats[CAIRO_FORMAT_RGBA128F + 1]; int force_precision; diff --git a/src/cairo-xlib-render-compositor.c b/src/cairo-xlib-render-compositor.c index c872f5680..a870c00e1 100644 --- a/src/cairo-xlib-render-compositor.c +++ b/src/cairo-xlib-render-compositor.c @@ -989,7 +989,7 @@ _cairo_xlib_font_create (cairo_xlib_display_t *display, cairo_xlib_font_t *priv; int i; - priv = _cairo_malloc (sizeof (cairo_xlib_font_t)); + priv = _cairo_calloc (sizeof (cairo_xlib_font_t)); if (unlikely (priv == NULL)) return NULL; @@ -1088,7 +1088,7 @@ _cairo_xlib_glyph_attach (cairo_xlib_display_t *display, { cairo_xlib_glyph_private_t *priv; - priv = _cairo_malloc (sizeof (*priv)); + priv = _cairo_calloc (sizeof (*priv)); if (unlikely (priv == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); diff --git a/src/cairo-xlib-screen.c b/src/cairo-xlib-screen.c index ff3bdfcf9..cd8e2a75d 100644 --- a/src/cairo-xlib-screen.c +++ b/src/cairo-xlib-screen.c @@ -330,7 +330,7 @@ _cairo_xlib_screen_get (Display *dpy, goto CLEANUP_DISPLAY; } - info = _cairo_malloc (sizeof (cairo_xlib_screen_t)); + info = _cairo_calloc (sizeof (cairo_xlib_screen_t)); if (unlikely (info == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto CLEANUP_DISPLAY; diff --git a/src/cairo-xlib-source.c b/src/cairo-xlib-source.c index 4c3b99d9e..69416d7d8 100644 --- a/src/cairo-xlib-source.c +++ b/src/cairo-xlib-source.c @@ -109,7 +109,7 @@ source (cairo_xlib_surface_t *dst, Picture picture, Pixmap pixmap) if (picture == None) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - source = _cairo_malloc (sizeof (*source)); + source = _cairo_calloc (sizeof (*source)); if (unlikely (source == NULL)) { XRenderFreePicture (dst->display->display, picture); if (pixmap) @@ -966,7 +966,7 @@ surface_source (cairo_xlib_surface_t *dst, _cairo_xlib_shm_surface_get_pixmap (src)) { cairo_xlib_proxy_t *proxy; - proxy = _cairo_malloc (sizeof(*proxy)); + proxy = _cairo_calloc (sizeof(*proxy)); if (unlikely (proxy == NULL)) return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY); diff --git a/src/cairo-xlib-surface-shm.c b/src/cairo-xlib-surface-shm.c index 10f947d9c..85a036938 100644 --- a/src/cairo-xlib-surface-shm.c +++ b/src/cairo-xlib-surface-shm.c @@ -576,7 +576,7 @@ _cairo_xlib_shm_pool_create(cairo_xlib_display_t *display, size_t bytes, maxbits = 16, minbits = MIN_BITS; Status success; - pool = _cairo_malloc (sizeof (cairo_xlib_shm_t)); + pool = _cairo_calloc (sizeof (cairo_xlib_shm_t)); if (pool == NULL) return NULL; @@ -653,7 +653,7 @@ _cairo_xlib_shm_info_create (cairo_xlib_display_t *display, assert (mem != NULL); - info = _cairo_malloc (sizeof (*info)); + info = _cairo_calloc (sizeof (*info)); if (info == NULL) { _cairo_mempool_free (&pool->mem, mem); return NULL; @@ -820,7 +820,7 @@ _cairo_xlib_shm_surface_create (cairo_xlib_surface_t *other, if (size < MIN_SIZE) return NULL; - shm = _cairo_malloc (sizeof (*shm)); + shm = _cairo_calloc (sizeof (*shm)); if (unlikely (shm == NULL)) return (cairo_xlib_shm_surface_t *)_cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY); @@ -1393,7 +1393,7 @@ _cairo_xlib_display_init_shm (cairo_xlib_display_t *display) if (!can_use_shm (display->display, &has_pixmap)) return; - shm = _cairo_malloc (sizeof (*shm)); + shm = _cairo_calloc (sizeof (*shm)); if (unlikely (shm == NULL)) return; diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c index b37b21bad..fac291199 100644 --- a/src/cairo-xlib-surface.c +++ b/src/cairo-xlib-surface.c @@ -47,6 +47,15 @@ #include "cairoint.h" +/** + * CAIRO_HAS_XLIB_XCB_FUNCTIONS: + * + * Defined if Cairo has support for XCB integration with Xlib. + * This macro can be used to conditionally compile backend-specific code. + * + * Since: 1.10 + **/ + #if !CAIRO_HAS_XLIB_XCB_FUNCTIONS #include "cairo-xlib-private.h" @@ -1764,7 +1773,7 @@ found: ; } - surface = _cairo_malloc (sizeof (cairo_xlib_surface_t)); + surface = _cairo_calloc (sizeof (cairo_xlib_surface_t)); if (unlikely (surface == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); diff --git a/src/cairo-xlib-visual.c b/src/cairo-xlib-visual.c index 979cd5b36..055e441e4 100644 --- a/src/cairo-xlib-visual.c +++ b/src/cairo-xlib-visual.c @@ -82,7 +82,7 @@ _cairo_xlib_visual_info_create (Display *dpy, for (i = 0; i < RAMP_SIZE; i++) ramp_index_to_short[i] = (0xffff * i + ((RAMP_SIZE-1)>>1)) / (RAMP_SIZE-1); - info = _cairo_malloc (sizeof (cairo_xlib_visual_info_t)); + info = _cairo_calloc (sizeof (cairo_xlib_visual_info_t)); if (unlikely (info == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); diff --git a/src/cairo.c b/src/cairo.c index 3d4fea601..78c60df5c 100644 --- a/src/cairo.c +++ b/src/cairo.c @@ -458,7 +458,6 @@ cairo_create (cairo_surface_t *target) return target->backend->create_context (target); } -slim_hidden_def (cairo_create); void _cairo_init (cairo_t *cr, @@ -528,7 +527,6 @@ cairo_destroy (cairo_t *cr) cr->backend->destroy (cr); } -slim_hidden_def (cairo_destroy); /** * cairo_get_user_data: @@ -632,7 +630,6 @@ cairo_save (cairo_t *cr) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def(cairo_save); /** * cairo_restore: @@ -656,7 +653,6 @@ cairo_restore (cairo_t *cr) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def(cairo_restore); /** * cairo_push_group: @@ -707,7 +703,6 @@ 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: @@ -740,7 +735,6 @@ cairo_push_group_with_content (cairo_t *cr, cairo_content_t content) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def(cairo_push_group_with_content); /** * cairo_pop_group: @@ -777,7 +771,6 @@ cairo_pop_group (cairo_t *cr) return group_pattern; } -slim_hidden_def(cairo_pop_group); /** * cairo_pop_group_to_source: @@ -815,7 +808,6 @@ cairo_pop_group_to_source (cairo_t *cr) cairo_set_source (cr, group_pattern); cairo_pattern_destroy (group_pattern); } -slim_hidden_def (cairo_pop_group_to_source); /** * cairo_set_operator: @@ -842,7 +834,6 @@ cairo_set_operator (cairo_t *cr, cairo_operator_t op) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_set_operator); #if 0 @@ -903,7 +894,6 @@ cairo_set_source_rgb (cairo_t *cr, double red, double green, double blue) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_set_source_rgb); /** * cairo_set_source_rgba: @@ -942,7 +932,6 @@ cairo_set_source_rgba (cairo_t *cr, if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_set_source_rgba); /** * cairo_set_source_surface: @@ -989,7 +978,6 @@ cairo_set_source_surface (cairo_t *cr, if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_set_source_surface); /** * cairo_set_source: @@ -1034,7 +1022,6 @@ cairo_set_source (cairo_t *cr, cairo_pattern_t *source) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_set_source); /** * cairo_get_source: @@ -1056,7 +1043,6 @@ cairo_get_source (cairo_t *cr) return cr->backend->get_source (cr); } -slim_hidden_def (cairo_get_source); /** * cairo_set_tolerance: @@ -1088,7 +1074,6 @@ cairo_set_tolerance (cairo_t *cr, double tolerance) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_set_tolerance); /** * cairo_set_antialias: @@ -1188,7 +1173,6 @@ cairo_set_line_width (cairo_t *cr, double width) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_set_line_width); /** * cairo_set_hairline: @@ -1229,7 +1213,6 @@ cairo_set_hairline (cairo_t *cr, cairo_bool_t set_hairline) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_set_hairline); /** * cairo_set_line_cap: @@ -1260,7 +1243,6 @@ cairo_set_line_cap (cairo_t *cr, cairo_line_cap_t line_cap) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_set_line_cap); /** * cairo_set_line_join: @@ -1291,7 +1273,6 @@ cairo_set_line_join (cairo_t *cr, cairo_line_join_t line_join) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_set_line_join); /** * cairo_set_dash: @@ -1342,7 +1323,6 @@ cairo_set_dash (cairo_t *cr, if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_set_dash); /** * cairo_get_dash_count: @@ -1461,7 +1441,6 @@ cairo_translate (cairo_t *cr, double tx, double ty) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_translate); /** * cairo_scale: @@ -1488,7 +1467,6 @@ cairo_scale (cairo_t *cr, double sx, double sy) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_scale); /** * cairo_rotate: @@ -1516,7 +1494,6 @@ cairo_rotate (cairo_t *cr, double angle) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_rotate); /** * cairo_transform: @@ -1542,7 +1519,6 @@ cairo_transform (cairo_t *cr, if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_transform); /** * cairo_set_matrix: @@ -1567,7 +1543,6 @@ cairo_set_matrix (cairo_t *cr, if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_set_matrix); /** * cairo_identity_matrix: @@ -1592,7 +1567,6 @@ cairo_identity_matrix (cairo_t *cr) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_identity_matrix); /** * cairo_user_to_device: @@ -1614,7 +1588,6 @@ cairo_user_to_device (cairo_t *cr, double *x, double *y) cr->backend->user_to_device (cr, x, y); } -slim_hidden_def (cairo_user_to_device); /** * cairo_user_to_device_distance: @@ -1637,7 +1610,6 @@ cairo_user_to_device_distance (cairo_t *cr, double *dx, double *dy) cr->backend->user_to_device_distance (cr, dx, dy); } -slim_hidden_def (cairo_user_to_device_distance); /** * cairo_device_to_user: @@ -1659,7 +1631,6 @@ cairo_device_to_user (cairo_t *cr, double *x, double *y) cr->backend->device_to_user (cr, x, y); } -slim_hidden_def (cairo_device_to_user); /** * cairo_device_to_user_distance: @@ -1704,7 +1675,6 @@ cairo_new_path (cairo_t *cr) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def(cairo_new_path); /** * cairo_new_sub_path: @@ -1760,8 +1730,6 @@ cairo_move_to (cairo_t *cr, double x, double y) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def(cairo_move_to); - /** * cairo_line_to: @@ -1790,7 +1758,6 @@ cairo_line_to (cairo_t *cr, double x, double y) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_line_to); /** * cairo_curve_to: @@ -1831,7 +1798,6 @@ cairo_curve_to (cairo_t *cr, if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_curve_to); /** * cairo_arc: @@ -1907,7 +1873,6 @@ cairo_arc (cairo_t *cr, if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_arc); /** * cairo_arc_negative: @@ -1953,7 +1918,6 @@ cairo_arc_negative (cairo_t *cr, if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_arc_negative); /* XXX: NYI void @@ -2052,7 +2016,6 @@ cairo_rel_line_to (cairo_t *cr, double dx, double dy) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def(cairo_rel_line_to); /** * cairo_rel_curve_to: @@ -2136,7 +2099,6 @@ cairo_rectangle (cairo_t *cr, if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_rectangle); #if 0 /* XXX: NYI */ @@ -2196,7 +2158,6 @@ cairo_close_path (cairo_t *cr) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def(cairo_close_path); /** * cairo_path_extents: @@ -2270,7 +2231,6 @@ cairo_paint (cairo_t *cr) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_paint); /** * cairo_paint_with_alpha: @@ -2297,7 +2257,6 @@ cairo_paint_with_alpha (cairo_t *cr, if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_paint_with_alpha); /** * cairo_mask: @@ -2334,7 +2293,6 @@ cairo_mask (cairo_t *cr, if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_mask); /** * cairo_mask_surface: @@ -2418,7 +2376,6 @@ cairo_stroke (cairo_t *cr) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def(cairo_stroke); /** * cairo_stroke_preserve: @@ -2447,7 +2404,6 @@ cairo_stroke_preserve (cairo_t *cr) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def(cairo_stroke_preserve); /** * cairo_fill: @@ -2473,7 +2429,6 @@ cairo_fill (cairo_t *cr) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_fill); /** * cairo_fill_preserve: @@ -2500,7 +2455,6 @@ cairo_fill_preserve (cairo_t *cr) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def(cairo_fill_preserve); /** * cairo_copy_page: @@ -2765,7 +2719,6 @@ cairo_clip (cairo_t *cr) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_clip); /** * cairo_clip_preserve: @@ -2803,7 +2756,6 @@ cairo_clip_preserve (cairo_t *cr) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def(cairo_clip_preserve); /** * cairo_reset_clip: @@ -2872,7 +2824,6 @@ cairo_clip_extents (cairo_t *cr, if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_clip_extents); /** * cairo_in_clip: @@ -2951,6 +2902,22 @@ cairo_copy_clip_rectangle_list (cairo_t *cr) * Since: 1.16 **/ +/** + * CAIRO_TAG_CONTENT: + * + * Create a content tag. + * + * Since: 1.18 + **/ + +/** + * CAIRO_TAG_CONTENT_REF: + * + * Create a content reference tag. + * + * Since: 1.18 + **/ + /** * cairo_tag_begin: * @cr: a cairo context @@ -3046,11 +3013,11 @@ cairo_tag_end (cairo_t *cr, const char *tag_name) * "sans-serif", "cursive", "fantasy", "monospace"), are likely to * work as expected. * - * If @family starts with the string "@cairo:", or if no native font + * If @family starts with the string "\@cairo:", or if no native font * backends are compiled in, cairo will use an internal font family. * The internal font family recognizes many modifiers in the @family * string, most notably, it recognizes the string "monospace". That is, - * the family name "@cairo:monospace" will use the monospace version of + * the family name "\@cairo:monospace" will use the monospace version of * the internal font family. * * For "real" font selection, see the font-backend-specific @@ -3218,7 +3185,6 @@ cairo_set_font_size (cairo_t *cr, double size) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_set_font_size); /** * cairo_set_font_matrix: @@ -3248,7 +3214,6 @@ cairo_set_font_matrix (cairo_t *cr, if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_set_font_matrix); /** * cairo_get_font_matrix: @@ -3303,7 +3268,6 @@ cairo_set_font_options (cairo_t *cr, if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_set_font_options); /** * cairo_get_font_options: @@ -3400,7 +3364,6 @@ cairo_get_scaled_font (cairo_t *cr) return cr->backend->get_scaled_font (cr); } -slim_hidden_def (cairo_get_scaled_font); /** * cairo_text_extents: @@ -3938,7 +3901,7 @@ cairo_get_operator (cairo_t *cr) } #if 0 -/** +/* * cairo_get_opacity: * @cr: a cairo context * @@ -3976,7 +3939,6 @@ cairo_get_tolerance (cairo_t *cr) return cr->backend->get_tolerance (cr); } -slim_hidden_def (cairo_get_tolerance); /** * cairo_get_antialias: @@ -4017,7 +3979,6 @@ cairo_has_current_point (cairo_t *cr) return cr->backend->has_current_point (cr); } -slim_hidden_def (cairo_has_current_point); /** * cairo_get_current_point: @@ -4068,7 +4029,6 @@ cairo_get_current_point (cairo_t *cr, double *x_ret, double *y_ret) if (y_ret) *y_ret = y; } -slim_hidden_def(cairo_get_current_point); /** * cairo_get_fill_rule: @@ -4088,7 +4048,6 @@ cairo_get_fill_rule (cairo_t *cr) return cr->backend->get_fill_rule (cr); } -slim_hidden_def (cairo_set_fill_rule); /** * cairo_get_line_width: @@ -4111,7 +4070,6 @@ cairo_get_line_width (cairo_t *cr) return cr->backend->get_line_width (cr); } -slim_hidden_def (cairo_get_line_width); /** * cairo_get_hairline: @@ -4131,7 +4089,6 @@ cairo_get_hairline (cairo_t *cr) return cr->backend->get_hairline (cr); } -slim_hidden_def (cairo_get_hairline); /** * cairo_get_line_cap: @@ -4189,7 +4146,6 @@ cairo_get_miter_limit (cairo_t *cr) return cr->backend->get_miter_limit (cr); } -slim_hidden_def (cairo_set_miter_limit); /** * cairo_get_matrix: @@ -4210,7 +4166,6 @@ cairo_get_matrix (cairo_t *cr, cairo_matrix_t *matrix) cr->backend->get_matrix (cr, matrix); } -slim_hidden_def (cairo_get_matrix); /** * cairo_get_target: @@ -4238,7 +4193,6 @@ cairo_get_target (cairo_t *cr) return cr->backend->get_original_target (cr); } -slim_hidden_def (cairo_get_target); /** * cairo_get_group_target: @@ -4305,7 +4259,6 @@ cairo_copy_path (cairo_t *cr) return cr->backend->copy_path (cr); } -slim_hidden_def (cairo_copy_path); /** * cairo_copy_path_flat: @@ -4400,7 +4353,6 @@ cairo_append_path (cairo_t *cr, if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_append_path); /** * cairo_status: @@ -4417,4 +4369,3 @@ cairo_status (cairo_t *cr) { return cr->status; } -slim_hidden_def (cairo_status); diff --git a/src/cairo.h b/src/cairo.h index a2c955281..d53cc3d09 100644 --- a/src/cairo.h +++ b/src/cairo.h @@ -50,14 +50,25 @@ # 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 +#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(CAIRO_WIN32_STATIC_BUILD) +# define _cairo_export __declspec(dllexport) +# define _cairo_import __declspec(dllimport) +#elif defined(__GNUC__) +# define _cairo_export __attribute__((__visibility__("default"))) +# define _cairo_import +#else +# define _cairo_export +# define _cairo_import #endif +#ifdef CAIRO_COMPILATION +# define _cairo_api _cairo_export +#else +# define _cairo_api _cairo_import +#endif + +#define cairo_public _cairo_api extern + CAIRO_BEGIN_DECLS #define CAIRO_VERSION_ENCODE(major, minor, micro) ( \ @@ -429,6 +440,38 @@ typedef enum _cairo_format { CAIRO_FORMAT_RGBA128F = 7 } cairo_format_t; +/** + * cairo_dither_t: + * @CAIRO_DITHER_NONE: No dithering. + * @CAIRO_DITHER_DEFAULT: Default choice at cairo compile time. Currently NONE. + * @CAIRO_DITHER_FAST: Fastest dithering algorithm supported by the backend + * @CAIRO_DITHER_GOOD: An algorithm with smoother dithering than FAST + * @CAIRO_DITHER_BEST: Best algorithm available in the backend + * + * Dither is an intentionally applied form of noise used to randomize + * quantization error, preventing large-scale patterns such as color banding + * in images (e.g. for gradients). Ordered dithering applies a precomputed + * threshold matrix to spread the errors smoothly. + * + * #cairo_dither_t is modeled on pixman dithering algorithm choice. + * As of Pixman 0.40, FAST corresponds to a 8x8 ordered bayer noise and GOOD + * and BEST use an ordered 64x64 precomputed blue noise. + * + * Since: 1.18 + **/ +typedef enum _cairo_dither { + CAIRO_DITHER_NONE, + CAIRO_DITHER_DEFAULT, + CAIRO_DITHER_FAST, + CAIRO_DITHER_GOOD, + CAIRO_DITHER_BEST +} cairo_dither_t; + +cairo_public void +cairo_pattern_set_dither (cairo_pattern_t *pattern, cairo_dither_t dither); + +cairo_public cairo_dither_t +cairo_pattern_get_dither (cairo_pattern_t *pattern); /** * cairo_write_func_t: @@ -2357,6 +2400,16 @@ cairo_public cairo_surface_t * cairo_surface_create_observer (cairo_surface_t *target, cairo_surface_observer_mode_t mode); +/** + * cairo_surface_observer_callback_t: + * @observer: the #cairo_surface_observer_t + * @target: the observed surface + * @data: closure used when adding the callback + * + * A generic callback function for surface operations. + * + * Since: 1.12 + **/ typedef void (*cairo_surface_observer_callback_t) (cairo_surface_t *observer, cairo_surface_t *target, void *data); @@ -2397,34 +2450,34 @@ cairo_surface_observer_add_finish_callback (cairo_surface_t *abstract_surface, void *data); cairo_public cairo_status_t -cairo_surface_observer_print (cairo_surface_t *surface, +cairo_surface_observer_print (cairo_surface_t *abstract_surface, cairo_write_func_t write_func, void *closure); cairo_public double -cairo_surface_observer_elapsed (cairo_surface_t *surface); +cairo_surface_observer_elapsed (cairo_surface_t *abstract_surface); cairo_public cairo_status_t -cairo_device_observer_print (cairo_device_t *device, +cairo_device_observer_print (cairo_device_t *abstract_device, cairo_write_func_t write_func, void *closure); cairo_public double -cairo_device_observer_elapsed (cairo_device_t *device); +cairo_device_observer_elapsed (cairo_device_t *abstract_device); cairo_public double -cairo_device_observer_paint_elapsed (cairo_device_t *device); +cairo_device_observer_paint_elapsed (cairo_device_t *abstract_device); cairo_public double -cairo_device_observer_mask_elapsed (cairo_device_t *device); +cairo_device_observer_mask_elapsed (cairo_device_t *abstract_device); cairo_public double -cairo_device_observer_fill_elapsed (cairo_device_t *device); +cairo_device_observer_fill_elapsed (cairo_device_t *abstract_device); cairo_public double -cairo_device_observer_stroke_elapsed (cairo_device_t *device); +cairo_device_observer_stroke_elapsed (cairo_device_t *abstract_device); cairo_public double -cairo_device_observer_glyphs_elapsed (cairo_device_t *device); +cairo_device_observer_glyphs_elapsed (cairo_device_t *abstract_device); cairo_public cairo_surface_t * cairo_surface_reference (cairo_surface_t *surface); diff --git a/src/cairoint.h b/src/cairoint.h index ddbbe7baa..b18a579be 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -49,10 +49,6 @@ #include "config.h" -#ifdef _MSC_VER -#define cairo_public __declspec(dllexport) -#endif - #include #include #include @@ -93,12 +89,6 @@ CAIRO_BEGIN_DECLS -#if _WIN32 && !_WIN32_WCE /* Permissions on WinCE? No worries! */ -cairo_private FILE * -_cairo_win32_tmpfile (void); -#define tmpfile() _cairo_win32_tmpfile() -#endif - #undef MIN #define MIN(a, b) ((a) < (b) ? (a) : (b)) @@ -185,7 +175,7 @@ do { \ static inline int cairo_const _cairo_popcount (uint32_t mask) { -#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) +#if defined (__GNUC__) return __builtin_popcount (mask); #else register int y; @@ -1610,6 +1600,7 @@ cairo_private cairo_bool_t _pixman_format_to_masks (pixman_format_code_t pixman_format, cairo_format_masks_t *masks); + cairo_private void _cairo_image_scaled_glyph_fini (cairo_scaled_font_t *scaled_font, cairo_scaled_glyph_t *scaled_glyph); @@ -1965,208 +1956,8 @@ _cairo_observers_notify (cairo_list_t *observers, void *arg); cairo_private cairo_status_t _cairo_fopen (const char *filename, const char *mode, FILE **file_out); -/* Avoid unnecessary PLT entries. */ -slim_hidden_proto (cairo_append_path); -slim_hidden_proto (cairo_arc); -slim_hidden_proto (cairo_arc_negative); -slim_hidden_proto (cairo_clip); -slim_hidden_proto (cairo_clip_extents); -slim_hidden_proto (cairo_clip_preserve); -slim_hidden_proto (cairo_close_path); -slim_hidden_proto (cairo_copy_path); -slim_hidden_proto (cairo_create); -slim_hidden_proto (cairo_curve_to); -slim_hidden_proto (cairo_destroy); -slim_hidden_proto (cairo_device_to_user); -slim_hidden_proto (cairo_fill); -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_get_custom_palette_color); -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_format_stride_for_width); -slim_hidden_proto (cairo_get_current_point); -slim_hidden_proto (cairo_get_hairline); -slim_hidden_proto (cairo_get_line_width); -slim_hidden_proto (cairo_get_matrix); -slim_hidden_proto (cairo_get_scaled_font); -slim_hidden_proto (cairo_get_source); -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_has_current_point); -slim_hidden_proto (cairo_identity_matrix); -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_format); -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_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_rotate); -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_mesh_pattern_begin_patch); -slim_hidden_proto (cairo_mesh_pattern_curve_to); -slim_hidden_proto (cairo_mesh_pattern_end_patch); -slim_hidden_proto (cairo_mesh_pattern_get_control_point); -slim_hidden_proto (cairo_mesh_pattern_get_corner_color_rgba); -slim_hidden_proto (cairo_mesh_pattern_get_patch_count); -slim_hidden_proto (cairo_mesh_pattern_get_path); -slim_hidden_proto (cairo_mesh_pattern_line_to); -slim_hidden_proto (cairo_mesh_pattern_move_to); -slim_hidden_proto (cairo_mesh_pattern_set_corner_color_rgba); -slim_hidden_proto (cairo_move_to); -slim_hidden_proto (cairo_new_path); -slim_hidden_proto (cairo_paint); -slim_hidden_proto (cairo_paint_with_alpha); -slim_hidden_proto_no_warn (cairo_path_destroy); -slim_hidden_proto (cairo_pattern_add_color_stop_rgba); -slim_hidden_proto (cairo_pattern_create_for_surface); -slim_hidden_proto (cairo_pattern_create_linear); -slim_hidden_proto (cairo_pattern_create_mesh); -slim_hidden_proto (cairo_pattern_create_radial); -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_rgba); -slim_hidden_proto (cairo_pattern_get_type); -slim_hidden_proto_no_warn (cairo_pattern_reference); -slim_hidden_proto (cairo_pattern_set_extend); -slim_hidden_proto (cairo_pattern_set_matrix); -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_recording_surface_create); -slim_hidden_proto (cairo_recording_surface_ink_extents); -slim_hidden_proto (cairo_rectangle); -slim_hidden_proto (cairo_region_contains_point); -slim_hidden_proto (cairo_region_contains_rectangle); -slim_hidden_proto (cairo_region_copy); -slim_hidden_proto (cairo_region_create); -slim_hidden_proto (cairo_region_create_rectangle); -slim_hidden_proto (cairo_region_create_rectangles); -slim_hidden_proto (cairo_region_destroy); -slim_hidden_proto (cairo_region_equal); -slim_hidden_proto (cairo_region_get_extents); -slim_hidden_proto (cairo_region_get_rectangle); -slim_hidden_proto (cairo_region_intersect); -slim_hidden_proto (cairo_region_intersect_rectangle); -slim_hidden_proto (cairo_region_is_empty); -slim_hidden_proto (cairo_region_num_rectangles); -slim_hidden_proto (cairo_region_reference); -slim_hidden_proto (cairo_region_status); -slim_hidden_proto (cairo_region_subtract); -slim_hidden_proto (cairo_region_subtract_rectangle); -slim_hidden_proto (cairo_region_translate); -slim_hidden_proto (cairo_region_union); -slim_hidden_proto (cairo_region_union_rectangle); -slim_hidden_proto (cairo_region_xor); -slim_hidden_proto (cairo_region_xor_rectangle); -slim_hidden_proto (cairo_rel_line_to); -slim_hidden_proto (cairo_restore); -slim_hidden_proto (cairo_rotate); -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_get_user_data); -slim_hidden_proto (cairo_scaled_font_glyph_extents); -slim_hidden_proto_no_warn (cairo_scaled_font_reference); -slim_hidden_proto (cairo_scaled_font_set_user_data); -slim_hidden_proto (cairo_scaled_font_status); -slim_hidden_proto (cairo_scaled_font_text_to_glyphs); -slim_hidden_proto (cairo_set_dash); -slim_hidden_proto (cairo_set_fill_rule); -slim_hidden_proto (cairo_set_font_matrix); -slim_hidden_proto (cairo_set_font_options); -slim_hidden_proto (cairo_set_font_size); -slim_hidden_proto (cairo_set_hairline); -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_miter_limit); -slim_hidden_proto (cairo_set_operator); -slim_hidden_proto (cairo_set_source); -slim_hidden_proto (cairo_set_source_rgb); -slim_hidden_proto (cairo_set_source_rgba); -slim_hidden_proto (cairo_set_source_surface); -slim_hidden_proto (cairo_set_tolerance); -slim_hidden_proto (cairo_status); -slim_hidden_proto (cairo_stroke); -slim_hidden_proto (cairo_stroke_preserve); -slim_hidden_proto (cairo_surface_copy_page); -slim_hidden_proto (cairo_surface_create_similar_image); -slim_hidden_proto (cairo_surface_destroy); -slim_hidden_proto (cairo_surface_finish); -slim_hidden_proto (cairo_surface_flush); -slim_hidden_proto (cairo_surface_get_device_offset); -slim_hidden_proto (cairo_surface_get_device_scale); -slim_hidden_proto (cairo_surface_get_font_options); -slim_hidden_proto (cairo_surface_get_mime_data); -slim_hidden_proto (cairo_surface_has_show_text_glyphs); -slim_hidden_proto (cairo_surface_mark_dirty); -slim_hidden_proto (cairo_surface_mark_dirty_rectangle); -slim_hidden_proto_no_warn (cairo_surface_reference); -slim_hidden_proto (cairo_surface_set_device_offset); -slim_hidden_proto (cairo_surface_set_device_scale); -slim_hidden_proto (cairo_surface_set_fallback_resolution); -slim_hidden_proto (cairo_surface_set_mime_data); -slim_hidden_proto (cairo_surface_show_page); -slim_hidden_proto (cairo_surface_status); -slim_hidden_proto (cairo_surface_supports_mime_type); -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_transform); -slim_hidden_proto (cairo_translate); -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_color_glyph_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_user_to_device); -slim_hidden_proto (cairo_user_to_device_distance); -slim_hidden_proto (cairo_version_string); - -#if CAIRO_HAS_PNG_FUNCTIONS - -slim_hidden_proto (cairo_image_surface_create_from_png_stream); -slim_hidden_proto (cairo_surface_write_to_png_stream); - -#endif - +cairo_private FILE * +_cairo_tmpfile (void); #include "cairo-mutex-private.h" #include "cairo-fixed-private.h" diff --git a/src/check-doc-syntax.sh b/src/check-doc-syntax.sh index 762a48429..57bbc91fd 100755 --- a/src/check-doc-syntax.sh +++ b/src/check-doc-syntax.sh @@ -28,7 +28,7 @@ enum_regexp="\([^%@']\|^\)\<\(FALSE\|TRUE\|NULL\|CAIRO_[0-9A-Z_]*\)\($\|[^(A-Za- if test "x$SGML_DOCS" = x; then enum_regexp='^[^:]*:[/ ][*]\(\|[ \t].*\)'$enum_regexp\($\|[^:]\) fi -if echo $FILES | xargs grep . /dev/null | sed -e '//,/<\/programlisting>/d' | grep "$enum_regexp" | grep -v '#####'; then +if echo $FILES | xargs grep . /dev/null | sed -e '//,/<\/programlisting>/d' -e '/\|\[/,/\]\|/d' | grep "$enum_regexp" | grep -v '#####'; then stat=1 echo Error: some macros in the docs are not prefixed by percent sign. echo Fix this by searching for the following regexp in the above files: @@ -42,7 +42,7 @@ else type_regexp='\(.'$type_regexp'\)\|\('$type_regexp'.\)' fi -if echo $FILES | xargs grep . /dev/null | sed -e '//,/<\/programlisting>/d' | grep -v "@Title" | grep "$type_regexp" | grep -v '#####'; then +if echo $FILES | xargs grep . /dev/null | sed -e '//,/<\/programlisting>/d' -e '/\|\[/,/\]\|/d' | grep -v "@Title" | grep "$type_regexp" | grep -v '#####'; then stat=1 echo Error: some type names in the docs are not prefixed by hash sign, echo neither are the only token in the doc line followed by colon. @@ -56,7 +56,7 @@ if test "x$SGML_DOCS" = x; then fi # We need to filter out gtk-doc markup errors for program listings. -if echo $FILES | xargs grep . /dev/null | sed -e '//,/<\/programlisting>/d' | grep "$func_regexp" | grep -v '^[^:]*: [*] [a-z_0-9]*:$' | grep -v '#####'; then +if echo $FILES | xargs grep . /dev/null | sed -e '//,/<\/programlisting>/d' -e '/\|\[/,/\]\|/d' | grep "$func_regexp" | grep -v '^[^:]*: [*] [a-z_0-9]*:$' | grep -v '#####'; then stat=1 echo Error: some function names in the docs are not followed by parentheses. echo Fix this by searching for the following regexp in the above files: diff --git a/src/check-has-hidden-symbols.c b/src/check-has-hidden-symbols.c deleted file mode 100644 index 120412776..000000000 --- a/src/check-has-hidden-symbols.c +++ /dev/null @@ -1,3 +0,0 @@ -#include "cairoint.h" - -CAIRO_HAS_HIDDEN_SYMBOLS diff --git a/src/check-link.c b/src/check-link.c deleted file mode 100644 index 2d943d644..000000000 --- a/src/check-link.c +++ /dev/null @@ -1,17 +0,0 @@ -#include -#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/src/check-plt.sh b/src/check-plt.sh deleted file mode 100755 index 6f3d07401..000000000 --- a/src/check-plt.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/sh - -LC_ALL=C -export LC_ALL - -if which readelf 2>/dev/null >/dev/null; then - : -else - echo "'readelf' not found; skipping test" - exit 0 -fi - -test -z "$srcdir" && srcdir=. -test -z "$MAKE" && MAKE=make -stat=0 - -if [ "x$CAIRO_HAS_HIDDEN_SYMBOLS" = x ]; then - $MAKE check-has-hidden-symbols.i > /dev/null || exit 1 - if tail -1 check-has-hidden-symbols.i | grep CAIRO_HAS_HIDDEN_SYMBOLS >/dev/null; then - echo "Compiler doesn't support symbol visibility; skipping test" - exit 0 - fi -fi - -for so in .libs/lib*.so "$@"; do - echo Checking "$so" for local PLT entries - readelf -W -r "$so" | grep 'JU\?MP_SLO' | grep 'cairo' >&2 && stat=1 -done - -exit $stat diff --git a/src/make-cairo-def.sh b/src/make-cairo-def.sh deleted file mode 100644 index 1a1f366e8..000000000 --- a/src/make-cairo-def.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/sh - -LC_ALL=C -export LC_ALL - -if [ $# -lt 3 ]; -then - echo "Generate cairo def file" - echo "Usage: $0 ..." - exit 1 -fi - -def_file="$1" -cairo_features_h="$2" -shift 2 - -#echo Generating $def_file - -(echo EXPORTS; \ - (cat $* || echo 'cairo_ERROR ()' ) | \ - egrep -v '^# *include' | \ - ( cat "$cairo_features_h" - | egrep -v '^#pragma' | cpp -D__cplusplus - || echo 'cairo_ERROR ()' ) | \ - egrep '^cairo_.* \(' | \ - sed -e 's/[ ].*//' | \ - sort; \ - ) > "$def_file" -grep -q -v cairo_ERROR "$def_file" || (rm "$def_file"; false) diff --git a/src/meson-check-def.sh b/src/meson-check-def.sh deleted file mode 100644 index 7c0e3e0e0..000000000 --- a/src/meson-check-def.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/sh - -LC_ALL=C -export LC_ALL - -if [ $# -lt 2 ]; -then - echo "Check that cairo library has same exported symbols as cairo.def" - echo "Usage: $0 " - exit 1 -fi - -def="$1" -so="$2" - -if which nm 2>/dev/null >/dev/null; then - : -else - echo "'nm' not found; skipping test" - exit 0 -fi - -stat=0 - -if [ "`uname -s`" = "Linux" ]; then - get_cairo_syms='( objdump -t "$so" | grep "^[^ ]* [^l.*]*[.]"; objdump -t "$so" | grep "[.]hidden.*\\&2 || stat=1 - -exit $stat diff --git a/src/meson.build b/src/meson.build index f777fcd1c..ac06ac61a 100644 --- a/src/meson.build +++ b/src/meson.build @@ -242,9 +242,10 @@ endif libcairo = library('cairo', cairo_sources, dependencies: deps, - c_args: cairo_no_warn_c_args + pthread_c_args, - cpp_args: cairo_no_warn_c_args + pthread_c_args, + c_args: cairo_no_warn_c_args + pthread_c_args + ['-DCAIRO_COMPILATION'], + cpp_args: cairo_no_warn_c_args + pthread_c_args + ['-DCAIRO_COMPILATION'], link_args: extra_link_args, + gnu_symbol_visibility: 'hidden', soversion: cairo_version_sonum, version: cairo_libversion, install: true, @@ -283,29 +284,4 @@ if shell.found() suite: ['fast', 'lint'], workdir: meson.current_source_dir()) endforeach - - env = environment() - env.set('CAIRO_HAS_HIDDEN_SYMBOLS', '1') - - cairo_def = custom_target('make-cairo-def', - input : cairo_headers, - output : 'cairo.def', - command : [ shell, - meson.current_source_dir()/'make-cairo-def.sh', - '@OUTPUT@', - cairo_features_file, - '@INPUT@' - ]) - - test('check-def', shell, - args: ['meson-check-def.sh', cairo_def, libcairo ], - env: env, - workdir: meson.current_source_dir()) - - test('check-plt.sh', shell, - args: ['check-plt.sh', libcairo ], - env: env, - suite: ['fast', 'plt'], - workdir: meson.current_source_dir()) - endif diff --git a/src/test-compositor-surface.c b/src/test-compositor-surface.c index d6e04a122..4518f509c 100644 --- a/src/test-compositor-surface.c +++ b/src/test-compositor-surface.c @@ -78,7 +78,7 @@ test_compositor_surface_create (const cairo_compositor_t *compositor, if (unlikely (pixman_image == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - surface = _cairo_malloc (sizeof (test_compositor_surface_t)); + surface = _cairo_calloc (sizeof (test_compositor_surface_t)); if (unlikely (surface == NULL)) { pixman_image_unref (pixman_image); return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); diff --git a/src/test-null-compositor-surface.c b/src/test-null-compositor-surface.c index 35913a2b9..ad2a35968 100644 --- a/src/test-null-compositor-surface.c +++ b/src/test-null-compositor-surface.c @@ -81,7 +81,7 @@ test_compositor_surface_create (const cairo_compositor_t *compositor, if (unlikely (pixman_image == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - surface = _cairo_malloc (sizeof (test_compositor_surface_t)); + surface = _cairo_calloc (sizeof (test_compositor_surface_t)); if (unlikely (surface == NULL)) { pixman_image_unref (pixman_image); return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); diff --git a/src/test-paginated-surface.c b/src/test-paginated-surface.c index 7967f7406..d33594d4b 100644 --- a/src/test-paginated-surface.c +++ b/src/test-paginated-surface.c @@ -74,7 +74,7 @@ _cairo_test_paginated_surface_create (cairo_surface_t *target) if (unlikely (status)) return _cairo_surface_create_in_error (status); - surface = _cairo_malloc (sizeof (test_paginated_surface_t)); + surface = _cairo_calloc (sizeof (test_paginated_surface_t)); if (unlikely (surface == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); diff --git a/src/win32/cairo-dwrite-font.cpp b/src/win32/cairo-dwrite-font.cpp index cf516d41c..9f6d362b3 100644 --- a/src/win32/cairo-dwrite-font.cpp +++ b/src/win32/cairo-dwrite-font.cpp @@ -47,6 +47,7 @@ #include "cairo-scaled-font-subsets-private.h" #include "cairo-dwrite.h" +#include #include #include @@ -110,6 +111,7 @@ _cairo_dwrite_error (HRESULT hr, const char *context) void *lpMsgBuf; if (!FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, NULL, hr, @@ -136,8 +138,9 @@ public: #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-function-type" #endif + HMODULE d2d1 = _cairo_win32_load_library_from_system32 (L"d2d1.dll"); D2D1CreateFactoryFunc createD2DFactory = (D2D1CreateFactoryFunc) - GetProcAddress(LoadLibraryW(L"d2d1.dll"), "D2D1CreateFactory"); + GetProcAddress(d2d1, "D2D1CreateFactory"); #ifdef __GNUC__ #pragma GCC diagnostic pop #endif @@ -224,21 +227,6 @@ RefPtr DWriteFactory::mDefaultRenderingParams; RefPtr D2DFactory::mFactoryInstance; RefPtr D2DFactory::mRenderTarget; -static int -_quality_from_antialias_mode(cairo_antialias_t antialias) -{ - switch (antialias) { - case CAIRO_ANTIALIAS_NONE: - return NONANTIALIASED_QUALITY; - case CAIRO_ANTIALIAS_FAST: - case CAIRO_ANTIALIAS_GRAY: - return ANTIALIASED_QUALITY; - default: - break; - } - return CLEARTYPE_QUALITY; -} - static RefPtr _create_rendering_params(IDWriteRenderingParams *params, const cairo_font_options_t *options, @@ -507,7 +495,7 @@ _cairo_dwrite_font_face_destroy (void *font_face) { cairo_dwrite_font_face_t *dwrite_font_face = static_cast(font_face); if (dwrite_font_face->dwriteface) - dwrite_font_face->dwriteface->Release(); + dwrite_font_face->dwriteface->Release(); if (dwrite_font_face->rendering_params) dwrite_font_face->rendering_params->Release(); return TRUE; @@ -532,10 +520,8 @@ _cairo_dwrite_glyph_run_from_glyphs(cairo_glyph_t *glyphs, FLOAT *advances = const_cast(run->glyphAdvances); DWRITE_GLYPH_OFFSET *offsets = const_cast(run->glyphOffsets); - cairo_dwrite_font_face_t *dwriteff = reinterpret_cast(scaled_font->base.font_face); - run->bidiLevel = 0; - run->fontFace = dwriteff->dwriteface; + run->fontFace = scaled_font->dwriteface; run->glyphCount = num_glyphs; run->isSideways = FALSE; @@ -628,6 +614,54 @@ do_grayscale(IDWriteFontFace *dwface, unsigned int ppem) return true; } +static void +set_dwrite_axes_from_string (const char *string, + DWRITE_FONT_AXIS_VALUE *dwrite_axes, + UINT32 count) +{ + const char *p = string; + + while (p && *p) { + const char *start; + const char *end, *end2; + DWRITE_FONT_AXIS_TAG tag; + double value; + + while (_cairo_isspace (*p)) p++; + + start = p; + end = strchr (p, ','); + if (end && (end - p < 6)) + goto skip; + + tag = DWRITE_MAKE_FONT_AXIS_TAG (p[0], p[1], p[2], p[3]); + + p += 4; + while (_cairo_isspace (*p)) p++; + if (*p == '=') p++; + + if (p - start < 5) + goto skip; + + value = _cairo_strtod (p, (char **) &end2); + + while (end2 && _cairo_isspace (*end2)) end2++; + + if (end2 && (*end2 != ',' && *end2 != '\0')) + goto skip; + + for (UINT32 i = 0; i < count; i++) { + if (dwrite_axes[i].axisTag == tag) { + dwrite_axes[i].value = value; + break; + } + } + +skip: + p = end ? end + 1 : NULL; + } +} + static cairo_status_t _cairo_dwrite_font_face_scaled_font_create (void *abstract_face, const cairo_matrix_t *font_matrix, @@ -639,7 +673,7 @@ _cairo_dwrite_font_face_scaled_font_create (void *abstract_face, cairo_dwrite_font_face_t *font_face = static_cast(abstract_face); /* Must do malloc and not C++ new, since Cairo frees this. */ - cairo_dwrite_scaled_font_t *dwrite_font = (cairo_dwrite_scaled_font_t*)_cairo_malloc( + cairo_dwrite_scaled_font_t *dwrite_font = (cairo_dwrite_scaled_font_t*)_cairo_calloc( sizeof(cairo_dwrite_scaled_font_t)); if (unlikely(dwrite_font == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -656,6 +690,60 @@ _cairo_dwrite_font_face_scaled_font_create (void *abstract_face, return status; } + if (options->variations) { + RefPtr dwriteface5; + + /* Since Windows 10 20348 */ + if (SUCCEEDED (font_face->dwriteface->QueryInterface(&dwriteface5))) { + RefPtr dwritefontresource; + + if (dwriteface5->HasVariations () && + SUCCEEDED (dwriteface5->GetFontResource (&dwritefontresource))) + { + UINT32 count = MIN (dwriteface5->GetFontAxisValueCount (), 500); + DWRITE_FONT_AXIS_VALUE *dwrite_axes = new DWRITE_FONT_AXIS_VALUE[count]; + UINT32 variables_count = 0; + + /* Sort variable axes first */ + for (UINT32 i = 0; i < count; i++) { + if (dwritefontresource->GetFontAxisAttributes (i) & DWRITE_FONT_AXIS_ATTRIBUTES_VARIABLE) { + if (variables_count != i) { + DWRITE_FONT_AXIS_VALUE swap_aux = dwrite_axes[variables_count]; + dwrite_axes[variables_count] = dwrite_axes[i]; + dwrite_axes[i] = swap_aux; + } + + variables_count++; + } + } + + if (SUCCEEDED (dwriteface5->GetFontAxisValues(dwrite_axes, count))) { + RefPtr dwriteface_new5; + + set_dwrite_axes_from_string (options->variations, dwrite_axes, variables_count); + + /* Can't use constexpr with mingw-w64 headers */ + const DWRITE_FONT_SIMULATIONS all_simulations = DWRITE_FONT_SIMULATIONS_BOLD | + DWRITE_FONT_SIMULATIONS_OBLIQUE; + if (SUCCEEDED (dwritefontresource->CreateFontFace(all_simulations, + dwrite_axes, + count, + &dwriteface_new5))) + { + dwrite_font->dwriteface = dwriteface_new5.forget().drop(); + } + } + + delete[] dwrite_axes; + } + } + } + + if (!dwrite_font->dwriteface) { + font_face->dwriteface->AddRef (); + dwrite_font->dwriteface = font_face->dwriteface; + } + dwrite_font->mat = dwrite_font->base.ctm; cairo_matrix_multiply(&dwrite_font->mat, &dwrite_font->mat, font_matrix); dwrite_font->mat_inverse = dwrite_font->mat; @@ -667,9 +755,9 @@ _cairo_dwrite_font_face_scaled_font_create (void *abstract_face, if (dwrite_font->measuring_mode == DWRITE_MEASURING_MODE_GDI_CLASSIC || dwrite_font->measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL) { DWRITE_MATRIX transform = _cairo_dwrite_matrix_from_matrix (&dwrite_font->mat); - font_face->dwriteface->GetGdiCompatibleMetrics(1, 1, &transform, &metrics); + dwrite_font->dwriteface->GetGdiCompatibleMetrics(1, 1, &transform, &metrics); } else { - font_face->dwriteface->GetMetrics(&metrics); + dwrite_font->dwriteface->GetMetrics(&metrics); } extents.ascent = (FLOAT)metrics.ascent / metrics.designUnitsPerEm; @@ -698,7 +786,7 @@ _cairo_dwrite_font_face_scaled_font_create (void *abstract_face, } if (default_quality == CAIRO_ANTIALIAS_GRAY) { - if (!do_grayscale(font_face->dwriteface, (unsigned int)_cairo_round(font_matrix->yy))) { + if (!do_grayscale(dwrite_font->dwriteface, (unsigned int)_cairo_round(font_matrix->yy))) { default_quality = CAIRO_ANTIALIAS_NONE; } } @@ -720,6 +808,9 @@ static void _cairo_dwrite_scaled_font_fini(void *scaled_font) { cairo_dwrite_scaled_font_t *dwrite_font = static_cast(scaled_font); + + dwrite_font->dwriteface->Release (); + if (dwrite_font->rendering_params) dwrite_font->rendering_params->Release(); } @@ -765,10 +856,9 @@ _cairo_dwrite_ucs4_to_index(void *scaled_font, uint32_t ucs4) { cairo_dwrite_scaled_font_t *dwritesf = static_cast(scaled_font); - cairo_dwrite_font_face_t *face = reinterpret_cast(dwritesf->base.font_face); + UINT16 index = 0; - UINT16 index; - face->dwriteface->GetGlyphIndicesA(&ucs4, 1, &index); + dwritesf->dwriteface->GetGlyphIndicesA(&ucs4, 1, &index); return index; } @@ -787,12 +877,12 @@ _cairo_dwrite_scaled_font_init_glyph_metrics(cairo_dwrite_scaled_font_t *scaled_ if (font_face->measuring_mode == DWRITE_MEASURING_MODE_GDI_CLASSIC || font_face->measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL) { DWRITE_MATRIX transform = _cairo_dwrite_matrix_from_matrix (&scaled_font->mat); - font_face->dwriteface->GetGdiCompatibleMetrics(1, 1, &transform, &fontMetrics); + scaled_font->dwriteface->GetGdiCompatibleMetrics(1, 1, &transform, &fontMetrics); BOOL natural = font_face->measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL; - hr = font_face->dwriteface->GetGdiCompatibleGlyphMetrics (1, 1, &transform, natural, &charIndex, 1, &metrics, FALSE); + hr = scaled_font->dwriteface->GetGdiCompatibleGlyphMetrics (1, 1, &transform, natural, &charIndex, 1, &metrics, FALSE); } else { - font_face->dwriteface->GetMetrics(&fontMetrics); - hr = font_face->dwriteface->GetDesignGlyphMetrics(&charIndex, 1, &metrics); + scaled_font->dwriteface->GetMetrics(&fontMetrics); + hr = scaled_font->dwriteface->GetDesignGlyphMetrics(&charIndex, 1, &metrics); } if (FAILED(hr)) { return CAIRO_INT_STATUS_UNSUPPORTED; @@ -838,52 +928,56 @@ _cairo_dwrite_scaled_font_init_glyph_metrics(cairo_dwrite_scaled_font_t *scaled_ * Used to determine the path of the glyphs. */ -class GeometryRecorder : public IDWriteGeometrySink +class GeometryRecorder final + : public IDWriteGeometrySink { public: GeometryRecorder(cairo_path_fixed_t *aCairoPath, const cairo_matrix_t &matrix) : mCairoPath(aCairoPath) , mMatrix(matrix) {} - // IUnknown interface - IFACEMETHOD(QueryInterface)(IID const& iid, OUT void** ppObject) + IFACEMETHOD (QueryInterface)(IID const& iid, OUT void** ppObject) noexcept override { - if (iid != __uuidof(IDWriteGeometrySink)) - return E_NOINTERFACE; + if (iid == __uuidof (IUnknown) || + iid == __uuidof (IDWriteGeometrySink)) + { + AddRef(); + *ppObject = this; + return S_OK; + } - *ppObject = static_cast(this); - - return S_OK; + *ppObject = nullptr; + return E_NOINTERFACE; } - IFACEMETHOD_(ULONG, AddRef)() + IFACEMETHOD_(ULONG, AddRef)() noexcept override { return 1; } - IFACEMETHOD_(ULONG, Release)() + IFACEMETHOD_(ULONG, Release)() noexcept override { return 1; } - IFACEMETHODIMP_(void) SetFillMode(D2D1_FILL_MODE fillMode) + IFACEMETHOD_(void, SetFillMode)(D2D1_FILL_MODE fillMode) noexcept override { return; } - STDMETHODIMP Close() + IFACEMETHOD (Close)() noexcept override { return S_OK; } - IFACEMETHODIMP_(void) SetSegmentFlags(D2D1_PATH_SEGMENT vertexFlags) + IFACEMETHOD_(void, SetSegmentFlags)(D2D1_PATH_SEGMENT vertexFlags) noexcept override { return; } - IFACEMETHODIMP_(void) BeginFigure( + IFACEMETHOD_(void, BeginFigure)( D2D1_POINT_2F startPoint, - D2D1_FIGURE_BEGIN figureBegin) + D2D1_FIGURE_BEGIN figureBegin) noexcept override { double x = startPoint.x; double y = startPoint.y; @@ -896,8 +990,8 @@ public: (void)status; /* squelch warning */ } - IFACEMETHODIMP_(void) EndFigure( - D2D1_FIGURE_END figureEnd) + IFACEMETHOD_(void, EndFigure)( + D2D1_FIGURE_END figureEnd) noexcept override { if (figureEnd == D2D1_FIGURE_END_CLOSED) { cairo_status_t status = _cairo_path_fixed_line_to(mCairoPath, @@ -907,9 +1001,9 @@ public: } } - IFACEMETHODIMP_(void) AddBeziers( + IFACEMETHOD_(void, AddBeziers)( const D2D1_BEZIER_SEGMENT *beziers, - UINT beziersCount) + UINT beziersCount) noexcept override { for (unsigned int i = 0; i < beziersCount; i++) { double x1 = beziers[i].point1.x; @@ -932,9 +1026,9 @@ public: } } - IFACEMETHODIMP_(void) AddLines( + IFACEMETHOD_(void, AddLines)( const D2D1_POINT_2F *points, - UINT pointsCount) + UINT pointsCount) noexcept override { for (unsigned int i = 0; i < pointsCount; i++) { double x = points[i].x; @@ -968,16 +1062,15 @@ _cairo_dwrite_scaled_font_init_glyph_path(cairo_dwrite_scaled_font_t *scaled_fon offset.ascenderOffset = 0; UINT16 glyphId = (UINT16)_cairo_scaled_glyph_index(scaled_glyph); FLOAT advance = 0.0; - cairo_dwrite_font_face_t *dwriteff = (cairo_dwrite_font_face_t*)scaled_font->base.font_face; - HRESULT hr = dwriteff->dwriteface->GetGlyphRunOutline(1, - &glyphId, - &advance, - &offset, - 1, - FALSE, - FALSE, - &recorder); + HRESULT hr = scaled_font->dwriteface->GetGlyphRunOutline(1, + &glyphId, + &advance, + &offset, + 1, + FALSE, + FALSE, + &recorder); if (!SUCCEEDED(hr)) return _cairo_dwrite_error (hr, "GetGlyphRunOutline failed"); @@ -1035,7 +1128,7 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s /* Y-axis is inverted */ offset.ascenderOffset = -(FLOAT)y; - run.fontFace = dwrite_font_face->dwriteface; + run.fontFace = scaled_font->dwriteface; run.fontEmSize = 1; run.glyphCount = 1; run.glyphIndices = &index; @@ -1047,17 +1140,17 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s matrix = _cairo_dwrite_matrix_from_matrix(&scaled_font->mat); /* The list of glyph image formats this renderer is prepared to support. */ - DWRITE_GLYPH_IMAGE_FORMATS supported_formats = + DWRITE_GLYPH_IMAGE_FORMATS supported_formats = static_cast( DWRITE_GLYPH_IMAGE_FORMATS_COLR | DWRITE_GLYPH_IMAGE_FORMATS_SVG | DWRITE_GLYPH_IMAGE_FORMATS_PNG | DWRITE_GLYPH_IMAGE_FORMATS_JPEG | DWRITE_GLYPH_IMAGE_FORMATS_TIFF | - DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8; + DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8); RefPtr fontFace2; UINT32 palette_count = 0; - if (SUCCEEDED(dwrite_font_face->dwriteface->QueryInterface(&fontFace2))) + if (SUCCEEDED(scaled_font->dwriteface->QueryInterface(&fontFace2))) palette_count = fontFace2->GetColorPaletteCount(); UINT32 palette_index = CAIRO_COLOR_PALETTE_DEFAULT; @@ -1226,93 +1319,501 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s return CAIRO_INT_STATUS_SUCCESS; } +// Helper for OS versions up to Windows 8 static cairo_int_status_t -_cairo_dwrite_scaled_font_init_glyph_surface(cairo_dwrite_scaled_font_t *scaled_font, - cairo_scaled_glyph_t *scaled_glyph) +init_glyph_surface_fallback_a8 (cairo_dwrite_scaled_font_t *scaled_font, + cairo_scaled_glyph_t *scaled_glyph, + int width, + int height, + double x1, + double y1, + DWRITE_MATRIX *matrix, + DWRITE_GLYPH_RUN *run) { - cairo_int_status_t status; - cairo_win32_surface_t *surface; - cairo_t *cr; - cairo_surface_t *image; - int width, height; - double x1, y1, x2, y2; + RefPtr bitmap; + HRESULT hr; - 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 = (int)(x2 - x1); - height = (int)(y2 - y1); + hr = WICImagingFactory::Instance()->CreateBitmap ((UINT)width, + (UINT)height, + GUID_WICPixelFormat8bppAlpha, + WICBitmapCacheOnLoad, + &bitmap); + if (FAILED(hr)) + return _cairo_dwrite_error (hr, "CreateBitmap failed"); + + D2D1_RENDER_TARGET_PROPERTIES properties = D2D1::RenderTargetProperties( + D2D1_RENDER_TARGET_TYPE_DEFAULT, + D2D1::PixelFormat( + DXGI_FORMAT_A8_UNORM, + D2D1_ALPHA_MODE_PREMULTIPLIED), + 0, + 0, + D2D1_RENDER_TARGET_USAGE_NONE, + D2D1_FEATURE_LEVEL_DEFAULT); + + RefPtr rt; + hr = D2DFactory::Instance()->CreateWicBitmapRenderTarget (bitmap, properties, &rt); + if (FAILED(hr)) + return _cairo_dwrite_error (hr, "CreateWicBitmapRenderTarget failed"); + + RefPtr brush; + hr = rt->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black, 1.0), &brush); + + rt->BeginDraw(); + + rt->SetTransform(*(D2D1_MATRIX_3X2_F*)matrix); + + rt->DrawGlyphRun({0, 0}, run, brush, scaled_font->measuring_mode); + + hr = rt->EndDraw(); + if (FAILED(hr)) + return _cairo_dwrite_error (hr, "EndDraw failed"); + + // TODO: rt->Flush()? + + cairo_surface_t *surface = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height); + if (cairo_surface_status (surface)) + return CAIRO_INT_STATUS_UNSUPPORTED; + + // Tell pixman that it should use component alpha blending when the surface is + // used as a source + pixman_image_set_component_alpha (((cairo_image_surface_t*)surface)->pixman_image, TRUE); + + int stride = cairo_image_surface_get_stride (surface); + WICRect rect = { 0, 0, width, height }; + bitmap->CopyPixels(&rect, + stride, + height * stride, + cairo_image_surface_get_data (surface)); + cairo_surface_mark_dirty (surface); + cairo_surface_set_device_offset (surface, -x1, -y1); + _cairo_scaled_glyph_set_surface (scaled_glyph, + &scaled_font->base, + (cairo_image_surface_t*)surface); + + return CAIRO_INT_STATUS_SUCCESS; +} + +static cairo_int_status_t +_cairo_dwrite_scaled_font_init_glyph_surface (cairo_dwrite_scaled_font_t *scaled_font, + cairo_scaled_glyph_t *scaled_glyph) +{ + HRESULT hr; + + double x1 = _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x); + double y1 = _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y); + double x2 = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.x); + double y2 = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y); + int width = (int)(x2 - x1); + int height = (int)(y2 - y1); + + if (width <= 0) + width = 1; + if (height <= 0) + height = 1; - DWRITE_GLYPH_RUN run; FLOAT advance = 0; UINT16 index = (UINT16)_cairo_scaled_glyph_index (scaled_glyph); DWRITE_GLYPH_OFFSET offset; double x = -x1 + .25 * _cairo_scaled_glyph_xphase (scaled_glyph); double y = -y1 + .25 * _cairo_scaled_glyph_yphase (scaled_glyph); - RECT area; - DWRITE_MATRIX matrix; - 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_int_status_t)cairo_status (cr); - cairo_destroy(cr); - if (status) - goto FAIL; - - /* - * We transform by the inverse transformation here. This will put our glyph + /* We transform by the inverse transformation here. This will put our glyph * locations in the space in which we draw. Which is later transformed by * the transformation matrix that we use. This will transform the * glyph positions back to where they were before when drawing, but the - * glyph shapes will be transformed by the transformation matrix. - */ + * glyph shapes will be transformed by the transformation matrix. */ cairo_matrix_transform_point(&scaled_font->mat_inverse, &x, &y); offset.advanceOffset = (FLOAT)x; - /* Y-axis is inverted */ - offset.ascenderOffset = -(FLOAT)y; + offset.ascenderOffset = -(FLOAT)y; /* Y axis is inverted */ - area.top = 0; - area.bottom = height; - area.left = 0; - area.right = width; + DWRITE_MATRIX matrix = _cairo_dwrite_matrix_from_matrix(&scaled_font->mat); + DWRITE_GLYPH_RUN run; run.glyphCount = 1; run.glyphAdvances = &advance; - run.fontFace = ((cairo_dwrite_font_face_t*)scaled_font->base.font_face)->dwriteface; + run.fontFace = scaled_font->dwriteface; run.fontEmSize = 1.0f; run.bidiLevel = 0; run.glyphIndices = &index; run.isSideways = FALSE; run.glyphOffsets = &offset; - matrix = _cairo_dwrite_matrix_from_matrix(&scaled_font->mat); + // Reduce the many Cairo antialias values to the + // three we actually care about: NONE, GRAY, RGB + enum { + ANTIALIAS_NONE, + ANTIALIAS_GRAY, + ANTIALIAS_CLEARTYPE, + } antialias = ANTIALIAS_CLEARTYPE; - status = _dwrite_draw_glyphs_to_gdi_surface_gdi (surface, &matrix, &run, - RGB(0,0,0), scaled_font, area); - if (status) - goto FAIL; + switch (scaled_font->antialias_mode) { + case CAIRO_ANTIALIAS_NONE: + antialias = ANTIALIAS_NONE; + break; + case CAIRO_ANTIALIAS_FAST: + case CAIRO_ANTIALIAS_GRAY: + antialias = ANTIALIAS_GRAY; + break; + case CAIRO_ANTIALIAS_DEFAULT: + case CAIRO_ANTIALIAS_GOOD: + case CAIRO_ANTIALIAS_BEST: + case CAIRO_ANTIALIAS_SUBPIXEL: + antialias = ANTIALIAS_CLEARTYPE; + break; + } - GdiFlush(); + // Set DWrite rendering options - image = _cairo_compute_glyph_mask (&surface->base, _quality_from_antialias_mode(scaled_font->antialias_mode)); - status = (cairo_int_status_t)image->status; - if (status) - goto FAIL; + DWRITE_RENDERING_MODE rendering_mode; + DWRITE_RENDERING_MODE1 rendering_mode1; + DWRITE_TEXT_ANTIALIAS_MODE text_antialias_mode; + DWRITE_TEXTURE_TYPE texture_type; - cairo_surface_set_device_offset (image, -x1, -y1); + switch (antialias) { + case ANTIALIAS_NONE: + rendering_mode1 = DWRITE_RENDERING_MODE1_ALIASED; + rendering_mode = DWRITE_RENDERING_MODE_ALIASED; + text_antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE; + texture_type = DWRITE_TEXTURE_ALIASED_1x1; + break; + case ANTIALIAS_GRAY: + rendering_mode1 = DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC; + rendering_mode = DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC; + text_antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE; + texture_type = DWRITE_TEXTURE_ALIASED_1x1; + break; + case ANTIALIAS_CLEARTYPE: + rendering_mode1 = DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC; + rendering_mode = DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC; + text_antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE; + texture_type = DWRITE_TEXTURE_CLEARTYPE_3x1; + break; + } + + DWRITE_GRID_FIT_MODE grid_fit_mode = DWRITE_GRID_FIT_MODE_DEFAULT; + + switch (cairo_font_options_get_hint_style (&scaled_font->base.options)) { + case CAIRO_HINT_STYLE_DEFAULT: + grid_fit_mode = DWRITE_GRID_FIT_MODE_DEFAULT; + break; + case CAIRO_HINT_STYLE_NONE: + grid_fit_mode = DWRITE_GRID_FIT_MODE_DISABLED; + break; + case CAIRO_HINT_STYLE_SLIGHT: + case CAIRO_HINT_STYLE_MEDIUM: + case CAIRO_HINT_STYLE_FULL: + grid_fit_mode = DWRITE_GRID_FIT_MODE_ENABLED; + break; + } + + cairo_subpixel_order_t subpixel_order; + subpixel_order = cairo_font_options_get_subpixel_order (&scaled_font->base.options); + + bool subpixel_order_is_vertical = false; + if (antialias == ANTIALIAS_CLEARTYPE) { + switch (subpixel_order) { + case CAIRO_SUBPIXEL_ORDER_DEFAULT: + case CAIRO_SUBPIXEL_ORDER_RGB: + case CAIRO_SUBPIXEL_ORDER_BGR: + break; + case CAIRO_SUBPIXEL_ORDER_VRGB: + case CAIRO_SUBPIXEL_ORDER_VBGR: + subpixel_order_is_vertical = true; + break; + } + } + + if (subpixel_order_is_vertical) { + // DirectWrite does not support vertical pixel geometries. + // As a workaround, apply a simmetry which swaps x and y + // coordinates, then re-swap while copying the back into + // the image surface + + // swap the two rows + std::swap (matrix.m11, matrix.m21); + std::swap (matrix.m12, matrix.m22); + } + + RefPtr dwrite_glyph_run_analysis; + if (DWriteFactory::Instance3()) { + hr = DWriteFactory::Instance3()->CreateGlyphRunAnalysis(&run, + &matrix, + rendering_mode1, + scaled_font->measuring_mode, + grid_fit_mode, + text_antialias_mode, + 0, // baselineOriginX, + 0, // baselineOriginY, + &dwrite_glyph_run_analysis); + } + else if (DWriteFactory::Instance2()) { + hr = DWriteFactory::Instance2()->CreateGlyphRunAnalysis(&run, + &matrix, + rendering_mode, + scaled_font->measuring_mode, + grid_fit_mode, + text_antialias_mode, + 0, // baselineOriginX, + 0, // baselineOriginY, + &dwrite_glyph_run_analysis); + } + else { + if (antialias == ANTIALIAS_GRAY) { + // IDWriteGlyphRunAnalysis supports gray-scale antialiasing only when + // created from IDWriteFactory2 or later. If we have IDWriteFactory + // only, fallback to rendering with Direct2D on A8 targets. + return init_glyph_surface_fallback_a8 (scaled_font, scaled_glyph, + width, height, x1, y1, &matrix, &run); + } + + hr = DWriteFactory::Instance()->CreateGlyphRunAnalysis(&run, 1, + &matrix, + rendering_mode, + scaled_font->measuring_mode, + 0, // baselineOriginX, + 0, // baselineOriginY, + &dwrite_glyph_run_analysis); + } + if (FAILED(hr)) + return CAIRO_INT_STATUS_UNSUPPORTED; + + cairo_format_t surface_format = antialias == ANTIALIAS_NONE ? CAIRO_FORMAT_A1 : + antialias == ANTIALIAS_GRAY ? CAIRO_FORMAT_A8 : + CAIRO_FORMAT_ARGB32; + + cairo_surface_t *surface = cairo_image_surface_create (surface_format, width, height); + if (cairo_surface_status (surface)) + return CAIRO_INT_STATUS_UNSUPPORTED; + + // Tell pixman that it should use component alpha blending when the surface is + // used as a source + pixman_image_set_component_alpha (((cairo_image_surface_t*)surface)->pixman_image, TRUE); + + // That's probably not needed right after creation + cairo_surface_flush (surface); + unsigned char *surface_data = cairo_image_surface_get_data (surface); + int surface_stride = cairo_image_surface_get_stride (surface); + + UINT32 dwrite_data_size; + BYTE *dwrite_data; + RECT dwrite_rect = { + 0, // left + 0, // top + width, // right + height // bottom + }; + + if (subpixel_order_is_vertical) { + std::swap (dwrite_rect.right, + dwrite_rect.bottom); + } + + // Whether IDWriteGlyphRunAnalysis::CreateAlphaTexture() can render directly + // on the cairo image surface (because the pixel formats match) or a separate + // buffer is needed + bool render_is_direct; + + switch (antialias) { + case ANTIALIAS_NONE: + { + dwrite_data_size = width * height; //TODO: check overflow + + dwrite_data = (BYTE*) _cairo_malloc (dwrite_data_size); + if (!dwrite_data) + return CAIRO_INT_STATUS_UNSUPPORTED; + + render_is_direct = false; + break; + } + case ANTIALIAS_GRAY: + { + // The image surface may have a stride that's bigger than width- + // account for that by passing stride as width to DWrite. Note: + // stride is a byte-size, but here pixel-size is exactly 1 byte. + dwrite_rect.right = cairo_image_surface_get_stride (surface); + + dwrite_data_size = dwrite_rect.right * height; //TODO: check overflow + dwrite_data = static_cast(surface_data); + + render_is_direct = true; + break; + } + case ANTIALIAS_CLEARTYPE: + { + dwrite_data_size = 3 * width * height; //TODO: check overflow + + dwrite_data = (BYTE*) _cairo_malloc (dwrite_data_size); + if (!dwrite_data) + return CAIRO_INT_STATUS_UNSUPPORTED; + + render_is_direct = false; + break; + } + } + + hr = dwrite_glyph_run_analysis->CreateAlphaTexture(texture_type, &dwrite_rect, dwrite_data, dwrite_data_size); + if (FAILED (hr)) + return CAIRO_INT_STATUS_UNSUPPORTED; + + // Most of the code here was copied and adapted from cairoft-font.c + switch (antialias) { + case ANTIALIAS_NONE: + { + unsigned char *src = static_cast(dwrite_data); + unsigned char *dst = surface_data; + + for (int i = 0; i < height; i++) { + unsigned char *d = dst; + + for (int j = 0; j < width / 8; j++) { + *d = (src[0] ? (1 << 0) : 0) + + (src[1] ? (1 << 1) : 0) + + (src[2] ? (1 << 2) : 0) + + (src[3] ? (1 << 3) : 0) + + (src[4] ? (1 << 4) : 0) + + (src[5] ? (1 << 5) : 0) + + (src[6] ? (1 << 6) : 0) + + (src[7] ? (1 << 7) : 0); + + d++; + src += 8; + } + + if (width % 8 != 0) { + *d = 0; + + for (int k = 0; k < width % 8; k++) { + *d += (src[k] ? (1 << k) : 0); + } + + d++; + src += (width % 8); + } + + dst += surface_stride; + } + break; + } + case ANTIALIAS_GRAY: + { + // Nothing to do + break; + } + case ANTIALIAS_CLEARTYPE: + { + unsigned char *src = static_cast(dwrite_data); + unsigned char *dst = surface_data; + + // The alpha channel is unused for component-alpha blending. + // Here we set the alpha channel anyway so that things work + // even in case of normal blending (but one likely gets some + // color fringing) + + switch (subpixel_order) { + case CAIRO_SUBPIXEL_ORDER_DEFAULT: + case CAIRO_SUBPIXEL_ORDER_RGB: + { + for (int i = 0; i < height; i++) { + UINT32 *d = reinterpret_cast(dst); + + for (int j = 0; j < width; j++) { + // CAIRO_FORMAT_ARGB32 is BGRA on little-endian + *d = (src[2] << 0) + + (src[1] << 8) + + (src[0] << 16) + + (src[1] << 24); // unused + + d++; + src += 3; + } + + dst += surface_stride; + } + } + break; + case CAIRO_SUBPIXEL_ORDER_BGR: + { + for (int i = 0; i < height; i++) { + UINT32 *d = reinterpret_cast(dst); + + for (int j = 0; j < width; j++) { + *d = (src[0] << 0) + + (src[1] << 8) + + (src[2] << 16) + + (src[1] << 24); // unused + + d++; + src += 3; + } + + dst += surface_stride; + } + } + break; + case CAIRO_SUBPIXEL_ORDER_VRGB: + { + size_t p; + + for (int i = 0; i < height; i++) { + UINT32 *d = reinterpret_cast(dst); + + p = i * 3; + for (int j = 0; j < width; j++) { + *d = (src[p + 2] << 0) + + (src[p + 1] << 8) + + (src[p + 0] << 16) + + (src[p + 1] << 24); // unused + + d++; + p += 3 * height; + } + + dst += surface_stride; + } + } + break; + case CAIRO_SUBPIXEL_ORDER_VBGR: + { + size_t p; + + for (int i = 0; i < height; i++) { + UINT32 *d = reinterpret_cast(dst); + + p = i * 3; + for (int j = 0; j < width; j++) { + *d = (src[p + 0] << 0) + + (src[p + 1] << 8) + + (src[p + 2] << 16) + + (src[p + 1] << 24); // unused + + d++; + p += 3 * height; + } + + dst += surface_stride; + } + } + break; + } + + break; + } + } + + // That's probably not needed. cairoft-font.c doesn't do that + cairo_surface_mark_dirty (surface); + + if (!render_is_direct) { + free (dwrite_data); + } + + cairo_surface_set_device_offset (surface, -x1, -y1); _cairo_scaled_glyph_set_surface (scaled_glyph, - &scaled_font->base, - (cairo_image_surface_t *) image); + &scaled_font->base, + (cairo_image_surface_t*)surface); - FAIL: - cairo_surface_destroy (&surface->base); - - return status; + return CAIRO_INT_STATUS_SUCCESS; } static cairo_int_status_t @@ -1323,18 +1824,17 @@ _cairo_dwrite_load_truetype_table(void *scaled_font, unsigned long *length) { cairo_dwrite_scaled_font_t *dwritesf = static_cast(scaled_font); - cairo_dwrite_font_face_t *face = reinterpret_cast(dwritesf->base.font_face); const void *data; UINT32 size; void *tableContext; BOOL exists; HRESULT hr; - hr = face->dwriteface->TryGetFontTable (be32_to_cpu (tag), - &data, - &size, - &tableContext, - &exists); + hr = dwritesf->dwriteface->TryGetFontTable (be32_to_cpu (tag), + &data, + &size, + &tableContext, + &exists); if (FAILED(hr)) return _cairo_dwrite_error (hr, "TryGetFontTable failed"); @@ -1349,7 +1849,7 @@ _cairo_dwrite_load_truetype_table(void *scaled_font, *length = size; if (tableContext) { - face->dwriteface->ReleaseFontTable(tableContext); + dwritesf->dwriteface->ReleaseFontTable(tableContext); } return (cairo_int_status_t)CAIRO_STATUS_SUCCESS; } @@ -1359,17 +1859,16 @@ _cairo_dwrite_is_synthetic(void *scaled_font, cairo_bool_t *is_synthetic) { cairo_dwrite_scaled_font_t *dwritesf = static_cast(scaled_font); - cairo_dwrite_font_face_t *face = reinterpret_cast(dwritesf->base.font_face); HRESULT hr; cairo_int_status_t status; - if (face->dwriteface->GetSimulations() != DWRITE_FONT_SIMULATIONS_NONE) { + if (dwritesf->dwriteface->GetSimulations() != DWRITE_FONT_SIMULATIONS_NONE) { *is_synthetic = FALSE; return CAIRO_INT_STATUS_SUCCESS; } RefPtr fontFace5; - if (FAILED(face->dwriteface->QueryInterface(&fontFace5))) { + if (FAILED(dwritesf->dwriteface->QueryInterface(&fontFace5))) { /* If IDWriteFontFace5 is not available, assume this version of * DirectWrite does not support variations. */ @@ -1689,7 +2188,6 @@ _dwrite_draw_glyphs_to_gdi_surface_d2d(cairo_win32_surface_t *surface, if (FAILED(hr)) return CAIRO_INT_STATUS_UNSUPPORTED; - float x = 0, y = 0; if (transform) { rt->SetTransform(D2D1::Matrix3x2F(transform->m11, transform->m12, @@ -1722,9 +2220,9 @@ _cairo_dwrite_show_glyphs_on_surface(void *surface, { // TODO: Check font & surface for types. cairo_dwrite_scaled_font_t *dwritesf = reinterpret_cast(scaled_font); - cairo_dwrite_font_face_t *dwriteff = reinterpret_cast(scaled_font->font_face); cairo_win32_surface_t *dst = reinterpret_cast(surface); cairo_int_status_t status; + /* We can only handle dwrite fonts */ if (cairo_scaled_font_get_type (scaled_font) != CAIRO_FONT_TYPE_DWRITE) return CAIRO_INT_STATUS_UNSUPPORTED; @@ -1747,10 +2245,6 @@ _cairo_dwrite_show_glyphs_on_surface(void *surface, AutoDWriteGlyphRun run; run.allocate(num_glyphs); - UINT16 *indices = const_cast(run.glyphIndices); - FLOAT *advances = const_cast(run.glyphAdvances); - DWRITE_GLYPH_OFFSET *offsets = const_cast(run.glyphOffsets); - BOOL transform = FALSE; _cairo_dwrite_glyph_run_from_glyphs(glyphs, num_glyphs, dwritesf, &run, &transform); @@ -1827,10 +2321,10 @@ compare_font_tables (cairo_dwrite_font_face_t *dwface, HRESULT hr; hr = dwface->dwriteface->TryGetFontTable(be32_to_cpu (tag), - &dw_data, - &dw_size, - &dw_tableContext, - &dw_exists); + &dw_data, + &dw_size, + &dw_tableContext, + &dw_exists); if (FAILED(hr)) return _cairo_dwrite_error (hr, "TryGetFontTable failed"); @@ -1866,7 +2360,7 @@ compare_font_tables (cairo_dwrite_font_face_t *dwface, cleanup: free (buffer); if (dw_tableContext) - dwface->dwriteface->ReleaseFontTable(dw_tableContext); + dwface->dwriteface->ReleaseFontTable(dw_tableContext); return status; } @@ -1931,6 +2425,8 @@ _cairo_dwrite_scaled_font_create_win32_scaled_font (cairo_scaled_font_t *scaled_ return CAIRO_INT_STATUS_UNSUPPORTED; } + /* TODO: use scaled font? */ + LOGFONTW logfont; if (FAILED(gdiInterop->ConvertFontFaceToLOGFONT (dwface->dwriteface, &logfont))) { return CAIRO_INT_STATUS_UNSUPPORTED; diff --git a/src/win32/cairo-dwrite-private.hpp b/src/win32/cairo-dwrite-private.hpp index c7a24822a..7834485f3 100644 --- a/src/win32/cairo-dwrite-private.hpp +++ b/src/win32/cairo-dwrite-private.hpp @@ -68,7 +68,8 @@ struct _cairo_dwrite_scaled_font { cairo_matrix_t mat; cairo_matrix_t mat_inverse; cairo_antialias_t antialias_mode; - IDWriteRenderingParams *rendering_params; + IDWriteFontFace *dwriteface; /* Can't use RefPtr because this struct is malloc'd. */ + IDWriteRenderingParams *rendering_params; /* Can't use RefPtr because this struct is malloc'd. */ DWRITE_MEASURING_MODE measuring_mode; }; typedef struct _cairo_dwrite_scaled_font cairo_dwrite_scaled_font_t; @@ -83,8 +84,9 @@ public: #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-function-type" #endif + HMODULE dwrite = _cairo_win32_load_library_from_system32 (L"dwrite.dll"); DWriteCreateFactoryFunc createDWriteFactory = (DWriteCreateFactoryFunc) - GetProcAddress(LoadLibraryW(L"dwrite.dll"), "DWriteCreateFactory"); + GetProcAddress(dwrite, "DWriteCreateFactory"); #ifdef __GNUC__ #pragma GCC diagnostic pop #endif diff --git a/src/win32/cairo-win32-device.c b/src/win32/cairo-win32-device.c index 781ee0cde..91ef74588 100644 --- a/src/win32/cairo-win32-device.c +++ b/src/win32/cairo-win32-device.c @@ -76,67 +76,21 @@ static const cairo_device_backend_t _cairo_win32_device_backend = { _cairo_win32_device_destroy, }; -#if 0 -D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT, - D2D1::PixelFormat( - DXGI_FORMAT_B8G8R8A8_UNORM, - D2D1_ALPHA_MODE_IGNORE), - 0, - 0, - D2D1_RENDER_TARGET_USAGE_NONE, - D2D1_FEATURE_LEVEL_DEFAULT - ); - -hr = m_pD2DFactory->CreateDCRenderTarget(&props, &device->d2d); -#endif - -static cairo_bool_t is_win98 (void) -{ - OSVERSIONINFO os; - - os.dwOSVersionInfoSize = sizeof (os); - GetVersionEx (&os); - - return (VER_PLATFORM_WIN32_WINDOWS == os.dwPlatformId && - os.dwMajorVersion == 4 && - os.dwMinorVersion == 10); -} - -static void * -_cairo_win32_device_get_alpha_blend (cairo_win32_device_t *device) -{ - void *func = NULL; - - if (is_win98 ()) - return NULL; - - device->msimg32_dll = LoadLibraryW (L"msimg32"); - if (device->msimg32_dll) - func = GetProcAddress (device->msimg32_dll, "AlphaBlend"); - - return func; -} - cairo_device_t * _cairo_win32_device_get (void) { cairo_win32_device_t *device; - CAIRO_MUTEX_INITIALIZE (); - if (__cairo_win32_device) return cairo_device_reference (__cairo_win32_device); - device = _cairo_malloc (sizeof (*device)); + device = _cairo_calloc (sizeof (*device)); _cairo_device_init (&device->base, &_cairo_win32_device_backend); device->compositor = _cairo_win32_gdi_compositor_get (); - device->msimg32_dll = NULL; - device->alpha_blend = _cairo_win32_device_get_alpha_blend (device); - - if (_cairo_atomic_ptr_cmpxchg ((void **)&__cairo_win32_device, NULL, device)) + if (_cairo_atomic_ptr_cmpxchg ((cairo_atomic_intptr_t *)&__cairo_win32_device, NULL, device)) return cairo_device_reference(&device->base); _cairo_win32_device_destroy (device); diff --git a/src/win32/cairo-win32-display-surface.c b/src/win32/cairo-win32-display-surface.c index e3b3eec2f..7f0770b4f 100644 --- a/src/win32/cairo-win32-display-surface.c +++ b/src/win32/cairo-win32-display-surface.c @@ -56,10 +56,6 @@ #include #include -#if defined(__MINGW32__) && !defined(ETO_PDY) -# define ETO_PDY 0x2000 -#endif - #define PELS_72DPI ((LONG)(72. / 0.0254)) /** @@ -99,8 +95,6 @@ _create_dc_and_bitmap (cairo_win32_display_surface_t *surface, unsigned char **bits_out, int *rowstride_out) { - cairo_status_t status; - BITMAPINFO *bitmap_info = NULL; struct { BITMAPINFOHEADER bmiHeader; @@ -205,16 +199,20 @@ _create_dc_and_bitmap (cairo_win32_display_surface_t *surface, } surface->win32.dc = CreateCompatibleDC (original_dc); - if (!surface->win32.dc) + if (!surface->win32.dc) { + fprintf (stderr, "%s:%s\n", __FUNCTION__, "CreateCompatibleDC"); goto FAIL; + } surface->bitmap = CreateDIBSection (surface->win32.dc, bitmap_info, DIB_RGB_COLORS, &bits, NULL, 0); - if (!surface->bitmap) + if (!surface->bitmap) { + _cairo_win32_print_api_error (__FUNCTION__, "CreateDIBSection"); goto FAIL; + } surface->is_dib = TRUE; @@ -222,8 +220,10 @@ _create_dc_and_bitmap (cairo_win32_display_surface_t *surface, surface->saved_dc_bitmap = SelectObject (surface->win32.dc, surface->bitmap); - if (!surface->saved_dc_bitmap) + if (!surface->saved_dc_bitmap) { + fprintf (stderr, "%s:%s\n", __FUNCTION__, "SelectObject"); goto FAIL; + } if (bitmap_info && num_palette > 2) free (bitmap_info); @@ -260,8 +260,6 @@ _create_dc_and_bitmap (cairo_win32_display_surface_t *surface, return CAIRO_STATUS_SUCCESS; FAIL: - status = _cairo_win32_print_gdi_error (__FUNCTION__); - if (bitmap_info && num_palette > 2) free (bitmap_info); @@ -280,7 +278,7 @@ _create_dc_and_bitmap (cairo_win32_display_surface_t *surface, surface->win32.dc = NULL; } - return status; + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); } static cairo_surface_t * @@ -295,7 +293,7 @@ _cairo_win32_display_surface_create_for_dc (HDC original_dc, unsigned char *bits; int rowstride; - surface = _cairo_malloc (sizeof (*surface)); + surface = _cairo_calloc (sizeof (*surface)); if (surface == NULL) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); @@ -551,7 +549,7 @@ _cairo_win32_display_surface_flush (void *abstract_surface, unsigned flags) fallback->win32.dc, surface->win32.extents.x, surface->win32.extents.y, SRCCOPY)) - status = _cairo_win32_print_gdi_error (__FUNCTION__); + status = _cairo_win32_print_api_error (__FUNCTION__, "BitBlt"); } else if (damage->region) { int n = cairo_region_num_rectangles (damage->region), i; for (i = 0; i < n; i++) { @@ -568,7 +566,7 @@ _cairo_win32_display_surface_flush (void *abstract_surface, unsigned flags) fallback->win32.dc, rect.x, rect.y, SRCCOPY)) { - status = _cairo_win32_print_gdi_error (__FUNCTION__); + status = _cairo_win32_print_api_error (__FUNCTION__, "BitBlt"); break; } } @@ -619,7 +617,7 @@ _cairo_win32_save_initial_clip (HDC hdc, cairo_win32_display_surface_t *surface) clipBoxType = GetClipBox (hdc, &rect); if (clipBoxType == ERROR) { - _cairo_win32_print_gdi_error (__FUNCTION__); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "GetClipBox"); SetGraphicsMode (hdc, gm); /* XXX: Can we make a more reasonable guess at the error cause here? */ return _cairo_error (CAIRO_STATUS_DEVICE_ERROR); @@ -752,8 +750,10 @@ _cairo_win32_display_surface_set_clip (cairo_win32_display_surface_t *surface, /* AND the new region into our DC */ status = CAIRO_STATUS_SUCCESS; - if (ExtSelectClipRgn (surface->win32.dc, gdi_region, RGN_AND) == ERROR) - status = _cairo_win32_print_gdi_error (__FUNCTION__); + if (ExtSelectClipRgn (surface->win32.dc, gdi_region, RGN_AND) == ERROR) { + fprintf (stderr, "%s:%s\n", __FUNCTION__, "ExtSelectClipRgn"); + status = _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); + } DeleteObject (gdi_region); @@ -992,7 +992,7 @@ cairo_win32_surface_create_with_format (HDC hdc, cairo_format_t format) break; } - surface = _cairo_malloc (sizeof (*surface)); + surface = _cairo_calloc (sizeof (*surface)); if (surface == NULL) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); diff --git a/src/win32/cairo-win32-font.c b/src/win32/cairo-win32-font.c index a561e74a4..21c19a141 100644 --- a/src/win32/cairo-win32-font.c +++ b/src/win32/cairo-win32-font.c @@ -45,19 +45,6 @@ #include -#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 /** @@ -156,28 +143,26 @@ _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font static HDC _get_global_font_dc (void) { + static cairo_atomic_once_t once = CAIRO_ATOMIC_ONCE_INIT; static DWORD hdc_tls_index; HDC hdc; - if (!hdc_tls_index) { - CAIRO_MUTEX_LOCK (_cairo_win32_font_dc_mutex); - if (!hdc_tls_index) { - hdc_tls_index = TlsAlloc (); - assert (hdc_tls_index != TLS_OUT_OF_INDEXES); - } - CAIRO_MUTEX_UNLOCK (_cairo_win32_font_dc_mutex); + if (_cairo_atomic_init_once_enter (&once)) { + hdc_tls_index = TlsAlloc (); + assert (hdc_tls_index != TLS_OUT_OF_INDEXES); + _cairo_atomic_init_once_leave (&once); } hdc = TlsGetValue (hdc_tls_index); if (!hdc) { hdc = CreateCompatibleDC (NULL); if (!hdc) { - _cairo_win32_print_gdi_error ("_get_global_font_dc"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "CreateCompatibleDC"); return NULL; } if (!SetGraphicsMode (hdc, GM_ADVANCED)) { - _cairo_win32_print_gdi_error ("_get_global_font_dc"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "SetGraphicsMode"); DeleteDC (hdc); return NULL; } @@ -271,7 +256,7 @@ _have_cleartype_quality (void) version_info.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); if (!GetVersionEx (&version_info)) { - _cairo_win32_print_gdi_error ("_have_cleartype_quality"); + _cairo_win32_print_api_error (__FUNCTION__, "GetVersionEx"); return FALSE; } @@ -287,7 +272,7 @@ cairo_win32_get_system_text_quality (void) UINT smoothing_type; if (!SystemParametersInfo (SPI_GETFONTSMOOTHING, 0, &font_smoothing, 0)) { - _cairo_win32_print_gdi_error ("_get_system_quality"); + _cairo_win32_print_api_error (__FUNCTION__, "SystemParametersInfo"); return DEFAULT_QUALITY; } @@ -295,7 +280,7 @@ cairo_win32_get_system_text_quality (void) if (_have_cleartype_quality ()) { if (!SystemParametersInfo (SPI_GETFONTSMOOTHINGTYPE, 0, &smoothing_type, 0)) { - _cairo_win32_print_gdi_error ("_get_system_quality"); + _cairo_win32_print_api_error (__FUNCTION__, "SystemParametersInfo"); return DEFAULT_QUALITY; } @@ -333,7 +318,7 @@ _win32_scaled_font_create (LOGFONTW *logfont, if (hdc == NULL) return _cairo_error (CAIRO_STATUS_NO_MEMORY); - f = _cairo_malloc (sizeof(cairo_win32_scaled_font_t)); + f = _cairo_calloc (sizeof(cairo_win32_scaled_font_t)); if (f == NULL) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -422,8 +407,10 @@ _win32_scaled_font_set_world_transform (cairo_win32_scaled_font_t *scaled_font, _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"); + if (!SetWorldTransform (hdc, &xform)) { + fprintf (stderr, "%s:%s\n", __FUNCTION__, "SetWorldTransform"); + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); + } return CAIRO_STATUS_SUCCESS; } @@ -431,8 +418,10 @@ _win32_scaled_font_set_world_transform (cairo_win32_scaled_font_t *scaled_font, 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"); + if (!ModifyWorldTransform (hdc, NULL, MWT_IDENTITY)) { + fprintf (stderr, "%s:%s\n", __FUNCTION__, "ModifyWorldTransform"); + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); + } return CAIRO_STATUS_SUCCESS; } @@ -450,8 +439,10 @@ _win32_scaled_font_get_scaled_hfont (cairo_win32_scaled_font_t *scaled_font, 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"); + if (!scaled_font->scaled_hfont) { + fprintf (stderr, "%s:%s\n", __FUNCTION__, "CreateFontIndirect"); + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); + } } *hfont_out = scaled_font->scaled_hfont; @@ -475,25 +466,30 @@ _win32_scaled_font_get_unscaled_hfont (cairo_win32_scaled_font_t *scaled_font, if (status) return status; - if (! SelectObject (hdc, scaled_hfont)) - return _cairo_win32_print_gdi_error ("_win32_scaled_font_get_unscaled_hfont:SelectObject"); + if (! SelectObject (hdc, scaled_hfont)) { + fprintf (stderr, "%s:%s\n", __FUNCTION__, "SelectObject"); + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); + } otm_size = GetOutlineTextMetrics (hdc, 0, NULL); - if (! otm_size) - return _cairo_win32_print_gdi_error ("_win32_scaled_font_get_unscaled_hfont:GetOutlineTextMetrics"); + if (! otm_size) { + fprintf (stderr, "%s:%s\n", __FUNCTION__, "GetOutlineTextMetrics"); + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); + } otm = _cairo_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; + fprintf (stderr, "%s:%s\n", __FUNCTION__, "GetOutlineTextMetrics"); + free (otm); + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); } scaled_font->em_square = otm->otmEMSquare; free (otm); + otm = NULL; logfont = scaled_font->logfont; logfont.lfHeight = -scaled_font->em_square; @@ -503,8 +499,10 @@ _win32_scaled_font_get_unscaled_hfont (cairo_win32_scaled_font_t *scaled_font, 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"); + if (! scaled_font->unscaled_hfont) { + fprintf (stderr, "%s:%s\n", __FUNCTION__, "CreateFontIndirect"); + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); + } } *hfont_out = scaled_font->unscaled_hfont; @@ -524,8 +522,10 @@ _cairo_win32_scaled_font_select_unscaled_font (cairo_scaled_font_t *scaled_font, return status; old_hfont = SelectObject (hdc, hfont); - if (!old_hfont) - return _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_select_unscaled_font"); + if (!old_hfont) { + fprintf (stderr, "%s:%s\n", __FUNCTION__, "CreateSolidBrush"); + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); + } status = _win32_scaled_font_set_identity_transform (hdc); if (status) { @@ -664,7 +664,7 @@ _cairo_win32_scaled_font_ucs4_to_index (void *abstract_font, 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"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "GetGlyphIndices"); glyph_index = 0; } @@ -694,7 +694,8 @@ _cairo_win32_scaled_font_set_metrics (cairo_win32_scaled_font_t *scaled_font) return status; if (!GetTextMetrics (hdc, &metrics)) { - status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_set_metrics:GetTextMetrics"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "GetTextMetrics"); + status = _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); } cairo_win32_scaled_font_done_font (&scaled_font->base); @@ -779,7 +780,8 @@ _cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_f return status; if (!GetCharWidth32(hdc, charIndex, charIndex, &width)) { - status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_init_glyph_metrics:GetCharWidth32"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "GetCharWidth32"); + status = _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); width = 0; } cairo_win32_scaled_font_done_font (&scaled_font->base); @@ -978,7 +980,8 @@ _flush_glyphs (cairo_glyph_state_t *state) elements, state->glyphs.num_elements, dx_elements)) { - return _cairo_win32_print_gdi_error ("_flush_glyphs"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "CreateSolidBrush"); + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); } _cairo_array_truncate (&state->glyphs, 0); @@ -1058,8 +1061,10 @@ _draw_glyphs_on_surface (cairo_win32_surface_t *surface, cairo_status_t status, status2; int i; - if (!SaveDC (surface->dc)) - return _cairo_win32_print_gdi_error ("_draw_glyphs_on_surface:SaveDC"); + if (!SaveDC (surface->dc)) { + fprintf (stderr, "%s:%s\n", __FUNCTION__, "SaveDC"); + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); + } status = cairo_win32_scaled_font_select_font (&scaled_font->base, surface->dc); if (status) @@ -1180,8 +1185,8 @@ _cairo_win32_scaled_font_index_to_ucs4 (void *abstract_font, res = GetFontUnicodeRanges(hdc, NULL); if (res == 0) { - status = _cairo_win32_print_gdi_error ( - "_cairo_win32_scaled_font_index_to_ucs4:GetFontUnicodeRanges"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "GetFontUnicodeRanges"); + status = _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); goto exit1; } @@ -1193,8 +1198,8 @@ _cairo_win32_scaled_font_index_to_ucs4 (void *abstract_font, res = GetFontUnicodeRanges(hdc, glyph_set); if (res == 0) { - status = _cairo_win32_print_gdi_error ( - "_cairo_win32_scaled_font_index_to_ucs4:GetFontUnicodeRanges"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "GetFontUnicodeRanges"); + status = _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); goto exit1; } @@ -1219,8 +1224,8 @@ _cairo_win32_scaled_font_index_to_ucs4 (void *abstract_font, 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"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "GetGlyphIndices"); + status = _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); goto exit2; } @@ -1489,7 +1494,8 @@ _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font &metrics, 0, NULL, &matrix); if (bytesGlyph == GDI_ERROR) { - status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_glyph_path"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "GetGlyphOutline"); + status = _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); goto CLEANUP_FONT; } @@ -1502,7 +1508,8 @@ _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_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"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "GetGlyphOutline"); + status = _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); goto CLEANUP_BUFFER; } @@ -1868,7 +1875,7 @@ cairo_win32_font_face_create_for_logfontw_hfont (LOGFONTW *logfont, HFONT font) } /* Otherwise create it and insert into hash table. */ - font_face = _cairo_malloc (sizeof (cairo_win32_font_face_t)); + font_face = _cairo_calloc (sizeof (cairo_win32_font_face_t)); if (!font_face) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); goto FAIL; @@ -2000,14 +2007,16 @@ cairo_win32_scaled_font_select_font (cairo_scaled_font_t *scaled_font, return status; old_hfont = SelectObject (hdc, hfont); - if (!old_hfont) - return _cairo_win32_print_gdi_error ("cairo_win32_scaled_font_select_font:SelectObject"); + if (!old_hfont) { + fprintf (stderr, "%s:%s\n", __FUNCTION__, "SelectObject"); + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); + } old_mode = SetGraphicsMode (hdc, GM_ADVANCED); if (!old_mode) { - status = _cairo_win32_print_gdi_error ("cairo_win32_scaled_font_select_font:SetGraphicsMode"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "SetGraphicsMode"); SelectObject (hdc, old_hfont); - return status; + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); } status = _win32_scaled_font_set_world_transform ((cairo_win32_scaled_font_t *)scaled_font, hdc); diff --git a/src/win32/cairo-win32-gdi-compositor.c b/src/win32/cairo-win32-gdi-compositor.c index bc1f69e70..347cd7ed5 100644 --- a/src/win32/cairo-win32-gdi-compositor.c +++ b/src/win32/cairo-win32-gdi-compositor.c @@ -55,23 +55,6 @@ #include "cairo-surface-inline.h" #include "cairo-surface-offset-private.h" -#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 - #define PELS_72DPI ((LONG)(72. / 0.0254)) /* the low-level interface */ @@ -105,7 +88,6 @@ struct copy_box { int tx, ty; HDC dst, src; BLENDFUNCTION bf; - cairo_win32_alpha_blend_func_t alpha_blend; }; static cairo_bool_t copy_box (cairo_box_t *box, void *closure) @@ -131,9 +113,9 @@ static cairo_bool_t alpha_box (cairo_box_t *box, void *closure) int height = _cairo_fixed_integer_part (box->p2.y - box->p1.y); TRACE ((stderr, "%s\n", __FUNCTION__)); - return cb->alpha_blend (cb->dst, x, y, width, height, - cb->src, x + cb->tx, y + cb->ty, width, height, - cb->bf); + return AlphaBlend (cb->dst, x, y, width, height, + cb->src, x + cb->tx, y + cb->ty, width, height, + cb->bf); } struct upload_box { @@ -184,8 +166,10 @@ fill_boxes (cairo_win32_display_surface_t *dst, fb.dc = dst->win32.dc; fb.brush = CreateSolidBrush (color_to_rgb(color)); - if (!fb.brush) - return _cairo_win32_print_gdi_error (__FUNCTION__); + if (!fb.brush) { + fprintf (stderr, "%s:%s\n", __FUNCTION__, "CreateSolidBrush"); + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); + } if (! _cairo_boxes_for_each_box (boxes, fill_box, &fb)) status = CAIRO_INT_STATUS_UNSUPPORTED; @@ -382,7 +366,6 @@ alpha_blend_boxes (cairo_win32_display_surface_t *dst, cb.bf.BlendFlags = 0; cb.bf.SourceConstantAlpha = alpha; cb.bf.AlphaFormat = (src->win32.format == CAIRO_FORMAT_ARGB32) ? AC_SRC_ALPHA : 0; - cb.alpha_blend = to_win32_device(dst->win32.base.device)->alpha_blend; cb.tx += cb.limit.x; cb.ty += cb.limit.y; @@ -397,10 +380,7 @@ alpha_blend_boxes (cairo_win32_display_surface_t *dst, static cairo_bool_t can_alpha_blend (cairo_win32_display_surface_t *dst) { - if ((dst->win32.flags & CAIRO_WIN32_SURFACE_CAN_ALPHABLEND) == 0) - return FALSE; - - return to_win32_device(dst->win32.base.device)->alpha_blend != NULL; + return (dst->win32.flags & CAIRO_WIN32_SURFACE_CAN_ALPHABLEND) != 0; } static cairo_status_t diff --git a/src/win32/cairo-win32-printing-surface.c b/src/win32/cairo-win32-printing-surface.c index a3dd907c2..c5b5f5cab 100644 --- a/src/win32/cairo-win32-printing-surface.c +++ b/src/win32/cairo-win32-printing-surface.c @@ -477,8 +477,10 @@ _cairo_win32_printing_surface_select_solid_brush (cairo_win32_printing_surface_t 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)"); + if (!surface->brush) { + fprintf (stderr, "%s:%s\n", __FUNCTION__, "CreateSolidBrush"); + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); + } surface->old_brush = SelectObject (surface->win32.dc, surface->brush); return CAIRO_STATUS_SUCCESS; @@ -501,13 +503,17 @@ _cairo_win32_printing_surface_get_ctm_clip_box (cairo_win32_printing_surface_t * XFORM xform; _cairo_matrix_to_win32_xform (&surface->ctm, &xform); - if (!ModifyWorldTransform (surface->win32.dc, &xform, MWT_LEFTMULTIPLY)) - return _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_get_clip_box:ModifyWorldTransform"); + if (!ModifyWorldTransform (surface->win32.dc, &xform, MWT_LEFTMULTIPLY)) { + fprintf (stderr, "%s:%s\n", __FUNCTION__, "ModifyWorldTransform"); + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); + } GetClipBox (surface->win32.dc, clip); _cairo_matrix_to_win32_xform (&surface->gdi_ctm, &xform); - if (!SetWorldTransform (surface->win32.dc, &xform)) - return _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_get_clip_box:SetWorldTransform"); + if (!SetWorldTransform (surface->win32.dc, &xform)) { + fprintf (stderr, "%s:%s\n", __FUNCTION__, "SetWorldTransform"); + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); + } return CAIRO_STATUS_SUCCESS; } @@ -887,7 +893,8 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_printing_surface_ _cairo_matrix_to_win32_xform (&m, &xform); if (! SetWorldTransform (surface->win32.dc, &xform)) { - status = _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_paint_image_pattern"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "SetWorldTransform"); + status = _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); goto CLEANUP_OPAQUE_IMAGE; } @@ -922,7 +929,8 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_printing_surface_ DIB_RGB_COLORS, SRCCOPY)) { - status = _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_paint(StretchDIBits)"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "StretchDIBits"); + status = _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); goto CLEANUP_OPAQUE_IMAGE; } } @@ -996,8 +1004,10 @@ _cairo_win32_printing_surface_paint_linear_pattern (cairo_win32_printing_surface _cairo_matrix_to_win32_xform (&mat, &xform); - if (!SetWorldTransform (surface->win32.dc, &xform)) - return _cairo_win32_print_gdi_error ("_win32_printing_surface_paint_linear_pattern:SetWorldTransform2"); + if (!SetWorldTransform (surface->win32.dc, &xform)) { + fprintf (stderr, "%s:%s\n", __FUNCTION__, "SetWorldTransform"); + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); + } GetClipBox (surface->win32.dc, &clip); @@ -1086,7 +1096,10 @@ _cairo_win32_printing_surface_paint_linear_pattern (cairo_win32_printing_surface vert, total_verts, rect, total_rects, GRADIENT_FILL_RECT_H)) - return _cairo_win32_print_gdi_error ("_win32_printing_surface_paint_linear_pattern:GradientFill"); + { + fprintf (stderr, "%s:%s\n", __FUNCTION__, "GradientFill"); + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); + } free (rect); free (vert); @@ -1524,7 +1537,7 @@ _cairo_win32_printing_surface_stroke (void *abstract_surface, dash_array = NULL; if (style->num_dashes) { pen_style |= PS_USERSTYLE; - dash_array = calloc (sizeof (DWORD), style->num_dashes); + dash_array = _cairo_calloc_ab (sizeof (DWORD), style->num_dashes); for (i = 0; i < style->num_dashes; i++) { dash_array[i] = (DWORD) (scale * style->dash[i]); } @@ -1556,13 +1569,15 @@ _cairo_win32_printing_surface_stroke (void *abstract_surface, style->num_dashes, dash_array); if (pen == NULL) { - status = _cairo_win32_print_gdi_error ("_win32_surface_stroke:ExtCreatePen"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "ExtCreatePen"); + status = _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); goto cleanup_composite; } obj = SelectObject (surface->win32.dc, pen); if (obj == NULL) { - status = _cairo_win32_print_gdi_error ("_win32_surface_stroke:SelectObject"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "SelectObject"); + status = _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); goto cleanup_composite; } @@ -1582,7 +1597,8 @@ _cairo_win32_printing_surface_stroke (void *abstract_surface, xform.eDy = 0.0f; if (!ModifyWorldTransform (surface->win32.dc, &xform, MWT_LEFTMULTIPLY)) { - status = _cairo_win32_print_gdi_error ("_win32_surface_stroke:SetWorldTransform"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "ModifyWorldTransform"); + status = _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); goto cleanup_composite; } @@ -1590,18 +1606,21 @@ _cairo_win32_printing_surface_stroke (void *abstract_surface, StrokePath (surface->win32.dc); } else { if (!WidenPath (surface->win32.dc)) { - status = _cairo_win32_print_gdi_error ("_win32_surface_stroke:WidenPath"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "WidenPath"); + status = _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); goto cleanup_composite; } if (!SelectClipPath (surface->win32.dc, RGN_AND)) { - status = _cairo_win32_print_gdi_error ("_win32_surface_stroke:SelectClipPath"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "SelectClipPath"); + status = _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); goto cleanup_composite; } /* Return to device space to paint the pattern */ _cairo_matrix_to_win32_xform (&surface->gdi_ctm, &xform); if (!SetWorldTransform (surface->win32.dc, &xform)) { - status = _cairo_win32_print_gdi_error ("_win32_surface_stroke:ModifyWorldTransform"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "SetWorldTransform"); + status = _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); goto cleanup_composite; } status = _cairo_win32_printing_surface_paint_pattern (surface, source, &extents.bounded); @@ -2102,8 +2121,10 @@ _cairo_win32_printing_surface_start_page (void *abstract_surface) surface->ctm.x0 = xform.eDx; surface->ctm.y0 = xform.eDy; cairo_matrix_init_identity (&surface->gdi_ctm); - if (!ModifyWorldTransform (surface->win32.dc, NULL, MWT_IDENTITY)) - return _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_start_page:ModifyWorldTransform"); + if (!ModifyWorldTransform (surface->win32.dc, NULL, MWT_IDENTITY)) { + fprintf (stderr, "%s:%s\n", __FUNCTION__, "ModifyWorldTransform"); + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); + } } surface->has_ctm = !_cairo_matrix_is_identity (&surface->ctm); @@ -2167,7 +2188,7 @@ cairo_win32_printing_surface_create (HDC hdc) cairo_win32_printing_surface_t *surface; cairo_surface_t *paginated; - surface = _cairo_malloc (sizeof (cairo_win32_printing_surface_t)); + surface = _cairo_calloc (sizeof (cairo_win32_printing_surface_t)); if (surface == NULL) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); diff --git a/src/win32/cairo-win32-private.h b/src/win32/cairo-win32-private.h index 6af09c0e1..a9eda8fdb 100644 --- a/src/win32/cairo-win32-private.h +++ b/src/win32/cairo-win32-private.h @@ -44,13 +44,6 @@ #include "cairo-surface-clipper-private.h" #include "cairo-surface-private.h" -#ifndef SHADEBLENDCAPS -#define SHADEBLENDCAPS 120 -#endif -#ifndef SB_NONE -#define SB_NONE 0 -#endif - #define WIN32_FONT_LOGICAL_SCALE 32 CAIRO_BEGIN_DECLS @@ -168,26 +161,10 @@ typedef struct _cairo_win32_printing_surface { } cairo_win32_printing_surface_t; #define to_win32_printing_surface(S) ((cairo_win32_printing_surface_t *)(S)) -typedef BOOL (WINAPI *cairo_win32_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); - typedef struct _cairo_win32_device { cairo_device_t base; - HMODULE msimg32_dll; - const cairo_compositor_t *compositor; - - cairo_win32_alpha_blend_func_t alpha_blend; } cairo_win32_device_t; #define to_win32_device(D) ((cairo_win32_device_t *)(D)) #define to_win32_device_from_surface(S) to_win32_device(((cairo_surface_t *)(S))->device) @@ -199,7 +176,7 @@ const cairo_compositor_t * _cairo_win32_gdi_compositor_get (void); cairo_status_t -_cairo_win32_print_gdi_error (const char *context); +_cairo_win32_print_api_error (const char *context, const char *api); cairo_bool_t _cairo_surface_is_win32 (const cairo_surface_t *surface); @@ -214,10 +191,6 @@ cairo_bool_t _cairo_win32_surface_get_extents (void *abstract_surface, cairo_rectangle_int_t *rectangle); -cairo_surface_t * -_cairo_compute_glyph_mask (cairo_surface_t *surface, - int quality); - uint32_t _cairo_win32_flags_for_dc (HDC dc, cairo_format_t format); @@ -260,6 +233,9 @@ _cairo_win32_scaled_font_is_bitmap (cairo_scaled_font_t *scaled_font); cairo_public BYTE cairo_win32_get_system_text_quality (void); +HMODULE +_cairo_win32_load_library_from_system32 (const wchar_t *name); + #if CAIRO_HAS_DWRITE_FONT cairo_int_status_t diff --git a/src/win32/cairo-win32-surface.c b/src/win32/cairo-win32-surface.c index ca5c9d823..488690e90 100644 --- a/src/win32/cairo-win32-surface.c +++ b/src/win32/cairo-win32-surface.c @@ -53,10 +53,6 @@ #include #include -#if defined(__MINGW32__) && !defined(ETO_PDY) -# define ETO_PDY 0x2000 -#endif - /** * SECTION:cairo-win32 * @Title: Win32 Surfaces @@ -83,40 +79,6 @@ * Since: 1.0 **/ -/** - * _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), - (LPWSTR) &lpMsgBuf, - 0, NULL)) { - fprintf (stderr, "%s: Unknown GDI error", context); - } else { - fprintf (stderr, "%s: %S", context, (wchar_t *)lpMsgBuf); - - LocalFree (lpMsgBuf); - } - - fflush (stderr); - - return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); -} - cairo_bool_t _cairo_win32_surface_get_extents (void *abstract_surface, cairo_rectangle_int_t *rectangle) @@ -301,7 +263,14 @@ _cairo_win32_surface_emit_glyphs (cairo_win32_surface_t *dst, 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); + /* When delta-y values are present in dxy_buf (the ETO_PDY flag is used), these + * represent "displacement along the vertical direction of the font" (per MSDN: + * https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-exttextoutw) + * with positive values being upward (observed behavior, not explicitly documented). + * This is the opposite of the top-to-bottom logical coordinate space used here, + * so the subtraction is reversed compared to what would otherwise be expected. + */ + dxy_buf[j+1] = _cairo_lround (logical_y - next_logical_y); logical_x = next_logical_x; logical_y = next_logical_y; @@ -322,7 +291,7 @@ _cairo_win32_surface_emit_glyphs (cairo_win32_surface_t *dst, num_glyphs, dxy_buf); if (!win_result) { - _cairo_win32_print_gdi_error("_cairo_win32_surface_show_glyphs(ExtTextOutW failed)"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "ExtTextOut"); } RestoreDC(dst->dc, -1); diff --git a/src/win32/cairo-win32-system.c b/src/win32/cairo-win32-system.c index 01bbe89df..c5ef24e8d 100644 --- a/src/win32/cairo-win32-system.c +++ b/src/win32/cairo-win32-system.c @@ -44,37 +44,129 @@ * And no other function should live here. */ - #include "cairoint.h" -#if CAIRO_MUTEX_IMPL_WIN32 -#if !CAIRO_WIN32_STATIC_BUILD - #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) +/** + * _cairo_win32_print_api_error: + * @context: context string to display along with the error + * @api: name of the failing api + * + * 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_api_error (const char *context, const char *api) { - switch (fdwReason) { + const DWORD lang_id = MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT); + const DWORD flags = FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_IGNORE_INSERTS | + FORMAT_MESSAGE_FROM_SYSTEM; + const DWORD last_error = GetLastError (); + void *lpMsgBuf = NULL; + + if (!FormatMessageW (flags, NULL, last_error, lang_id, (LPWSTR) &lpMsgBuf, 0, NULL)) { + fprintf (stderr, "%s: %s failed with error code %lu\n", context, api, last_error); + } + else { + fprintf (stderr, "%s: %s failed - %S\n", context, api, (wchar_t *)lpMsgBuf); + LocalFree (lpMsgBuf); + } + + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); +} + +/** + * _cairo_win32_load_library_from_system32: + * @name: name of the module to load from System32 + * + * Helper function to load system modules in the System32 + * folder. + * + * Return value: An module HANDLE, NULL on error. + **/ +HMODULE +_cairo_win32_load_library_from_system32 (const wchar_t *name) +{ + HMODULE module_handle; + + module_handle = LoadLibraryExW (name, NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); + if (module_handle == NULL) { + DWORD code = GetLastError(); + if (code == ERROR_INVALID_PARAMETER) { + /* Support for flag LOAD_LIBRARY_SEARCH_SYSTEM32 was backported + * to Windows Vista / 7 with Update KB2533623. If the flag is + * not supported, simply use LoadLibrary */ + return LoadLibraryW (name); + } + } + + return module_handle; +} + +#if CAIRO_MUTEX_IMPL_WIN32 + +static void NTAPI +cairo_win32_tls_callback (PVOID hinstance, DWORD dwReason, PVOID lpvReserved) +{ + switch (dwReason) { case DLL_PROCESS_ATTACH: CAIRO_MUTEX_INITIALIZE (); break; case DLL_PROCESS_DETACH: - CAIRO_MUTEX_FINALIZE (); + if (lpvReserved == NULL) { + CAIRO_MUTEX_FINALIZE (); + } break; } - - return TRUE; } +#ifdef _MSC_VER + +#ifdef _M_IX86 +# define SYMBOL_PREFIX "_" +#else +# define SYMBOL_PREFIX "" #endif + +#ifdef __cplusplus +# define EXTERN_C_BEGIN extern "C" { +# define EXTERN_C_END } +# define EXTERN_CONST extern const +#else +# define EXTERN_C_BEGIN +# define EXTERN_C_END +# define EXTERN_CONST const #endif + +#define DEFINE_TLS_CALLBACK(func) \ +__pragma (section (".CRT$XLD", long, read)) \ + \ +static void NTAPI func (PVOID, DWORD, PVOID); \ + \ +EXTERN_C_BEGIN \ +__declspec (allocate (".CRT$XLD")) \ +EXTERN_CONST PIMAGE_TLS_CALLBACK _ptr_##func = func; \ +EXTERN_C_END \ + \ +__pragma (comment (linker, "/INCLUDE:" SYMBOL_PREFIX "_tls_used")) \ +__pragma (comment (linker, "/INCLUDE:" SYMBOL_PREFIX "_ptr_" #func)) + +#else /* _MSC_VER */ + +#define DEFINE_TLS_CALLBACK(func) \ +static void NTAPI func (PVOID, DWORD, PVOID); \ + \ +__attribute__ ((used, section (".CRT$XLD"))) \ +static const PIMAGE_TLS_CALLBACK _ptr_##func = func; + + +#endif /* !_MSC_VER */ + +DEFINE_TLS_CALLBACK (cairo_win32_tls_callback); + +#endif /* CAIRO_MUTEX_IMPL_WIN32 */ diff --git a/src/win32/dw-extra.h b/src/win32/dw-extra.h index 424fb606d..a9daced21 100644 --- a/src/win32/dw-extra.h +++ b/src/win32/dw-extra.h @@ -23,6 +23,8 @@ struct DWRITE_COLOR_GLYPH_RUN1_WORKAROUND : DWRITE_COLOR_GLYPH_RUN typedef DWRITE_COLOR_GLYPH_RUN1 DWRITE_COLOR_GLYPH_RUN1_WORKAROUND; #endif +#if !defined(__MINGW64_VERSION_MAJOR) || __MINGW64_VERSION_MAJOR < 11 DEFINE_ENUM_FLAG_OPERATORS(DWRITE_GLYPH_IMAGE_FORMATS); +#endif #endif /* DWRITE_EXTRA_H */ diff --git a/subprojects/expat.wrap b/subprojects/expat.wrap index 3f7091485..53d13b943 100644 --- a/subprojects/expat.wrap +++ b/subprojects/expat.wrap @@ -1,11 +1,13 @@ [wrap-file] -directory = expat-2.2.9 -source_url = https://github.com/libexpat/libexpat/releases/download/R_2_2_9/expat-2.2.9.tar.xz -source_filename = expat-2.2.9.tar.bz2 -source_hash = 1ea6965b15c2106b6bbe883397271c80dfa0331cdf821b2c319591b55eadc0a4 -patch_filename = expat_2.2.9-4_patch.zip -patch_url = https://wrapdb.mesonbuild.com/v2/expat_2.2.9-4/get_patch -patch_hash = 8337fcf3928bbf9048a1a6a93b41a55588a5c9838a860bcc7c57f0e2a9517e95 +directory = expat-2.6.4 +source_url = https://github.com/libexpat/libexpat/releases/download/R_2_6_4/expat-2.6.4.tar.xz +source_filename = expat-2.6.4.tar.bz2 +source_hash = a695629dae047055b37d50a0ff4776d1d45d0a4c842cf4ccee158441f55ff7ee +patch_filename = expat_2.6.4-1_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/expat_2.6.4-1/get_patch +patch_hash = e4ffff014e06b805fbb36cd1e911e90829dc1e07301a3aee53231f9048758558 +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/expat_2.6.4-1/expat-2.6.4.tar.bz2 +wrapdb_version = 2.6.4-1 [provide] -expat = expat_dep \ No newline at end of file +expat = expat_dep diff --git a/subprojects/fontconfig.wrap b/subprojects/fontconfig.wrap index b6b77f4fe..2a72b98a8 100644 --- a/subprojects/fontconfig.wrap +++ b/subprojects/fontconfig.wrap @@ -1,5 +1,10 @@ -[wrap-git] -directory=fontconfig -url=https://gitlab.freedesktop.org/fontconfig/fontconfig.git -push-url=git@gitlab.freedesktop.org:fontconfig/fontconfig.git -revision=main +[wrap-file] +directory = fontconfig-2.16.0 +source_url = https://www.freedesktop.org/software/fontconfig/release/fontconfig-2.16.0.tar.xz +source_filename = fontconfig-2.16.0.tar.xz +source_hash = 6a33dc555cc9ba8b10caf7695878ef134eeb36d0af366041f639b1da9b6ed220 +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/fontconfig_2.16.0-1/fontconfig-2.16.0.tar.xz +wrapdb_version = 2.16.0-1 + +[provide] +fontconfig = fontconfig_dep diff --git a/subprojects/freetype2.wrap b/subprojects/freetype2.wrap index c346deb01..acad6f487 100644 --- a/subprojects/freetype2.wrap +++ b/subprojects/freetype2.wrap @@ -1,4 +1,11 @@ -[wrap-git] -directory=freetype -url=https://gitlab.freedesktop.org/freetype/freetype.git -revision=VER-2-11-0 +[wrap-file] +directory = freetype-2.13.3 +source_url = https://download.savannah.gnu.org/releases/freetype/freetype-2.13.3.tar.xz +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/freetype2_2.13.3-1/freetype-2.13.3.tar.xz +source_filename = freetype-2.13.3.tar.xz +source_hash = 0550350666d427c74daeb85d5ac7bb353acba5f76956395995311a9c6f063289 +wrapdb_version = 2.13.3-1 + +[provide] +freetype2 = freetype_dep +freetype = freetype_dep diff --git a/subprojects/glib.wrap b/subprojects/glib.wrap index 51d9cf8d4..71b6cd18b 100644 --- a/subprojects/glib.wrap +++ b/subprojects/glib.wrap @@ -1,9 +1,10 @@ [wrap-file] -directory = glib-2.74.0 -source_url = https://download.gnome.org/sources/glib/2.74/glib-2.74.0.tar.xz -source_filename = glib-2.74.0.tar.xz -source_hash = 3652c7f072d7b031a6b5edd623f77ebc5dcd2ae698598abcc89ff39ca75add30 -wrapdb_version = 2.74.0-1 +directory = glib-2.84.0 +source_url = https://download.gnome.org/sources/glib/2.84/glib-2.84.0.tar.xz +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/glib_2.84.0-1/glib-2.84.0.tar.xz +source_filename = glib-2.84.0.tar.xz +source_hash = f8823600cb85425e2815cfad82ea20fdaa538482ab74e7293d58b3f64a5aff6a +wrapdb_version = 2.84.0-1 [provide] dependency_names = gthread-2.0, gobject-2.0, gmodule-no-export-2.0, gmodule-export-2.0, gmodule-2.0, glib-2.0, gio-2.0, gio-windows-2.0, gio-unix-2.0 diff --git a/subprojects/libpng.wrap b/subprojects/libpng.wrap index 599045ba8..ec796cd88 100644 --- a/subprojects/libpng.wrap +++ b/subprojects/libpng.wrap @@ -1,11 +1,13 @@ [wrap-file] -directory = libpng-1.6.37 -source_url = https://github.com/glennrp/libpng/archive/v1.6.37.tar.gz -source_filename = libpng-1.6.37.tar.gz -source_hash = ca74a0dace179a8422187671aee97dd3892b53e168627145271cad5b5ac81307 -patch_url = https://wrapdb.mesonbuild.com/v1/projects/libpng/1.6.37/3/get_zip -patch_filename = libpng-1.6.37-3-wrap.zip -patch_hash = 6c9f32fd9150b3a96ab89be52af664e32207e10aa9f5fb9aa015989ee2dd7100 +directory = libpng-1.6.47 +source_url = https://github.com/glennrp/libpng/archive/v1.6.47.tar.gz +source_filename = libpng-1.6.47.tar.gz +source_hash = 631a4c58ea6c10c81f160c4b21fa8495b715d251698ebc2552077e8450f30454 +patch_filename = libpng_1.6.47-1_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/libpng_1.6.47-1/get_patch +patch_hash = a21f619a39da40a215e6c0d51e92af173c14b5e958bad0c0069eb91a6b9b0a3d +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/libpng_1.6.47-1/libpng-1.6.47.tar.gz +wrapdb_version = 1.6.47-1 [provide] libpng = libpng_dep diff --git a/subprojects/pixman.wrap b/subprojects/pixman.wrap index 71d585829..2bc079ed0 100644 --- a/subprojects/pixman.wrap +++ b/subprojects/pixman.wrap @@ -1,5 +1,10 @@ -[wrap-git] -directory=pixman -url=https://gitlab.freedesktop.org/pixman/pixman.git -push-url=git@gitlab.freedesktop.org:pixman/pixman.git -revision=master +[wrap-file] +directory = pixman-0.44.2 +source_url = https://www.cairographics.org/releases/pixman-0.44.2.tar.gz +source_filename = pixman-0.44.2.tar.gz +source_hash = 6349061ce1a338ab6952b92194d1b0377472244208d47ff25bef86fc71973466 +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/pixman_0.44.2-1/pixman-0.44.2.tar.gz +wrapdb_version = 0.44.2-1 + +[provide] +pixman-1 = idep_pixman diff --git a/subprojects/zlib.wrap b/subprojects/zlib.wrap index 4595c930a..aa14de177 100644 --- a/subprojects/zlib.wrap +++ b/subprojects/zlib.wrap @@ -1,13 +1,13 @@ [wrap-file] -directory = zlib-1.2.11 -source_url = https://zlib.net/fossils/zlib-1.2.11.tar.gz -source_fallback_url = https://gstreamer.freedesktop.org/data/src/mirror/zlib-1.2.11.tar.gz -source_filename = zlib-1.2.11.tar.gz -source_hash = c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1 -patch_url = https://wrapdb.mesonbuild.com/v1/projects/zlib/1.2.11/5/get_zip -patch_filename = zlib-1.2.11-5-wrap.zip -patch_hash = 728c8e24acbc2e6682fbd950fec39e2fc77528af361adb87259f8a8511434004 +directory = zlib-1.3.1 +source_url = http://zlib.net/fossils/zlib-1.3.1.tar.gz +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/zlib_1.3.1-1/zlib-1.3.1.tar.gz +source_filename = zlib-1.3.1.tar.gz +source_hash = 9a93b2b7dfdac77ceba5a558a580e74667dd6fede4585b91eefb60f03b72df23 +patch_filename = zlib_1.3.1-1_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/zlib_1.3.1-1/get_patch +patch_hash = e79b98eb24a75392009cec6f99ca5cdca9881ff20bfa174e8b8926d5c7a47095 +wrapdb_version = 1.3.1-1 [provide] zlib = zlib_dep - diff --git a/test/bug-431.c b/test/bug-431.c index 663fe0c45..717b03b7f 100644 --- a/test/bug-431.c +++ b/test/bug-431.c @@ -53,6 +53,10 @@ draw (cairo_t *cr, int width, int height) cairo_mask(cr, mask_pattern); cairo_restore(cr); + cairo_surface_destroy (png_surface); + cairo_pattern_destroy (png_pattern); + cairo_pattern_destroy (mask_pattern); + return CAIRO_TEST_SUCCESS; } diff --git a/test/create-from-broken-png-stream.c b/test/create-from-broken-png-stream.c index 7c02a2639..88cce0aff 100644 --- a/test/create-from-broken-png-stream.c +++ b/test/create-from-broken-png-stream.c @@ -61,13 +61,10 @@ preamble (cairo_test_context_t *ctx) surface = cairo_image_surface_create_from_png_stream (read_png_from_data, &offset); - /* XXX: The actual error is CAIRO_STATUS_PNG_ERROR, but - * _cairo_surface_create_in_error() does not support that. - */ - expected = CAIRO_STATUS_NO_MEMORY; + expected = CAIRO_STATUS_PNG_ERROR; status = cairo_surface_status (surface); cairo_surface_destroy (surface); - if (status != CAIRO_STATUS_NO_MEMORY) { + if (status != expected) { cairo_test_log (ctx, "Error: expected error %s, but got %s\n", cairo_status_to_string (expected), diff --git a/test/dithergradient.c b/test/dithergradient.c new file mode 100644 index 000000000..1ad1aadc7 --- /dev/null +++ b/test/dithergradient.c @@ -0,0 +1,80 @@ +/* + * Copyright © 2023 Marc Jeanmougin + * + * 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: Marc Jeanmougin + */ + +#include "cairo-test.h" + +static void +set_dither_source (cairo_t *cr, int width) +{ + cairo_pattern_t *gradient = cairo_pattern_create_linear (0, 0, width, 0); + cairo_pattern_add_color_stop_rgba (gradient, 0., 25./255, 25./255, 25./255, 1.0); + cairo_pattern_add_color_stop_rgba (gradient, 1., 45./255, 45./255, 45./255, 1.0); + + cairo_set_source (cr, gradient); + cairo_pattern_set_dither (gradient, CAIRO_DITHER_BEST); + cairo_pattern_destroy (gradient); +} + +/* History: + * + * 2023: v3 of a patch to use pixman dithering with cairo + */ +static cairo_test_status_t +draw (cairo_t *cr, int width, int height) +{ + set_dither_source (cr, width); + cairo_paint (cr); + + return CAIRO_TEST_SUCCESS; +} + +static cairo_test_status_t +draw2 (cairo_t *cr, int width, int height) +{ + cairo_set_source_rgb (cr, 0, 0, 0); + cairo_paint (cr); + + set_dither_source (cr, width); + + cairo_set_operator (cr, CAIRO_OPERATOR_ADD); + for (int i = 0; i < 5; i++) { + cairo_paint (cr); + } + + return CAIRO_TEST_SUCCESS; +} + +CAIRO_TEST (dithergradient, + "Testing the creation of a dithered gradient (in argb32)", + "gradient, dither", /* keywords */ + NULL, /* requirements */ + 400, 100, + NULL, draw) +CAIRO_TEST (dithergradient2, + "Testing the creation of a dithered gradient (in argb32)", + "gradient, dither", /* keywords */ + NULL, /* requirements */ + 400, 100, + NULL, draw2) diff --git a/test/font-variations.c b/test/font-variations.c index f278fdf2e..a1794aa57 100644 --- a/test/font-variations.c +++ b/test/font-variations.c @@ -117,15 +117,11 @@ test_variation (cairo_test_context_t *ctx, return CAIRO_TEST_FAILURE; } -#ifdef HAVE_FT_GET_VAR_DESIGN_COORDINATES ret = FT_Get_Var_Design_Coordinates (ft_face, 20, coords); if (ret != 0) { cairo_test_log (ctx, "Failed to get coords"); return CAIRO_TEST_FAILURE; } -#else - return CAIRO_TEST_UNTESTED; -#endif for (i = 0; i < ft_mm_var->num_axis; i++) { FT_Var_Axis *axis = &ft_mm_var->axis[i]; diff --git a/test/ft-variable-font.c b/test/ft-variable-font.c new file mode 100644 index 000000000..2adba66dd --- /dev/null +++ b/test/ft-variable-font.c @@ -0,0 +1,127 @@ +/* + * Copyright © 2021 Adrian Johnson + * + * 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: Adrian Johnson + */ + +#include "cairo-test.h" +#include + +#define SIZE 200 +#define HEIGHT SIZE +#define WIDTH (SIZE * 1.5) +#define FONT "Noto Sans" + +static cairo_test_status_t +set_variable_font (cairo_t *cr) +{ + cairo_font_options_t *font_options; + cairo_font_face_t *font_face; + FcPattern *pattern; + FcPattern *resolved; + FcChar8 *font_name; + FcBool variable; + FcResult result; + + pattern = FcPatternCreate (); + if (pattern == NULL) + return CAIRO_TEST_NO_MEMORY; + + FcPatternAddString (pattern, FC_FAMILY, (FcChar8 *) FONT); + FcPatternAddBool (pattern, FC_VARIABLE, TRUE); + FcConfigSubstitute (NULL, pattern, FcMatchPattern); + + font_options = cairo_font_options_create (); + cairo_get_font_options (cr, font_options); + cairo_ft_font_options_substitute (font_options, pattern); + + FcDefaultSubstitute (pattern); + resolved = FcFontMatch (NULL, pattern, &result); + if (resolved == NULL) { + FcPatternDestroy (pattern); + return CAIRO_TEST_NO_MEMORY; + } + + if (FcPatternGetString (resolved, FC_FAMILY, 0, &font_name) == FcResultMatch) { + if (strcmp((char*)font_name, FONT) != 0) { + const cairo_test_context_t *ctx = cairo_test_get_context (cr); + cairo_test_log (ctx, "Could not find %s font\n", FONT); + return CAIRO_TEST_UNTESTED; + } + } else { + return CAIRO_TEST_FAILURE; + } + if (FcPatternGetBool (resolved, FC_VARIABLE, 0, &variable) == FcResultMatch) { + if (!variable) { + const cairo_test_context_t *ctx = cairo_test_get_context (cr); + cairo_test_log (ctx, "Could not find %s font\n", FONT); + return CAIRO_TEST_UNTESTED; + } + } else { + return CAIRO_TEST_FAILURE; + } + + font_face = cairo_ft_font_face_create_for_pattern (resolved); + cairo_set_font_face (cr, font_face); + + cairo_font_options_destroy (font_options); + cairo_font_face_destroy (font_face); + FcPatternDestroy (pattern); + FcPatternDestroy (resolved); + + return CAIRO_TEST_SUCCESS; +} + +static cairo_test_status_t +draw (cairo_t *cr, int width, int height) +{ + cairo_test_status_t result; + cairo_font_options_t *font_options; + + cairo_set_source_rgb (cr, 1, 1, 1); + cairo_paint (cr); + cairo_set_source_rgb (cr, 0, 0, 0); + + result = set_variable_font (cr); + if (result != CAIRO_TEST_SUCCESS) + return result; + + font_options = cairo_font_options_create (); + cairo_font_options_set_variations (font_options, "wght=700"); + cairo_set_font_options (cr, font_options); + cairo_font_options_destroy (font_options); + + cairo_set_font_size (cr, SIZE/2); + cairo_move_to (cr, SIZE/8, 0.7 * SIZE); + + cairo_show_text(cr, "Test"); + + return CAIRO_TEST_SUCCESS; +} + +CAIRO_TEST (ft_variable_font, + "Test variable font", + "ft, font", /* keywords */ + NULL, /* requirements */ + WIDTH, HEIGHT, + NULL, draw) diff --git a/test/glyph-path.c b/test/glyph-path.c new file mode 100644 index 000000000..b61f193a1 --- /dev/null +++ b/test/glyph-path.c @@ -0,0 +1,82 @@ +/* + * Copyright © 2024 worldiety GmbH + * + * 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 + * worldiety not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. worldiety makes no representations about the + * suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * WORLDIETY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL WORLDIETY 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: Heiko Lewin + */ +#include "cairo-test.h" + +#define WIDTH 128 +#define HEIGHT 64 + + +static cairo_test_status_t +draw(cairo_t *cr, int width, int height) { + cairo_glyph_t *glyphs = NULL; + int num_glyphs = 0; + cairo_path_t *path = NULL, *path2 = NULL; + (void)width; + (void)height; + + /* black on white color */ + cairo_set_source_rgb(cr, 1., 1., 1.); + cairo_paint(cr); + cairo_set_source_rgb(cr, 0, 0, 0); + + + /* translate to some point well outside the surface */ + cairo_translate(cr, -width * 100, 0); + + /* create a simple path to illustrate the correct behaviour */ + cairo_rectangle(cr, 0, 0, width/2.0, 2); + path = cairo_copy_path(cr); + cairo_new_path(cr); + + /* create another path from glyphs - this is broken when clipping to early */ + { + cairo_set_font_size(cr, 32); + cairo_scaled_font_t *sf = cairo_get_scaled_font(cr); + cairo_scaled_font_text_to_glyphs(sf, 0, 0, "Test", 4, &glyphs, &num_glyphs, 0, 0, 0); + cairo_glyph_path(cr, glyphs, num_glyphs); + path2 = cairo_copy_path(cr); + } + + /* translate to a visible point and draw both paths */ + cairo_identity_matrix(cr); + cairo_translate(cr, width/4.0, 48); + + cairo_append_path(cr, path); + cairo_append_path(cr, path2); + cairo_fill(cr); + + cairo_path_destroy(path); + cairo_path_destroy(path2); + free(glyphs); + + return CAIRO_TEST_SUCCESS; +} + +CAIRO_TEST (glyph_path, + "Tests cairo_glyph_path", + "text, glyph, path", /* keywords */ + "target=raster", /* should be enough */ + WIDTH, HEIGHT, + NULL, draw) diff --git a/test/gradient-scale-crash.c b/test/gradient-scale-crash.c new file mode 100644 index 000000000..b265e429b --- /dev/null +++ b/test/gradient-scale-crash.c @@ -0,0 +1,55 @@ +/* + * Copyright © 2024 Koichi Akabe + * + * 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: Koichi Akabe + */ + +#include "cairo-test.h" + +static cairo_test_status_t +draw (cairo_t *cr, int width, int height) +{ + cairo_pattern_t *p = cairo_pattern_create_linear (0, 0, 0, 100); + + cairo_pattern_add_color_stop_rgb (p, 0, 1, 1, 1); + cairo_pattern_add_color_stop_rgb (p, 1, 1, 0, 0); + + cairo_matrix_t m; + cairo_matrix_init (&m, 100000, 0, 0, 100000, 0, 0); + cairo_pattern_set_matrix (p, &m); + + cairo_set_source (cr, p); + cairo_rectangle (cr, 0, 0, 100, 100); + cairo_paint (cr); + + cairo_pattern_destroy (p); + + return CAIRO_TEST_SUCCESS; +} + +CAIRO_TEST (gradient_scale_crash, + "Verify fix for https://gitlab.freedesktop.org/cairo/cairo/-/issues/789", + "gradient, pattern", /* keywords */ + NULL, /* requirements */ + 0, 0, + NULL, draw) diff --git a/test/leaks.c b/test/leaks.c new file mode 100644 index 000000000..ad7c85817 --- /dev/null +++ b/test/leaks.c @@ -0,0 +1,62 @@ +/* + * Copyright © 2023 Uli Schlachter + * + * 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: Uli Schlachter + */ + +#include "cairo-test.h" + + +// Once upon a time, _cairo_gstate_fini(), _cairo_scaled_font_fini_internal(), +// and _cairo_ft_scaled_font_fini() leaked font options. +static cairo_test_status_t +leaks_set_scaled_font (cairo_t *cr, int width, int height) +{ + cairo_font_options_t *opt; + cairo_matrix_t matrix; + cairo_scaled_font_t *font; + + cairo_matrix_init_identity (&matrix); + + opt = cairo_font_options_create (); + cairo_font_options_set_custom_palette_color (opt, 0, 1, 1, 1, 1); + + font = cairo_scaled_font_create (cairo_get_font_face (cr), &matrix, &matrix, opt); + + cairo_set_scaled_font (cr, font); + + cairo_font_options_destroy (opt); + cairo_scaled_font_destroy (font); + + // Fill the output so that the same ref image works for everying + cairo_paint (cr); + + return CAIRO_TEST_SUCCESS; +} + +CAIRO_TEST (leaks_set_scaled_font, + "Regression test for font options memory leak in cairo_set_scaled_font", + "leak", /* keywords */ + NULL, /* requirements */ + 1, 1, + NULL, leaks_set_scaled_font) diff --git a/test/meson.build b/test/meson.build index 1d76d5daa..786ac2a84 100644 --- a/test/meson.build +++ b/test/meson.build @@ -124,6 +124,7 @@ test_sources = [ 'device-offset-fractional.c', 'device-offset-positive.c', 'device-offset-scale.c', + 'dithergradient.c', 'error-setters.c', 'extend-pad.c', 'extend-pad-border.c', @@ -153,12 +154,14 @@ test_sources = [ 'font-matrix-translation.c', 'font-options.c', 'glyph-cache-pressure.c', + 'glyph-path.c', 'get-and-set.c', 'get-clip.c', 'get-group-target.c', 'get-path-extents.c', 'gradient-alpha.c', 'gradient-constant-alpha.c', + 'gradient-scale-crash.c', 'gradient-zero-stops.c', 'gradient-zero-stops-mask.c', 'group-clip.c', @@ -190,6 +193,7 @@ test_sources = [ 'large-source.c', 'large-source-roi.c', 'large-twin-antialias-mixed.c', + 'leaks.c', 'leaky-dash.c', 'leaky-dashed-rectangle.c', 'leaky-dashed-stroke.c', @@ -427,6 +431,7 @@ test_ft_font_sources = [ 'ft-text-vertical-layout-type1.c', 'ft-text-vertical-layout-type3.c', 'ft-text-antialias-none.c', + 'ft-variable-font.c', ] test_ft_svg_font_sources = [ @@ -654,9 +659,10 @@ exe = executable('cairo-test-suite', [cairo_test_suite_sources, test_sources, ca libpdiff_dep], ) +fs = import('fs') build_dir_files = ['completion.bash', 'index.html', 'testtable.js', 'view-test-results.py'] foreach file : build_dir_files - configure_file(input: file, output : file, copy: true) + fs.copyfile(file) endforeach if build_machine.system() != 'windows' @@ -691,6 +697,6 @@ test('cairo', exe, # The SVG renderer debug tools can only be built if the _cairo_debug_svg_render() # function has been exposed by defining DEBUG_SVG_RENDER -if conf.get('HAVE_FT_SVG_DOCUMENT', 0) == 1 and cc.get_define('DEBUG_SVG_RENDER') != '' +if conf.get('HAVE_FT_SVG_DOCUMENT', 0) == 1 and cc.has_define('DEBUG_SVG_RENDER') subdir('svg') endif diff --git a/test/mime-unique-id.c b/test/mime-unique-id.c index aab93164d..8d4a16133 100644 --- a/test/mime-unique-id.c +++ b/test/mime-unique-id.c @@ -79,10 +79,13 @@ * * If the size check fails, manually check the output and if the * surfaces are still embedded only once, update the expected sizes. + * + * Note: The PS2 output will embed the image more than once due to the + * lower MAX_L2_FORM_DATA for PS2 in cairo-ps-surface.c. */ -#define PS2_EXPECTED_SIZE 417510 -#define PS3_EXPECTED_SIZE 381554 -#define PDF_EXPECTED_SIZE 162923 +#define PS2_EXPECTED_SIZE 626926 +#define PS3_EXPECTED_SIZE 381555 +#define PDF_EXPECTED_SIZE 162692 #define SIZE_TOLERANCE 5000 static const char *png_filename = "romedalen.png"; diff --git a/test/pdf-structure.c b/test/pdf-structure.c index ee4efe511..a12d0305f 100644 --- a/test/pdf-structure.c +++ b/test/pdf-structure.c @@ -33,6 +33,9 @@ #ifdef HAVE_UNISTD_H #include /* __unix__ */ #endif +#if HAVE_SYS_WAIT_H +#include +#endif #include #include @@ -177,6 +180,54 @@ test_group (cairo_t *cr) cairo_tag_end (cr, "Document"); } +/* https://bugzilla.mozilla.org/show_bug.cgi?id=1896173 + * This particular combination of tags and groups resulted in a crash. + */ +static void +test_group2 (cairo_t *cr) +{ + cairo_tag_begin (cr, "H", ""); + text (cr, "Heading"); + cairo_tag_end (cr, "H"); + + cairo_push_group (cr); + + cairo_tag_begin (cr, "P", ""); + text (cr, "Para1"); + cairo_tag_end (cr, "P"); + + cairo_pop_group_to_source (cr); + cairo_paint (cr); + + cairo_set_source_rgb (cr, 0, 0, 0); + text (cr, "text"); +} + +/* Check that the fix for test_group2() works when there is a top level tag. */ +static void +test_group3 (cairo_t *cr) +{ + cairo_tag_begin (cr, "Document", NULL); + + cairo_tag_begin (cr, "H", ""); + text (cr, "Heading"); + cairo_tag_end (cr, "H"); + + cairo_push_group (cr); + + cairo_tag_begin (cr, "P", ""); + text (cr, "Para1"); + cairo_tag_end (cr, "P"); + + cairo_pop_group_to_source (cr); + cairo_paint (cr); + + cairo_set_source_rgb (cr, 0, 0, 0); + text (cr, "text"); + + cairo_tag_end (cr, "Document"); +} + static void test_group_ref (cairo_t *cr) { @@ -434,6 +485,8 @@ static const struct pdf_structure_test pdf_structure_tests[] = { { "simple", test_simple }, { "simple-ref", test_simple_ref }, { "group", test_group }, + { "group2", test_group2 }, + { "group3", test_group3 }, { "group-ref", test_group_ref }, { "repeated-group", test_repeated_group }, { "multipage-simple", test_multipage_simple }, @@ -504,7 +557,7 @@ check_pdf (cairo_test_context_t *ctx, const struct pdf_structure_test *test, con if (WEXITSTATUS (ret) == 0) result = CAIRO_TEST_SUCCESS; else if (WEXITSTATUS (ret) == 4) - result = CAIRO_TEST_UNTESTED; /* pdfinfo not found, wrong version, missing ref */ + result = CAIRO_TEST_UNTESTED; /* pdfinfo not found or wrong version */ } free (command); diff --git a/test/pdf-tagged-text.c b/test/pdf-tagged-text.c index 3883d418e..094b1c8b0 100644 --- a/test/pdf-tagged-text.c +++ b/test/pdf-tagged-text.c @@ -113,6 +113,8 @@ static const char *roman_numerals[] = { #define MAX_PARAGRAPH_LINES 20 +static const char *utf8_destination = "l\xc3\xa4nk"; + static int paragraph_num_lines; static char *paragraph_text[MAX_PARAGRAPH_LINES]; static double paragraph_height; @@ -329,20 +331,20 @@ draw_cover (cairo_surface_t *surface, cairo_t *cr) cairo_select_font_face (cr, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); cairo_set_font_size(cr, 16); - cairo_move_to (cr, PAGE_WIDTH/3, PAGE_HEIGHT/3); + cairo_move_to (cr, PAGE_WIDTH/3, 0.15*PAGE_HEIGHT); cairo_tag_begin (cr, "Span", NULL); cairo_show_text (cr, "PDF Features Test"); cairo_tag_end (cr, "Span"); /* Test URL link using "rect" attribute. The entire rectangle surrounding the URL should be a clickable link. */ - cairo_move_to (cr, PAGE_WIDTH/3, 2*PAGE_HEIGHT/3); + cairo_move_to (cr, PAGE_WIDTH/3, 0.2*PAGE_HEIGHT); cairo_select_font_face (cr, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_set_font_size(cr, TEXT_SIZE); cairo_set_source_rgb (cr, 0, 0, 1); cairo_show_text (cr, cairo_url); cairo_text_extents (cr, cairo_url, &text_extents); url_box.x = PAGE_WIDTH/3 - url_box_margin; - url_box.y = 2*PAGE_HEIGHT/3 - url_box_margin; + url_box.y = 0.2*PAGE_HEIGHT - url_box_margin; url_box.width = text_extents.width + 2*url_box_margin; url_box.height = -text_extents.height + 2*url_box_margin; cairo_rectangle(cr, url_box.x, url_box.y, url_box.width, url_box.height); @@ -355,28 +357,52 @@ draw_cover (cairo_surface_t *surface, cairo_t *cr) /* Create link to not yet emmited page number */ cairo_tag_begin (cr, CAIRO_TAG_LINK, "page=5"); - cairo_move_to (cr, PAGE_WIDTH/3, 4*PAGE_HEIGHT/5); + cairo_move_to (cr, PAGE_WIDTH/3, 0.25*PAGE_HEIGHT); cairo_show_text (cr, "link to page 5"); cairo_tag_end (cr, CAIRO_TAG_LINK); /* Create link to not yet emmited destination */ cairo_tag_begin (cr, CAIRO_TAG_LINK, "dest='Section 3.3'"); - cairo_move_to (cr, PAGE_WIDTH/3, 4.2*PAGE_HEIGHT/5); + cairo_move_to (cr, PAGE_WIDTH/3, 0.3*PAGE_HEIGHT); cairo_show_text (cr, "link to page section 3.3"); cairo_tag_end (cr, CAIRO_TAG_LINK); /* Create link to external file */ + cairo_move_to (cr, PAGE_WIDTH/3, 0.35*PAGE_HEIGHT); cairo_tag_begin (cr, CAIRO_TAG_LINK, "file='foo.pdf' page=1"); - cairo_move_to (cr, PAGE_WIDTH/3, 4.4*PAGE_HEIGHT/5); cairo_show_text (cr, "link file 'foo.pdf'"); cairo_tag_end (cr, CAIRO_TAG_LINK); + /* Create link to missing dest */ + cairo_move_to (cr, PAGE_WIDTH/3, 0.4*PAGE_HEIGHT); + cairo_tag_begin (cr, CAIRO_TAG_LINK, "dest='I don\\'t exist'"); + cairo_show_text (cr, "link to missing dest"); + cairo_tag_end (cr, CAIRO_TAG_LINK); + + /* Create link to missing dest with URI fallback*/ + cairo_move_to (cr, PAGE_WIDTH/3, 0.45*PAGE_HEIGHT); + xasprintf(&attrib, "dest='I also don\\'t exist' uri='%s'", cairo_url); + cairo_tag_begin (cr, CAIRO_TAG_LINK, attrib); + cairo_show_text (cr, "link to missing dest with uri fallback"); + cairo_tag_end (cr, CAIRO_TAG_LINK); + free (attrib); + + /* Create link to utf8 dest */ + cairo_move_to (cr, PAGE_WIDTH/3, 0.5*PAGE_HEIGHT); + xasprintf(&attrib, "dest='%s'", utf8_destination); + cairo_tag_begin (cr, CAIRO_TAG_LINK, attrib); + cairo_show_text (cr, "link to utf8 dest"); + cairo_tag_end (cr, CAIRO_TAG_LINK); + free (attrib); + draw_page_num (surface, cr, "cover", 0); } static void create_document (cairo_surface_t *surface, cairo_t *cr) { + char *attrib; + layout_paragraph (cr); cairo_pdf_surface_set_thumbnail_size (surface, PAGE_WIDTH/10, PAGE_HEIGHT/10); @@ -491,6 +517,14 @@ create_document (cairo_surface_t *surface, cairo_t *cr) cairo_show_text (cr, "link to page 3"); cairo_tag_end (cr, CAIRO_TAG_LINK); + /* Create utf8 dest */ + cairo_move_to (cr, PAGE_WIDTH/3, 4*PAGE_HEIGHT/5); + xasprintf(&attrib, "name='%s'", utf8_destination); + cairo_tag_begin (cr, CAIRO_TAG_DEST, attrib); + cairo_show_text (cr, utf8_destination); + cairo_tag_end (cr, CAIRO_TAG_DEST); + free (attrib); + cairo_tag_end (cr, "Document"); } diff --git a/test/reference/a1-image-sample.gl.xfail.png b/test/reference/a1-image-sample.gl.xfail.png deleted file mode 100644 index 384ba4a04..000000000 Binary files a/test/reference/a1-image-sample.gl.xfail.png and /dev/null differ diff --git a/test/reference/alpha-similar.gl.argb32.xfail.png b/test/reference/alpha-similar.gl.argb32.xfail.png deleted file mode 100644 index 579aae131..000000000 Binary files a/test/reference/alpha-similar.gl.argb32.xfail.png and /dev/null differ diff --git a/test/reference/alpha-similar.gl.rgb24.xfail.png b/test/reference/alpha-similar.gl.rgb24.xfail.png deleted file mode 100644 index 86366d26f..000000000 Binary files a/test/reference/alpha-similar.gl.rgb24.xfail.png and /dev/null differ diff --git a/test/reference/big-line.ps.ref.png b/test/reference/big-line.ps.ref.png index b5b227f8f..f498a8ab4 100644 Binary files a/test/reference/big-line.ps.ref.png and b/test/reference/big-line.ps.ref.png differ diff --git a/test/reference/bug-51910.quartz.ref.png b/test/reference/bug-51910.quartz.ref.png index cc900e68c..f38b99391 100644 Binary files a/test/reference/bug-51910.quartz.ref.png and b/test/reference/bug-51910.quartz.ref.png differ diff --git a/test/reference/bug-seams.quartz.xfail.png b/test/reference/bug-seams.quartz.xfail.png index 25c98b36a..0250ef5dd 100644 Binary files a/test/reference/bug-seams.quartz.xfail.png and b/test/reference/bug-seams.quartz.xfail.png differ diff --git a/test/reference/bug-source-cu.ps.argb32.ref.png b/test/reference/bug-source-cu.ps.ref.png similarity index 74% rename from test/reference/bug-source-cu.ps.argb32.ref.png rename to test/reference/bug-source-cu.ps.ref.png index ca0fdd934..51bcb3eca 100644 Binary files a/test/reference/bug-source-cu.ps.argb32.ref.png and b/test/reference/bug-source-cu.ps.ref.png differ diff --git a/test/reference/bug-source-cu.ps.rgb24.ref.png b/test/reference/bug-source-cu.ps.rgb24.ref.png deleted file mode 100644 index 5caf13915..000000000 Binary files a/test/reference/bug-source-cu.ps.rgb24.ref.png and /dev/null differ diff --git a/test/reference/clip-disjoint-quad.ps.ref.png b/test/reference/clip-disjoint-quad.ps.ref.png index d7c2621a4..411f8195a 100644 Binary files a/test/reference/clip-disjoint-quad.ps.ref.png and b/test/reference/clip-disjoint-quad.ps.ref.png differ diff --git a/test/reference/clip-fill-rule-pixel-aligned.ps.rgb24.ref.png b/test/reference/clip-fill-rule-pixel-aligned.ps.rgb24.ref.png index 01760134b..3ba525475 100644 Binary files a/test/reference/clip-fill-rule-pixel-aligned.ps.rgb24.ref.png and b/test/reference/clip-fill-rule-pixel-aligned.ps.rgb24.ref.png differ diff --git a/test/reference/clip-operator.gl.argb32.ref.png b/test/reference/clip-operator.gl.argb32.ref.png deleted file mode 100644 index 92d8b755c..000000000 Binary files a/test/reference/clip-operator.gl.argb32.ref.png and /dev/null differ diff --git a/test/reference/clip-rectilinear.ps.ref.png b/test/reference/clip-rectilinear.ps.ref.png index 06a924069..575709ab7 100644 Binary files a/test/reference/clip-rectilinear.ps.ref.png and b/test/reference/clip-rectilinear.ps.ref.png differ diff --git a/test/reference/coverage-intersecting-quads.xlib.xfail.png b/test/reference/coverage-intersecting-quads.xlib.xfail.png index d6b8c2ef2..9e8806b9d 100644 Binary files a/test/reference/coverage-intersecting-quads.xlib.xfail.png and b/test/reference/coverage-intersecting-quads.xlib.xfail.png differ diff --git a/test/reference/coverage-intersecting-triangles.image.xfail.png b/test/reference/coverage-intersecting-triangles.image.xfail.png index c0290e492..f67ccd500 100644 Binary files a/test/reference/coverage-intersecting-triangles.image.xfail.png and b/test/reference/coverage-intersecting-triangles.image.xfail.png differ diff --git a/test/reference/coverage-intersecting-triangles.xlib.xfail.png b/test/reference/coverage-intersecting-triangles.xlib.xfail.png index e64cd4741..cf492c541 100644 Binary files a/test/reference/coverage-intersecting-triangles.xlib.xfail.png and b/test/reference/coverage-intersecting-triangles.xlib.xfail.png differ diff --git a/test/reference/coverage-rectangles.xlib.xfail.png b/test/reference/coverage-rectangles.xlib.xfail.png index 622c2d75e..4ad7ec5d2 100644 Binary files a/test/reference/coverage-rectangles.xlib.xfail.png and b/test/reference/coverage-rectangles.xlib.xfail.png differ diff --git a/test/reference/coverage-row-triangles.xlib.xfail.png b/test/reference/coverage-row-triangles.xlib.xfail.png index f8582fbb9..c55db811f 100644 Binary files a/test/reference/coverage-row-triangles.xlib.xfail.png and b/test/reference/coverage-row-triangles.xlib.xfail.png differ diff --git a/test/reference/coverage-triangles.image.ref.png b/test/reference/coverage-triangles.image.ref.png new file mode 100644 index 000000000..2094a6dda Binary files /dev/null and b/test/reference/coverage-triangles.image.ref.png differ diff --git a/test/reference/coverage-triangles.recording.ref.png b/test/reference/coverage-triangles.recording.ref.png new file mode 100644 index 000000000..2094a6dda Binary files /dev/null and b/test/reference/coverage-triangles.recording.ref.png differ diff --git a/test/reference/coverage-triangles.script.ref.png b/test/reference/coverage-triangles.script.ref.png new file mode 100644 index 000000000..2094a6dda Binary files /dev/null and b/test/reference/coverage-triangles.script.ref.png differ diff --git a/test/reference/coverage-triangles.xcb-fallback.rgb24.xfail.png b/test/reference/coverage-triangles.xcb-fallback.rgb24.xfail.png new file mode 100644 index 000000000..2094a6dda Binary files /dev/null and b/test/reference/coverage-triangles.xcb-fallback.rgb24.xfail.png differ diff --git a/test/reference/coverage-triangles.xcb-render-0_0.xfail.png b/test/reference/coverage-triangles.xcb-render-0_0.xfail.png new file mode 100644 index 000000000..2094a6dda Binary files /dev/null and b/test/reference/coverage-triangles.xcb-render-0_0.xfail.png differ diff --git a/test/reference/coverage-triangles.xfail.png b/test/reference/coverage-triangles.xfail.png deleted file mode 100644 index dea5983ae..000000000 Binary files a/test/reference/coverage-triangles.xfail.png and /dev/null differ diff --git a/test/reference/coverage-triangles.xlib-render-0_0.rgb24.ref.png b/test/reference/coverage-triangles.xlib-render-0_0.rgb24.ref.png new file mode 100644 index 000000000..2094a6dda Binary files /dev/null and b/test/reference/coverage-triangles.xlib-render-0_0.rgb24.ref.png differ diff --git a/test/reference/coverage-triangles.xlib-render.rgb24.xfail.png b/test/reference/coverage-triangles.xlib-render.rgb24.xfail.png new file mode 100644 index 000000000..2094a6dda Binary files /dev/null and b/test/reference/coverage-triangles.xlib-render.rgb24.xfail.png differ diff --git a/test/reference/coverage-triangles.xlib.xfail.png b/test/reference/coverage-triangles.xlib.xfail.png index 133fd3384..aad003434 100644 Binary files a/test/reference/coverage-triangles.xlib.xfail.png and b/test/reference/coverage-triangles.xlib.xfail.png differ diff --git a/test/reference/dash-caps-joins.quartz.xfail.png b/test/reference/dash-caps-joins.quartz.xfail.png index cd9fe93ba..fb3df5984 100644 Binary files a/test/reference/dash-caps-joins.quartz.xfail.png and b/test/reference/dash-caps-joins.quartz.xfail.png differ diff --git a/test/reference/dash-state.quartz.xfail.png b/test/reference/dash-state.quartz.xfail.png index ef38975ca..e4a77dc5f 100644 Binary files a/test/reference/dash-state.quartz.xfail.png and b/test/reference/dash-state.quartz.xfail.png differ diff --git a/test/reference/dash-zero-length.quartz.rgb24.xfail.png b/test/reference/dash-zero-length.quartz.rgb24.xfail.png index 68802c584..8b531ff7e 100644 Binary files a/test/reference/dash-zero-length.quartz.rgb24.xfail.png and b/test/reference/dash-zero-length.quartz.rgb24.xfail.png differ diff --git a/test/reference/device-offset-fractional.gl.xfail.png b/test/reference/device-offset-fractional.gl.xfail.png deleted file mode 100644 index 96b0a6a62..000000000 Binary files a/test/reference/device-offset-fractional.gl.xfail.png and /dev/null differ diff --git a/test/reference/dithergradient.image.argb32.ref.png b/test/reference/dithergradient.image.argb32.ref.png new file mode 100644 index 000000000..f67d369f0 Binary files /dev/null and b/test/reference/dithergradient.image.argb32.ref.png differ diff --git a/test/reference/dithergradient.image.rgb24.ref.png b/test/reference/dithergradient.image.rgb24.ref.png new file mode 100644 index 000000000..f67d369f0 Binary files /dev/null and b/test/reference/dithergradient.image.rgb24.ref.png differ diff --git a/test/reference/dithergradient.image16.rgb24.ref.png b/test/reference/dithergradient.image16.rgb24.ref.png new file mode 100644 index 000000000..91c9f5e2d Binary files /dev/null and b/test/reference/dithergradient.image16.rgb24.ref.png differ diff --git a/test/reference/egl-surface-source.base.argb32.ref.png b/test/reference/egl-surface-source.base.argb32.ref.png deleted file mode 100644 index 018297208..000000000 Binary files a/test/reference/egl-surface-source.base.argb32.ref.png and /dev/null differ diff --git a/test/reference/egl-surface-source.base.rgb24.ref.png b/test/reference/egl-surface-source.base.rgb24.ref.png deleted file mode 100644 index 0d68a82cc..000000000 Binary files a/test/reference/egl-surface-source.base.rgb24.ref.png and /dev/null differ diff --git a/test/reference/egl-surface-source.image16.ref.png b/test/reference/egl-surface-source.image16.ref.png deleted file mode 100644 index 2a7460e28..000000000 Binary files a/test/reference/egl-surface-source.image16.ref.png and /dev/null differ diff --git a/test/reference/egl-surface-source.ref.png b/test/reference/egl-surface-source.ref.png deleted file mode 100644 index 018297208..000000000 Binary files a/test/reference/egl-surface-source.ref.png and /dev/null differ diff --git a/test/reference/extended-blend-alpha-mask.argb32.ref.png b/test/reference/extended-blend-alpha-mask.argb32.ref.png index 13df56ffa..1b0eaf0cd 100644 Binary files a/test/reference/extended-blend-alpha-mask.argb32.ref.png and b/test/reference/extended-blend-alpha-mask.argb32.ref.png differ diff --git a/test/reference/extended-blend-alpha.quartz.rgb24.ref.png b/test/reference/extended-blend-alpha.quartz.rgb24.ref.png index 1b3dae712..f749e062a 100644 Binary files a/test/reference/extended-blend-alpha.quartz.rgb24.ref.png and b/test/reference/extended-blend-alpha.quartz.rgb24.ref.png differ diff --git a/test/reference/extended-blend-solid-alpha.quartz.rgb24.ref.png b/test/reference/extended-blend-solid-alpha.quartz.rgb24.ref.png index 1b3dae712..f749e062a 100644 Binary files a/test/reference/extended-blend-solid-alpha.quartz.rgb24.ref.png and b/test/reference/extended-blend-solid-alpha.quartz.rgb24.ref.png differ diff --git a/test/reference/filter-bilinear-extents.quartz.argb32.xfail.png b/test/reference/filter-bilinear-extents.quartz.argb32.xfail.png new file mode 100644 index 000000000..d39ff8311 Binary files /dev/null and b/test/reference/filter-bilinear-extents.quartz.argb32.xfail.png differ diff --git a/test/reference/filter-bilinear-extents.quartz.rgb24.xfail.png b/test/reference/filter-bilinear-extents.quartz.rgb24.xfail.png new file mode 100644 index 000000000..e4f8c9545 Binary files /dev/null and b/test/reference/filter-bilinear-extents.quartz.rgb24.xfail.png differ diff --git a/test/reference/filter-bilinear-extents.quartz.xfail.png b/test/reference/filter-bilinear-extents.quartz.xfail.png deleted file mode 100644 index 312ee802d..000000000 Binary files a/test/reference/filter-bilinear-extents.quartz.xfail.png and /dev/null differ diff --git a/test/reference/filter-nearest-offset.gl.xfail.png b/test/reference/filter-nearest-offset.gl.xfail.png deleted file mode 100644 index a777e7cc0..000000000 Binary files a/test/reference/filter-nearest-offset.gl.xfail.png and /dev/null differ diff --git a/test/reference/filter-nearest-transformed.gl.xfail.png b/test/reference/filter-nearest-transformed.gl.xfail.png deleted file mode 100644 index ba8170b0b..000000000 Binary files a/test/reference/filter-nearest-transformed.gl.xfail.png and /dev/null differ diff --git a/test/reference/finer-grained-fallbacks.gl.argb32.ref.png b/test/reference/finer-grained-fallbacks.gl.argb32.ref.png deleted file mode 100644 index 69ec48776..000000000 Binary files a/test/reference/finer-grained-fallbacks.gl.argb32.ref.png and /dev/null differ diff --git a/test/reference/ft-color-font.image16.ref.png b/test/reference/ft-color-font.image16.ref.png index 43b39dc37..f428cc065 100644 Binary files a/test/reference/ft-color-font.image16.ref.png and b/test/reference/ft-color-font.image16.ref.png differ diff --git a/test/reference/ft-color-font.ref.png b/test/reference/ft-color-font.ref.png index 9ccb673f7..d500fc026 100644 Binary files a/test/reference/ft-color-font.ref.png and b/test/reference/ft-color-font.ref.png differ diff --git a/test/reference/ft-color-font.script.ref.png b/test/reference/ft-color-font.script.ref.png deleted file mode 100644 index 15c054e19..000000000 Binary files a/test/reference/ft-color-font.script.ref.png and /dev/null differ diff --git a/test/reference/ft-color-font.script.xfail.png b/test/reference/ft-color-font.script.xfail.png index 238827723..6ec7a984e 100644 Binary files a/test/reference/ft-color-font.script.xfail.png and b/test/reference/ft-color-font.script.xfail.png differ diff --git a/test/reference/ft-variable-font.image16.ref.png b/test/reference/ft-variable-font.image16.ref.png new file mode 100644 index 000000000..94d4d63c4 Binary files /dev/null and b/test/reference/ft-variable-font.image16.ref.png differ diff --git a/test/reference/ft-variable-font.pdf.ref.png b/test/reference/ft-variable-font.pdf.ref.png new file mode 100644 index 000000000..f782a8ee4 Binary files /dev/null and b/test/reference/ft-variable-font.pdf.ref.png differ diff --git a/test/reference/ft-variable-font.ps.ref.png b/test/reference/ft-variable-font.ps.ref.png new file mode 100644 index 000000000..1e1fdf249 Binary files /dev/null and b/test/reference/ft-variable-font.ps.ref.png differ diff --git a/test/reference/ft-variable-font.ref.png b/test/reference/ft-variable-font.ref.png new file mode 100644 index 000000000..49050251a Binary files /dev/null and b/test/reference/ft-variable-font.ref.png differ diff --git a/test/reference/ft-variable-font.script.xfail.png b/test/reference/ft-variable-font.script.xfail.png new file mode 100644 index 000000000..8463a4a38 Binary files /dev/null and b/test/reference/ft-variable-font.script.xfail.png differ diff --git a/test/reference/ft-variable-font.svg.ref.png b/test/reference/ft-variable-font.svg.ref.png new file mode 100644 index 000000000..eeb99d7c9 Binary files /dev/null and b/test/reference/ft-variable-font.svg.ref.png differ diff --git a/test/reference/gl-surface-source.base.argb32.ref.png b/test/reference/gl-surface-source.base.argb32.ref.png deleted file mode 100644 index 018297208..000000000 Binary files a/test/reference/gl-surface-source.base.argb32.ref.png and /dev/null differ diff --git a/test/reference/gl-surface-source.base.rgb24.ref.png b/test/reference/gl-surface-source.base.rgb24.ref.png deleted file mode 100644 index 0d68a82cc..000000000 Binary files a/test/reference/gl-surface-source.base.rgb24.ref.png and /dev/null differ diff --git a/test/reference/gl-surface-source.image16.ref.png b/test/reference/gl-surface-source.image16.ref.png deleted file mode 100644 index 2a7460e28..000000000 Binary files a/test/reference/gl-surface-source.image16.ref.png and /dev/null differ diff --git a/test/reference/gl-surface-source.ref.png b/test/reference/gl-surface-source.ref.png deleted file mode 100644 index 018297208..000000000 Binary files a/test/reference/gl-surface-source.ref.png and /dev/null differ diff --git a/test/reference/glyph-path.image.argb32.ref.png b/test/reference/glyph-path.image.argb32.ref.png new file mode 100644 index 000000000..bf61b6581 Binary files /dev/null and b/test/reference/glyph-path.image.argb32.ref.png differ diff --git a/test/reference/glyph-path.image.rgb24.ref.png b/test/reference/glyph-path.image.rgb24.ref.png new file mode 100644 index 000000000..bf61b6581 Binary files /dev/null and b/test/reference/glyph-path.image.rgb24.ref.png differ diff --git a/test/reference/glyph-path.image16.rgb24.ref.png b/test/reference/glyph-path.image16.rgb24.ref.png new file mode 100644 index 000000000..be94f8463 Binary files /dev/null and b/test/reference/glyph-path.image16.rgb24.ref.png differ diff --git a/test/reference/implicit-close.ps.ref.png b/test/reference/implicit-close.ps.ref.png index cb84de031..66baf2480 100644 Binary files a/test/reference/implicit-close.ps.ref.png and b/test/reference/implicit-close.ps.ref.png differ diff --git a/test/reference/leaks-set-scaled-font.ref.png b/test/reference/leaks-set-scaled-font.ref.png new file mode 100644 index 000000000..7d5589c1d Binary files /dev/null and b/test/reference/leaks-set-scaled-font.ref.png differ diff --git a/test/reference/line-width-large-overlap-dashed.quartz.xfail.png b/test/reference/line-width-large-overlap-dashed.quartz.xfail.png index 78dbe5976..b8afa547e 100644 Binary files a/test/reference/line-width-large-overlap-dashed.quartz.xfail.png and b/test/reference/line-width-large-overlap-dashed.quartz.xfail.png differ diff --git a/test/reference/line-width-large-overlap-rotated.ps.ref.png b/test/reference/line-width-large-overlap-rotated.ps.ref.png index 3d500d9df..5bca185a9 100644 Binary files a/test/reference/line-width-large-overlap-rotated.ps.ref.png and b/test/reference/line-width-large-overlap-rotated.ps.ref.png differ diff --git a/test/reference/line-width-large-overlap.base.argb32.ref.png b/test/reference/line-width-large-overlap.base.argb32.ref.png deleted file mode 100644 index 3c3464bed..000000000 Binary files a/test/reference/line-width-large-overlap.base.argb32.ref.png and /dev/null differ diff --git a/test/reference/line-width-large-overlap.base.rgb24.ref.png b/test/reference/line-width-large-overlap.base.rgb24.ref.png deleted file mode 100644 index 3c3464bed..000000000 Binary files a/test/reference/line-width-large-overlap.base.rgb24.ref.png and /dev/null differ diff --git a/test/reference/line-width-large-overlap.ps.ref.png b/test/reference/line-width-large-overlap.ps.ref.png deleted file mode 100644 index 89092b9cb..000000000 Binary files a/test/reference/line-width-large-overlap.ps.ref.png and /dev/null differ diff --git a/test/reference/line-width-overlap-dashed.quartz.xfail.png b/test/reference/line-width-overlap-dashed.quartz.xfail.png index ce8ff7bc9..0e9c37412 100644 Binary files a/test/reference/line-width-overlap-dashed.quartz.xfail.png and b/test/reference/line-width-overlap-dashed.quartz.xfail.png differ diff --git a/test/reference/linear-gradient-one-stop.ps.rgb24.ref.png b/test/reference/linear-gradient-one-stop.ps.rgb24.ref.png index d54bba273..efc12ee71 100644 Binary files a/test/reference/linear-gradient-one-stop.ps.rgb24.ref.png and b/test/reference/linear-gradient-one-stop.ps.rgb24.ref.png differ diff --git a/test/reference/long-lines.ps.ref.png b/test/reference/long-lines.ps.ref.png index 79ae24cf5..e2ffa14d8 100644 Binary files a/test/reference/long-lines.ps.ref.png and b/test/reference/long-lines.ps.ref.png differ diff --git a/test/reference/long-lines.ps.xfail.png b/test/reference/long-lines.ps.xfail.png deleted file mode 100644 index 766efb75b..000000000 Binary files a/test/reference/long-lines.ps.xfail.png and /dev/null differ diff --git a/test/reference/mask-alpha.quartz.argb32.ref.png b/test/reference/mask-alpha.quartz.argb32.ref.png index a7bfbb2a8..56f27d100 100644 Binary files a/test/reference/mask-alpha.quartz.argb32.ref.png and b/test/reference/mask-alpha.quartz.argb32.ref.png differ diff --git a/test/reference/mask-alpha.quartz.rgb24.ref.png b/test/reference/mask-alpha.quartz.rgb24.ref.png deleted file mode 100644 index d4cc59c83..000000000 Binary files a/test/reference/mask-alpha.quartz.rgb24.ref.png and /dev/null differ diff --git a/test/reference/mask-glyphs.gl.ref.png b/test/reference/mask-glyphs.gl.ref.png deleted file mode 100644 index d3410976f..000000000 Binary files a/test/reference/mask-glyphs.gl.ref.png and /dev/null differ diff --git a/test/reference/mask.quartz.argb32.ref.png b/test/reference/mask.quartz.argb32.ref.png index ab800daf7..b173221ed 100644 Binary files a/test/reference/mask.quartz.argb32.ref.png and b/test/reference/mask.quartz.argb32.ref.png differ diff --git a/test/reference/operator-clear.quartz.argb32.ref.png b/test/reference/operator-clear.quartz.argb32.ref.png index a76ebfc82..fb85d2610 100644 Binary files a/test/reference/operator-clear.quartz.argb32.ref.png and b/test/reference/operator-clear.quartz.argb32.ref.png differ diff --git a/test/reference/operator-clear.quartz.rgb24.ref.png b/test/reference/operator-clear.quartz.rgb24.ref.png index 7b44e219c..1b016a9c2 100644 Binary files a/test/reference/operator-clear.quartz.rgb24.ref.png and b/test/reference/operator-clear.quartz.rgb24.ref.png differ diff --git a/test/reference/operator-source.quartz.argb32.ref.png b/test/reference/operator-source.quartz.argb32.ref.png index 8d4f80dae..ac1afbaa9 100644 Binary files a/test/reference/operator-source.quartz.argb32.ref.png and b/test/reference/operator-source.quartz.argb32.ref.png differ diff --git a/test/reference/partial-clip-text-bottom.ps.ref.png b/test/reference/partial-clip-text-bottom.ps.ref.png index 026bb421a..d4d82ddee 100644 Binary files a/test/reference/partial-clip-text-bottom.ps.ref.png and b/test/reference/partial-clip-text-bottom.ps.ref.png differ diff --git a/test/reference/partial-clip-text-left.ps.ref.png b/test/reference/partial-clip-text-left.ps.ref.png index 5c9b0fe36..7387e382e 100644 Binary files a/test/reference/partial-clip-text-left.ps.ref.png and b/test/reference/partial-clip-text-left.ps.ref.png differ diff --git a/test/reference/pdf-operators-text.script.xfail.png b/test/reference/pdf-operators-text.script.xfail.png index ae4df9932..62050a832 100644 Binary files a/test/reference/pdf-operators-text.script.xfail.png and b/test/reference/pdf-operators-text.script.xfail.png differ diff --git a/test/reference/pdf-structure-group2.ref.txt b/test/reference/pdf-structure-group2.ref.txt new file mode 100644 index 000000000..f15c0bc24 --- /dev/null +++ b/test/reference/pdf-structure-group2.ref.txt @@ -0,0 +1,4 @@ +H (block) + "Heading" +P (block) + "Para1" diff --git a/test/reference/pdf-structure-group3.ref.txt b/test/reference/pdf-structure-group3.ref.txt new file mode 100644 index 000000000..9db4d26d2 --- /dev/null +++ b/test/reference/pdf-structure-group3.ref.txt @@ -0,0 +1,6 @@ +Document + H (block) + "Heading" + P (block) + "Para1" + "text" diff --git a/test/reference/pthread-same-source.quartz.ref.png b/test/reference/pthread-same-source.quartz.ref.png index 2cd620f43..822b6e39e 100644 Binary files a/test/reference/pthread-same-source.quartz.ref.png and b/test/reference/pthread-same-source.quartz.ref.png differ diff --git a/test/reference/radial-gradient-one-stop.quartz.ref.png b/test/reference/radial-gradient-one-stop.quartz.ref.png index cf37c2f48..dada71735 100644 Binary files a/test/reference/radial-gradient-one-stop.quartz.ref.png and b/test/reference/radial-gradient-one-stop.quartz.ref.png differ diff --git a/test/reference/random-clip.quartz.ref.png b/test/reference/random-clip.quartz.ref.png index aa617d675..b4a493461 100644 Binary files a/test/reference/random-clip.quartz.ref.png and b/test/reference/random-clip.quartz.ref.png differ diff --git a/test/reference/record-replay-extend-repeat.svg.argb32.ref.png b/test/reference/record-replay-extend-repeat.svg.argb32.ref.png new file mode 100644 index 000000000..40a697d07 Binary files /dev/null and b/test/reference/record-replay-extend-repeat.svg.argb32.ref.png differ diff --git a/test/reference/record-replay-extend-repeat.svg.ref.png b/test/reference/record-replay-extend-repeat.svg.ref.png deleted file mode 100644 index 5e0746b39..000000000 Binary files a/test/reference/record-replay-extend-repeat.svg.ref.png and /dev/null differ diff --git a/test/reference/record-replay-extend-repeat.svg.rgb24.ref.png b/test/reference/record-replay-extend-repeat.svg.rgb24.ref.png index 3f52c58b2..025976531 100644 Binary files a/test/reference/record-replay-extend-repeat.svg.rgb24.ref.png and b/test/reference/record-replay-extend-repeat.svg.rgb24.ref.png differ diff --git a/test/reference/recording-surface-extend-none.quartz.argb32.ref.png b/test/reference/recording-surface-extend-none.quartz.argb32.ref.png index 07d737a13..59b1a194e 100644 Binary files a/test/reference/recording-surface-extend-none.quartz.argb32.ref.png and b/test/reference/recording-surface-extend-none.quartz.argb32.ref.png differ diff --git a/test/reference/recording-surface-extend-none.quartz.rgb24.ref.png b/test/reference/recording-surface-extend-none.quartz.rgb24.ref.png index 0df693529..9b1642b28 100644 Binary files a/test/reference/recording-surface-extend-none.quartz.rgb24.ref.png and b/test/reference/recording-surface-extend-none.quartz.rgb24.ref.png differ diff --git a/test/reference/recording-surface-extend-repeat.quartz.argb32.ref.png b/test/reference/recording-surface-extend-repeat.quartz.argb32.ref.png index 2f6f274de..adcdfb4fd 100644 Binary files a/test/reference/recording-surface-extend-repeat.quartz.argb32.ref.png and b/test/reference/recording-surface-extend-repeat.quartz.argb32.ref.png differ diff --git a/test/reference/recording-surface-extend-repeat.quartz.rgb24.ref.png b/test/reference/recording-surface-extend-repeat.quartz.rgb24.ref.png index a8943a706..439591038 100644 Binary files a/test/reference/recording-surface-extend-repeat.quartz.rgb24.ref.png and b/test/reference/recording-surface-extend-repeat.quartz.rgb24.ref.png differ diff --git a/test/reference/recording-surface-extend-repeat.svg.argb32.ref.png b/test/reference/recording-surface-extend-repeat.svg.argb32.ref.png new file mode 100644 index 000000000..09b04846e Binary files /dev/null and b/test/reference/recording-surface-extend-repeat.svg.argb32.ref.png differ diff --git a/test/reference/recording-surface-extend-repeat.svg.ref.png b/test/reference/recording-surface-extend-repeat.svg.ref.png deleted file mode 100644 index 2938781b5..000000000 Binary files a/test/reference/recording-surface-extend-repeat.svg.ref.png and /dev/null differ diff --git a/test/reference/recording-surface-extend-repeat.svg.rgb24.ref.png b/test/reference/recording-surface-extend-repeat.svg.rgb24.ref.png index e04fe7e2e..ec8774986 100644 Binary files a/test/reference/recording-surface-extend-repeat.svg.rgb24.ref.png and b/test/reference/recording-surface-extend-repeat.svg.rgb24.ref.png differ diff --git a/test/reference/recording-surface-over.gl.argb32.ref.png b/test/reference/recording-surface-over.gl.argb32.ref.png deleted file mode 100644 index 50e6f5ab0..000000000 Binary files a/test/reference/recording-surface-over.gl.argb32.ref.png and /dev/null differ diff --git a/test/reference/recording-surface-over.quartz.argb32.ref.png b/test/reference/recording-surface-over.quartz.argb32.ref.png index 07d737a13..59b1a194e 100644 Binary files a/test/reference/recording-surface-over.quartz.argb32.ref.png and b/test/reference/recording-surface-over.quartz.argb32.ref.png differ diff --git a/test/reference/recording-surface-over.quartz.rgb24.ref.png b/test/reference/recording-surface-over.quartz.rgb24.ref.png index 0df693529..9b1642b28 100644 Binary files a/test/reference/recording-surface-over.quartz.rgb24.ref.png and b/test/reference/recording-surface-over.quartz.rgb24.ref.png differ diff --git a/test/reference/recording-surface-source.quartz.argb32.ref.png b/test/reference/recording-surface-source.quartz.argb32.ref.png index bd5d7497b..44a9c26d5 100644 Binary files a/test/reference/recording-surface-source.quartz.argb32.ref.png and b/test/reference/recording-surface-source.quartz.argb32.ref.png differ diff --git a/test/reference/recording-surface-source.quartz.rgb24.ref.png b/test/reference/recording-surface-source.quartz.rgb24.ref.png index ddba6f3ff..cb4f6bbf9 100644 Binary files a/test/reference/recording-surface-source.quartz.rgb24.ref.png and b/test/reference/recording-surface-source.quartz.rgb24.ref.png differ diff --git a/test/reference/scale-offset-image.gl.ref.png b/test/reference/scale-offset-image.gl.ref.png deleted file mode 100644 index d2a845c5a..000000000 Binary files a/test/reference/scale-offset-image.gl.ref.png and /dev/null differ diff --git a/test/reference/scale-offset-similar.gl.ref.png b/test/reference/scale-offset-similar.gl.ref.png deleted file mode 100644 index d2a845c5a..000000000 Binary files a/test/reference/scale-offset-similar.gl.ref.png and /dev/null differ diff --git a/test/reference/self-copy-overlap.xcb.argb32.ref.png b/test/reference/self-copy-overlap.xcb.argb32.ref.png new file mode 100644 index 000000000..bf15ed94a Binary files /dev/null and b/test/reference/self-copy-overlap.xcb.argb32.ref.png differ diff --git a/test/reference/self-copy-overlap.xlib.argb32.ref.png b/test/reference/self-copy-overlap.xlib.argb32.ref.png new file mode 100644 index 000000000..bf15ed94a Binary files /dev/null and b/test/reference/self-copy-overlap.xlib.argb32.ref.png differ diff --git a/test/reference/self-copy.ps.ref.png b/test/reference/self-copy.ps.ref.png new file mode 100644 index 000000000..0031d5847 Binary files /dev/null and b/test/reference/self-copy.ps.ref.png differ diff --git a/test/reference/self-copy.ps2.ref.png b/test/reference/self-copy.ps2.ref.png deleted file mode 100644 index 0ddf4cade..000000000 Binary files a/test/reference/self-copy.ps2.ref.png and /dev/null differ diff --git a/test/reference/self-copy.ps3.ref.png b/test/reference/self-copy.ps3.ref.png deleted file mode 100644 index 0ddf4cade..000000000 Binary files a/test/reference/self-copy.ps3.ref.png and /dev/null differ diff --git a/test/reference/self-intersecting.xcb-window&.rgb24.ref.png b/test/reference/self-intersecting.xcb-window&.rgb24.ref.png new file mode 100644 index 000000000..bc31b33e7 Binary files /dev/null and b/test/reference/self-intersecting.xcb-window&.rgb24.ref.png differ diff --git a/test/reference/self-intersecting.xcb-window.rgb24.ref.png b/test/reference/self-intersecting.xcb-window.rgb24.ref.png new file mode 100644 index 000000000..bc31b33e7 Binary files /dev/null and b/test/reference/self-intersecting.xcb-window.rgb24.ref.png differ diff --git a/test/reference/self-intersecting.xcb.ref.png b/test/reference/self-intersecting.xcb.ref.png new file mode 100644 index 000000000..bc31b33e7 Binary files /dev/null and b/test/reference/self-intersecting.xcb.ref.png differ diff --git a/test/reference/self-intersecting.xlib-window.rgb24.ref.png b/test/reference/self-intersecting.xlib-window.rgb24.ref.png new file mode 100644 index 000000000..bc31b33e7 Binary files /dev/null and b/test/reference/self-intersecting.xlib-window.rgb24.ref.png differ diff --git a/test/reference/self-intersecting.xlib.ref.png b/test/reference/self-intersecting.xlib.ref.png new file mode 100644 index 000000000..bc31b33e7 Binary files /dev/null and b/test/reference/self-intersecting.xlib.ref.png differ diff --git a/test/reference/source-clip-scale.gl.ref.png b/test/reference/source-clip-scale.gl.ref.png deleted file mode 100644 index fcffbef1f..000000000 Binary files a/test/reference/source-clip-scale.gl.ref.png and /dev/null differ diff --git a/test/reference/surface-pattern-operator.quartz.argb32.ref.png b/test/reference/surface-pattern-operator.quartz.argb32.ref.png index e2a411682..413ccefcc 100644 Binary files a/test/reference/surface-pattern-operator.quartz.argb32.ref.png and b/test/reference/surface-pattern-operator.quartz.argb32.ref.png differ diff --git a/test/reference/surface-pattern-operator.quartz.rgb24.ref.png b/test/reference/surface-pattern-operator.quartz.rgb24.ref.png index 02eec1c85..7e4ef3638 100644 Binary files a/test/reference/surface-pattern-operator.quartz.rgb24.ref.png and b/test/reference/surface-pattern-operator.quartz.rgb24.ref.png differ diff --git a/test/reference/surface-pattern.quartz.xfail.png b/test/reference/surface-pattern.quartz.xfail.png index 42938f026..41ed28068 100644 Binary files a/test/reference/surface-pattern.quartz.xfail.png and b/test/reference/surface-pattern.quartz.xfail.png differ diff --git a/test/reference/text-pattern.quartz.argb32.ref.png b/test/reference/text-pattern.quartz.argb32.ref.png index b3f869b50..3964f5438 100644 Binary files a/test/reference/text-pattern.quartz.argb32.ref.png and b/test/reference/text-pattern.quartz.argb32.ref.png differ diff --git a/test/reference/text-pattern.quartz.rgb24.ref.png b/test/reference/text-pattern.quartz.rgb24.ref.png index bb50f4dff..35f28a708 100644 Binary files a/test/reference/text-pattern.quartz.rgb24.ref.png and b/test/reference/text-pattern.quartz.rgb24.ref.png differ diff --git a/test/reference/text-unhinted-metrics.xcb-render-0_0.ref.png b/test/reference/text-unhinted-metrics.xcb-render-0_0.ref.png new file mode 100644 index 000000000..baf3f96ec Binary files /dev/null and b/test/reference/text-unhinted-metrics.xcb-render-0_0.ref.png differ diff --git a/test/reference/text-unhinted-metrics.xcb-window&.rgb24.ref.png b/test/reference/text-unhinted-metrics.xcb-window&.rgb24.ref.png new file mode 100644 index 000000000..baf3f96ec Binary files /dev/null and b/test/reference/text-unhinted-metrics.xcb-window&.rgb24.ref.png differ diff --git a/test/reference/text-unhinted-metrics.xcb-window.rgb24.ref.png b/test/reference/text-unhinted-metrics.xcb-window.rgb24.ref.png new file mode 100644 index 000000000..baf3f96ec Binary files /dev/null and b/test/reference/text-unhinted-metrics.xcb-window.rgb24.ref.png differ diff --git a/test/reference/tighten-bounds.quartz.argb32.ref.png b/test/reference/tighten-bounds.quartz.argb32.ref.png index dc4aacdd8..5f9deec6e 100644 Binary files a/test/reference/tighten-bounds.quartz.argb32.ref.png and b/test/reference/tighten-bounds.quartz.argb32.ref.png differ diff --git a/test/reference/tighten-bounds.quartz.rgb24.ref.png b/test/reference/tighten-bounds.quartz.rgb24.ref.png index 8d11e0b85..0aeddcd3b 100644 Binary files a/test/reference/tighten-bounds.quartz.rgb24.ref.png and b/test/reference/tighten-bounds.quartz.rgb24.ref.png differ diff --git a/test/reference/trap-clip.quartz.argb32.ref.png b/test/reference/trap-clip.quartz.argb32.ref.png index 66a1e8afe..8bf6a5668 100644 Binary files a/test/reference/trap-clip.quartz.argb32.ref.png and b/test/reference/trap-clip.quartz.argb32.ref.png differ diff --git a/test/reference/trap-clip.quartz.rgb24.ref.png b/test/reference/trap-clip.quartz.rgb24.ref.png deleted file mode 100644 index 38e6d31df..000000000 Binary files a/test/reference/trap-clip.quartz.rgb24.ref.png and /dev/null differ diff --git a/test/reference/unbounded-operator.gl.argb32.xfail.png b/test/reference/unbounded-operator.gl.argb32.xfail.png deleted file mode 100644 index 34e32eba1..000000000 Binary files a/test/reference/unbounded-operator.gl.argb32.xfail.png and /dev/null differ diff --git a/test/reference/unbounded-operator.gl.rgb24.xfail.png b/test/reference/unbounded-operator.gl.rgb24.xfail.png deleted file mode 100644 index b91da8f08..000000000 Binary files a/test/reference/unbounded-operator.gl.rgb24.xfail.png and /dev/null differ diff --git a/test/reference/unbounded-operator.quartz.argb32.ref.png b/test/reference/unbounded-operator.quartz.argb32.ref.png index b2e99165e..040801d51 100644 Binary files a/test/reference/unbounded-operator.quartz.argb32.ref.png and b/test/reference/unbounded-operator.quartz.argb32.ref.png differ diff --git a/test/reference/unbounded-operator.quartz.rgb24.ref.png b/test/reference/unbounded-operator.quartz.rgb24.ref.png index ea41dc892..eaaaaf7ef 100644 Binary files a/test/reference/unbounded-operator.quartz.rgb24.ref.png and b/test/reference/unbounded-operator.quartz.rgb24.ref.png differ diff --git a/test/reference/user-font-color.pdf.ref.png b/test/reference/user-font-color.pdf.ref.png deleted file mode 100644 index 5221769ca..000000000 Binary files a/test/reference/user-font-color.pdf.ref.png and /dev/null differ diff --git a/test/reference/user-font-color.pdf.xfail.png b/test/reference/user-font-color.pdf.xfail.png new file mode 100644 index 000000000..e3aedeb1d Binary files /dev/null and b/test/reference/user-font-color.pdf.xfail.png differ diff --git a/test/reference/user-font-color.script.xfail.png b/test/reference/user-font-color.script.xfail.png index c74331eaf..5d5cdafdb 100644 Binary files a/test/reference/user-font-color.script.xfail.png and b/test/reference/user-font-color.script.xfail.png differ diff --git a/test/reference/user-font-mask.image16.ref.png b/test/reference/user-font-mask.image16.ref.png index 0a63ddedc..9069fc1e4 100644 Binary files a/test/reference/user-font-mask.image16.ref.png and b/test/reference/user-font-mask.image16.ref.png differ diff --git a/test/reference/user-font-subpixel.xcb-render-0_0.ref.png b/test/reference/user-font-subpixel.xcb-render-0_0.ref.png new file mode 100644 index 000000000..bf8d4ff4c Binary files /dev/null and b/test/reference/user-font-subpixel.xcb-render-0_0.ref.png differ diff --git a/test/reference/user-font-subpixel.xcb-window&.rgb24.ref.png b/test/reference/user-font-subpixel.xcb-window&.rgb24.ref.png new file mode 100644 index 000000000..bf8d4ff4c Binary files /dev/null and b/test/reference/user-font-subpixel.xcb-window&.rgb24.ref.png differ diff --git a/test/reference/user-font-subpixel.xcb-window.rgb24.ref.png b/test/reference/user-font-subpixel.xcb-window.rgb24.ref.png new file mode 100644 index 000000000..bf8d4ff4c Binary files /dev/null and b/test/reference/user-font-subpixel.xcb-window.rgb24.ref.png differ diff --git a/test/reference/user-font-subpixel.xcb.ref.png b/test/reference/user-font-subpixel.xcb.ref.png new file mode 100644 index 000000000..bf8d4ff4c Binary files /dev/null and b/test/reference/user-font-subpixel.xcb.ref.png differ diff --git a/util/README b/util/README index b75ae4336..90e1f7fab 100644 --- a/util/README +++ b/util/README @@ -3,22 +3,6 @@ Cairo Utilities There are a varieties of utilities we use with cairo. - -malloc-stats ------------- - -This is a small shared library designed to be preloaded by the -linker and its purpose is to make the malloc_stats() function -of glibc produce more useful information. - -Build by: - - make malloc-stats.so - -and use by: - - LD_PRELOAD=$(blddir)/util/libmalloc-stats.so app-to-run - cairo-trace ----------- diff --git a/util/cairo-fdr/meson.build b/util/cairo-fdr/meson.build index 001af27bc..c333bf765 100644 --- a/util/cairo-fdr/meson.build +++ b/util/cairo-fdr/meson.build @@ -5,6 +5,7 @@ cairo_fdr_sources = [ libcairofdr = library('cairo-fdr', cairo_fdr_sources, include_directories: [incbase, incsrc], dependencies: deps, + link_args: extra_link_args, install: true, - install_dir: join_paths(get_option('prefix'), get_option('libdir'), 'cairo'), + install_dir: get_option('libdir') / 'cairo', ) diff --git a/util/cairo-gobject/meson.build b/util/cairo-gobject/meson.build index 0a525b6fa..660088771 100644 --- a/util/cairo-gobject/meson.build +++ b/util/cairo-gobject/meson.build @@ -12,6 +12,9 @@ libcairogobject = library('cairo-gobject', cairo_gobject_sources, dependencies: [glib_dep, gobject_dep, libcairo_dep], soversion: cairo_version_sonum, version: cairo_libversion, + gnu_symbol_visibility: 'hidden', + c_args: ['-DCAIRO_COMPILATION'], + link_args: extra_link_args, install: true, ) diff --git a/util/cairo-script/cairo-script-file.c b/util/cairo-script/cairo-script-file.c index 7027f6027..c45cc5086 100644 --- a/util/cairo-script/cairo-script-file.c +++ b/util/cairo-script/cairo-script-file.c @@ -42,7 +42,7 @@ #include #if HAVE_LZO -#include +#include #endif #define CHUNK_SIZE 32768 diff --git a/util/cairo-script/cairo-script-interpreter.c b/util/cairo-script/cairo-script-interpreter.c index a578ec43a..e3aa3bae8 100644 --- a/util/cairo-script/cairo-script-interpreter.c +++ b/util/cairo-script/cairo-script-interpreter.c @@ -34,9 +34,10 @@ #include "config.h" -#include "cairo-script-private.h" #include "cairo.h" +#include "cairo-script-private.h" + #include #include #include @@ -635,7 +636,6 @@ cairo_script_interpreter_reference (csi_t *ctx) ctx->ref_count++; return ctx; } -slim_hidden_def (cairo_script_interpreter_reference); cairo_status_t cairo_script_interpreter_finish (csi_t *ctx) @@ -684,7 +684,6 @@ cairo_script_interpreter_destroy (csi_t *ctx) return status; } -slim_hidden_def (cairo_script_interpreter_destroy); cairo_status_t cairo_script_interpreter_translate_stream (FILE *stream, diff --git a/util/cairo-script/cairo-script-operators.c b/util/cairo-script/cairo-script-operators.c index 21fba5cc7..a5eca6ffc 100644 --- a/util/cairo-script/cairo-script-operators.c +++ b/util/cairo-script/cairo-script-operators.c @@ -60,7 +60,7 @@ #endif #if HAVE_LZO -#include +#include #endif #ifdef HAVE_MMAP diff --git a/util/cairo-script/cairo-script-private.h b/util/cairo-script/cairo-script-private.h index c60b4185c..74ede82f5 100644 --- a/util/cairo-script/cairo-script-private.h +++ b/util/cairo-script/cairo-script-private.h @@ -39,6 +39,7 @@ #include "cairo-script-interpreter.h" +#include #include #ifdef _MSC_VER @@ -97,29 +98,7 @@ #endif -#if __GNUC__ >= 3 && defined(__ELF__) && !defined(__sun) -# define slim_hidden_proto(name) slim_hidden_proto1(name, slim_hidden_int_name(name)) csi_private -# define slim_hidden_proto_no_warn(name) slim_hidden_proto1(name, slim_hidden_int_name(name)) csi_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 _csi_dummy_prototype(void) -# define slim_hidden_proto_no_warn(name) int _csi_dummy_prototype(void) -# define slim_hidden_def(name) int _csi_dummy_prototype(void) -#endif - -#if __GNUC__ >= 3 +#if defined (__GNUC__) #define csi_pure __attribute__((pure)) #define csi_const __attribute__((const)) #else @@ -127,7 +106,7 @@ #define csi_const #endif -#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__) +#if defined(__GNUC__) && defined(__OPTIMIZE__) #define _CSI_BOOLEAN_EXPR(expr) \ __extension__ ({ \ int _csi_boolean_var_; \ @@ -145,10 +124,6 @@ #endif #ifdef __GNUC__ -#ifndef offsetof -#define offsetof(type, member) \ - ((char *) &((type *) 0)->member - (char *) 0) -#endif #define csi_container_of(ptr, type, member) ({ \ const typeof(((type *) 0)->member) *mptr__ = (ptr); \ (type *) ((char *) mptr__ - offsetof (type, member)); \ @@ -158,8 +133,7 @@ (type *)((char *) (ptr) - (char *) &((type *)0)->member) #endif -/* slim_internal.h */ -#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) && defined(__ELF__) && !defined(__sun) +#if defined(__GNUC__) && defined(__ELF__) && !defined(__sun) #define csi_private_no_warn __attribute__((__visibility__("hidden"))) #elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550) #define csi_private_no_warn __hidden @@ -989,7 +963,4 @@ _csi_push_ostack_real (csi_t *ctx, csi_real_t v) return _csi_stack_push (ctx, &ctx->ostack, &obj); } -slim_hidden_proto_no_warn (cairo_script_interpreter_destroy); -slim_hidden_proto_no_warn (cairo_script_interpreter_reference); - #endif /* CAIRO_SCRIPT_PRIVATE_H */ diff --git a/util/cairo-script/cairo-script-scanner.c b/util/cairo-script/cairo-script-scanner.c index fe6512dd9..167cd7a1e 100644 --- a/util/cairo-script/cairo-script-scanner.c +++ b/util/cairo-script/cairo-script-scanner.c @@ -46,7 +46,7 @@ #include #if HAVE_LZO -#include +#include #endif #define DEBUG_SCAN 0 @@ -1559,7 +1559,7 @@ _translate_real (csi_t *ctx, { uint8_t hdr; - if (real >= INT32_MIN && real <= INT32_MAX && (int) real == real) + if ((double)real >= INT32_MIN && (double)real <= INT32_MAX && (int) real == real) return _translate_integer (ctx, real, closure); #if WORDS_BIGENDIAN diff --git a/util/cairo-script/meson.build b/util/cairo-script/meson.build index 51e0ce7cd..60cec2b6e 100644 --- a/util/cairo-script/meson.build +++ b/util/cairo-script/meson.build @@ -30,6 +30,8 @@ libcairoscript = library('cairo-script-interpreter', dependencies: deps + [libcairo_dep, lzo_dep], soversion: cairo_version_sonum, version: cairo_libversion, + c_args: ['-DCAIRO_COMPILATION'], + link_args: extra_link_args, install: true, ) diff --git a/util/cairo-sphinx/.gitignore b/util/cairo-sphinx/.gitignore deleted file mode 100644 index 56ecd5de8..000000000 --- a/util/cairo-sphinx/.gitignore +++ /dev/null @@ -1 +0,0 @@ -cairo-sphinx diff --git a/util/cairo-sphinx/fdr.c b/util/cairo-sphinx/fdr.c deleted file mode 100644 index a28251650..000000000 --- a/util/cairo-sphinx/fdr.c +++ /dev/null @@ -1,257 +0,0 @@ -/* cairo-fdr - a 'flight data recorder', a black box, for cairo - * - * Copyright © 2009 Chris Wilson - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -static void *_dlhandle = RTLD_NEXT; -#define DLCALL(name, args...) ({ \ - static typeof (&name) name##_real; \ - if (name##_real == NULL) { \ - name##_real = dlsym (_dlhandle, #name); \ - if (name##_real == NULL && _dlhandle == RTLD_NEXT) { \ - _dlhandle = dlopen ("libcairo.so", RTLD_LAZY); \ - name##_real = dlsym (_dlhandle, #name); \ - assert (name##_real != NULL); \ - } \ - } \ - (*name##_real) (args); \ -}) - -static cairo_device_t *fdr_context; -static const cairo_user_data_key_t fdr_key; - -static void -fdr_get_extents (cairo_surface_t *surface, - cairo_rectangle_t *extents) -{ - cairo_t *cr; - - cr = DLCALL (cairo_create, surface); - DLCALL (cairo_clip_extents, cr, - &extents->x, &extents->y, &extents->width, &extents->height); - DLCALL (cairo_destroy, cr); - - extents->width -= extents->x; - extents->height -= extents->y; -} - -static void -fdr_surface_destroy (void *surface) -{ - DLCALL (cairo_surface_destroy, surface); -} - -static void -fdr_surface_reference (void *surface) -{ - DLCALL (cairo_surface_reference, surface); -} - -static cairo_surface_t * -fdr_surface_get_tee (cairo_surface_t *surface) -{ - return DLCALL (cairo_surface_get_user_data, surface, &fdr_key); -} - -static cairo_surface_t * -fdr_tee_surface_index (cairo_surface_t *surface, int index) -{ - return DLCALL (cairo_tee_surface_index, surface, index); -} - -static cairo_status_t -fdr_write (void *closure, const unsigned char *data, unsigned int len) -{ - int fd = (int) (intptr_t) closure; - while (len) { - int ret = write (fd, data, len); - if (ret < 0) { - switch (errno) { - case EAGAIN: - case EINTR: - continue; - default: - return CAIRO_STATUS_WRITE_ERROR; - } - } else if (ret == 0) { - return CAIRO_STATUS_WRITE_ERROR; - } else { - data += ret; - len -= ret; - } - } - return CAIRO_STATUS_SUCCESS; -} - -cairo_t * -cairo_create (cairo_surface_t *surface) -{ - cairo_surface_t *tee; - - tee = fdr_surface_get_tee (surface); - if (tee == NULL) { - cairo_surface_t *script; - cairo_rectangle_t extents; - cairo_content_t content; - - if (fdr_context == NULL) { - const char *env = getenv ("CAIRO_SPHINX_FD"); - int fd = env ? atoi (env) : 1; - fdr_context = DLCALL (cairo_script_create_for_stream, - fdr_write, (void *) (intptr_t) fd); - } - - fdr_get_extents (surface, &extents); - content = DLCALL (cairo_surface_get_content, surface); - - tee = DLCALL (cairo_tee_surface_create, surface); - script = DLCALL (cairo_script_surface_create, - fdr_context, content, extents.width, extents.height); - DLCALL (cairo_tee_surface_add, tee, script); - - DLCALL (cairo_surface_set_user_data, surface, - &fdr_key, tee, fdr_surface_destroy); - } - - return DLCALL (cairo_create, tee); -} - -static void -fdr_remove_tee (cairo_surface_t *surface) -{ - fdr_surface_reference (surface); - DLCALL (cairo_surface_set_user_data, surface, &fdr_key, NULL, NULL); - fdr_surface_destroy (surface); -} - -void -cairo_destroy (cairo_t *cr) -{ - cairo_surface_t *tee; - - tee = DLCALL (cairo_get_target, cr); - DLCALL (cairo_destroy, cr); - - if (DLCALL (cairo_surface_get_reference_count, tee) == 1) - fdr_remove_tee (fdr_tee_surface_index (tee, 0)); -} - -void -cairo_pattern_destroy (cairo_pattern_t *pattern) -{ - if (DLCALL (cairo_pattern_get_type, pattern) == CAIRO_PATTERN_TYPE_SURFACE) { - cairo_surface_t *surface; - - if (DLCALL (cairo_pattern_get_surface, pattern, &surface) == CAIRO_STATUS_SUCCESS && - DLCALL (cairo_surface_get_type, surface) == CAIRO_SURFACE_TYPE_TEE && - DLCALL (cairo_surface_get_reference_count, surface) == 2) - { - fdr_remove_tee (fdr_tee_surface_index (surface, 0)); - } - } - - DLCALL (cairo_pattern_destroy, pattern); -} - -cairo_surface_t * -cairo_get_target (cairo_t *cr) -{ - cairo_surface_t *tee; - - tee = DLCALL (cairo_get_target, cr); - return fdr_tee_surface_index (tee, 0); -} - -cairo_surface_t * -cairo_get_group_target (cairo_t *cr) -{ - cairo_surface_t *tee; - - tee = DLCALL (cairo_get_group_target, cr); - return fdr_tee_surface_index (tee, 0); -} - -cairo_pattern_t * -cairo_pattern_create_for_surface (cairo_surface_t *surface) -{ - cairo_surface_t *tee; - - tee = fdr_surface_get_tee (surface); - if (tee != NULL) - surface = tee; - - return DLCALL (cairo_pattern_create_for_surface, surface); -} - -cairo_status_t -cairo_pattern_get_surface (cairo_pattern_t *pattern, - cairo_surface_t **surface) -{ - cairo_status_t status; - cairo_surface_t *tee; - - status = DLCALL (cairo_pattern_get_surface, pattern, surface); - if (status != CAIRO_STATUS_SUCCESS) - return status; - - tee = fdr_surface_get_tee (*surface); - if (tee != NULL) - *surface = tee; - - return CAIRO_STATUS_SUCCESS; -} - -void -cairo_set_source_surface (cairo_t *cr, - cairo_surface_t *surface, - double x, double y) -{ - cairo_surface_t *tee; - - tee = fdr_surface_get_tee (surface); - if (tee != NULL) - surface = tee; - - DLCALL (cairo_set_source_surface, cr, surface, x, y); -} - -cairo_surface_t * -cairo_surface_create_similar (cairo_surface_t *surface, - cairo_content_t content, - int width, int height) -{ - cairo_surface_t *tee; - - tee = fdr_surface_get_tee (surface); - if (tee != NULL) - surface = tee; - - return DLCALL (cairo_surface_create_similar, - surface, content, width, height); -} diff --git a/util/cairo-sphinx/meson.build b/util/cairo-sphinx/meson.build deleted file mode 100644 index 20ea04d7f..000000000 --- a/util/cairo-sphinx/meson.build +++ /dev/null @@ -1,25 +0,0 @@ -libcairo_sphinx_sources = [ - 'fdr.c', -] - -cairo_sphinx_sources = [ - 'sphinx.c', -] - -libcairosphinx = library('cairo-sphinx', libcairo_sphinx_sources, - include_directories: [incbase, incsrc], - dependencies: deps, - install: true, - install_dir: join_paths(get_option('prefix'), get_option('libdir'), 'cairo'), -) - -libdir = join_paths(get_option('prefix'), get_option('libdir')) - -cairosphinx_exe = executable('cairo-sphinx', cairo_sphinx_sources, - include_directories: [incbase], - c_args: ['-DLIBDIR="@0@"'.format(libdir)] + pthread_c_args, - dependencies: deps + [glib_dep, rt_dep, libcairo_dep, cairoboilerplate_dep, libcairoscript_dep], - link_with: [libcairosphinx], - link_args: extra_link_args, - install: true, -) diff --git a/util/cairo-sphinx/sphinx.c b/util/cairo-sphinx/sphinx.c deleted file mode 100644 index 467f26cab..000000000 --- a/util/cairo-sphinx/sphinx.c +++ /dev/null @@ -1,1559 +0,0 @@ -/* - * The intention for sphinx is for detection of rendering errors inside - * applications by simultaneously rendering on to the target device and on - * an image surface and comparing the two. If it found a discrepancy, it - * would then dump the trace that reproduces the error. (Then apply - * delta-debugging to reduce that down to a minimal trace.) - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(HAVE_POLL_H) -#include -#elif defined(HAVE_SYS_POLL_H) -#include -#else -#error No poll.h equivalent found -#endif - -#include -#include -#include -#include - -#include /* for checksumming */ - -#ifndef CAIRO_HAS_REAL_PTHREAD -# error "cairo-sphinx needs real pthreads" -#endif - -#ifndef MAP_NORESERVE -#define MAP_NORESERVE 0 -#endif - -#define DATA_SIZE (256 << 20) -#define SHM_PATH_XXX "/shmem-cairo-sphinx" - -struct client { - int sk; - const cairo_boilerplate_target_t *target; - cairo_surface_t *surface; - void *base; - - cairo_script_interpreter_t *csi; - struct context_closure { - struct context_closure *next; - unsigned long id; - cairo_t *context; - cairo_surface_t *surface; - cairo_surface_t *original; - } *contexts; - - unsigned long context_id; -}; - -struct surface_tag { - long width, height; -}; -static const cairo_user_data_key_t surface_tag; - -static int -client_socket (const char *socket_path); - -static int -writen (int fd, const void *ptr, int len) -{ -#if 1 - const uint8_t *data = ptr; - while (len) { - int ret = write (fd, data, len); - if (ret < 0) { - switch (errno) { - case EAGAIN: - case EINTR: - continue; - default: - return FALSE; - } - } else if (ret == 0) { - return FALSE; - } else { - data += ret; - len -= ret; - } - } - return TRUE; -#else - int ret = send (fd, ptr, len, 0); - return ret == len; -#endif -} - -static int -readn (int fd, void *ptr, int len) -{ -#if 0 - uint8_t *data = ptr; - while (len) { - int ret = read (fd, data, len); - if (ret < 0) { - switch (errno) { - case EAGAIN: - case EINTR: - continue; - default: - return FALSE; - } - } else if (ret == 0) { - return FALSE; - } else { - data += ret; - len -= ret; - } - } - return TRUE; -#else - int ret = recv (fd, ptr, len, MSG_WAITALL); - return ret == len; -#endif -} -static int -open_devnull_to_fd (int want_fd, int flags) -{ - int error; - int got_fd; - - close (want_fd); - - got_fd = open("/dev/null", flags | O_CREAT, 0700); - if (got_fd == -1) - return -1; - - error = dup2 (got_fd, want_fd); - close (got_fd); - - return error; -} - -static int -daemonize (void) -{ - void (*oldhup) (int); - - /* Let the parent go. */ - switch (fork ()) { - case -1: return -1; - case 0: break; - default: _exit (0); - } - - /* Become session leader. */ - if (setsid () == -1) - return -1; - - /* Refork to yield session leadership. */ - oldhup = signal (SIGHUP, SIG_IGN); - switch (fork ()) { - case -1: return -1; - case 0: break; - default: _exit (0); - } - signal (SIGHUP, oldhup); - - /* Establish stdio. */ - if (open_devnull_to_fd (0, O_RDONLY) == -1) - return -1; - if (open_devnull_to_fd (1, O_WRONLY | O_APPEND) == -1) - return -1; - if (dup2 (1, 2) == -1) - return -1; - - return 0; -} - -static int -server_socket (const char *socket_path) -{ - long flags; - struct sockaddr_un addr; - int sk; - - unlink (socket_path); - - sk = socket (PF_UNIX, SOCK_STREAM, 0); - if (sk == -1) - return -1; - - memset (&addr, 0, sizeof (addr)); - addr.sun_family = AF_UNIX; - strcpy (addr.sun_path, socket_path); - if (bind (sk, (struct sockaddr *) &addr, sizeof (addr)) == -1) { - close (sk); - return -1; - } - - flags = fcntl (sk, F_GETFL); - if (flags == -1 || fcntl (sk, F_SETFL, flags | O_NONBLOCK) == -1) { - close (sk); - return -1; - } - - if (listen (sk, 5) == -1) { - close (sk); - return -1; - } - - return sk; -} - -static int -readline (int fd, char *line, int max) -{ - int len = 0; - do { - int ret = read (fd, &line[len], 1); - if (ret <= 0) - return -1; - } while (line[len] != '\n' && ++len < max); - line[len] = '\0'; - return len; -} - -struct clients { - int count, size; - int complete; - - cairo_surface_t *recording; - unsigned long serial; - - struct client_info { - int sk; - int trace; - unsigned long image_serial; - cairo_surface_t *image; - char *name; - char *target; - char *reference; - - uint8_t *out_buf; - int out_len; - int out_size; - } *clients; - const char *shm_path; - unsigned long offset; - uint8_t *base; -}; - -static void * -clients_shm (const char *shm_path) -{ - void *base; - int fd; - - shm_unlink (shm_path); - fd = shm_open (shm_path, O_RDWR | O_EXCL | O_CREAT, 0777); - if (fd == -1) - return MAP_FAILED; - - if (ftruncate (fd, DATA_SIZE) == -1) { - close (fd); - return MAP_FAILED; - } - - base = mmap (NULL, DATA_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - close (fd); - - return base; -} - -static int -clients_init (struct clients *clients) -{ - clients->count = 0; - clients->complete = 0; - clients->size = 4; - clients->clients = xmalloc (clients->size * sizeof (struct client_info)); - - clients->shm_path = SHM_PATH_XXX; - clients->base = clients_shm (clients->shm_path); - if (clients->base == MAP_FAILED) - return -1; - clients->offset = 0; - - clients->recording = NULL; - clients->serial = 0; - - return 0; -} - -static void -clients_add_command (struct clients *clients, int fd, char *info) -{ - struct client_info *c; - char buf[1024]; - int len; - char *str; - - if (clients->count == clients->size) { - clients->size *= 2; - clients->clients = xrealloc (clients->clients, - clients->size * sizeof (struct client_info)); - } - - c = &clients->clients[clients->count++]; - c->sk = fd; - c->trace = -1; - c->image_serial = 0; - c->image = NULL; - c->name = c->target = c->reference = NULL; - - c->out_size = 8192; - c->out_buf = xmalloc (c->out_size); - c->out_len = 0; - - str = strstr (info, "name="); - if (str != NULL) { - char *sp = strchr (str + 5, ' '); - int len; - if (sp) - len = sp - str - 5; - else - len = strlen (str + 5); - c->name = xmalloc (len + 1); - memcpy (c->name, str + 5, len); - c->name[len] = '\0'; - } - - str = strstr (info, "target="); - if (str != NULL) { - char *sp = strchr (str + 7, ' '); - int len; - if (sp) - len = sp - str - 7; - else - len = strlen (str + 7); - c->target = xmalloc (len + 1); - memcpy (c->target, str + 7, len); - c->target[len] = '\0'; - } - - str = strstr (info, "reference="); - if (str != NULL) { - char *sp = strchr (str + 10, ' '); - int len; - if (sp) - len = sp - str - 10; - else - len = strlen (str + 10); - c->reference = xmalloc (len + 1); - memcpy (c->reference, str + 10, len); - c->reference[len] = '\0'; - } - - len = sprintf (buf, "%s\n", clients->shm_path); - writen (fd, buf, len); -} - -static void -clients_add_trace (struct clients *clients, int fd, char *info) -{ - char *str, *sp; - char *name; - int i; - - str = strstr (info, "name="); - assert (str != NULL); - sp = strchr (str + 5, ' '); - if (sp) - i = sp - str - 5; - else - i = strlen (str + 5); - - name = xmalloc (i + 1); - memcpy (name, str + 5, i); - name[i] = '\0'; - - for (i = 0; i < clients->count; i++) { - struct client_info *c = &clients->clients[i]; - if (strcmp (name, c->name) == 0) { - c->trace = fd; - break; - } - } - - free (name); -} - -static int -clients_image (struct clients *clients, int fd, char *info) -{ - struct client_info *c = NULL; - int format, width, height, stride, size; - int i; - - for (i = 0; i < clients->count; i++) { - if (clients->clients[i].sk == fd) { - c = &clients->clients[i]; - break; - } - } - - if (c == NULL) - return 0; - - if (sscanf (info, "%lu %d %d %d %d", - &c->image_serial, &format, &width, &height, &stride) != 5) - { - return 0; - } - - size = height * stride; - size = (size + 4095) & -4096; - assert (clients->offset + size <= DATA_SIZE); - - c->image = - cairo_image_surface_create_for_data (clients->base + clients->offset, - format, width, height, stride); - - if (! writen (fd, &clients->offset, sizeof (clients->offset))) - return 0; - - clients->offset += size; - - return 1; -} - -static int -u8_cmp (const void *A, const void *B) -{ - const uint8_t *a = A, *b = B; - return (int) *a - (int) *b; -} - -static uint8_t -median (uint8_t *values, int count) -{ - /* XXX could use a fast median here if we cared */ - qsort (values, count, 1, u8_cmp); - return values[count/2]; -} - -static uint32_t -get_pixel32 (int x, int y, const uint8_t *data, int stride) -{ - return ((uint32_t *)(data + y * stride))[x]; -} - -static uint8_t -get_median_32 (int x, int y, int channel, - const uint8_t *data, int width, int height, int stride) -{ - uint8_t neighbourhood[25]; - int cnt = 0; - int xx, yy; - - for (yy = y - 2; yy <= y + 2; yy++) { - if (yy < 0) - continue; - if (yy >= height) - continue; - - for (xx = x - 2; xx <= x + 2; xx++) { - if (xx < 0) - continue; - if (xx >= width) - continue; - - neighbourhood[cnt++] = (get_pixel32 (xx, yy, data, stride) >> (channel*8)) & 0xff; - } - } - - return median (neighbourhood, cnt); -} - -static uint8_t -get_pixel8 (int x, int y, const uint8_t *data, int stride) -{ - return data[y * stride + x]; -} - -static uint8_t -get_median_8 (int x, int y, const uint8_t *data, int width, int height, int stride) -{ - uint8_t neighbourhood[25]; - int cnt = 0; - int xx, yy; - - for (yy = y - 2; yy <= y + 2; yy++) { - if (yy < 0) - continue; - if (yy >= height) - continue; - - for (xx = x - 2; xx <= x + 2; xx++) { - if (xx < 0) - continue; - if (xx >= width) - continue; - - neighbourhood[cnt++] = get_pixel8 (xx, yy, data, stride); - } - } - - return median (neighbourhood, cnt); -} - -static cairo_bool_t -compare_images (cairo_surface_t *a, - cairo_surface_t *b) -{ - int width, height, stride; - const uint8_t *aa, *bb; - int x, y; - - if (cairo_surface_status (a) || cairo_surface_status (b)) - return FALSE; - - if (cairo_surface_get_type (a) != cairo_surface_get_type (b)) - return FALSE; - - if (cairo_image_surface_get_format (a) != cairo_image_surface_get_format (b)) - return FALSE; - - if (cairo_image_surface_get_width (a) != cairo_image_surface_get_width (b)) - return FALSE; - - if (cairo_image_surface_get_height (a) != cairo_image_surface_get_height (b)) - return FALSE; - - if (cairo_image_surface_get_stride (a) != cairo_image_surface_get_stride (b)) - return FALSE; - - - width = cairo_image_surface_get_width (a); - height = cairo_image_surface_get_height (a); - stride = cairo_image_surface_get_stride (a); - - aa = cairo_image_surface_get_data (a); - bb = cairo_image_surface_get_data (b); - switch (cairo_image_surface_get_format (a)) { - case CAIRO_FORMAT_ARGB32: - for (y = 0; y < height; y++) { - const uint32_t *ua = (uint32_t *) aa; - const uint32_t *ub = (uint32_t *) bb; - for (x = 0; x < width; x++) { - if (ua[x] != ub[x]) { - int channel; - - for (channel = 0; channel < 4; channel++) { - int va, vb; - unsigned diff; - - va = (ua[x] >> (channel*8)) & 0xff; - vb = (ub[x] >> (channel*8)) & 0xff; - diff = abs (va - vb); - if (diff > 1) { - va = get_median_32 (x, y, channel, aa, width, height, stride); - vb = get_median_32 (x, y, channel, bb, width, height, stride); - diff = abs (va - vb); - if (diff > 1) - return FALSE; - } - } - } - } - aa += stride; - bb += stride; - } - break; - - case CAIRO_FORMAT_RGB24: - for (y = 0; y < height; y++) { - const uint32_t *ua = (uint32_t *) aa; - const uint32_t *ub = (uint32_t *) bb; - for (x = 0; x < width; x++) { - if ((ua[x] & 0x00ffffff) != (ub[x] & 0x00ffffff)) { - int channel; - - for (channel = 0; channel < 3; channel++) { - int va, vb; - unsigned diff; - - va = (ua[x] >> (channel*8)) & 0xff; - vb = (ub[x] >> (channel*8)) & 0xff; - diff = abs (va - vb); - if (diff > 1) { - va = get_median_32 (x, y, channel, aa, width, height, stride); - vb = get_median_32 (x, y, channel, bb, width, height, stride); - diff = abs (va - vb); - if (diff > 1) - return FALSE; - } - } - } - } - aa += stride; - bb += stride; - } - break; - - case CAIRO_FORMAT_A8: - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) { - if (aa[x] != bb[x]) { - unsigned diff = abs (aa[x] - bb[x]); - if (diff > 1) { - int8_t va, vb; - - va = get_median_8 (x, y, aa, width, height, stride); - vb = get_median_8 (x, y, bb, width, height, stride); - diff = abs (va - vb); - if (diff > 1) - return FALSE; - } - - } - } - aa += stride; - bb += stride; - } - break; - - case CAIRO_FORMAT_A1: - width /= 8; - for (y = 0; y < height; y++) { - if (memcmp (aa, bb, width)) - return FALSE; - aa += stride; - bb += stride; - } - break; - - case CAIRO_FORMAT_INVALID: - case CAIRO_FORMAT_RGB16_565: /* XXX */ - case CAIRO_FORMAT_RGB30: - case CAIRO_FORMAT_RGB96F: - case CAIRO_FORMAT_RGBA128F: - break; - } - - return TRUE; -} - -static int -check_images (struct clients *clients) -{ - int i, j; - - for (i = 0; i < clients->count; i++) { - struct client_info *c = &clients->clients[i]; - - if (c->reference == NULL) - continue; - - for (j = 0; j < clients->count; j++) { - struct client_info *ref = &clients->clients[j]; - - if (strcmp (c->reference, ref->name)) - continue; - - if (! compare_images (c->image, ref->image)) - return 0; - } - } - - return 1; -} - -static gchar * -checksum (const char *filename) -{ - gchar *str = NULL; - gchar *data; - gsize len; - - if (g_file_get_contents (filename, &data, &len, NULL)) { - str = g_compute_checksum_for_data (G_CHECKSUM_SHA1, (guchar *) data, len); - g_free (data); - } - - return str; -} - -static void -write_trace (struct clients *clients) -{ - cairo_device_t *ctx; - gchar *csum; - char buf[4096]; - int i; - - mkdir ("output", 0777); - - ctx = cairo_script_create ("output/cairo-sphinx.trace"); - cairo_script_from_recording_surface (ctx, clients->recording); - cairo_device_destroy (ctx); - - csum = checksum ("output/cairo-sphinx.trace"); - - sprintf (buf, "output/%s.trace", csum); - if (! g_file_test (buf, G_FILE_TEST_EXISTS)) { - rename ("output/cairo-sphinx.trace", buf); - - sprintf (buf, "output/%s.recording.png", csum); - cairo_surface_write_to_png (clients->recording, buf); - - for (i = 0; i < clients->count; i++) { - struct client_info *c = &clients->clients[i]; - if (c->image != NULL) { - sprintf (buf, "output/%s.%s.png", csum, c->name); - cairo_surface_write_to_png (c->image, buf); - } - } - } -} - -static void -clients_complete (struct clients *clients, int fd) -{ - int i; - - for (i = 0; i < clients->count; i++) { - if (clients->clients[i].sk == fd) { - break; - } - } - if (i == clients->count) - return; - - if (++clients->complete != clients->count) - return; - - clients->offset = 0; - clients->complete = 0; - - if (! check_images (clients)) - write_trace (clients); - - /* ack */ - for (i = 0; i < clients->count; i++) { - struct client_info *c = &clients->clients[i]; - - cairo_surface_destroy (c->image); - c->image = NULL; - - if (! writen (c->sk, &clients->serial, sizeof (clients->serial))) - continue; - - c->image_serial = 0; - } - - clients->recording = NULL; - clients->serial = 0; -} - -static void -clients_recording (struct clients *clients, int fd, char *info) -{ - sscanf (info, "%p %lu", &clients->recording, &clients->serial); - clients_complete (clients, fd); -} - -static void -clients_remove (struct clients *clients, int fd) -{ - int i, j; - - for (i = 0; i < clients->count; i++) { - struct client_info *c = &clients->clients[i]; - if (c->sk == fd) { - free (c->out_buf); - break; - } - } - - for (j = i++; i < clients->count; i++) - clients->clients[j] = clients->clients[i]; - - clients->count = j; -} - -static void -clients_send_trace (struct clients *clients, - const char * const line, const int len) -{ - int i; - - for (i = 0; i < clients->count; i++) { - struct client_info *c = &clients->clients[i]; - int ret, rem = len; - - if (c->trace == -1) - continue; - - if (c->out_len) { - ret = write (c->trace, c->out_buf, c->out_len); - if (ret > 0) { - c->out_len -= ret; - if (c->out_len) - memmove (c->out_buf, c->out_buf + ret, c->out_len); - } - } - - if (! c->out_len) { - ret = write (c->trace, line, rem); - if (ret > 0) - rem -= ret; - } - - if (rem) { - if (c->out_len + rem > c->out_size) { - c->out_size *= 2; - c->out_buf = xrealloc (c->out_buf, c->out_size); - } - - memcpy (c->out_buf + c->out_len, line, rem); - c->out_len += rem; - } - } -} - -static void -clients_fini (struct clients *clients) -{ - shm_unlink (clients->shm_path); - munmap (clients->base, DATA_SIZE); - free (clients->clients); -} - -static int -nonblocking (int fd) -{ - long flags; - - flags = fcntl (fd, F_GETFL); - if (flags == -1) - return -1; - - return fcntl (fd, F_SETFL, flags | O_NONBLOCK); -} - -static void * -request_image (struct client *c, - struct context_closure *closure, - cairo_format_t format, - int width, int height, int stride) -{ - char buf[1024]; - unsigned long offset = -1; - int len; - - assert (format != CAIRO_FORMAT_INVALID); - - len = sprintf (buf, ".image %lu %d %d %d %d\n", - closure->id, format, width, height, stride); - writen (c->sk, buf, len); - - readn (c->sk, &offset, sizeof (offset)); - if (offset == (unsigned long) -1) - return NULL; - - return (uint8_t *) c->base + offset; -} - -static cairo_format_t -format_for_content (cairo_content_t content) -{ - switch (content) { - case CAIRO_CONTENT_ALPHA: - return CAIRO_FORMAT_A8; - case CAIRO_CONTENT_COLOR: - return CAIRO_FORMAT_RGB24; - default: - case CAIRO_CONTENT_COLOR_ALPHA: - return CAIRO_FORMAT_ARGB32; - } -} - -static void -get_surface_size (cairo_surface_t *surface, - int *width, int *height, - cairo_format_t *format) -{ - if (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_IMAGE) { - *width = cairo_image_surface_get_width (surface); - *height = cairo_image_surface_get_height (surface); - *format = cairo_image_surface_get_format (surface); - } else { - struct surface_tag *tag; - - tag = cairo_surface_get_user_data (surface, &surface_tag); - if (tag != NULL) { - *width = tag->width; - *height = tag->height; - } else { - double x0, x1, y0, y1; - cairo_t *cr; - - /* presumably created using cairo_surface_create_similar() */ - cr = cairo_create (surface); - cairo_clip_extents (cr, &x0, &y0, &x1, &y1); - cairo_destroy (cr); - - tag = xmalloc (sizeof (*tag)); - *width = tag->width = ceil (x1 - x0); - *height = tag->height = ceil (y1 - y0); - - if (cairo_surface_set_user_data (surface, &surface_tag, tag, free)) - exit (-1); - } - } -} - - -static void -send_surface (struct client *c, - struct context_closure *closure) -{ - cairo_surface_t *source = closure->surface; - cairo_surface_t *image; - cairo_format_t format = CAIRO_FORMAT_INVALID; - cairo_t *cr; - int width, height, stride; - void *data; - unsigned long serial; - - get_surface_size (source, &width, &height, &format); - if (format == CAIRO_FORMAT_INVALID) - format = format_for_content (cairo_surface_get_content (source)); - - stride = cairo_format_stride_for_width (format, width); - - data = request_image (c, closure, format, width, height, stride); - if (data == NULL) - exit (-1); - - image = cairo_image_surface_create_for_data (data, - format, - width, height, - stride); - cr = cairo_create (image); - cairo_surface_destroy (image); - - cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); - cairo_set_source_surface (cr, source, 0, 0); - cairo_paint (cr); - cairo_destroy (cr); - - /* signal completion */ - writen (c->sk, ".complete\n", strlen (".complete\n")); - - /* wait for image check */ - serial = 0; - readn (c->sk, &serial, sizeof (serial)); - if (serial != closure->id) - exit (-1); -} - -static void -send_recording (struct client *c, - struct context_closure *closure) -{ - cairo_surface_t *source = closure->surface; - char buf[1024]; - int len; - unsigned long serial; - - assert (cairo_surface_get_type (source) == CAIRO_SURFACE_TYPE_RECORDING); - len = sprintf (buf, ".recording %p %lu\n", source, closure->id); - writen (c->sk, buf, len); - - /* wait for image check */ - - serial = 0; - readn (c->sk, &serial, sizeof (serial)); - if (serial != closure->id) - exit (-1); -} - -static cairo_surface_t * -_surface_create (void *closure, - cairo_content_t content, - double width, double height, - long uid) -{ - struct client *c = closure; - cairo_surface_t *surface; - - surface = cairo_surface_create_similar (c->surface, - content, width, height); - if (cairo_surface_get_type (surface) != CAIRO_SURFACE_TYPE_IMAGE) { - struct surface_tag *tag; - - tag = xmalloc (sizeof (*tag)); - tag->width = width; - tag->height = height; - if (cairo_surface_set_user_data (surface, &surface_tag, tag, free)) - exit (-1); - } - - return surface; -} - -static cairo_t * -_context_create (void *closure, cairo_surface_t *surface) -{ - struct client *c = closure; - struct context_closure *l; - cairo_bool_t foreign = FALSE; - - l = xmalloc (sizeof (*l)); - l->next = c->contexts; - l->surface = surface; - l->original = cairo_surface_reference (surface); - l->id = ++c->context_id; - if (l->id == 0) - l->id = ++c->context_id; - c->contexts = l; - - /* record everything, including writes to images */ - if (c->target == NULL) { - if (cairo_surface_get_type (surface) != CAIRO_SURFACE_TYPE_RECORDING) { - cairo_format_t format; - int width, height; - - get_surface_size (surface, &width, &height, &format); - l->surface = cairo_surface_create_similar (c->surface, - cairo_surface_get_content (surface), - width, height); - foreign = TRUE; - } - } - - l->context = cairo_create (l->surface); - if (foreign) { - cairo_set_source_surface (l->context, surface, 0, 0); - cairo_paint (l->context); - } - - return l->context; -} - -static void -_context_destroy (void *closure, void *ptr) -{ - struct client *c = closure; - struct context_closure *l, **prev = &c->contexts; - - while ((l = *prev) != NULL) { - if (l->context == ptr) { - if (cairo_surface_status (l->surface) == CAIRO_STATUS_SUCCESS) { - if (c->target == NULL) - send_recording (c, l); - else - send_surface (c, l); - } else { - exit (-1); - } - - cairo_surface_destroy (l->original); - *prev = l->next; - free (l); - return; - } - prev = &l->next; - } -} - -static void * -recorder (void *arg) -{ - struct client client; - const cairo_script_interpreter_hooks_t hooks = { - .closure = &client, - .surface_create = _surface_create, - .context_create = _context_create, - .context_destroy = _context_destroy, - }; - char *buf; - int buf_size; - int len = 0, ret; - struct pollfd pfd; - - client.target = NULL; - client.sk = client_socket ("/tmp/cairo-sphinx"); - if (client.sk < 0) - return NULL; - - buf_size = 65536; - buf = xmalloc (buf_size); - - len = sprintf (buf, "client-command target=recording name=.recorder\n"); - if (! writen (client.sk, buf, len)) - return NULL; - - /* drain the shm_path */ - len = readline (client.sk, buf, buf_size); - - pfd.fd = client_socket ("/tmp/cairo-sphinx"); - if (pfd.fd < 0) - return NULL; - - len = sprintf (buf, "client-trace name=.recorder\n"); - if (! writen (pfd.fd, buf, len)) - return NULL; - - client.surface = cairo_recording_surface_create (CAIRO_CONTENT_COLOR_ALPHA, - NULL); - - client.context_id = 0; - client.csi = cairo_script_interpreter_create (); - cairo_script_interpreter_install_hooks (client.csi, &hooks); - - nonblocking (pfd.fd); - pfd.events = POLLIN; - len = 0; - while (poll (&pfd, 1, -1) > 0) { - while ((ret = read (pfd.fd, buf + len, buf_size - len)) > 0) { - int end; - - if (ret == buf_size - len) { - buf_size *= 2; - buf = xrealloc (buf, buf_size); - } - len += ret; - - for (end = len; end > 0 && buf[--end] != '\n'; ) - ; - if (end > 0) { - buf[end] = '\0'; - cairo_script_interpreter_feed_string (client.csi, buf, end); - - len -= end + 1; - if (len) - memmove (buf, buf + end + 1, len); - } - } - if (ret == 0) - break; - if (! (errno == EAGAIN || errno == EINTR)) - break; - } - - cairo_script_interpreter_finish (client.csi); - cairo_script_interpreter_destroy (client.csi); - - cairo_surface_destroy (client.surface); - return NULL; -} - -static int -do_server (const char *path) -{ - pthread_t thread; - struct clients clients; - char line[4096]; - struct pollfd *pfd; - int num_pfd, size_pfd; - int n, cnt, ret = 1; - int sk, source = -1; - int waiter = -1, waiter_count = 0; - int len; - - signal (SIGPIPE, SIG_IGN); - - if (clients_init (&clients) < 0) { - fprintf (stderr, "Failed to initialise clients structure\n"); - return -1; - } - - sk = server_socket (path); - if (sk < 0) { - fprintf (stderr, "Failed to create server socket\n"); - return 1; - } - - if (daemonize () < 0) - return 1; - - if (pthread_create (&thread, NULL, recorder, NULL) < 0) { - fprintf (stderr, "Failed to create spawn recording thread\n"); - return 1; - } - - size_pfd = 4; - pfd = xmalloc (sizeof (*pfd) * size_pfd); - pfd[0].fd = sk; - pfd[0].events = POLLIN; - num_pfd = 1; - - while ((cnt = poll (pfd, num_pfd, -1)) > 0) { - int have_source; - - if (pfd[0].revents) { - while ((sk = accept (pfd[0].fd, NULL, NULL)) != -1) { - len = readline (sk, line, sizeof (line)); - if (strcmp (line, "source") == 0) { - - if (source != -1) - exit (1); - - source = sk; - if (nonblocking (sk) < 0) { - close (sk); - continue; - } - } else if (strncmp (line, "client-command", 14) == 0) { - if (source == -1) - clients_add_command (&clients, sk, line); - } else if (strncmp (line, "client-trace", 12) == 0) { - if (source == -1) { - clients_add_trace (&clients, sk, line); - if (nonblocking (sk) < 0) { - close (sk); - continue; - } - - if (clients.count == waiter_count) { - for (n = 1; n < num_pfd; n++) { - if (pfd[n].fd == waiter) { - pfd[n].fd = -1; - break; - } - } - close (waiter); - waiter_count = -1; - } - } - } else if (strncmp (line, "wait", 4) == 0) { - int count = atoi (line + 5) + 1; - if (clients.count == count) { - close (sk); - continue; - } else { - waiter = sk; - waiter_count = count; - } - } - - if (num_pfd == size_pfd) { - size_pfd *= 2; - pfd = xrealloc (pfd, sizeof (*pfd) * size_pfd); - } - - pfd[num_pfd].fd = sk; - pfd[num_pfd].events = POLLIN; - pfd[num_pfd].revents = 0; - num_pfd++; - } - cnt--; - } - - have_source = 0; - for (n = 1; cnt && n < num_pfd; n++) { - if (! pfd[n].revents) - continue; - cnt--; - - if (pfd[n].fd == -1) - continue; - - if (source == pfd[n].fd) { - have_source = n; - } else { - len = readline (pfd[n].fd, line, sizeof (line)); - if (len < 0) { - clients_remove (&clients, pfd[n].fd); - close (pfd[n].fd); - pfd[n].fd = -1; - continue; - } - - if (strncmp (line, ".image", 6) == 0) { - if (! clients_image (&clients, pfd[n].fd, line + 7)) { - clients_remove (&clients, pfd[n].fd); - close (pfd[n].fd); - pfd[n].fd = -1; - continue; - } - } else if (strncmp (line, ".complete", 9) == 0) { - clients_complete (&clients, pfd[n].fd); - } else if (strncmp (line, ".recording", 10) == 0) { - clients_recording (&clients, pfd[n].fd, line + 6); - } else { - printf ("do_command (%s)\n", line); - } - } - } - - if (have_source) { - do { - len = read (source, line, sizeof (line)); - if (len > 0) { - clients_send_trace (&clients, line, len); - } else if (len == 0) { - close (source); - pfd[have_source].fd = source = -1; - goto done; - } else - break; - } while (1); - } - - for (n = cnt = 1; n < num_pfd; n++) { - if (pfd[n].fd != -1) { - if (cnt != n) - pfd[cnt] = pfd[n]; - cnt++; - } - } - num_pfd = cnt; - } - -done: - ret = 0; - for (n = 0; n < num_pfd; n++) { - if (pfd[n].fd != -1) - close (pfd[n].fd); - } - free (pfd); - clients_fini (&clients); - - return ret; -} - -static void * -client_shm (const char *shm_path) -{ - void *base; - int fd; - - fd = shm_open (shm_path, O_RDWR, 0); - if (fd == -1) - return MAP_FAILED; - - base = mmap (NULL, DATA_SIZE, - PROT_READ | PROT_WRITE, -#ifdef MAP_NORESERVE - MAP_SHARED | MAP_NORESERVE, -#else - MAP_SHARED, -#endif - fd, 0); - close (fd); - - return base; -} - -static int -client_socket (const char *socket_path) -{ - struct sockaddr_un addr; - int sk; - - sk = socket (PF_UNIX, SOCK_STREAM, 0); - if (sk == -1) - return -1; - - memset (&addr, 0, sizeof (addr)); - addr.sun_family = AF_UNIX; - strcpy (addr.sun_path, socket_path); - - if (connect (sk, (struct sockaddr *) &addr, sizeof (addr)) == -1) - return -1; - - return sk; -} - -static int -do_client (int fd, - const char *target, - const char *name, - const char *reference, - cairo_content_t content) -{ - struct client client; - const cairo_script_interpreter_hooks_t hooks = { - .closure = &client, - .surface_create = _surface_create, - .context_create = _context_create, - .context_destroy = _context_destroy, - }; - void *closure; - char *buf; - int buf_size; - int len = 0, ret; - struct pollfd pfd; - - client.sk = fd; - client.target = cairo_boilerplate_get_target_by_name (target, content); - client.context_id = 0; - - client.surface = client.target->create_surface (NULL, content, 1, 1, 1, 1, - CAIRO_BOILERPLATE_MODE_TEST, - &closure); - if (client.surface == NULL) { - fprintf (stderr, "Failed to create target surface: %s.\n", - client.target->name); - return 1; - } - - buf_size = 65536; - buf = xmalloc (buf_size); - - if (reference != NULL) { - len = sprintf (buf, - "client-command name=%s target=%s reference=%s\n", - name, target, reference); - } else { - len = sprintf (buf, - "client-command name=%s target=%s\n", - name, target); - } - if (! writen (fd, buf, len)) - return 1; - - len = readline (fd, buf, buf_size); - client.base = client_shm (buf); - if (client.base == MAP_FAILED) { - fprintf (stderr, "Failed to map shared memory segment '%s'.\n", buf); - return 1; - } - - if (daemonize () < 0) - return 1; - - pfd.fd = client_socket ("/tmp/cairo-sphinx"); - if (pfd.fd < 0) - return 1; - - len = sprintf (buf, "client-trace name=%s\n", name); - if (! writen (pfd.fd, buf, len)) - return 1; - - client.csi = cairo_script_interpreter_create (); - cairo_script_interpreter_install_hooks (client.csi, &hooks); - - nonblocking (pfd.fd); - pfd.events = POLLIN; - len = 0; - while (poll (&pfd, 1, -1) > 0) { - while ((ret = read (pfd.fd, buf + len, buf_size - len)) > 0) { - int end; - - if (ret == buf_size - len) { - buf_size *= 2; - buf = xrealloc (buf, buf_size); - } - len += ret; - - for (end = len; end > 0 && buf[--end] != '\n'; ) - ; - if (end > 0) { - buf[end] = '\0'; - cairo_script_interpreter_feed_string (client.csi, buf, end); - - len -= end + 1; - if (len) - memmove (buf, buf + end + 1, len); - } - } - if (ret == 0) - break; - if (! (errno == EAGAIN || errno == EINTR)) - break; - } - - cairo_script_interpreter_finish (client.csi); - cairo_script_interpreter_destroy (client.csi); - - cairo_surface_destroy (client.surface); - close (fd); - - return 0; -} - -static int -do_exec (int fd, char **argv) -{ - char buf[4096]; - - if (*argv == NULL) - return 0; - - snprintf (buf, sizeof (buf), "%s/cairo-trace.so", LIBDIR); - setenv ("LD_PRELOAD", buf, 1); - - snprintf (buf, sizeof (buf), "0"); - setenv ("CAIRO_TRACE_LINE_INFO", buf, 1); - - snprintf (buf, sizeof (buf), "%d", fd); - setenv ("CAIRO_TRACE_FD", buf, 1); - putenv (buf); - - return execvp (argv[0], argv); -} - -static int -do_wait (int fd) -{ - char buf; - int ret = read (fd, &buf, 1); - return ret != 0; -} - -int -main (int argc, char **argv) -{ - char buf[4096]; - int len; - int fd; - - if (argc == 1) - return do_server ("/tmp/cairo-sphinx"); - - fd = client_socket ("/tmp/cairo-sphinx"); - if (fd < 0) - return 1; - - if (strcmp (argv[1], "client") == 0) { - return do_client (fd, argv[2], argv[3], argv[4], - CAIRO_CONTENT_COLOR_ALPHA); - } - - if (strcmp (argv[1], "wait") == 0) { - len = snprintf (buf, sizeof (buf), "wait %s\n", argv[2]); - if (! writen (fd, buf, len)) - return 1; - - return do_wait (fd); - } - - if (strcmp (argv[1], "exec") == 0) { - len = snprintf (buf, sizeof (buf), "source\n"); - if (! writen (fd, buf, len)) - return 1; - - return do_exec (fd, argv+2); - } - - if (strcmp (argv[1], "replay") == 0) { - len = snprintf (buf, sizeof (buf), "replay %s\n", argv[2]); - return ! writen (fd, buf, len); - } - - return 0; -} diff --git a/util/cairo-trace/meson.build b/util/cairo-trace/meson.build index c4a504759..f088c774c 100644 --- a/util/cairo-trace/meson.build +++ b/util/cairo-trace/meson.build @@ -11,10 +11,10 @@ shared_lib_ext = libcairo.full_path().split('.')[-1] libcairotrace = library('cairo-trace', cairo_trace_sources, include_directories: [incbase, incsrc], dependencies: deps, - link_args: extra_link_args, c_args: ['-DSHARED_LIB_EXT="@0@"'.format(shared_lib_ext),] + pthread_c_args, + link_args: extra_link_args, install: true, - install_dir: join_paths(get_option('prefix'), get_option('libdir'), 'cairo'), + install_dir: get_option('libdir') / 'cairo', ) trace_conf = configuration_data() diff --git a/util/cairo-trace/trace.c b/util/cairo-trace/trace.c index 1bdb07591..9b7a83370 100644 --- a/util/cairo-trace/trace.c +++ b/util/cairo-trace/trace.c @@ -100,7 +100,7 @@ */ #define CAIRO_BITSWAP8(c) ((((c) * 0x0802LU & 0x22110LU) | ((c) * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16) -#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4) +#if defined(__GNUC__) #ifdef __MINGW32__ #define CAIRO_PRINTF_FORMAT(fmt_index, va_index) \ __attribute__((__format__(__MINGW_PRINTF_FORMAT, fmt_index, va_index))) @@ -143,7 +143,7 @@ static void *_dlhandle = RTLD_NEXT; #endif #define BUCKET(b, ptr) (((uintptr_t) (ptr) >> PTR_SHIFT) % ARRAY_LENGTH (b)) -#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__) +#if defined(__GNUC__) && defined(__OPTIMIZE__) #define _BOOLEAN_EXPR(expr) \ __extension__ ({ \ int _boolean_var_; \ @@ -220,7 +220,7 @@ static void _init_trace (void); #define INIT_TRACE_ONCE() pthread_once (&once_control, _init_trace) -#if __GNUC__ >= 3 && defined(__ELF__) && !defined(__sun) +#if defined(__GNUC__) && defined(__ELF__) && !defined(__sun) # define _enter_trace() INIT_TRACE_ONCE () # define _exit_trace() do { } while (0) # define _should_trace() 1 @@ -1742,7 +1742,7 @@ _emit_image (cairo_surface_t *image, break; case CAIRO_FORMAT_A8: for (row = height; row--; ) { - _write_data (&stream, rowdata, width); + _write_data (&stream, data, width); data += stride; } break; diff --git a/util/malloc-stats.c b/util/malloc-stats.c deleted file mode 100644 index a086b0543..000000000 --- a/util/malloc-stats.c +++ /dev/null @@ -1,376 +0,0 @@ -/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */ -/* - * 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, Inc. not be used in advertising or publicity pertaining to - * distribution of the software without specific, written prior - * permission. Red Hat, Inc. makes no representations about the - * suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL, - * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER - * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR - * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Author: Behdad Esfahbod - */ - -/* A simple malloc wrapper that prints out statistics on termination */ - -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif - -#include -#include -#include - -/* caller-logging */ - -#include - -struct alloc_stat_t { - unsigned int num; - unsigned long long size; -}; - -struct alloc_stats_t { - struct alloc_stat_t malloc, realloc, total; -}; - -struct func_stat_t { - struct func_stat_t *next; - - const void *addr; - const char *name; - - struct alloc_stats_t stat; -}; - -static struct alloc_stats_t total_allocations; -static struct func_stat_t *func_stats[31627]; -static int func_stats_num; - -#ifndef ARRAY_LENGTH -#define ARRAY_LENGTH(__array) ((int) (sizeof (__array) / sizeof (__array[0]))) -#endif -static void -alloc_stats_add (struct alloc_stats_t *stats, int is_realloc, size_t size) -{ - struct alloc_stat_t *stat = is_realloc ? &stats->realloc : &stats->malloc; - - stats->total.num++; - stats->total.size += size; - - stat->num++; - stat->size += size; -} - -#include - -static void * -_perm_alloc (size_t size) -{ - static uint8_t *ptr; - static size_t rem; - - void *ret; - -#define SUPERBLOCK_SIZE (1<<23) -#define align(x, y) (((x) + ((y)-1)) & ~((y)-1)) - - size = align (size, 2 * sizeof (void *)); - if (size > rem || rem == 0) { - ptr = malloc (SUPERBLOCK_SIZE); - if (ptr == NULL) - exit (1); - rem = SUPERBLOCK_SIZE; - } - -#undef SUPERBLOCK_SIZE -#undef align - - ret = ptr; - rem -= size; - ptr += size; - - return ret; -} - -static void -resolve_addrs (struct func_stat_t *func_stats, int num) -{ - int i; - void **addrs; - char **strings; - - addrs = malloc (num * sizeof (void *)); - for (i = 0; i < num; i++) - addrs[i] = (void *) func_stats[i].addr; - - strings = backtrace_symbols (addrs, num); - - for (i = 0; i < num; i++) { - char *p; - char *name; - int len; - - p = strchr (strings[i], '\t'); - if (p) - p++; - else - p = strings[i]; - - len = strlen (p) + 1; - name = _perm_alloc (len); - memcpy (name, p, len); - func_stats[i].name = name; - } - - free (strings); - free (addrs); -} - -static void -func_stats_add (const void *caller, int is_realloc, size_t size) -{ - int i; - struct func_stat_t *elt; - - alloc_stats_add (&total_allocations, is_realloc, size); - - i = ((uintptr_t) caller ^ 1215497) % ARRAY_LENGTH (func_stats); - for (elt = func_stats[i]; elt != NULL; elt = elt->next) { - if (elt->addr == caller) - break; - } - - if (elt == NULL) { - func_stats_num++; - - elt = _perm_alloc (sizeof (struct func_stat_t)); - elt->next = func_stats[i]; - func_stats[i] = elt; - elt->addr = caller; - elt->name = NULL; - memset (&elt->stat, 0, sizeof (struct alloc_stats_t)); - } - - alloc_stats_add (&elt->stat, is_realloc, size); -} - -/* wrapper stuff */ - -#include - -static void *(*old_malloc)(size_t); -static void *(*old_calloc)(size_t, size_t); -static void *(*old_realloc)(void *, size_t); -static int enable_hook = 0; - -static void init(void); - -void * -malloc(size_t size) -{ - if (!old_malloc) - init (); - - if (enable_hook) { - enable_hook = 0; - void *caller = __builtin_return_address(0); - func_stats_add (caller, 0, size); - enable_hook = 1; - } - - return old_malloc (size); -} - -void * -calloc(size_t nmemb, size_t size) -{ - if (!old_calloc) - init (); - - if (enable_hook) { - enable_hook = 0; - void *caller = __builtin_return_address(0); - func_stats_add (caller, 0, nmemb * size); - enable_hook = 1; - } - - return old_calloc (nmemb, size); -} - -void * -realloc(void *ptr, size_t size) -{ - if (!old_malloc) - init (); - - if (enable_hook) { - enable_hook = 0; - void *caller = __builtin_return_address(0); - func_stats_add (caller, 1, size); - enable_hook = 1; - } - - return old_realloc (ptr, size); -} - -static void -init(void) -{ - old_malloc = dlsym(RTLD_NEXT, "malloc"); - if (!old_malloc) { - fprintf(stderr, "%s\n", dlerror()); - exit(1); - } - old_calloc = dlsym(RTLD_NEXT, "calloc"); - if (!old_calloc) { - fprintf(stderr, "%s\n", dlerror()); - exit(1); - } - old_realloc = dlsym(RTLD_NEXT, "realloc"); - if (!old_realloc) { - fprintf(stderr, "%s\n", dlerror()); - exit(1); - } - enable_hook = 1; -} - -/* reporting */ - -#include - -static void -add_alloc_stats (struct alloc_stats_t *a, struct alloc_stats_t *b) -{ - a->total.num += b->total.num; - a->total.size += b->total.size; - a->malloc.num += b->malloc.num; - a->malloc.size += b->malloc.size; - a->realloc.num += b->realloc.num; - a->realloc.size += b->realloc.size; -} - -static void -dump_alloc_stats (struct alloc_stats_t *stats, const char *name) -{ - printf ("%8u %'11llu %8u %'11llu %8u %'11llu %s\n", - stats->total.num, stats->total.size, - stats->malloc.num, stats->malloc.size, - stats->realloc.num, stats->realloc.size, - name); -} - -static int -compare_func_stats_name (const void *pa, const void *pb) -{ - const struct func_stat_t *a = pa, *b = pb; - int i; - - i = strcmp (a->name, b->name); - if (i) - return i; - - return ((char *) a->addr - (char *) b->addr); -} - -static int -compare_func_stats (const void *pa, const void *pb) -{ - const struct func_stat_t *a = pa, *b = pb; - - if (a->stat.total.num != b->stat.total.num) - return (a->stat.total.num - b->stat.total.num); - - if (a->stat.total.size != b->stat.total.size) - return (a->stat.total.size - b->stat.total.size); - - return compare_func_stats_name (pa, pb); -} - -static int -merge_similar_entries (struct func_stat_t *func_stats, int num) -{ - int i, j; - - j = 0; - for (i = 1; i < num; i++) { - if (i != j && 0 == strcmp (func_stats[i].name, func_stats[j].name)) { - add_alloc_stats (&func_stats[j].stat, &func_stats[i].stat); - } else { - j++; - if (i != j) - func_stats[j] = func_stats[i]; - } - } - j++; - - return j; -} - -__attribute__ ((destructor)) -static void -malloc_stats (void) -{ - unsigned int i, j; - struct func_stat_t *sorted_func_stats; - - enable_hook = 0; - - if (! func_stats_num) - return; - - sorted_func_stats = malloc (sizeof (struct func_stat_t) * (func_stats_num + 1)); - if (sorted_func_stats == NULL) - return; - - j = 0; - for (i = 0; i < ARRAY_LENGTH (func_stats); i++) { - struct func_stat_t *elt; - for (elt = func_stats[i]; elt != NULL; elt = elt->next) - sorted_func_stats[j++] = *elt; - } - - resolve_addrs (sorted_func_stats, j); - - /* merge entries with same name */ - qsort (sorted_func_stats, j, - sizeof (struct func_stat_t), compare_func_stats_name); - j = merge_similar_entries (sorted_func_stats, j); - - qsort (sorted_func_stats, j, - sizeof (struct func_stat_t), compare_func_stats); - - /* add total */ - sorted_func_stats[j].next = NULL; - sorted_func_stats[j].addr = (void *) -1; - sorted_func_stats[j].name = "(total)"; - sorted_func_stats[j].stat = total_allocations; - j++; - - setlocale (LC_ALL, ""); - - printf (" TOTAL MALLOC REALLOC\n"); - printf (" num size num size num size\n"); - - for (i = 0; i < j; i++) { - dump_alloc_stats (&sorted_func_stats[i].stat, - sorted_func_stats[i].name); - } - - /* XXX free other stuff? */ - - free (sorted_func_stats); -} diff --git a/util/meson.build b/util/meson.build index 3c3bf26c2..1e186bf66 100644 --- a/util/meson.build +++ b/util/meson.build @@ -22,15 +22,6 @@ if conf.get('CAIRO_HAS_TRACE', 0) == 1 endif endif -if (glib_dep.found() and - png_dep.found() and - host_machine.system() != 'windows' and - conf.get('CAIRO_HAS_DLSYM', 0) == 1 and - feature_conf.get('CAIRO_HAS_SCRIPT_SURFACE', 0) == 1 and - feature_conf.get('CAIRO_HAS_TEE_SURFACE', 0) == 1) - subdir('cairo-sphinx') -endif - if gtk_dep.found() cairo_utils += [ ['show-contour.c', {'deps': [gtk_dep]}], @@ -50,7 +41,3 @@ foreach util : cairo_utils dependencies: deps + util_deps + [libcairo_dep, libcairoscript_dep], ) endforeach - -if conf.get('CAIRO_HAS_DLSYM', 0) == 1 and cc.has_header('execinfo.h') - libmallocstats = library('malloc-stats', 'malloc-stats.c', dependencies : dl_dep) -endif