Skip to content
Commits on Source (50)
/subprojects/*/
stages:
- build
- analysis
- docs
- deploy
# Common variables
variables:
CCACHE_DIR: _ccache
COMMON_MESON_FLAGS: "-Dwerror=true -Dglib:werror=false"
LOADERS_FLAGS: "-Dpng=enabled -Djpeg=enabled -Dtiff=enabled"
MESON_TEST_TIMEOUT_MULTIPLIER: 3
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gdk-pixbuf/fedora:v3"
.only-default:
only:
- branches
except:
- tags
.build-linux:
extends: .only-default
before_script:
- mkdir -p _ccache
script:
- meson setup ${COMMON_MESON_FLAGS} ${LOADERS_FLAGS} ${BUILD_OPTS} _build .
- meson compile -C _build
- .gitlab/scripts/run-tests.sh _build
artifacts:
when: always
name: "gdk-pixbuf-${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}"
paths:
- "${CI_PROJECT_DIR}/_build/meson-logs"
- "${CI_PROJECT_DIR}/_build/report-${CI_JOB_NAME}.xml"
reports:
junit:
- "${CI_PROJECT_DIR}/_build/report-${CI_JOB_NAME}.xml"
cache:
key: "$CI_JOB_NAME"
paths:
- _ccache/
style-check-diff:
extends: .only-default
image: $FEDORA_IMAGE
stage: .pre
allow_failure: true
script:
- .gitlab/scripts/run-style-check-diff.sh
meson-fedora-x86_64:
stage: build
extends: .build-linux
image: ${FEDORA_IMAGE}
needs: []
macos:
stage: build
needs: []
only:
- branches@GNOME/gdk-pixbuf
except:
- tags
tags:
- macos
before_script:
- pip3 install --user meson==0.56.2
- pip3 install --user ninja
- export PATH=/Users/gitlabrunner/Library/Python/3.7/bin:$PATH
script:
- meson setup -Dintrospection=disabled -Dinstalled_tests=false -Dman=false -Dgtk_doc=false _build
- meson compile -C _build
artifacts:
when: always
paths:
- "${CI_PROJECT_DIR}/_build/meson-logs"
msys2-mingw64:
stage: build
needs: []
tags:
- win32-ps
variables:
MSYSTEM: "MINGW64"
CHERE_INVOKING: "yes"
script:
- C:\msys64\usr\bin\pacman --noconfirm -Syyuu
- C:\msys64\usr\bin\bash -lc "bash -x ./.gitlab/ci/test-msys2.sh"
artifacts:
name: "gdk-pixbuf-${env:CI_JOB_NAME}-${env:CI_COMMIT_REF_NAME}"
when: always
paths:
- _build/meson-logs
release-build:
stage: build
extends: .build-linux
image: ${FEDORA_IMAGE}
needs: []
variables:
BUILD_OPTS: "-Dbuildtype=release"
reference:
stage: docs
image: ${FEDORA_IMAGE}
needs: []
variables:
BUILD_OPTS: "-Dbuildtype=release -Dgtk_doc=true"
script:
- meson setup ${COMMON_MESON_FLAGS} ${LOADERS_FLAGS} ${BUILD_OPTS} _build .
- meson compile -C _build
- mkdir -p _reference
- mv _build/docs/gdk-pixbuf/ _reference/gdk-pixbuf/
- mv _build/docs/gdk-pixdata/ _reference/gdk-pixdata/
artifacts:
when: on_success
paths:
- _reference
static-scan:
image: $FEDORA_IMAGE
stage: analysis
needs: []
variables:
BUILD_OPTS: "--buildtype=debug"
script:
- meson setup ${COMMON_MESON_FLAGS} ${LOADERS_FLAGS} ${BUILD_OPTS} _scan_build
- ninja -C _scan_build scan-build
artifacts:
paths:
- _scan_build/meson-logs
allow_failure: true
# Run tests with the address sanitizer. We need to turn off introspection,
# since it is incompatible with asan
asan-build:
image: $FEDORA_IMAGE
tags: [ asan ]
stage: analysis
needs: []
variables:
script:
- CC=clang meson setup --buildtype=debugoptimized -Db_sanitize=address -Db_lundef=false -Dintrospection=disabled _build
- meson compile -C _build
- .gitlab/scripts/run-tests.sh _build
artifacts:
paths:
- _build/meson-logs
allow_failure: true
release-dist:
stage: build
image: ${FEDORA_IMAGE}
needs: []
variables:
BUILD_OPTS: "-Dbuildtype=release -Dgtk_doc=true"
script:
- meson ${COMMON_MESON_FLAGS} ${LOADERS_FLAGS} ${BUILD_OPTS} _build .
- meson compile -C _build
- meson dist -C _build
- tar -c -J -f _build/gdk-pixbuf-docs-${CI_COMMIT_TAG}.tar.xz _build/docs/gdk-pixbuf/
- tar -c -J -f _build/gdk-pixdata-docs-${CI_COMMIT_TAG}.tar.xz _build/docs/gdk-pixdata/
artifacts:
when: on_success
paths:
- _build/meson-dist/gdk-pixbuf-${CI_COMMIT_TAG}.tar.xz
- _build/gdk-pixbuf-docs-${CI_COMMIT_TAG}.tar.xz
- _build/gdk-pixdata-docs-${CI_COMMIT_TAG}.tar.xz
only:
- tags
pages:
stage: deploy
needs: [reference]
script:
- mv _reference public
artifacts:
paths:
- public
only:
- master
FROM fedora:33
RUN dnf -y install \
ccache \
clang \
clang-analyzer \
gcc \
gcc-c++ \
gettext \
gettext-devel \
git \
glib2-devel \
gobject-introspection-devel \
gtk-doc \
itstool \
jasper-devel \
lcov \
libasan \
libjpeg-turbo-devel \
libpng-devel \
libtiff-devel \
libX11-devel \
meson \
python3 \
python3-jinja2 \
python3-markdown \
python3-pip \
python3-pygments \
python3-toml \
python3-typogrify \
python3-wheel \
redhat-rpm-config \
shared-mime-info \
which \
&& dnf clean all
RUN pip3 install meson==0.56.0
ARG HOST_USER_ID=5555
ENV HOST_USER_ID ${HOST_USER_ID}
RUN useradd -u $HOST_USER_ID -ms /bin/bash user
USER user
WORKDIR /home/user
ENV LANG C.UTF-8
#!/bin/bash
read_arg() {
# $1 = arg name
# $2 = arg value
# $3 = arg parameter
local rematch='^[^=]*=(.*)$'
if [[ $2 =~ $rematch ]]; then
read "$1" <<< "${BASH_REMATCH[1]}"
else
read "$1" <<< "$3"
# There is no way to shift our callers args, so
# return 1 to indicate they should do it instead.
return 1
fi
}
set -e
build=0
run=0
push=0
list=0
print_help=0
no_login=0
while (($# > 0)); do
case "${1%%=*}" in
build) build=1;;
run) run=1;;
push) push=1;;
list) list=1;;
help) print_help=1;;
--base|-b) read_arg base "$@" || shift;;
--base-version) read_arg base_version "$@" || shift;;
--no-login) no_login=1;;
*) echo -e "\e[1;31mERROR\e[0m: Unknown option '$1'"; exit 1;;
esac
shift
done
if [ $print_help == 1 ]; then
echo "$0 - Build and run Docker images"
echo ""
echo "Usage: $0 <command> [options] [basename]"
echo ""
echo "Available commands"
echo ""
echo " build --base=<BASENAME> - Build Docker image <BASENAME>.Dockerfile"
echo " run --base=<BASENAME> - Run Docker image <BASENAME>"
echo " push --base=<BASENAME> - Push Docker image <BASENAME> to the registry"
echo " list - List available images"
echo " help - This help message"
echo ""
exit 0
fi
cd "$(dirname "$0")"
if [ $list == 1 ]; then
echo "Available Docker images:"
for f in *.Dockerfile; do
filename=$( basename -- "$f" )
basename="${filename%.*}"
echo -e " \e[1;39m$basename\e[0m"
done
exit 0
fi
# All commands after this require --base to be set
if [ -z $base ]; then
echo "Usage: $0 <command>"
exit 1
fi
if [ ! -f "$base.Dockerfile" ]; then
echo -e "\e[1;31mERROR\e[0m: Dockerfile for '$base' not found"
exit 1
fi
if [ -z $base_version ]; then
base_version="latest"
elif [ $base_version != "latest" ]; then
base_version="v$base_version"
fi
if [ ! -x "$(command -v docker)" ] || [ docker --help |& grep -q podman ]; then
# Docker is actually implemented by podman, and its OCI output
# is incompatible with some of the dockerd instances on GitLab
# CI runners.
echo "Using: Podman"
format="--format docker"
CMD="podman"
else
echo "Using: Docker"
format=""
CMD="sudo docker"
fi
REGISTRY="registry.gitlab.gnome.org"
TAG="${REGISTRY}/gnome/gdk-pixbuf/${base}:${base_version}"
if [ $build == 1 ]; then
echo -e "\e[1;32mBUILDING\e[0m: ${base} as ${TAG}"
${CMD} build \
${format} \
--build-arg HOST_USER_ID="$UID" \
--tag "${TAG}" \
--file "${base}.Dockerfile" .
exit $?
fi
if [ $push == 1 ]; then
echo -e "\e[1;32mPUSHING\e[0m: ${base} as ${TAG}"
if [ $no_login == 0 ]; then
${CMD} login ${REGISTRY}
fi
${CMD} push ${TAG}
exit $?
fi
if [ $run == 1 ]; then
echo -e "\e[1;32mRUNNING\e[0m: ${base} as ${TAG}"
${CMD} run \
--rm \
--volume "$(pwd)/..:/home/user/app" \
--workdir "/home/user/app" \
--tty \
--interactive "${TAG}" \
bash
exit $?
fi
#!/bin/bash
set -e
builddir=$(mktemp -d build_XXXXXX)
srcdir=$(pwd)
mkdir -p _ccache
export CCACHE_BASEDIR="$(pwd)"
export CCACHE_DIR="${CCACHE_BASEDIR}/_ccache"
ccache --zero-stats
ccache --show-stats
# Disable ccache while running Meson, to avoid cached compiler tests
export CCACHE_DISABLE=true
meson ${BUILD_OPTS} ${builddir} ${srcdir} || exit $?
unset CCACHE_DISABLE
cd ${builddir}
ninja || exit $?
meson test -t 2 || exit $?
cd ..
rm -rf ${builddir}
ccache --show-stats
#!/bin/bash
set -e
if [[ "$MSYSTEM" == "MINGW32" ]]; then
export MSYS2_ARCH="i686"
else
export MSYS2_ARCH="x86_64"
fi
pacman --noconfirm -Suy
pacman --noconfirm -S --needed \
base-devel \
mingw-w64-$MSYS2_ARCH-gobject-introspection \
mingw-w64-$MSYS2_ARCH-glib2 \
mingw-w64-$MSYS2_ARCH-libjpeg-turbo \
mingw-w64-$MSYS2_ARCH-libpng \
mingw-w64-$MSYS2_ARCH-libtiff \
mingw-w64-$MSYS2_ARCH-meson \
mingw-w64-$MSYS2_ARCH-toolchain
meson setup --buildtype debug \
-Dpng=enabled \
-Djpeg=enabled \
-Dtiff=enabled \
_build
meson compile -C _build
meson test -C _build
#!/usr/bin/env python3
#
# === clang-format-diff.py - ClangFormat Diff Reformatter ---*- python -*-=== #
#
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
# ===---------------------------------------------------------------------=== #
"""
This script reads input from a unified diff and reformats all the changed
lines. This is useful to reformat all the lines touched by a specific patch.
Example usage for git/svn users:
git diff -U0 --no-color HEAD^ | clang-format-diff.py -p1 -i
svn diff --diff-cmd=diff -x-U0 | clang-format-diff.py -i
"""
from __future__ import absolute_import, division, print_function
import argparse
import difflib
import re
import subprocess
import sys
if sys.version_info.major >= 3:
from io import StringIO
else:
from io import BytesIO as StringIO
def main():
parser = argparse.ArgumentParser(
description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('-i', action='store_true', default=False,
help='apply edits to files instead of displaying a '
'diff')
parser.add_argument('-p', metavar='NUM', default=0,
help='strip the smallest prefix containing P slashes')
parser.add_argument('-regex', metavar='PATTERN', default=None,
help='custom pattern selecting file paths to reformat '
'(case sensitive, overrides -iregex)')
parser.add_argument('-iregex', metavar='PATTERN',
default=r'.*\.(cpp|cc|c\+\+|cxx|c|cl|h|hh|hpp|m|mm|inc'
r'|js|ts|proto|protodevel|java|cs)',
help='custom pattern selecting file paths to reformat '
'(case insensitive, overridden by -regex)')
parser.add_argument('-sort-includes', action='store_true', default=False,
help='let clang-format sort include blocks')
parser.add_argument('-v', '--verbose', action='store_true',
help='be more verbose, ineffective without -i')
parser.add_argument('-style',
help='formatting style to apply (LLVM, Google, '
'Chromium, Mozilla, WebKit)')
parser.add_argument('-binary', default='clang-format',
help='location of binary to use for clang-format')
args = parser.parse_args()
# Extract changed lines for each file.
filename = None
lines_by_file = {}
for line in sys.stdin:
match = re.search(r'^\+\+\+\ (.*?/){%s}(\S*)' % args.p, line)
if match:
filename = match.group(2)
if filename is None:
continue
if args.regex is not None:
if not re.match('^%s$' % args.regex, filename):
continue
else:
if not re.match('^%s$' % args.iregex, filename, re.IGNORECASE):
continue
match = re.search(r'^@@.*\+(\d+)(,(\d+))?', line)
if match:
start_line = int(match.group(1))
line_count = 1
if match.group(3):
line_count = int(match.group(3))
if line_count == 0:
continue
end_line = start_line + line_count - 1
lines_by_file.setdefault(filename, []).extend(
['-lines', str(start_line) + ':' + str(end_line)])
# Reformat files containing changes in place.
# We need to count amount of bytes generated in the output of
# clang-format-diff. If clang-format-diff doesn't generate any bytes it
# means there is nothing to format.
format_line_counter = 0
for filename, lines in lines_by_file.items():
if args.i and args.verbose:
print('Formatting {}'.format(filename))
command = [args.binary, filename]
if args.i:
command.append('-i')
if args.sort_includes:
command.append('-sort-includes')
command.extend(lines)
if args.style:
command.extend(['-style', args.style])
p = subprocess.Popen(command,
stdout=subprocess.PIPE,
stderr=None,
stdin=subprocess.PIPE,
universal_newlines=True)
stdout, _ = p.communicate()
if p.returncode != 0:
sys.exit(p.returncode)
if not args.i:
with open(filename) as f:
code = f.readlines()
formatted_code = StringIO(stdout).readlines()
diff = difflib.unified_diff(code, formatted_code,
filename, filename,
'(before formatting)',
'(after formatting)')
diff_string = ''.join(diff)
if diff_string:
format_line_counter += sys.stdout.write(diff_string)
if format_line_counter > 0:
sys.exit(1)
if __name__ == '__main__':
main()
#!/usr/bin/env python3
# Turns a Meson testlog.json file into a JUnit XML report
#
# Copyright 2019 GNOME Foundation
#
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# Original author: Emmanuele Bassi
import argparse
import datetime
import json
import os
import sys
import xml.etree.ElementTree as ET
aparser = argparse.ArgumentParser(description='Turns a Meson test log into a JUnit report')
aparser.add_argument('--project-name', metavar='NAME',
help='The project name',
default='unknown')
aparser.add_argument('--backend', metavar='NAME',
help='The used backend',
default='unknown')
aparser.add_argument('--job-id', metavar='ID',
help='The job ID for the report',
default='Unknown')
aparser.add_argument('--branch', metavar='NAME',
help='Branch of the project being tested',
default='master')
aparser.add_argument('--output', metavar='FILE',
help='The output file, stdout by default',
type=argparse.FileType('w', encoding='UTF-8'),
default=sys.stdout)
aparser.add_argument('infile', metavar='FILE',
help='The input testlog.json, stdin by default',
type=argparse.FileType('r', encoding='UTF-8'),
default=sys.stdin)
args = aparser.parse_args()
outfile = args.output
testsuites = ET.Element('testsuites')
testsuites.set('id', '{}/{}'.format(args.job_id, args.branch))
testsuites.set('package', args.project_name)
testsuites.set('timestamp', datetime.datetime.utcnow().isoformat(timespec='minutes'))
suites = {}
for line in args.infile:
data = json.loads(line)
(full_suite, unit_name) = data['name'].split(' / ')
(project_name, suite_name) = full_suite.split(':')
duration = data['duration']
return_code = data['returncode']
result = data['result']
log = data['stdout']
unit = {
'suite': suite_name,
'name': unit_name,
'duration': duration,
'returncode': return_code,
'result': result,
'stdout': log,
}
units = suites.setdefault(suite_name, [])
units.append(unit)
for name, units in suites.items():
print('Processing suite {} (units: {})'.format(name, len(units)))
def if_failed(unit):
if unit['result'] in ['ERROR', 'FAIL', 'UNEXPECTEDPASS', 'TIMEOUT']:
return True
return False
def if_succeded(unit):
if unit['result'] in ['OK', 'EXPECTEDFAIL', 'SKIP']:
return True
return False
successes = list(filter(if_succeded, units))
failures = list(filter(if_failed, units))
print(' - {}: {} pass, {} fail'.format(name, len(successes), len(failures)))
testsuite = ET.SubElement(testsuites, 'testsuite')
testsuite.set('name', '{}/{}'.format(args.project_name, name))
testsuite.set('tests', str(len(units)))
testsuite.set('errors', str(len(failures)))
testsuite.set('failures', str(len(failures)))
for unit in successes:
testcase = ET.SubElement(testsuite, 'testcase')
testcase.set('classname', '{}/{}'.format(args.project_name, unit['suite']))
testcase.set('name', '{}/{}'.format(args.backend, unit['name']))
testcase.set('time', str(unit['duration']))
for unit in failures:
testcase = ET.SubElement(testsuite, 'testcase')
testcase.set('classname', '{}/{}'.format(args.project_name, unit['suite']))
testcase.set('name', '{}/{}'.format(args.backend, unit['name']))
testcase.set('time', str(unit['duration']))
failure = ET.SubElement(testcase, 'failure')
failure.set('classname', '{}/{}'.format(args.project_name, unit['suite']))
testcase.set('name', '{}/{}'.format(args.backend, unit['name']))
failure.set('type', 'error')
failure.text = unit['stdout']
output = ET.tostring(testsuites, encoding='unicode')
outfile.write(output)
#!/bin/bash
set -e
# We need to add a new remote for the upstream master, since this script could
# be running in a personal fork of the repository which has out of date branches.
if [ "${CI_PROJECT_NAMESPACE}" != "GNOME" ]; then
echo "Retrieving the current upstream repository from ${CI_PROJECT_NAMESPACE}/${CI_PROJECT_NAME}..."
git remote add upstream https://gitlab.gnome.org/GNOME/gdk-pixbuf.git
git fetch upstream
ORIGIN="upstream"
else
echo "Reusing the existing repository on ${CI_PROJECT_NAMESPACE}/${CI_PROJECT_NAME}"
ORIGIN="origin"
fi
# Work out the newest common ancestor between the detached HEAD that this CI job
# has checked out, and the upstream target branch (which will typically be
# `upstream/master` or `upstream/gtk-3-24`).
#
# `${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}` is only defined if we’re running in
# a merge request pipeline; fall back to `${CI_DEFAULT_BRANCH}` otherwise.
newest_common_ancestor_sha=$(diff --old-line-format='' --new-line-format='' <(git rev-list --first-parent "${ORIGIN}/${CI_MERGE_REQUEST_TARGET_BRANCH_NAME:-${CI_DEFAULT_BRANCH}}") <(git rev-list --first-parent HEAD) | head -1)
git diff -U0 --no-color "${newest_common_ancestor_sha}" | .gitlab/scripts/clang-format-diff.py -binary "clang-format" -p1
exit_status=$?
# The style check is not infallible. The clang-format configuration cannot
# perfectly describe GTK’s coding style: in particular, it cannot align
# function arguments. The documented coding style for GTK takes priority over
# clang-format suggestions. Hopefully we can eventually improve clang-format to
# be configurable enough for our coding style. That’s why this CI check is OK
# to fail: the idea is that people can look through the output and ignore it if
# it’s wrong. (That situation can also happen if someone touches pre-existing
# badly formatted code and it doesn’t make sense to tidy up the wider coding
# style with the changes they’re making.)
echo ""
echo "Note that clang-format output is advisory and cannot always match the"
echo "GTK coding style, documented at:"
echo " https://gitlab.gnome.org/GNOME/gtk/blob/master/docs/CODING-STYLE"
echo "Warnings from this tool can be ignored in favour of the documented "
echo "coding style, or in favour of matching the style of existing"
echo "surrounding code."
exit ${exit_status}
#!/bin/bash
set +x
set +e
srcdir=$( pwd )
builddir=$1
backend=$2
meson test -C ${builddir}
# Store the exit code for the CI run, but always
# generate the reports
exit_code=$?
cd ${builddir}
${srcdir}/.gitlab/scripts/meson-junit-report.py \
--project-name=gdk-pixbuf \
--job-id="${CI_JOB_NAME}" \
--output=report-${CI_JOB_NAME}.xml \
meson-logs/testlog.json
exit $exit_code
2.42.8 (stable)
===
- Clear the pixbuf's memory buffer to avoid returning uninitialized memory [#199]
- Turn GdkPixbufModule functions into typed callbacks [!123]
- tiff: Use non-deprecated C99 integer types [!124]
- gif: Check for overflow when compositing or clearing frames [#190]
- Change png/jpeg/tiff build options from boolean to feature [!118]
- jpeg: Do not rely on UB around setjmp/longjmp [#143]
- Build fixes [!114, #185, #182]
- Documentation fixes [!120, !125]
- Translation updates
2.42.6 (stable)
===
......
......@@ -393,6 +393,7 @@ gdk_pixbuf_io_init_modules (const char *filename,
channel = g_io_channel_new_file (filename, "r", &local_error);
if (!channel) {
char *filename_utf8 = g_filename_display_name (filename);
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_INVALID_ARGUMENT,
......@@ -401,9 +402,10 @@ gdk_pixbuf_io_init_modules (const char *filename,
"Try running the command\n"
" gdk-pixbuf-query-loaders > %s\n"
"to make things work again for the time being.",
filename, local_error->message, filename);
filename_utf8, local_error->message, filename_utf8);
g_clear_error (&local_error);
g_string_free (tmp_buf, TRUE);
g_free (filename_utf8);
return FALSE;
}
......@@ -544,11 +546,13 @@ gdk_pixbuf_io_init_modules (const char *filename,
g_io_channel_unref (channel);
if (g_slist_length (file_formats) <= num_formats) {
char *filename_utf8 = g_filename_display_name (filename);
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_NOT_INITIALIZED,
"No new GdkPixbufModule loaded from '%s'",
filename);
filename_utf8);
g_free (filename_utf8);
return FALSE;
}
#endif
......@@ -797,11 +801,13 @@ gdk_pixbuf_load_module_unlocked (GdkPixbufModule *image_module,
module = g_module_open (path, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
if (!module) {
char *path_utf8 = g_filename_display_name (path);
g_set_error (error,
GDK_PIXBUF_ERROR,
GDK_PIXBUF_ERROR_FAILED,
_("Unable to load image-loading module: %s: %s"),
path, g_module_error ());
path_utf8, g_module_error ());
g_free (path_utf8);
return FALSE;
}
......@@ -812,11 +818,13 @@ gdk_pixbuf_load_module_unlocked (GdkPixbufModule *image_module,
(* fill_vtable) (image_module);
return TRUE;
} else {
char *path_utf8 = g_filename_display_name (path);
g_set_error (error,
GDK_PIXBUF_ERROR,
GDK_PIXBUF_ERROR_FAILED,
_("Image-loading module %s does not export the proper interface; perhaps it’s from a different gdk-pixbuf version?"),
path);
path_utf8);
g_free (path_utf8);
return FALSE;
}
}
......
......@@ -214,56 +214,189 @@ struct _GdkPixbufModulePattern {
int relevance;
};
/**
* GdkPixbufModuleLoadFunc:
* @f: the file stream from which the image should be loaded
* @error: return location for a loading error
*
* Loads a file from a standard C file stream into a new `GdkPixbuf`.
*
* In case of error, this function should return `NULL` and set the `error` argument.
*
* Returns: (transfer full): a newly created `GdkPixbuf` for the contents of the file
*/
typedef GdkPixbuf *(* GdkPixbufModuleLoadFunc) (FILE *f,
GError **error);
/**
* GdkPixbufModuleLoadXpmDataFunc:
* @data: (array zero-terminated=1): the XPM data
*
* Loads XPM data into a new `GdkPixbuf`.
*
* Returns: (transfer full): a newly created `GdkPixbuf` for the XPM data
*/
typedef GdkPixbuf *(* GdkPixbufModuleLoadXpmDataFunc) (const char **data);
/**
* GdkPixbufModuleLoadAnimationFunc:
* @f: the file stream from which the image should be loaded
* @error: return location for a loading error
*
* Loads a file from a standard C file stream into a new `GdkPixbufAnimation`.
*
* In case of error, this function should return `NULL` and set the `error` argument.
*
* Returns: (transfer full): a newly created `GdkPixbufAnimation` for the contents of the file
*/
typedef GdkPixbufAnimation *(* GdkPixbufModuleLoadAnimationFunc) (FILE *f,
GError **error);
/**
* GdkPixbufModuleBeginLoadFunc:
* @size_func: the function to be called when the size is known
* @prepared_func: the function to be called when the data has been prepared
* @updated_func: the function to be called when the data has been updated
* @user_data: the data to be passed to the functions
* @error: return location for a loading error
*
* Sets up the image loading state.
*
* The image loader is responsible for storing the given function pointers
* and user data, and call them when needed.
*
* The image loader should set up an internal state object, and return it
* from this function; the state object will then be updated from the
* [callback@GdkPixbuf.PixbufModuleIncrementLoadFunc] callback, and will be freed
* by [callback@GdkPixbuf.PixbufModuleStopLoadFunc] callback.
*
* Returns: (transfer full): the data to be passed to
* [callback@GdkPixbuf.PixbufModuleIncrementLoadFunc]
* and [callback@GdkPixbuf.PixbufModuleStopLoadFunc], or `NULL` in case of error
*/
typedef gpointer (* GdkPixbufModuleBeginLoadFunc) (GdkPixbufModuleSizeFunc size_func,
GdkPixbufModulePreparedFunc prepared_func,
GdkPixbufModuleUpdatedFunc updated_func,
gpointer user_data,
GError **error);
/**
* GdkPixbufModuleStopLoadFunc:
* @context: (transfer full): the state object created by [callback@GdkPixbuf.PixbufModuleBeginLoadFunc]
* @error: return location for a loading error
*
* Finalizes the image loading state.
*
* This function is called on success and error states.
*
* Returns: `TRUE` if the loading operation was successful
*/
typedef gboolean (* GdkPixbufModuleStopLoadFunc) (gpointer context,
GError **error);
/**
* GdkPixbufModuleIncrementLoadFunc:
* @context: (transfer none): the state object created by [callback@GdkPixbuf.PixbufModuleBeginLoadFunc]
* @buf: (array length=size) (element-type guint8): the data to load
* @size: the length of the data to load
* @error: return location for a loading error
*
* Incrementally loads a buffer into the image data.
*
* Returns: `TRUE` if the incremental load was successful
*/
typedef gboolean (* GdkPixbufModuleIncrementLoadFunc) (gpointer context,
const guchar *buf,
guint size,
GError **error);
/**
* GdkPixbufModuleSaveFunc:
* @f: the file stream into which the image should be saved
* @pixbuf: the image to save
* @param_keys: (nullable) (array zero-terminated=1): parameter keys to save
* @param_values: (nullable) (array zero-terminated=1): parameter values to save
* @error: return location for a saving error
*
* Saves a `GdkPixbuf` into a standard C file stream.
*
* The optional `param_keys` and `param_values` arrays contain the keys and
* values (in the same order) for attributes to be saved alongside the image
* data.
*
* Returns: `TRUE` on success; in case of failure, `FALSE` is returned and
* the `error` is set
*/
typedef gboolean (* GdkPixbufModuleSaveFunc) (FILE *f,
GdkPixbuf *pixbuf,
gchar **param_keys,
gchar **param_values,
GError **error);
/**
* GdkPixbufModuleSaveCallbackFunc:
* @save_func: the function to call when saving
* @user_data: (closure): the data to pass to @save_func
* @pixbuf: the `GdkPixbuf` to save
* @option_keys: (nullable) (array zero-terminated=1): an array of option names
* @option_values: (nullable) (array zero-terminated=1): an array of option values
* @error: return location for a save error
*
* Saves a `GdkPixbuf` by calling the provided function.
*
* The optional `option_keys` and `option_values` arrays contain the keys and
* values (in the same order) for attributes to be saved alongside the image
* data.
*
* Returns: `TRUE` on success; in case of failure, `FALSE` is returned and
* the `error` is set
*/
typedef gboolean (* GdkPixbufModuleSaveCallbackFunc) (GdkPixbufSaveFunc save_func,
gpointer user_data,
GdkPixbuf *pixbuf,
gchar **option_keys,
gchar **option_values,
GError **error);
/**
* GdkPixbufModuleSaveOptionSupportedFunc:
* @option_key: the option key to check
*
* Checks whether the given `option_key` is supported when saving.
*
* Returns: `TRUE` if the option is supported
*/
typedef gboolean (* GdkPixbufModuleSaveOptionSupportedFunc) (const gchar *option_key);
typedef struct _GdkPixbufModule GdkPixbufModule;
struct _GdkPixbufModule {
char *module_name;
char *module_path;
GModule *module;
GdkPixbufFormat *info;
GdkPixbuf *(* load) (FILE *f,
GError **error);
GdkPixbuf *(* load_xpm_data) (const char **data);
/* Incremental loading */
/* Atomic loading */
GdkPixbufModuleLoadFunc load;
GdkPixbufModuleLoadXpmDataFunc load_xpm_data;
gpointer (* begin_load) (GdkPixbufModuleSizeFunc size_func,
GdkPixbufModulePreparedFunc prepared_func,
GdkPixbufModuleUpdatedFunc updated_func,
gpointer user_data,
GError **error);
gboolean (* stop_load) (gpointer context,
GError **error);
gboolean (* load_increment) (gpointer context,
const guchar *buf,
guint size,
GError **error);
/* Incremental loading */
GdkPixbufModuleBeginLoadFunc begin_load;
GdkPixbufModuleStopLoadFunc stop_load;
GdkPixbufModuleIncrementLoadFunc load_increment;
/* Animation loading */
GdkPixbufAnimation *(* load_animation) (FILE *f,
GError **error);
GdkPixbufModuleLoadAnimationFunc load_animation;
/* Saving */
gboolean (* save) (FILE *f,
GdkPixbuf *pixbuf,
gchar **param_keys,
gchar **param_values,
GError **error);
gboolean (*save_to_callback) (GdkPixbufSaveFunc save_func,
gpointer user_data,
GdkPixbuf *pixbuf,
gchar **option_keys,
gchar **option_values,
GError **error);
gboolean (* is_save_option_supported) (const gchar *option_key);
/*< private >*/
void (*_reserved1) (void);
void (*_reserved2) (void);
void (*_reserved3) (void);
void (*_reserved4) (void);
GdkPixbufModuleSaveFunc save;
GdkPixbufModuleSaveCallbackFunc save_to_callback;
GdkPixbufModuleSaveOptionSupportedFunc is_save_option_supported;
/*< private >*/
void (*_reserved1) (void);
void (*_reserved2) (void);
void (*_reserved3) (void);
void (*_reserved4) (void);
};
/**
......@@ -275,7 +408,6 @@ struct _GdkPixbufModule {
*
* Since: 2.2
*/
typedef void (* GdkPixbufModuleFillVtableFunc) (GdkPixbufModule *module);
/**
......
......@@ -631,7 +631,7 @@ gdk_pixbuf_new (GdkColorspace colorspace,
if (rowstride <= 0)
return NULL;
buf = g_try_malloc_n (height, rowstride);
buf = g_try_malloc0_n (height, rowstride);
if (!buf)
return NULL;
......@@ -817,7 +817,7 @@ gdk_pixbuf_get_bits_per_sample (const GdkPixbuf *pixbuf)
* This function will cause an implicit copy of the pixbuf data if the
* pixbuf was created from read-only data.
*
* Please see the section on [image data](#image-data) for information
* Please see the section on [image data](class.Pixbuf.html#image-data) for information
* about how the pixel data is stored in memory.
*
* Return value: (array): A pointer to the pixbuf's pixel data.
......@@ -864,7 +864,7 @@ downgrade_to_pixels (const GdkPixbuf *pixbuf)
* This function will cause an implicit copy of the pixbuf data if the
* pixbuf was created from read-only data.
*
* Please see the section on [image data](#image-data) for information
* Please see the section on [image data](class.Pixbuf.html#image-data) for information
* about how the pixel data is stored in memory.
*
* Return value: (array length=length): A pointer to the pixbuf's
......
......@@ -1307,10 +1307,10 @@ gdk_pixbuf__bmp_image_load_increment(gpointer data,
case READ_STATE_PALETTE:
if (!DecodeColormap (context->buff, context, error)) {
g_set_error (error,
GDK_PIXBUF_ERROR,
GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
_("Error while decoding colormap"));
g_set_error_literal (error,
GDK_PIXBUF_ERROR,
GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
_("Error while decoding colormap"));
return FALSE;
}
break;
......
......@@ -369,7 +369,7 @@ composite_frame (GdkPixbufGifAnim *anim, GdkPixbufFrame *frame)
for (i = 0; i < n_indexes; i++) {
guint8 index = index_buffer[i];
guint x, y;
int offset;
gsize offset;
if (index == frame->transparent_index)
continue;
......@@ -379,11 +379,13 @@ composite_frame (GdkPixbufGifAnim *anim, GdkPixbufFrame *frame)
if (x >= anim->width || y >= anim->height)
continue;
offset = y * gdk_pixbuf_get_rowstride (anim->last_frame_data) + x * 4;
pixels[offset + 0] = frame->color_map[index * 3 + 0];
pixels[offset + 1] = frame->color_map[index * 3 + 1];
pixels[offset + 2] = frame->color_map[index * 3 + 2];
pixels[offset + 3] = 255;
if (g_size_checked_mul (&offset, gdk_pixbuf_get_rowstride (anim->last_frame_data), y) &&
g_size_checked_add (&offset, offset, x * 4)) {
pixels[offset + 0] = frame->color_map[index * 3 + 0];
pixels[offset + 1] = frame->color_map[index * 3 + 1];
pixels[offset + 2] = frame->color_map[index * 3 + 2];
pixels[offset + 3] = 255;
}
}
out:
......@@ -448,8 +450,11 @@ gdk_pixbuf_gif_anim_iter_get_pixbuf (GdkPixbufAnimationIter *anim_iter)
x_end = MIN (anim->last_frame->x_offset + anim->last_frame->width, anim->width);
y_end = MIN (anim->last_frame->y_offset + anim->last_frame->height, anim->height);
for (y = anim->last_frame->y_offset; y < y_end; y++) {
guchar *line = pixels + y * gdk_pixbuf_get_rowstride (anim->last_frame_data) + anim->last_frame->x_offset * 4;
memset (line, 0, (x_end - anim->last_frame->x_offset) * 4);
gsize offset;
if (g_size_checked_mul (&offset, gdk_pixbuf_get_rowstride (anim->last_frame_data), y) &&
g_size_checked_add (&offset, offset, anim->last_frame->x_offset * 4)) {
memset (pixels + offset, 0, (x_end - anim->last_frame->x_offset) * 4);
}
}
break;
case GDK_PIXBUF_FRAME_REVERT:
......
......@@ -552,7 +552,7 @@ jpeg_destroy_exif_context (JpegExifContext *context)
/* Shared library entry point */
static GdkPixbuf *
gdk_pixbuf__jpeg_image_load (FILE *f, GError **error)
gdk_pixbuf__real_jpeg_image_load (FILE *f, struct jpeg_decompress_struct *cinfo, GError **error)
{
gint i;
char otag_str[5];
......@@ -565,7 +565,6 @@ gdk_pixbuf__jpeg_image_load (FILE *f, GError **error)
* at most 4."
*/
guchar **lptr;
struct jpeg_decompress_struct cinfo;
struct error_handler_data jerr;
stdio_src_ptr src;
gchar *icc_profile_base64;
......@@ -573,7 +572,7 @@ gdk_pixbuf__jpeg_image_load (FILE *f, GError **error)
JpegExifContext exif_context = { 0, };
/* setup error handler */
cinfo.err = jpeg_std_error (&jerr.pub);
cinfo->err = jpeg_std_error (&jerr.pub);
jerr.pub.error_exit = fatal_error_handler;
jerr.pub.output_message = output_message_handler;
jerr.error = error;
......@@ -583,7 +582,7 @@ gdk_pixbuf__jpeg_image_load (FILE *f, GError **error)
if (pixbuf)
g_object_unref (pixbuf);
jpeg_destroy_decompress (&cinfo);
jpeg_destroy_decompress (cinfo);
jpeg_destroy_exif_context (&exif_context);
/* error should have been set by fatal_error_handler () */
......@@ -591,14 +590,14 @@ gdk_pixbuf__jpeg_image_load (FILE *f, GError **error)
}
/* load header, setup */
jpeg_create_decompress (&cinfo);
jpeg_create_decompress (cinfo);
cinfo.src = (struct jpeg_source_mgr *)
(*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT,
cinfo->src = (struct jpeg_source_mgr *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
sizeof (stdio_source_mgr));
src = (stdio_src_ptr) cinfo.src;
src = (stdio_src_ptr) cinfo->src;
src->buffer = (JOCTET *)
(*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT,
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
JPEG_PROG_BUF_SIZE * sizeof (JOCTET));
src->pub.init_source = stdio_init_source;
......@@ -610,21 +609,23 @@ gdk_pixbuf__jpeg_image_load (FILE *f, GError **error)
src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
src->pub.next_input_byte = NULL; /* until buffer loaded */
jpeg_save_markers (&cinfo, JPEG_APP0+1, 0xffff);
jpeg_save_markers (&cinfo, JPEG_APP0+2, 0xffff);
jpeg_save_markers (&cinfo, JPEG_COM, 0xffff);
jpeg_read_header (&cinfo, TRUE);
jpeg_save_markers (cinfo, JPEG_APP0+1, 0xffff);
jpeg_save_markers (cinfo, JPEG_APP0+2, 0xffff);
jpeg_save_markers (cinfo, JPEG_COM, 0xffff);
jpeg_read_header (cinfo, TRUE);
/* parse exif data */
jpeg_parse_exif (&exif_context, &cinfo);
jpeg_parse_exif (&exif_context, cinfo);
jpeg_start_decompress (&cinfo);
cinfo.do_fancy_upsampling = FALSE;
cinfo.do_block_smoothing = FALSE;
jpeg_start_decompress (cinfo);
cinfo->do_fancy_upsampling = FALSE;
cinfo->do_block_smoothing = FALSE;
pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
cinfo.out_color_components == 4 ? TRUE : FALSE,
8, cinfo.output_width, cinfo.output_height);
cinfo->out_color_components == 4 ? TRUE : FALSE,
8,
cinfo->output_width,
cinfo->output_height);
if (!pixbuf) {
/* broken check for *error == NULL for robustness against
......@@ -640,28 +641,28 @@ gdk_pixbuf__jpeg_image_load (FILE *f, GError **error)
goto out;
}
comment = jpeg_get_comment (&cinfo);
comment = jpeg_get_comment (cinfo);
if (comment != NULL) {
gdk_pixbuf_set_option (pixbuf, "comment", comment);
g_free (comment);
}
switch (cinfo.density_unit) {
switch (cinfo->density_unit) {
case 1:
/* Dots per inch (no conversion required) */
density_str = g_strdup_printf ("%d", cinfo.X_density);
density_str = g_strdup_printf ("%d", cinfo->X_density);
gdk_pixbuf_set_option (pixbuf, "x-dpi", density_str);
g_free (density_str);
density_str = g_strdup_printf ("%d", cinfo.Y_density);
density_str = g_strdup_printf ("%d", cinfo->Y_density);
gdk_pixbuf_set_option (pixbuf, "y-dpi", density_str);
g_free (density_str);
break;
case 2:
/* Dots per cm - convert into dpi */
density_str = g_strdup_printf ("%d", DPCM_TO_DPI (cinfo.X_density));
density_str = g_strdup_printf ("%d", DPCM_TO_DPI (cinfo->X_density));
gdk_pixbuf_set_option (pixbuf, "x-dpi", density_str);
g_free (density_str);
density_str = g_strdup_printf ("%d", DPCM_TO_DPI (cinfo.Y_density));
density_str = g_strdup_printf ("%d", DPCM_TO_DPI (cinfo->Y_density));
gdk_pixbuf_set_option (pixbuf, "y-dpi", density_str);
g_free (density_str);
break;
......@@ -683,24 +684,24 @@ gdk_pixbuf__jpeg_image_load (FILE *f, GError **error)
dptr = gdk_pixbuf_get_pixels (pixbuf);
/* decompress all the lines, a few at a time */
while (cinfo.output_scanline < cinfo.output_height) {
while (cinfo->output_scanline < cinfo->output_height) {
lptr = lines;
for (i = 0; i < cinfo.rec_outbuf_height; i++) {
for (i = 0; i < cinfo->rec_outbuf_height; i++) {
*lptr++ = dptr;
dptr += gdk_pixbuf_get_rowstride (pixbuf);
}
jpeg_read_scanlines (&cinfo, lines, cinfo.rec_outbuf_height);
jpeg_read_scanlines (cinfo, lines, cinfo->rec_outbuf_height);
switch (cinfo.out_color_space) {
switch (cinfo->out_color_space) {
case JCS_GRAYSCALE:
explode_gray_into_buf (&cinfo, lines);
explode_gray_into_buf (cinfo, lines);
break;
case JCS_RGB:
/* do nothing */
break;
case JCS_CMYK:
convert_cmyk_to_rgb (&cinfo, lines);
convert_cmyk_to_rgb (cinfo, lines);
break;
default:
g_clear_object (&pixbuf);
......@@ -708,19 +709,27 @@ gdk_pixbuf__jpeg_image_load (FILE *f, GError **error)
GDK_PIXBUF_ERROR,
GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
_("Unsupported JPEG color space (%s)"),
colorspace_name (cinfo.out_color_space));
colorspace_name (cinfo->out_color_space));
goto out;
}
}
out:
jpeg_finish_decompress (&cinfo);
jpeg_destroy_decompress (&cinfo);
jpeg_finish_decompress (cinfo);
jpeg_destroy_decompress (cinfo);
jpeg_destroy_exif_context (&exif_context);
return pixbuf;
}
static GdkPixbuf *
gdk_pixbuf__jpeg_image_load (FILE *f, GError **error)
{
struct jpeg_decompress_struct cinfo;
return gdk_pixbuf__real_jpeg_image_load (f, &cinfo, error);
}
/**** Progressive image loading handling *****/
......
......@@ -29,6 +29,7 @@
#include "config.h"
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
......@@ -97,13 +98,13 @@ tiff_image_parse (TIFF *tiff, TiffContext *context, GError **error)
gint width, height, rowstride, bytes;
GdkPixbuf *pixbuf;
guint16 bits_per_sample = 0;
uint16 orientation = 0;
uint16 transform = 0;
uint16 codec;
uint16_t orientation = 0;
uint16_t transform = 0;
uint16_t codec;
gchar *icc_profile_base64;
const gchar *icc_profile;
guint icc_profile_size;
uint16 resolution_unit;
uint16_t resolution_unit;
gchar *density_str;
gint retval;
......@@ -279,7 +280,7 @@ tiff_image_parse (TIFF *tiff, TiffContext *context, GError **error)
if (context)
(* context->prepared_func) (pixbuf, NULL, context->user_data);
if (!TIFFReadRGBAImageOriented (tiff, width, height, (uint32 *)pixels, ORIENTATION_TOPLEFT, 1)) {
if (!TIFFReadRGBAImageOriented (tiff, width, height, (uint32_t *)pixels, ORIENTATION_TOPLEFT, 1)) {
g_set_error_literal (error,
GDK_PIXBUF_ERROR,
GDK_PIXBUF_ERROR_FAILED,
......@@ -951,7 +952,7 @@ gdk_pixbuf__tiff_image_save_to_callback (GdkPixbufSaveFunc save_func,
if (x_dpi != NULL && y_dpi != NULL) {
char *endptr = NULL;
uint16 resolution_unit = RESUNIT_INCH;
uint16_t resolution_unit = RESUNIT_INCH;
float x_dpi_value, y_dpi_value;
x_dpi_value = strtol (x_dpi, &endptr, 10);
......
......@@ -309,8 +309,8 @@ endforeach
# Build the loaders using native Windows components as dynamic modules, if requested
if native_windows_loaders
if not (builtin_loaders.contains('windows') or builtin_all_loaders)
foreach name, loader: windows_native_loader_formats
loader_sources = windows_base_loader_sources + [ 'io-gdip-@0@.c'.format(name) ]
foreach loader: windows_native_loader_formats
loader_sources = windows_base_loader_sources + [ 'io-gdip-@0@.c'.format(loader) ]
mod = shared_module('pixbufloader-gdip-@0@'.format(loader),
loader_sources,
......
project('gdk-pixbuf', 'c',
version: '2.42.6',
version: '2.42.8',
license: 'LGPL-2.1-or-later',
default_options: [
'buildtype=debugoptimized',
......@@ -253,57 +253,47 @@ endif
enabled_loaders = []
loaders_deps = []
if get_option('png')
# We have a vast selection of libpng versions to choose from
foreach png: [ 'libpng16', 'libpng15', 'libpng14', 'libpng13', 'libpng12', 'libpng10' ]
if not enabled_loaders.contains('png')
png_dep = dependency(png, required: false)
png_opt = get_option('png')
if not png_opt.disabled()
png_dep = dependency('libpng', required: false)
if not png_dep.found() and cc.has_header('png.h')
# MSVC: First look for the DLL + import .lib build of libpng,
# which is normally libpngxx.lib, when libpng's pkg-config can't
# be found, which is quite normal on MSVC.
foreach png: [ 'libpng16', 'libpng15', 'libpng14', 'libpng12', 'libpng13', 'libpng10' ]
png_dep = cc.find_library(png, required: false)
if png_dep.found()
enabled_loaders += 'png'
loaders_deps += png_dep
endif
endif
endforeach
if not enabled_loaders.contains('png')
if cc.get_id() == 'msvc' and cc.has_header('png.h')
# MSVC: First look for the DLL + import .lib build of libpng,
# which is normally libpngxx.lib, when libpng's pkg-config can't
# be found, which is quite normal on MSVC.
foreach png: [ 'libpng16', 'libpng15', 'libpng14', 'libpng12', 'libpng13', 'libpng10' ]
if not enabled_loaders.contains('png')
png_dep = cc.find_library(png, required: false)
if png_dep.found()
enabled_loaders += 'png'
loaders_deps += png_dep
endif
endif
endforeach
# If we still can't find libpng, try looking for the static libpng.lib,
# which means we need to ensure we have the static zlib .lib as well
if not enabled_loaders.contains('png')
png_dep = cc.find_library('libpng', required: false)
zlib_dep = cc.find_library('zlib', required: false)
if png_dep.found() and zlib_dep.found()
enabled_loaders += 'png'
loaders_deps += [ png_dep, zlib_dep ]
endif
break
endif
endif
endforeach
# Finally, look for the dependency in a fallback subproject if allowed by
# the --wrap-mode option. We don't directly call subproject() here because
# that will bypass --wrap-mode and cause issues for distro packagers.
# See: https://mesonbuild.com/Reference-manual.html#dependency
# If we still can't find libpng, try looking for the static libpng.lib,
# which means we need to ensure we have the static zlib .lib as well
if not png_dep.found()
png_dep = dependency('', required: false, fallback: 'libpng')
if png_dep.found()
enabled_loaders += 'png'
loaders_deps += png_dep
png_dep = cc.find_library('libpng', required: false)
zlib_dep = cc.find_library('zlib', required: false)
if png_dep.found() and zlib_dep.found()
loaders_deps += zlib_dep
endif
endif
endif
# Finally, look for the dependency in a fallback subproject if allowed by
# the --wrap-mode option. We don't directly call subproject() here because
# that will bypass --wrap-mode and cause issues for distro packagers.
# See: https://mesonbuild.com/Reference-manual.html#dependency
if not png_dep.found()
png_dep = dependency('libpng',
fallback: ['libpng', 'libpng_dep'],
required: png_opt,
)
endif
if png_dep.found()
enabled_loaders += 'png'
loaders_deps += png_dep
endif
endif
# On Windows, check whether we are building the native Windows loaders
......@@ -323,46 +313,66 @@ if native_windows_loaders
endif
# Don't check and build the jpeg loader if native_windows_loaders is true
if get_option('jpeg') and not native_windows_loaders
if cc.has_header('jpeglib.h')
jpeg_opt = get_option('jpeg')
if not jpeg_opt.disabled() and not native_windows_loaders
jpeg_dep = dependency('libjpeg', required: false)
if not jpeg_dep.found() and cc.has_header('jpeglib.h')
jpeg_dep = cc.find_library('jpeg', required: false)
if cc.get_id() == 'msvc' and not jpeg_dep.found()
# The IJG JPEG library builds the .lib file as libjpeg.lib in its MSVC build system,
# so look for it as well when jpeg.lib cannot be found
jpeg_dep = cc.find_library('libjpeg', required: false)
endif
endif
if not jpeg_dep.found()
jpeg_dep = dependency('libjpeg', required: false, fallback: 'libjpeg')
endif
# Finally, look for the dependency in a fallback
if not jpeg_dep.found()
jpeg_dep = dependency('libjpeg',
fallback: ['libjpeg-turbo', 'jpeg_dep'],
required: jpeg_opt,
)
endif
if jpeg_dep.found() and cc.has_function('jpeg_destroy_decompress', dependencies: jpeg_dep)
enabled_loaders += 'jpeg'
loaders_deps += jpeg_dep
if jpeg_dep.found()
enabled_loaders += 'jpeg'
loaders_deps += jpeg_dep
gdk_pixbuf_conf.set('HAVE_PROGRESSIVE_JPEG',
cc.has_function('jpeg_simple_progression',
dependencies: jpeg_dep))
if jpeg_dep.type_name() == 'internal'
has_destroy_decompress = true
has_simple_progression = true
else
has_destroy_decompress = cc.has_function('jpeg_destroy_decompress', dependencies: jpeg_dep)
has_simple_progression = cc.has_function('jpeg_simple_progression', dependencies: jpeg_dep)
endif
if has_destroy_decompress and has_simple_progression
gdk_pixbuf_conf.set('HAVE_PROGRESSIVE_JPEG', has_simple_progression)
endif
endif
endif
# Don't check and build the tiff loader if native_windows_loaders is true
if get_option('tiff') and not native_windows_loaders
tiff_opt = get_option('tiff')
if not tiff_opt.disabled() and not native_windows_loaders
tiff_dep = dependency('libtiff-4', required: false)
if not tiff_dep.found()
# Fallback when no pkg-config file is found for libtiff on MSVC, which is quite normal
if cc.get_id() == 'msvc' and cc.has_header('tiff.h')
# First look for the DLL builds of libtiff, then the static builds
tiff_dep = cc.find_library('libtiff_i', required: false)
if not tiff_dep.found()
# For the static lib, zlib and libjpeg .lib's have been looked for first, and
# they are optional for libtiff
tiff_dep = cc.find_library('libtiff', required: false)
endif
if not tiff_dep.found() and cc.has_header('tiff.h')
# First look for the DLL builds of libtiff, then the static builds
tiff_dep = cc.find_library('libtiff_i', required: false)
if not tiff_dep.found()
# For the static lib, zlib and libjpeg .lib's have been looked for first, and
# they are optional for libtiff
tiff_dep = cc.find_library('libtiff', required: false)
endif
endif
# We currently don't have a fallback subproject, but this handles error
# reporting if tiff_opt is enabled.
if not tiff_dep.found()
tiff_dep = dependency('libtiff-4', required: tiff_opt)
endif
if tiff_dep.found()
enabled_loaders += 'tiff'
loaders_deps += tiff_dep
......