Compare commits

..

18 Commits

Author SHA1 Message Date
Chun-wei Fan
24d25b0db5 build: Check HarfBuzz has GDI support built in on Windows
We are using APIs from there.  Also enable GDI and DirectWrite if we are
building HarfBuzz as a fallback, and remove an extraneous HarfBuzz dependency
declaration.
2022-07-08 17:14:04 +08:00
Chun-wei Fan
30147b1a99 gtkimcontextime.c: Port to Pango2 APIs
Update the code to use Pango2 APIs, by removing includes to pangowin32, which
is gone, and replacing relevant calls to Pango2 equivilants.

Replace the call to pango_win32_font_logfontw() by retrieving instead the
underlying hb_font_t, and calling hb_uniscribe_font_get_logfontw(), but preedit
fonts are currently not working until a resolution to HarfBuzz issue #3683 can
be found.  Since we are still using Windows IME APIs for input, we need the
HarfBuzz GDI/Uniscribe items to be included in the HarfBuzz builds.
2022-07-08 17:14:04 +08:00
Chun-wei Fan
3979def662 GSK Vulkan: WIP port to Pango2 2022-07-08 17:14:04 +08:00
Chun-wei Fan
71ea2e2ecb gdk/win32: WIP Port to Pango2 2022-07-08 17:13:54 +08:00
Chun-wei Fan
c79b4e2e56 build: Don't try to use pangowin32 in deps
It's no longer there for Pango2.
2022-07-08 11:53:29 +08:00
Matthias Clasen
f7c4b26c59 Make a standalone font explorer
This is the font features demo, broken out as
a standalone application and cleaned up.
2022-07-06 13:45:11 -04:00
Matthias Clasen
a13cfde2a9 fixup clear_template 2022-07-05 20:43:53 -04:00
Emmanuele Bassi
3a5d161b8a Add gtk_widget_clear_template()
The dual of gtk_widget_init_template(), which should be used to clear
the template data associated with a specific GtkWidget type.
2022-07-05 20:43:53 -04:00
Matthias Clasen
baabb57df3 font demo: Keep up with api churn 2022-07-05 14:22:04 -04:00
Matthias Clasen
a69d39d945 fontchooser: Small fixes
Make initial property values match.
2022-07-05 14:22:04 -04:00
Matthias Clasen
646149bc72 Fontchooser: Add palette support
For fonts that have color palettes, optionally
allow the user to select one.

This is behind the new GTK_FONT_CHOOSER_LEVEL_PALETTE
flag. If it is enabled, you can use
gtk_font_chooser_get_palette() to get the
selected palette name.

The testfontchooserdialog test lets you play with
this. Fonts to try tihs with are Amiri Quran Colored
or the Bungee Color family.
2022-07-04 10:37:20 -04:00
Matthias Clasen
b01eb0600c Font demo: Add color palettes 2022-07-04 10:36:52 -04:00
Matthias Clasen
5b92bf51a0 Font demo: Keep a single paragraph
This is currently required for line height to
take effect (we may want to make the leading-trim
changeable).
2022-07-04 10:36:52 -04:00
Matthias Clasen
8ab180b3a9 Port to pango2 api 2022-07-04 10:36:48 -04:00
Matthias Clasen
897195b2f5 Compare family names case-insensitively 2022-07-04 10:36:47 -04:00
Matthias Clasen
d595cc1c55 Use modern C++
This is needed to build HarfBuzz as a subproject.
2022-07-04 10:36:47 -04:00
Matthias Clasen
2841256260 fontchooser: Make size level effective
We were not hiding the size controls on the tweaks
page, which is arguably what should happen when
the size level is disabled.
2022-07-04 10:36:47 -04:00
Matthias Clasen
ff0fec0f7d Beef up testfontchooserdialog
Allow testing levels.
2022-07-04 10:36:47 -04:00
2554 changed files with 135255 additions and 203526 deletions

View File

@@ -4,7 +4,6 @@ AlwaysBreakAfterDefinitionReturnType: All
BreakBeforeBinaryOperators: None
BinPackParameters: false
SpaceAfterCStyleCast: true
PointerAlignment: Right
# Our column limit is actually 80, but setting that results in clang-format
# making a lot of dubious hanging-indent choices; disable it and assume the
# developer will line wrap appropriately. clang-format will still check

1
.gitignore vendored
View File

@@ -1,2 +1 @@
/subprojects/*/
.flatpak-builder/

View File

@@ -3,7 +3,6 @@ include:
file: 'flatpak/flatpak_ci_initiative.yml'
stages:
- check
- build
- analysis
- docs
@@ -22,35 +21,29 @@ stages:
# Common variables
variables:
COMMON_MESON_FLAGS: "-Dwerror=true -Dcairo:werror=false -Dgi-docgen:werror=false -Dgraphene:werror=false -Dlibepoxy:werror=false -Dlibsass:werror=false -Dpango:werror=false -Dsassc:werror=false -Dgdk-pixbuf:werror=false -Dglib:werror=false -Dlibcloudproviders:werror=false -Dlibpng:werror=false -Dlibtiff:werror=false -Dsysprof:werror=false -Dwayland-protocols:werror=false -Dharfbuzz:werror=false -Dfreetype2:werror=false -Dfontconfig:werror=false -Dfribidi:werror=false -Dlibffi:werror=false -Dlibjpeg-turbo:werror=false -Dmutest:werror=false -Dpixman:werror=false -Dproxy-libintl:werror=false"
COMMON_MESON_FLAGS: "-Dwerror=true -Dglib:werror=false -Dpango:werror=false -Dgtk-doc:werror=false -Dwayland-protocols:werror=false -Dsysprof:werror=false"
BACKEND_FLAGS: "-Dx11-backend=true -Dwayland-backend=true -Dbroadway-backend=true"
FEATURE_FLAGS: "-Dvulkan=enabled -Dcloudproviders=enabled -Dbuild-testsuite=true -Dintrospection=enabled"
FEATURE_FLAGS: "-Dvulkan=enabled -Dcloudproviders=enabled"
MESON_TEST_TIMEOUT_MULTIPLIER: 3
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v46"
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v38"
FLATPAK_IMAGE: "registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:master"
workflow:
rules:
- if: $CI_COMMIT_TAG
- if: $CI_COMMIT_BRANCH
default:
retry:
max: 2
when:
- 'runner_system_failure'
- 'stuck_or_timeout_failure'
- 'scheduler_failure'
- 'api_failure'
interruptible: true
.only-default:
only:
- branches
except:
- tags
style-check-diff:
extends: .only-default
image: $FEDORA_IMAGE
stage: check
when: manual
stage: .pre
allow_failure: true
script:
- .gitlab-ci/run-style-check-diff.sh
.build-fedora-default:
extends: .only-default
image: $FEDORA_IMAGE
artifacts:
when: always
@@ -58,7 +51,6 @@ style-check-diff:
junit:
- "${CI_PROJECT_DIR}/_build/report-x11.xml"
- "${CI_PROJECT_DIR}/_build/report-wayland.xml"
- "${CI_PROJECT_DIR}/_build/report-wayland_gles.xml"
- "${CI_PROJECT_DIR}/_build/report-broadway.xml"
name: "gtk-${CI_COMMIT_REF_NAME}"
paths:
@@ -70,12 +62,16 @@ style-check-diff:
- "${CI_PROJECT_DIR}/_build/testsuite/tools/output/*/*"
- "${CI_PROJECT_DIR}/_build/testsuite/gsk/compare/*/*/*.png"
- "${CI_PROJECT_DIR}/_build/testsuite/css/output/*/*.syscap"
- "${CI_PROJECT_DIR}/_build/testsuite/headless/*/*.log"
- "${CI_PROJECT_DIR}/_build_hello/meson-logs"
cache:
key: "$CI_JOB_NAME"
paths:
- _ccache/
- subprojects/gdk-pixbuf/
- subprojects/glib/
- subprojects/graphene/
- subprojects/libepoxy/
- subprojects/pango/
fedora-x86_64:
extends: .build-fedora-default
@@ -85,18 +81,19 @@ fedora-x86_64:
EXTRA_MESON_FLAGS: "--buildtype=debug --default-library=both"
script:
- .gitlab-ci/show-info-linux.sh
- export PATH="$HOME/.local/bin:$PATH"
- meson subprojects download
- meson subprojects update --reset
- meson setup
${COMMON_MESON_FLAGS}
${EXTRA_MESON_FLAGS}
${BACKEND_FLAGS}
${FEATURE_FLAGS}
- meson subprojects update
- mkdir _install
- meson --prefix=${CI_PROJECT_DIR}/_install
${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS} ${BACKEND_FLAGS} ${FEATURE_FLAGS}
_build
- meson compile -C _build
- meson install -C _build
- PKG_CONFIG_PATH=${CI_PROJECT_DIR}/_install/lib64/pkgconfig:${CI_PROJECT_DIR}/_install/share/pkgconfig meson setup _build_hello examples/hello
- LD_LIBRARY_PATH=${CI_PROJECT_DIR}/_install/lib64 meson compile -C _build_hello
- .gitlab-ci/run-tests.sh _build x11
- .gitlab-ci/run-tests.sh _build wayland
- .gitlab-ci/run-tests.sh _build wayland_gles
- .gitlab-ci/run-tests.sh _build waylandgles
- .gitlab-ci/run-tests.sh _build broadway
release-build:
extends: .build-fedora-default
@@ -106,69 +103,38 @@ release-build:
EXTRA_MESON_FLAGS: "--buildtype=release"
script:
- .gitlab-ci/show-info-linux.sh
- export PATH="$HOME/.local/bin:$PATH"
- meson subprojects download
- meson subprojects update --reset
- mkdir _install
- meson setup
--prefix=${CI_PROJECT_DIR}/_install
${COMMON_MESON_FLAGS}
${EXTRA_MESON_FLAGS}
${BACKEND_FLAGS}
${FEATURE_FLAGS}
- meson subprojects update
- meson ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS} ${BACKEND_FLAGS} ${FEATURE_FLAGS}
_build
- meson compile -C _build
- meson install -C _build
- PKG_CONFIG_PATH=${CI_PROJECT_DIR}/_install/lib64/pkgconfig:${CI_PROJECT_DIR}/_install/share/pkgconfig meson setup _build_hello examples/hello
- LD_LIBRARY_PATH=${CI_PROJECT_DIR}/_install/lib64 meson compile -C _build_hello
- ninja -C _build
- .gitlab-ci/run-tests.sh _build x11
fedora-clang:
installed-tests:
extends: .build-fedora-default
stage: build
needs: []
variables:
EXTRA_MESON_FLAGS: "--buildtype=release"
EXTRA_MESON_FLAGS: "--prefix=/usr --libdir=/usr/lib64 -Dinstall-tests=true"
G_TEST_ACCESSIBLE: 1
script:
- .gitlab-ci/show-info-linux.sh
- export PATH="$HOME/.local/bin:$PATH"
- export CC=clang
- meson subprojects download
- meson subprojects update --reset
- meson setup
${COMMON_MESON_FLAGS}
${EXTRA_MESON_FLAGS}
${BACKEND_FLAGS}
${FEATURE_FLAGS}
- meson subprojects update
- meson ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS} ${BACKEND_FLAGS} ${FEATURE_FLAGS}
_build
- meson compile -C _build
- ninja -C _build
- sudo ninja -C _build install
- dbus-run-session xvfb-run -a -s "-screen 0 1024x768x24"
gnome-desktop-testing-runner
--report-directory=_build/installed-tests-report/failed/
--parallel=0
gtk-4.0
artifacts:
paths:
- "_build/installed-tests-report/"
fedora-mingw64:
extends: .build-fedora-default
stage: build
needs: []
before_script:
- sudo dnf install -y
mingw64-filesystem
mingw64-gcc
mingw64-binutils
mingw64-cairo
mingw64-gdk-pixbuf
mingw64-gstreamer1-plugins-bad-free
mingw64-glib2
mingw64-libepoxy
mingw64-pango
# mingw64-graphene (rawhide)
script:
- .gitlab-ci/show-info-linux.sh
- export PATH="$HOME/.local/bin:$PATH"
- pip3 install --user meson~=1.0
- meson subprojects download
- meson subprojects update --reset
- meson -Dintrospection=disabled -Dgraphene:introspection=disabled _build
- meson compile -C _build
.mingw-defaults:
extends: .only-default
stage: build
tags:
- win32-ps
@@ -198,45 +164,39 @@ msys2-mingw64:
- "${CI_PROJECT_DIR}/_build/gtkdll.tar.gz"
macos:
# Sadly, this fails regularly, and its failure is never enlightening
allow_failure: true
rules:
- if: $CI_PROJECT_NAMESPACE == "GNOME"
extends: .only-default
only:
- branches@GNOME/gtk
stage: build
tags:
- macos
needs: []
before_script:
- bash .gitlab-ci/show-info-osx.sh
- pip3 install --user meson~=1.0
- pip3 install --user meson==0.60.3
- pip3 install --user ninja
- export PATH=/Users/gitlabrunner/Library/Python/3.7/bin:$PATH
- export MESON_FORCE_BACKTRACE=1
script:
- meson setup ${COMMON_MESON_FLAGS}
-Dx11-backend=false
- meson -Dx11-backend=false
-Dbroadway-backend=true
-Dmacos-backend=true
-Dmedia-gstreamer=disabled
-Dintrospection=disabled
-Dcpp_std=c++11
-Dpixman:tests=disabled
-Dlibjpeg-turbo:simd=disabled
-Ddemos=false
-Dbuild-tests=false
-Dbuild-examples=false
-Dbuild-testsuite=false
_build
- meson compile -C _build
- ninja -C _build
artifacts:
when: always
paths:
- "${CI_PROJECT_DIR}/_build/meson-logs"
vs2017-x64:
extends: .only-default
# TODO: Uncomment this when ready to merge.
# rules:
# - if: $CI_PROJECT_NAMESPACE == "GNOME"
#only:
# - branches@GNOME/gtk
stage: build
tags:
- win32-ps
@@ -249,7 +209,7 @@ vs2017-x64:
- "${CI_PROJECT_DIR}/_build/meson-logs"
.flatpak-defaults:
image: "quay.io/gnome_infrastructure/gnome-runtime-images:gnome-master"
image: $FLATPAK_IMAGE
stage: flatpak
allow_failure: true
tags:
@@ -259,104 +219,73 @@ vs2017-x64:
- "${APPID}-dev.flatpak"
- 'repo.tar'
expire_in: 1 day
rules:
# Only build Flatpak bundles automatically on main
- if: $CI_COMMIT_BRANCH == "main"
- if: $CI_COMMIT_BRANCH != "main"
when: "manual"
script:
- bash -x ./.gitlab-ci/flatpak-build.sh "${APPID}"
flatpak:demo:
extends: '.flatpak-defaults'
# Manual jobs, for branches and MRs
.flatpak-manual:
extends: .flatpak-defaults
when: manual
# Only build Flatpak bundles automatically on main
.flatpak-main:
extends: .flatpak-defaults
only:
- main
flatpak-manual:demo:
extends: .flatpak-manual
needs: []
variables:
APPID: org.gtk.Demo4
flatpak:demo:aarch64:
extends: '.flatpak-defaults'
flatpak-main:demo:
extends: .flatpak-main
needs: []
tags:
- flatpak-aarch64
variables:
APPID: org.gtk.Demo4
flatpak:widget-factory:
extends: '.flatpak-defaults'
flatpak-manual:widget-factory:
extends: .flatpak-manual
needs: []
variables:
APPID: org.gtk.WidgetFactory4
flatpak:widget-factory:aarch64:
extends: '.flatpak-defaults'
flatpak-main:widget-factory:
extends: .flatpak-main
needs: []
tags:
- flatpak-aarch64
variables:
APPID: org.gtk.WidgetFactory4
flatpak:icon-browser:
extends: '.flatpak-defaults'
flatpak-manual:icon-browser:
extends: .flatpak-manual
needs: []
variables:
APPID: org.gtk.IconBrowser4
flatpak:icon-browser:aarch64:
extends: '.flatpak-defaults'
flatpak-main:icon-browser:
extends: .flatpak-main
needs: []
tags:
- flatpak-aarch64
variables:
APPID: org.gtk.IconBrowser4
flatpak:node-editor:
extends: '.flatpak-defaults'
needs: []
variables:
APPID: org.gtk.gtk4.NodeEditor
flatpak:node-editor:aarch64:
extends: '.flatpak-defaults'
needs: []
tags:
- flatpak-aarch64
variables:
APPID: org.gtk.gtk4.NodeEditor
# Publish the demo apps to the GNOME Nightly repo
# https://wiki.gnome.org/Apps/Nightly
# https://gitlab.gnome.org/GNOME/Initiatives/-/wikis/DevOps-with-Flatpak
nightly demo:
extends: '.publish_nightly'
needs: ['flatpak:demo']
nightly demo aarch64:
extends: '.publish_nightly'
needs: ['flatpak:demo:aarch64']
dependencies: ['flatpak-main:demo']
needs: ['flatpak-main:demo']
nightly factory:
extends: '.publish_nightly'
needs: ['flatpak:widget-factory']
nightly factory aarch64:
extends: '.publish_nightly'
needs: ['flatpak:widget-factory:aarch64']
dependencies: ['flatpak-main:widget-factory']
needs: ['flatpak-main:widget-factory']
nightly icon-browser:
extends: '.publish_nightly'
needs: ['flatpak:icon-browser']
nightly icon-browser aarch64:
extends: '.publish_nightly'
needs: ['flatpak:icon-browser:aarch64']
nightly node-editor:
extends: '.publish_nightly'
needs: ['flatpak:node-editor']
nightly node-editor aarch64:
extends: '.publish_nightly'
needs: ['flatpak:node-editor:aarch64']
dependencies: ['flatpak-main:icon-browser']
needs: ['flatpak-main:icon-browser']
static-scan:
image: $FEDORA_IMAGE
@@ -365,31 +294,23 @@ static-scan:
variables:
EXTRA_MESON_FLAGS: "--buildtype=debug"
script:
- export PATH="$HOME/.local/bin:$PATH"
- meson setup
${COMMON_MESON_FLAGS}
${EXTRA_MESON_FLAGS}
${BACKEND_FLAGS}
${FEATURE_FLAGS}
_scan_build
- meson ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS} _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
# and f16c, since they are incompatible with asan
# 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: []
when: manual
variables:
script:
- export PATH="$HOME/.local/bin:$PATH"
- CC=clang meson setup --buildtype=debugoptimized -Db_sanitize=address -Db_lundef=false -Dintrospection=disabled -Df16c=disabled _build
- CC=clang meson --buildtype=debugoptimized -Db_sanitize=address -Db_lundef=false -Dintrospection=disabled _build
- ninja -C _build
- .gitlab-ci/run-tests.sh _build wayland
artifacts:
@@ -401,21 +322,10 @@ reference:
image: $FEDORA_IMAGE
stage: docs
needs: []
variables:
EXTRA_MESON_FLAGS: "--buildtype=release --force-fallback-for=gdk-pixbuf,pango"
script:
- export PATH="$HOME/.local/bin:$PATH"
- meson setup
${COMMON_MESON_FLAGS}
--buildtype=release
--force-fallback-for=gdk-pixbuf,pango
-Dintrospection=enabled
-Dgtk_doc=true
-Dgdk-pixbuf:gtk_doc=true
-Dpango:gtk_doc=true
-Ddemos=false
-Dbuild-examples=false
-Dbuild-tests=false
-Dbuild-testsuite=false
_build
- meson ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS} -Dgtk_doc=true -Dgdk-pixbuf:gtk_doc=true -Dpango:gtk_doc=true _build
- meson compile -C _build
- mkdir -p _reference/
- mv _build/docs/reference/gdk/gdk4/ _reference/gdk4/
@@ -438,9 +348,9 @@ reference:
publish-docs:
image: fedora:latest
stage: publish
interruptible: false
needs: ['reference']
script:
- "curl -X POST -F token=${PAGES_TRIGGER_TOKEN} -F ref=docs-gtk-org https://gitlab.gnome.org/api/v4/projects/665/trigger/pipeline"
rules:
- if: $CI_COMMIT_REF_NAME == "main"
only:
refs:
- main

View File

@@ -1,4 +1,4 @@
FROM fedora:38
FROM fedora:36
RUN dnf -y install \
adwaita-icon-theme \
@@ -18,9 +18,7 @@ RUN dnf -y install \
dejavu-sans-mono-fonts \
desktop-file-utils \
diffutils \
docbook-style-xsl \
elfutils-libelf-devel \
expat-devel \
fribidi-devel \
gcc \
gcc-c++ \
@@ -32,7 +30,7 @@ RUN dnf -y install \
glib2-static \
glibc-devel \
glibc-headers \
gnupg2 \
gnome-desktop-testing \
gobject-introspection-devel \
graphene-devel \
graphviz \
@@ -73,22 +71,18 @@ RUN dnf -y install \
mesa-libEGL-devel \
mesa-libGLES-devel \
meson \
mutter \
ninja-build \
pango-devel \
pcre-devel \
pcre-static \
pipewire \
pipewire-gstreamer \
python3 \
python3-docutils \
python3-gobject \
python3-jinja2 \
python3-markdown \
python3-packaging \
python3-pip \
python3-pydbus \
python3-pygments \
python3-toml \
python3-typogrify \
python3-wheel \
redhat-rpm-config \
@@ -99,8 +93,9 @@ RUN dnf -y install \
weston \
weston-libs \
which \
wireplumber \
xorg-x11-server-Xvfb \
&& dnf install -y 'dnf-command(builddep)' \
&& dnf builddep -y wayland \
&& dnf clean all
# Enable sudo for wheel users

View File

@@ -16,11 +16,11 @@ flatpak-builder \
flatpak build ${builddir} meson \
--prefix=/app \
--libdir=/app/lib \
--buildtype=debugoptimized \
--buildtype=release \
-Dx11-backend=true \
-Dwayland-backend=true \
-Dprint-backends=file \
-Dbuild-tests=false \
-Dbuild-testsuite=false \
-Dbuild-examples=false \
-Dintrospection=disabled \
-Ddemos=true \

View File

@@ -23,7 +23,6 @@ push=0
list=0
print_help=0
no_login=0
no_cache=0
while (($# > 0)); do
case "${1%%=*}" in
@@ -35,7 +34,6 @@ while (($# > 0)); do
--base|-b) read_arg base "$@" || shift;;
--version|-v) read_arg base_version "$@" || shift;;
--no-login) no_login=1;;
--no-cache) no_cache=1;;
*) echo -e "\e[1;31mERROR\e[0m: Unknown option '$1'"; exit 1;;
esac
shift
@@ -105,21 +103,11 @@ TAG="${REGISTRY}/gnome/gtk/${base}:${base_version}"
if [ $build == 1 ]; then
echo -e "\e[1;32mBUILDING\e[0m: ${base} as ${TAG}"
if [ $no_cache == 0 ]; then
${CMD} build \
${format} \
--build-arg HOST_USER_ID="$UID" \
--tag "${TAG}" \
--file "${base}.Dockerfile" .
else
${CMD} build \
${format} \
--no-cache \
--build-arg HOST_USER_ID="$UID" \
--tag "${TAG}" \
--file "${base}.Dockerfile" .
fi
${CMD} build \
${format} \
--build-arg HOST_USER_ID="$UID" \
--tag "${TAG}" \
--file "${base}.Dockerfile" .
exit $?
fi
@@ -138,8 +126,7 @@ if [ $run == 1 ]; then
echo -e "\e[1;32mRUNNING\e[0m: ${base} as ${TAG}"
${CMD} run \
--rm \
--userns=keep-id \
--volume "$(pwd)/..:/home/user/app:rw,z" \
--volume "$(pwd)/..:/home/user/app" \
--workdir "/home/user/app" \
--tty \
--interactive "${TAG}" \

View File

@@ -2,43 +2,25 @@
set -e
ancestor_horizon=31 # days (one month)
# Recently, git is picky about directory ownership. Tell it not to worry.
git config --global --add safe.directory "$PWD"
# We need to add a new remote for the upstream target branch, since this script
# could be running in a personal fork of the repository which has out of date
# branches.
#
# Limit the fetch to a certain date horizon to limit the amount of data we get.
# If the branch was forked from origin/main before this horizon, it should
# probably be rebased.
if ! git ls-remote --exit-code upstream >/dev/null 2>&1 ; then
# We need to add a new remote for the upstream main, 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/gtk.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/main` or `upstream/glib-2-62`).
# `${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}` or `${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME}`
# are only defined if were running in a merge request pipeline,
# fall back to `${CI_DEFAULT_BRANCH}` or `${CI_COMMIT_BRANCH}` respectively
# otherwise.
source_branch="${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME:-${CI_COMMIT_BRANCH}}"
target_branch="${CI_MERGE_REQUEST_TARGET_BRANCH_NAME:-${CI_DEFAULT_BRANCH}}"
git fetch --shallow-since="$(date --date="${ancestor_horizon} days ago" +%Y-%m-%d)" origin "${source_branch}"
git fetch --shallow-since="$(date --date="${ancestor_horizon} days ago" +%Y-%m-%d)" upstream "${target_branch}"
newest_common_ancestor_sha=$(git merge-base upstream/${target_branch} origin/${source_branch})
if [ -z "${newest_common_ancestor_sha}" ]; then
echo "Couldnt find common ancestor with upstream main branch. This typically"
echo "happens if you branched from main a long time ago. Please update"
echo "your clone, rebase, and re-push your branch."
exit 1
fi
# `upstream/main` or `upstream/gtk-3-24`).
#
# `${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}` is only defined if were 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-ci/clang-format-diff.py -binary "clang-format" -p1
exit_status=$?
@@ -54,7 +36,7 @@ exit_status=$?
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/main/docs/CODING-STYLE.md"
echo " https://gitlab.gnome.org/GNOME/gtk/blob/main/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."

View File

@@ -6,23 +6,19 @@ set +e
srcdir=$( pwd )
builddir=$1
backend=$2
multiplier=${MESON_TEST_TIMEOUT_MULTIPLIER:-1}
# Ignore memory leaks lower in dependencies
export LSAN_OPTIONS=suppressions=$srcdir/lsan.supp:print_suppressions=0:verbosity=1:log_threads=1
export LSAN_OPTIONS=suppressions=$srcdir/lsan.supp:print_suppressions=0
export G_SLICE=always-malloc
case "${backend}" in
x11)
xvfb-run -a -s "-screen 0 1024x768x24 -noreset" \
meson test -C ${builddir} \
--quiet \
--timeout-multiplier "${multiplier}" \
--timeout-multiplier "${MESON_TEST_TIMEOUT_MULTIPLIER}" \
--print-errorlogs \
--setup=${backend} \
--suite=gtk \
--no-suite=failing \
--no-suite=flaky \
--no-suite=gsk-compare-broadway
# Store the exit code for the CI run, but always
@@ -30,7 +26,7 @@ case "${backend}" in
exit_code=$?
;;
wayland*)
wayland)
export XDG_RUNTIME_DIR="$(mktemp -p $(pwd) -d xdg-runtime-XXXXXX)"
weston --backend=headless-backend.so --socket=wayland-5 --idle-time=0 &
@@ -38,17 +34,31 @@ case "${backend}" in
export WAYLAND_DISPLAY=wayland-5
meson test -C ${builddir} \
--quiet \
--timeout-multiplier "${multiplier}" \
--timeout-multiplier "${MESON_TEST_TIMEOUT_MULTIPLIER}" \
--print-errorlogs \
--setup=${backend} \
--suite=gtk \
--no-suite=failing \
--no-suite=flaky \
--no-suite=${backend}_failing \
--no-suite=gsk-compare-broadway
exit_code=$?
exit_code=$?
kill ${compositor}
;;
waylandgles)
export XDG_RUNTIME_DIR="$(mktemp -p $(pwd) -d xdg-runtime-XXXXXX)"
weston --backend=headless-backend.so --socket=wayland-6 --idle-time=0 &
compositor=$!
export WAYLAND_DISPLAY=wayland-6
meson test -C ${builddir} \
--timeout-multiplier "${MESON_TEST_TIMEOUT_MULTIPLIER}" \
--print-errorlogs \
--setup=${backend} \
--suite=gtk \
--no-suite=gsk-compare-broadway
exit_code=$?
kill ${compositor}
;;
@@ -60,15 +70,14 @@ case "${backend}" in
export BROADWAY_DISPLAY=:5
meson test -C ${builddir} \
--quiet \
--timeout-multiplier "${multiplier}" \
--timeout-multiplier "${MESON_TEST_TIMEOUT_MULTIPLIER}" \
--print-errorlogs \
--setup=${backend} \
--suite=gtk \
--no-suite=failing \
--no-suite=flaky \
--no-suite=gsk-compare-opengl
# don't let Broadway failures fail the run, for now
exit_code=0
kill ${server}
;;
@@ -82,18 +91,17 @@ esac
cd ${builddir}
$srcdir/.gitlab-ci/meson-junit-report.py \
--project-name=gtk \
--backend="${backend}" \
--job-id="${CI_JOB_NAME}" \
--output="report-${backend}.xml" \
"meson-logs/testlog-${backend}.json"
--project-name=gtk \
--backend=${backend} \
--job-id="${CI_JOB_NAME}" \
--output=report-${backend}.xml \
meson-logs/testlog-${backend}.json
$srcdir/.gitlab-ci/meson-html-report.py \
--project-name=gtk \
--backend="${backend}" \
--job-id="${CI_JOB_NAME}" \
--reftest-output-dir="testsuite/reftests/output/${backend}" \
--output="report-${backend}.html" \
"meson-logs/testlog-${backend}.json"
--project-name=gtk \
--backend=${backend} \
--job-id="${CI_JOB_NAME}" \
--reftest-output-dir="testsuite/reftests/output/${backend}" \
--output=report-${backend}.html \
meson-logs/testlog-${backend}.json
exit $exit_code

View File

@@ -5,7 +5,7 @@ call "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliar
@echo on
:: FIXME: make warnings fatal
pip3 install --upgrade --user meson~=0.64 || goto :error
pip3 install --upgrade --user meson==0.60.3 || goto :error
meson -Ddebug=false -Dmedia-gstreamer=disabled _build || goto :error
ninja -C _build || goto :error

View File

@@ -28,7 +28,7 @@ pacman --noconfirm -S --needed \
mingw-w64-$MSYS2_ARCH-graphene \
mingw-w64-$MSYS2_ARCH-json-glib \
mingw-w64-$MSYS2_ARCH-libepoxy \
mingw-w64-$MSYS2_ARCH-pango \
mingw-w64-$MSYS2_ARCH-pango2 \
mingw-w64-$MSYS2_ARCH-fribidi \
mingw-w64-$MSYS2_ARCH-gst-plugins-bad-libs \
mingw-w64-$MSYS2_ARCH-shared-mime-info \
@@ -38,6 +38,25 @@ mkdir -p _ccache
export CCACHE_BASEDIR="$(pwd)"
export CCACHE_DIR="${CCACHE_BASEDIR}/_ccache"
# https://gitlab.gnome.org/GNOME/gtk/-/issues/2243
# https://gitlab.gnome.org/GNOME/gtk/-/issues/3002
if ! pkg-config --atleast-version=2.66.0 glib-2.0; then
git clone https://gitlab.gnome.org/GNOME/glib.git _glib
meson setup _glib_build _glib
meson compile -C _glib_build
meson install -C _glib_build
fi
pkg-config --modversion glib-2.0
if ! pkg-config --atleast-version=1.50.0 pango; then
git clone https://gitlab.gnome.org/GNOME/pango.git _pango
meson setup _pango_build _pango
meson compile -C _pango_build
meson install -C _pango_build
fi
pkg-config --modversion pango
# Build
ccache --zero-stats
ccache --show-stats

View File

@@ -21,7 +21,7 @@ many things that we value:
Please, do not use the issue tracker for support questions. If you have
questions on how to use GTK effectively, you can use:
- the `gtk` [room on matrix](https://matrix.to/#/#gtk:gnome.org)
- the `#gtk` IRC channel on irc.gnome.org
- the [gtk tag on the GNOME Discourse instance](https://discourse.gnome.org/tag/gtk)
You can also look at the GTK tag on [Stack
@@ -44,7 +44,6 @@ If you're reporting a bug make sure to list:
0. which version of GTK are you using?
0. which operating system are you using?
0. what display and graphics driver are you using?
0. the necessary steps to reproduce the issue
0. the expected outcome
0. a description of the behavior; screenshots are also welcome

841
NEWS
View File

@@ -1,844 +1,3 @@
Overview of Changes in 4.11.3, xx-xx-xxxx
=========================================
* GtkGridView:
- Respect css border-spacing
- Don't leak the factories
* GtkListView:
- Don't leak the factories
* GtkNotebook:
- Make the pages model implement GtkSelectionModel
* GtkScrolledWindow:
- Propagate child measure size whenever possible
* GtkPopoverMenu:
- Avoid unnecessary left padding
* Css:
- Add new binding-friendly css provider apis
* Theme:
- Show focus in the shortcuts window
* Tests:
- Improve test coverage
* Wayland:
- Make exporting surface handles more flexible
* Build:
- Some build options have been renamed:
demos -> build-demos
profile -> demo-profile
The old names still work
* Deprecations:
- gtk_css_provider_load_from_data
- gdk_wayland_toplevel_unexport_handle
- gdk_pixbuf_get_from_surface
- gdk_pixbuf_get_from_texture
- gtk_image_new_from_pixbuf
- gtk_image_set_from_pixbuf
- gtk_picture_new_for_pixbuf
- gtk_picture_set_pixbuf
* Translation updates:
Basque
Catalan
Russian
Overview of Changes in 4.11.2, 09-05-2023
=========================================
* GtkGLArea:
- Add an allowed-apis property
* GtkListBox:
- Fix a problem with gtk_list_box_remove_all
* Add the GtkSectionModel interface, and implement it in most
of our list models
* GtkListView:
- Support displaying sections
* GtkCenterBox:
- Add a shrink-center-last property
* GtkButton, GtkMenuButton:
- Add a can-shrink property
* GtkPopover:
- Fix problems with grabs
* GtkFileChooser:
- Fix a problem with removing files
- Make the date, time and location columns work
- Fix filtering in the save entry popup
- A few memory leak fixes
- Handle webdav in the pathbar
* GtkBox:
- Support baselines in vertical orientation with GtkBox:baseline-child
* Dialogs:
- Destroy windows promptly when the async callback finishes
- Detect absence of the OpenURI portal and fall back
* Theme:
- Add explicit style classes to a number of widgets
- Fix some contrast issues in the dark theme
* Accessibility:
- Fix alert dialogs in the a11y tree
- Improve accessibility of GtkShortcutsWindow
* Layout:
- Some fixes to baseline alignment
- Separate GTK_ALIGN_BASELINE_CENTER and _FILL
* CSS:
- Fix a crash with color transitions
* GSK:
- Fix problems with negative scales
- Improve scaling of offscreens for (cross-fades, masks, blends)
* GL:
- Add GdkGLTextureBuilder, a more flexible api for creating textures
- Support setting update regions for GL textures
- Ensure that we work with GLES 2
* Vulkan:
- More fixes to the experimental Vulkan renderer
- Rework glyph caching
* Wayland:
- Don't destroy wl_surfaces on hide
- Plug leaks of compositor-side resources
* X11:
- Fix artifacts in gnome-shell frame decorations
* Windows:
- Fix GL context initialization
* Inspector:
- Improve the action list
- Improve the accessibility pane
- Fix a crash
* Tools:
- gtk4-node-editor: Improve scaling
- gtk4-node-editor: Preserve aspect ratio of textures
- gtk4-node-editor: Add some smarter editing
- gtk4-demo: Make the stylus demo work with mice
* Deprecations:
- gtk_widget_get_allocated_width/height/baseline
- GTK_ALIGN_BASELINE
* Translation updates
Bulgarian
Chinese (China)
Friulian
Galician
Hebrew
Persian
Polish
Portuguese
`Russian
Turkish
Overview of Changes in 4.11.1, 03-04-2023
=========================================
* GtkLabel, GtkLinkButton:
- Make file:// uris work again
* GtkListView/GtkColumnView/GtkGridView:
- Fix clipping issues
- Handle focus movement better
- Introduce ::tab-behavior properties
- Introduce GtkListItem::focusable
- Introduce GtkColumnViewCell
- Introduce row factories in GtkColumnView
- Make list grid and column views inert when not rendering
* Drag-and-Drop:
- Support resizing drag surfaces, using the new
GdkDragSurface::compute-size signal
* Theme:
- Port .boxed-list style from Adwaita
- Make insensitive pictures appear grayed out
* Accessibility:
- Fix memory leaks
- Fix a crash
* GDK:
- Add gdk_surface_get_scale to get the fractional scale
- Use fractional scales on Wayland with cairo
- Use fractional scales on Wayland with GL if GDK_DEBUG=gl-fractional
is set. This support is still experimental
* GSK:
- Allow limiting texture sizes with GSK_MAX_TEXTURE_SIZE
- Use samplers for GL texture filtering
- Fix problems with texture slicing
- Avoid re-uploading textures when possible
- Use mipmaps when it is beneficial
* Wayland:
- Fix handling of Drag hotspots
- Fix a crash with cursor size 0
- Support absolute paths in WAYLAND_DISPLAY
- Use the fractional scale protocol
- Use a viewporter to set buffer scale
* Windows:
- Fix problems with WGL
* Vulkan:
- Some fixes to the experimental Vulkan renderer
- Support fractional scaling
* Debugging:
- Show more Wayland-specific information in the inspector
* Deprecations:
- gtk_widget_translate_coordinates
- gdk_surface_create_similar_surface
* Documentation:
- Add a section on coordinate systems
* Build:
- Require wayland-protocols 1.31
* Translation updates
- British English
- Bulgarian
- Chinese (China)
- Dutch
- French
- Persian
- Russian
Overview of Changes in 4.10.1, 14-03-2023
=========================================
* GtkFileChooser
- Improve search performance
- Be safe against pathless files
- Fix memory leaks
- Only show local files in recent files
- Show most recent files first
- Make files non-selectable in selet_folder mode
* GtkListView / GtkColumnView / GtkGridView
- Fix scrolling problems
- Support CSS border-spacing
* GtkComboBox
- Fix a size allocation problem
* gtk
- Size allocation fixes
* Accessibility
- Miscellaneous property fixes and improvements
* Wayland
- Fix an ordering problem in surface disposal
* Windows
- Fix Visual Studio build with older GLib
* Translation updates
Basque
Bulgarian
Catalan
Czech
Danish
Finnish
Friulian
Galician
Georgian
Hungarian
Lithuanian
Polish
Portuguese
Swedish
Turkish
Ukrainian
Overview of Changes in 4.10.0, 04-03-2023
=========================================
* GtkTextView
- Document hanging indentation
* GtkListView
- Fix a size allocation problem
* GtkFileChooser
- Fix paned behavior
- Fix a crash
* GtkText
- Fix various problems with undo
* Accessibility
- Make some getters transfer-full
- Allow setting accessible parents and siblings
- Add a role for toggle buttons
- Miscellaneous property fixes and improvements
* gtk
- Improve the handling resize-during-size-allocate
* gdk
- Introduce GdkTextureDownloader and use it
- Make gdk_texture_get_format public
* gsk
- Make mask nodes more versatile
- Improve the GL implementation for texture scale nodes
* X11
- Fix key handling during DND
* Tools
- gtk-builder-tool: Try harder to handle templates
- gtk-builder-tool: Prefer properties over <child>
* Translation updates
Basque
Belarusian
Bulgarian
Indonesian
Galician
Georgian
German
Hebrew
Lithuanian
Portuguese
Spanish
Swedish
Turkish
Ukrainian
Overview of Changes in 4.9.4, 12-02-2023
========================================
* Printing:
- Add a CPDB backend
- Drop the lpr backend
* GtkFileDialog:
- Robustness fixes
* GtkScaleButton:
- Add an 'active' property
* GtkSearchEntry:
- Add placeholder text
* Fix conflicting type names between gtk and gio
* Gsk:
- Settable filtering for scaled textures
- Add mask nodes
- Some robustness and crash fixes
* Wayland:
- Handle dispatch failing in more places
* Deprecations:
- GtkVolumeButton
* Translation updates:
Belarusian
Chinese (Taiwan)
Georgian
Turkish
Ukrainian
Overview of Changes in 4.9.3, 04-02-2023
========================================
* Add GtkUriLauncher, as replacement for gtk_show_uri
* Add GdkMonitor::description
* Fix problems with tooltip sizing
* Deprecations:
- GtkStatusbar
- GtkAssistant
- GtkLockButton
- gtk_gesture_set_sequence_state
* GtkColumnView:
- Only create widgets for visible columns
* GtkFileDialog:
- Drop shortcut folders API
* GtkCalendar:
- Make marked days work again
* GtkSwitch:
- Make state and active independently settable
* GtkFileChooser:
- Fix a crash with DND
- Fix excessively wide sidebar
- Make context menus work again
* Accessibility:
- Make GtkAccessible public, so it can be implemented outside GTK
- Support accessible implementation for editables
* CSS:
- Fix randomly stopping CSS animations
* GL:
- Fix synchronization with GStreamer
- Fix problems with 3rd party GL in the same thread
* Wayland:
- Fix startup notification with xdg_activation
* Broadway:
- Implement modal windows
* macOS:
- Make DND work
* Build:
- Require graphene 1.10
- Require gobject-introspection 1.72
* Translation updates
Catalan
Galician
German
Hebrew
Indonesian
Portuguese
Russian
Spanish
Swedish
Turkish
Ukrainian
Overview of Changes in 4.9.2, 26-12-2022
========================================
* GtkFileChooserWidget:
- Add a grid view
* GtkText, GtkTextView:
- Fix activation of the on-screen keyboard
- Prevent unexpected text direction changes
* GtkCenterBox:
- Add properties for children
* GtkTreeExpander:
- Add a hide-expander property
* GtkStringList:
- Add a construct-only strings property
* GtkBuilder:
- Support parsing Pango attributes in string form
* GtkGestureStylus:
- Add a stylus-only property
* GtkFileLauncher:
- New async-style api to replace gtk_show_uri
* GtkColorDialog, GtkFontDialog, GtkFileDialog,
GtkAlertDialog:
- APIs have seen some tweaks
- Prefer portals when available
- Fixes for cancellation
* Add GDK_DEBUG=no-portals
* Improve file DND with remote files
* GtkInfoBar has been deprecated
* gtk_widget_show/hide have been deprecated
* gtk_show_uri has been deprecated
* Wayland:
- Fix button mask handling
- Fix problems with cursor size on hi-dpi screens
- Support newer versions of some protocols
- Fix handling of surrounding text in input methods
* X11:
- Fix some ordering problems with surface destruction
* Windows:
- Improved system settings integration
- Fix window resizing work with native decorations
- Include a full hicolor index.theme file as a resource
* Translation updates
Croatian
Dutch
Hungarian
Interlingua
Persian
Turkish
Ukrainian
Overview of Changes in 4.9.1, 31-10-2022
========================================
Note that deprecations are an early outlook at changes
that will appear in an eventual GTK 5 release, which is
still far away. We are introducing deprecations in 4.10
as a way to give users time to adapt, and to provide
feedback on our plans.
* GtkTreeView, GtkIconView, GtkComboBox and
auxiliary classes have been deprecated
* GtkEntryCompletion has been deprecated
* GtkStyleContext has been deprecated
* gtk_render_ and gtk_snapshot_render_ APIs
have been deprecated
* GtkAppChooser widgets have been deprecated
* GtkMessageDialog has been deprecated and
replaced by a new async dialog API
* GtkDialog has been deprecated
* GtkColorChooser, GtkFontChooser, GtkFileChooser
interfaces and their implementations have been
deprecated. A new family of async dialog APIs
has been introduced to replace them
* GtkColorDialog, GtkFontDialog, GtkFileDialog
and GtkAlertDialog are new dialog classes with
a consistent and well-bindable API
* GtkMountOperation:
- Fix the dialog to look reasonable
- Make it work under non-X11
* GtkStringSorter:
- Support different collation methods
* Accessibility:
- Introduce GtkAccessibleRange and implement it
* Debugging:
- Unify formatting for debug output
- Make make debug options available in
non-debug builds
* Increase the memory limit for the jpeg loader to 1G
* Translation updates:
Abkhazian
Basque
Bulgarian
Croatian
Friulian
Georgian
German
Hungarian
Russian
Turkish
Overview of Changes in 4.8.1, 16-09-2022
========================================
* Input:
- Fix problems with input method interactions that caused
dead keys not to work
- Accept single-key compose sequences (these are used with
some keyboard layouts)
* GtkColumnView:
- Flip column order in right-to-left context
* GtkGridView:
- Fix problems with rubberbanding
* GtkFileChooser:
- Fix positioning of popovers in the places view
- Make ~ and . keyboard shortcuts work again
* gsk:
- Make glyph upload more similar to icons
* Make file transfer via portals work, this fixes file
copy/paste and dnd in flatpaks
* Translation updates:
Catalan
Chinese (China)
Chinese (Taiwan)
Latvian
Overview of Changes in 4.8.0, 06-09-2022
========================================
* GtkTreeView:
- Fix a problem with scrolling animations
- Fix some event handling problems
- Drop unreachable code
* GtkText:
- Respect the no-emoji input hint fully
* GtkEmojiChooser:
- Fix arrow key navigation
* GtkFontChooser:
- Improve the handling of OpenType font features
* GtkTreeListModel:
- Fix handling of collapsed child nodes
* GtkInscription:
- Fix accessible name
* Theme:
- Fix placeholder text in HighContrast
* Increase the memory limit for the jpeg loader to 300M
* Miscellaneous memory leak fixes
* Wayland:
- Refator handling of text protocol client updates
* Windows:
- Support high-resolution scroll wheel events
- Generate GdkWin32.gir
- Implement color picking
* Translation updates
Abkhazian
Basque
Brazilian Portuguese
Bulgarian
Catalan
Chinese (China)
Croatian
Czech
Danish
Dutch
Galician
Georgian
German
Hungarian
Icelandic
Indonesian
Korean
Latvian
Lithuanian
Persian
Polish
Portuguese
Russian
Serbian
Spanish
Swedish
Turkish
Ukrainian
Overview of Changes in 4.7.2, 10-08-2022
========================================
* GtkTextView:
- Fix child positioning with gutters
* GtkText:
- Update placeholder visibility when necessary
* GtkPicture:
- Add a content-fit property
* GtkPopover:
- Fix a size allocation problem with the arrow
* GtkTreeView:
- Fix a problem with DND
* GtkTreePopover:
- Support scrolling
* GtkGridView:
- Fix issues with rubberband selection
* GtkLabel:
- Add a tabs property
* GtkSnapshot:
- Make GtkSnapshot work from bindings
* GtkScrolledWindow:
- Scroll at a reasonable speed
* GtkPaned:
- Avoid an infinite loop
* GtkWindow:
- Improve generation and handling of crossing events
* CSS:
- Fix handling of certain transform values
* Media support:
- Add audio support to the ffmpeg backend
- Avoid oom with pathological jpeg images
* GDK:
- Fix handling of touchpad hold events
- Add support for hi-resolution scroll events
* X11:
- Fix preferred action for DND
* Windows:
- Fix DND
* List models:
- Fix items-changed emission
- Add more list model tests
* Demos:
- Add a winning sound to game demos
- Make app icons work uninstalled
* Translation updates:
Abkhazian
Basque
Catalan
Georgian
German
Indonesian
Occitan
Persian
Portuguese
Russian
Spanish
Ukrainian
Overview of Changes in 4.7.1, 12-07-2022
========================================
* GtkInscription:
- A new label-like widget for use in list views
* GtkColorChooser:
- Style improvements
* GtkFontChooser:
- Improve support for OpenType features a bit
* GtkLabel:
- Allow selectable labels to be activated via mnemonic
* GtkTextView:
- Implement GetCharacterExtents for accessibility
* GtkStack:
- Fix a poblem with stack page accessibility
* GtkListView:
- Cull listitems that are out of view
- Make all our list models implement ::n-items and
::item-type properties
* Translations:
- Stop translating property nicks and blurbs
- Fix extracting translations from ui files
* Debugging:
- Support GTK_DEBUG=invert-text-dir
- Allow inspecting inspectors
- Replace GTK_USE_PORTAL with GDK_DEBUG=portals
- Improve responsiveness of the inspector
* CSS:
- Allow fractional letterspacing
* Theme:
- Improve legibility of selectable labels
* Demos:
- Improve the font features demo
- Add demos for GtkInscription
* Wayland:
- Freeze popups when hidden
- Only send smooth scroll events for tablet tools
- Make scaled cursor image have the right size
- Fix problems with the activation protocol
- Don't force the HighContrast icon theme
- Support xdg_toplevel.bounds
* X11:
- Always update the shadoe size
* Windows:
- Improve touchpad support by using DirectManipulation
- Add more directories to the builtin hicolor icon theme
* Translation updates:
Basque
Catalan
Chinese (China)
Galician
German
Lithuanian
Nepali
Occitan
Persian
Polish
Portuguese
Russian
Serbian
Spanish
Swedish
Turkish
Ukrainian
Overview of Changes in 4.7.0, 07-05-2022
========================================

View File

@@ -116,12 +116,19 @@ docs/reference/gtk/html/gtk-building.html
Or [online](https://docs.gtk.org/gtk4/building.html)
Building from git
-----------------
Default branch renamed to `main`
--------------------------------
The GTK sources are hosted on [gitlab.gnome.org](http://gitlab.gnome.org). The main
development branch is called `main`, and stable branches are named after their minor
version, for example `gtk-4-10`.
The default development branch of GTK has been renamed to `main`.
To update your local checkout, use:
```sh
git checkout master
git branch -m master main
git fetch
git branch --unset-upstream
git branch -u origin/main
git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/main
```
How to report bugs
------------------

View File

@@ -54,7 +54,8 @@
"builddir" : true,
"config-opts" : [
"--libdir=/app/lib",
"-Dtests=false"
"-Dtests=false",
"-Dbenchmarks=false"
],
"sources" : [
{
@@ -104,8 +105,8 @@
"sources": [
{
"type": "archive",
"url": "https://boostorg.jfrog.io/artifactory/main/release/1.79.0/source/boost_1_79_0.tar.bz2",
"sha256": "475d589d51a7f8b3ba2ba4eda022b170e562ca3b760ee922c146b6c65856ef39"
"url": "https://boostorg.jfrog.io/artifactory/main/release/1.69.0/source/boost_1_69_0.tar.bz2",
"sha256": "8f32d4617390d1c2d16f26a27ab60d97807b35440d45891fa340fc2648b04406"
}
]
},
@@ -185,9 +186,9 @@
"builddir" : true,
"config-opts" : [
"--libdir=/app/lib",
"-Dvulkan=disabled",
"-Denable_vulkan=no",
"-Dbuildtype=debugoptimized",
"-Ddemo-profile=devel"
"-Dprofile=devel"
],
"sources" : [
{

View File

@@ -54,7 +54,8 @@
"builddir" : true,
"config-opts" : [
"--libdir=/app/lib",
"-Dtests=false"
"-Dtests=false",
"-Dbenchmarks=false"
],
"sources" : [
{
@@ -114,9 +115,9 @@
"builddir" : true,
"config-opts" : [
"--libdir=/app/lib",
"-Dvulkan=disabled",
"-Denable_vulkan=no",
"-Dbuildtype=debugoptimized",
"-Ddemo-profile=devel"
"-Dprofile=devel"
],
"sources" : [
{

View File

@@ -54,7 +54,8 @@
"builddir" : true,
"config-opts" : [
"--libdir=/app/lib",
"-Dtests=false"
"-Dtests=false",
"-Dbenchmarks=false"
],
"sources" : [
{
@@ -114,9 +115,9 @@
"builddir" : true,
"config-opts" : [
"--libdir=/app/lib",
"-Dvulkan=disabled",
"-Denable_vulkan=no",
"-Dbuildtype=debugoptimized",
"-Ddemo-profile=devel"
"-Dprofile=devel"
],
"sources" : [
{

View File

@@ -1,138 +0,0 @@
{
"app-id" : "org.gtk.gtk4.NodeEditor",
"runtime" : "org.gnome.Platform",
"runtime-version" : "master",
"sdk" : "org.gnome.Sdk",
"command" : "gtk4-node-editor",
"tags" : [
"devel",
"development",
"nightly"
],
"desktop-file-name-prefix" : "(Development) ",
"finish-args" : [
"--device=dri",
"--share=ipc",
"--socket=fallback-x11",
"--socket=wayland",
"--talk-name=org.gtk.vfs",
"--talk-name=org.gtk.vfs.*"
],
"cleanup" : [
"/include",
"/lib/pkgconfig",
"/share/pkgconfig",
"/share/aclocal",
"/man",
"/share/man",
"/share/gtk-doc",
"*.la",
".a",
"/lib/girepository-1.0",
"/share/gir-1.0",
"/share/doc"
],
"modules" : [
{
"name" : "wayland",
"buildsystem" : "meson",
"builddir" : true,
"config-opts" : [
"-Ddocumentation=false"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.freedesktop.org/wayland/wayland.git",
"branch" : "main"
}
]
},
{
"name" : "graphene",
"buildsystem" : "meson",
"builddir" : true,
"config-opts" : [
"--libdir=/app/lib",
"-Dtests=false"
],
"sources" : [
{
"type" : "git",
"url" : "https://github.com/ebassi/graphene.git"
}
]
},
{
"name" : "libsass",
"buildsystem" : "meson",
"builddir" : true,
"config-opts" : [
"--libdir=/app/lib"
],
"sources" : [
{
"type" : "git",
"url" : "https://github.com/lazka/libsass.git",
"branch" : "meson"
}
]
},
{
"name" : "sassc",
"buildsystem" : "meson",
"builddir" : true,
"config-opts" : [
"--libdir=/app/lib"
],
"sources" : [
{
"type" : "git",
"url" : "https://github.com/lazka/sassc.git",
"branch" : "meson"
}
]
},
{
"name" : "pango",
"buildsystem" : "meson",
"builddir" : true,
"config-opts" : [
"--libdir=/app/lib"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/pango.git",
"branch" : "main"
}
]
},
{
"name" : "gtk",
"buildsystem" : "meson",
"builddir" : true,
"config-opts" : [
"--libdir=/app/lib",
"-Dvulkan=disabled",
"-Dbuildtype=debugoptimized",
"-Ddemo-profile=devel"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/gtk.git",
"branch" : "main"
}
]
}
],
"build-options" : {
"env" : {
"DBUS_SESSION_BUS_ADDRESS" : "''",
"GSK_RENDERER" : "opengl",
"GDK_DEBUG" : "vulkan-disable",
"G_ENABLE_DEBUG" : "true"
}
}
}

View File

@@ -1,201 +0,0 @@
#!/usr/bin/env python3
#
# SPDX-FileCopyrightText: 2022 Collabora Inc.
# 2023 Emmanuele Bassi
#
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# Original author: Xavier Claessens <xclaesse@gmail.com>
import argparse
import textwrap
from pathlib import Path
# Disable line length warnings as wrapping the C code templates would be hard
# flake8: noqa: E501
def gen_versions_macros(args, current_major_version, current_minor_version, current_micro_version):
with args.out_path.open("w", encoding="utf-8") as ofile, args.in_path.open(
"r", encoding="utf-8"
) as ifile:
for line in ifile.readlines():
if "@GDK_VERSIONS@" in line:
ofile.write(
textwrap.dedent(
f"""\
/**
* GDK_MAJOR_VERSION:
*
* The major version component of the library's version, e.g. "1" for "1.2.3".
*/
#define GDK_MAJOR_VERSION ({current_major_version})
/**
* GDK_MINOR_VERSION:
*
* The minor version component of the library's version, e.g. "2" for "1.2.3".
*/
#define GDK_MINOR_VERSION ({current_minor_version})
/**
* GDK_MICRO_VERSION:
*
* The micro version component of the library's version, e.g. "3" for "1.2.3".
*/
#define GDK_MICRO_VERSION ({current_micro_version})
"""
)
)
for minor in range(0, current_minor_version + 2, 2):
ofile.write(
textwrap.dedent(
f"""\
/**
* GDK_VERSION_{current_major_version}_{minor}:
*
* A macro that evaluates to the {current_major_version}.{minor} version of GTK, in a format
* that can be used by the C pre-processor.
*
* Since: {current_major_version}.{minor}
*/
#define GDK_VERSION_{current_major_version}_{minor} (G_ENCODE_VERSION ({current_major_version}, {minor}))
"""
)
)
else:
ofile.write(line)
def gen_visibility_macros(args, current_major_version, current_minor_version, current_micro_version):
"""
Generates a set of macros for each minor stable version of GTK
- GDK_DEPRECATED
- GDK_DEPRECATED_IN_…
- GDK_DEPRECATED_MACRO_IN_…
- GDK_DEPRECATED_ENUMERATOR_IN_…
- GDK_DEPRECATED_TYPE_IN_…
- GDK_AVAILABLE_IN_ALL
- GDK_AVAILABLE_IN_…
- GDK_AVAILABLE_STATIC_INLINE_IN_…
- GDK_AVAILABLE_MACRO_IN_…
- GDK_AVAILABLE_ENUMERATOR_IN_…
- GDK_AVAILABLE_TYPE_IN_…
- GDK_UNAVAILABLE(maj,min)
- GDK_UNAVAILABLE_STATIC_INLINE(maj,min)
"""
ns = args.namespace
with args.out_path.open("w", encoding="utf-8") as f:
f.write(
textwrap.dedent(
f"""\
#pragma once
#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined({ns}_STATIC_COMPILATION)
# define _{ns}_EXPORT __declspec(dllexport)
# define _{ns}_IMPORT __declspec(dllimport)
#elif __GNUC__ >= 4
# define _{ns}_EXPORT __attribute__((visibility("default")))
# define _{ns}_IMPORT
#else
# define _{ns}_EXPORT
# define _{ns}_IMPORT
#endif
#ifdef GTK_COMPILATION
# define _{ns}_API _{ns}_EXPORT
#else
# define _{ns}_API _{ns}_IMPORT
#endif
#define _{ns}_EXTERN _{ns}_API extern
#define {ns}_VAR _{ns}_EXTERN
#define {ns}_AVAILABLE_IN_ALL _{ns}_EXTERN
#ifdef GDK_DISABLE_DEPRECATION_WARNINGS
#define {ns}_DEPRECATED _{ns}_EXTERN
#define {ns}_DEPRECATED_FOR(f) _{ns}_EXTERN
#define {ns}_UNAVAILABLE(maj,min) _{ns}_EXTERN
#define {ns}_UNAVAILABLE_STATIC_INLINE(maj,min)
#else
#define {ns}_DEPRECATED G_DEPRECATED _{ns}_EXTERN
#define {ns}_DEPRECATED_FOR(f) G_DEPRECATED_FOR(f) _{ns}_EXTERN
#define {ns}_UNAVAILABLE(maj,min) G_UNAVAILABLE(maj,min) _{ns}_EXTERN
#define {ns}_UNAVAILABLE_STATIC_INLINE(maj,min) G_UNAVAILABLE(maj,min)
#endif
"""
)
)
for minor in range(0, current_minor_version + 2, 2):
f.write(
textwrap.dedent(
f"""
#if GDK_VERSION_MIN_REQUIRED >= GDK_VERSION_4_{minor}
#define {ns}_DEPRECATED_IN_{current_major_version}_{minor} {ns}_DEPRECATED
#define {ns}_DEPRECATED_IN_{current_major_version}_{minor}_FOR(f) {ns}_DEPRECATED_FOR (f)
#define {ns}_DEPRECATED_MACRO_IN_{current_major_version}_{minor} GDK_DEPRECATED_MACRO
#define {ns}_DEPRECATED_MACRO_IN_{current_major_version}_{minor}_FOR(f) GDK_DEPRECATED_MACRO_FOR (f)
#define {ns}_DEPRECATED_ENUMERATOR_IN_{current_major_version}_{minor} GDK_DEPRECATED_ENUMERATOR
#define {ns}_DEPRECATED_ENUMERATOR_IN_{current_major_version}_{minor}_FOR(f) GDK_DEPRECATED_ENUMERATOR_FOR (f)
#define {ns}_DEPRECATED_TYPE_IN_{current_major_version}_{minor} GDK_DEPRECATED_TYPE
#define {ns}_DEPRECATED_TYPE_IN_{current_major_version}_{minor}_FOR(f) GDK_DEPRECATED_TYPE_FOR (f)
#else
#define {ns}_DEPRECATED_IN_{current_major_version}_{minor} _{ns}_EXTERN
#define {ns}_DEPRECATED_IN_{current_major_version}_{minor}_FOR(f) _{ns}_EXTERN
#define {ns}_DEPRECATED_MACRO_IN_{current_major_version}_{minor}
#define {ns}_DEPRECATED_MACRO_IN_{current_major_version}_{minor}_FOR(f)
#define {ns}_DEPRECATED_ENUMERATOR_IN_{current_major_version}_{minor}
#define {ns}_DEPRECATED_ENUMERATOR_IN_{current_major_version}_{minor}_FOR(f)
#define {ns}_DEPRECATED_TYPE_IN_{current_major_version}_{minor}
#define {ns}_DEPRECATED_TYPE_IN_{current_major_version}_{minor}_FOR(f)
#endif
#if GDK_VERSION_MAX_ALLOWED < GDK_VERSION_{current_major_version}_{minor}
#define {ns}_AVAILABLE_IN_{current_major_version}_{minor} {ns}_UNAVAILABLE ({current_major_version}, {minor})
#define {ns}_AVAILABLE_STATIC_INLINE_IN_{current_major_version}_{minor} GDK_UNAVAILABLE_STATIC_INLINE ({current_major_version}, {minor})
#define {ns}_AVAILABLE_MACRO_IN_{current_major_version}_{minor} GDK_UNAVAILABLE_MACRO ({current_major_version}, {minor})
#define {ns}_AVAILABLE_ENUMERATOR_IN_{current_major_version}_{minor} GDK_UNAVAILABLE_ENUMERATOR ({current_major_version}, {minor})
#define {ns}_AVAILABLE_TYPE_IN_{current_major_version}_{minor} GDK_UNAVAILABLE_TYPE ({current_major_version}, {minor})
#else
#define {ns}_AVAILABLE_IN_{current_major_version}_{minor} _{ns}_EXTERN
#define {ns}_AVAILABLE_STATIC_INLINE_IN_{current_major_version}_{minor}
#define {ns}_AVAILABLE_MACRO_IN_{current_major_version}_{minor}
#define {ns}_AVAILABLE_ENUMERATOR_IN_{current_major_version}_{minor}
#define {ns}_AVAILABLE_TYPE_IN_{current_major_version}_{minor}
#endif
"""
)
)
def main():
parser = argparse.ArgumentParser()
parser.add_argument("gtk_version", help="Current GLib version")
subparsers = parser.add_subparsers()
versions_parser = subparsers.add_parser(
"versions-macros", help="Generate versions macros"
)
versions_parser.add_argument("in_path", help="input file", type=Path)
versions_parser.add_argument("out_path", help="output file", type=Path)
versions_parser.set_defaults(func=gen_versions_macros)
visibility_parser = subparsers.add_parser(
"visibility-macros", help="Generate visibility macros"
)
visibility_parser.add_argument("namespace", help="Macro namespace")
visibility_parser.add_argument("out_path", help="output file", type=Path)
visibility_parser.set_defaults(func=gen_visibility_macros)
args = parser.parse_args()
version = [int(i) for i in args.gtk_version.split(".")]
args.func(args, version[0], version[1], version[2])
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,45 @@
#!/usr/bin/env python3
import os
import sys
import subprocess
if 'DESTDIR' not in os.environ:
gtk_api_version = sys.argv[1]
gtk_abi_version = sys.argv[2]
gtk_libdir = sys.argv[3]
gtk_datadir = sys.argv[4]
gtk_bindir = sys.argv[5]
gtk_moduledir = os.path.join(gtk_libdir, 'gtk-' + gtk_api_version, gtk_abi_version)
gtk_printmodule_dir = os.path.join(gtk_moduledir, 'printbackends')
gtk_mediamodule_dir = os.path.join(gtk_moduledir, 'media')
print('Compiling GSettings schemas...')
glib_compile_schemas = subprocess.check_output(['pkg-config',
'--variable=glib_compile_schemas',
'gio-2.0']).strip()
if not os.path.exists(glib_compile_schemas):
# pkg-config variables only available since GLib 2.62.0.
glib_compile_schemas = 'glib-compile-schemas'
subprocess.call([glib_compile_schemas,
os.path.join(gtk_datadir, 'glib-2.0', 'schemas')])
print('Updating icon cache...')
update_icon_cache = os.path.join(gtk_bindir, 'gtk4-update-icon-cache')
subprocess.call([update_icon_cache, '-q', '-t' ,'-f',
os.path.join(gtk_datadir, 'icons', 'hicolor')])
print('Updating module cache for print backends...')
os.makedirs(gtk_printmodule_dir, exist_ok=True)
gio_querymodules = subprocess.check_output(['pkg-config',
'--variable=gio_querymodules',
'gio-2.0']).strip()
if not os.path.exists(gio_querymodules):
# pkg-config variables only available since GLib 2.62.0.
gio_querymodules = 'gio-querymodules'
subprocess.call([gio_querymodules, gtk_printmodule_dir])
print('Updating module cache for media backends...')
os.makedirs(gtk_mediamodule_dir, exist_ok=True)
subprocess.call([gio_querymodules, gtk_mediamodule_dir])

View File

@@ -202,36 +202,43 @@ constraint_editor_window_load (ConstraintEditorWindow *self,
}
static void
open_response_cb (GObject *source,
GAsyncResult *result,
void *user_data)
open_response_cb (GtkNativeDialog *dialog,
int response,
ConstraintEditorWindow *self)
{
GtkFileDialog *dialog = GTK_FILE_DIALOG (source);
ConstraintEditorWindow *self = user_data;
GFile *file;
gtk_native_dialog_hide (dialog);
file = gtk_file_dialog_open_finish (dialog, result, NULL);
if (file)
if (response == GTK_RESPONSE_ACCEPT)
{
GFile *file;
file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
constraint_editor_window_load (self, file);
g_object_unref (file);
}
gtk_native_dialog_destroy (dialog);
}
static void
open_cb (GtkWidget *button,
ConstraintEditorWindow *self)
{
GtkFileDialog *dialog;
GFile *cwd;
GtkFileChooserNative *dialog;
dialog = gtk_file_dialog_new ();
gtk_file_dialog_set_title (dialog, "Open file");
cwd = g_file_new_for_path (".");
gtk_file_dialog_set_initial_folder (dialog, cwd);
dialog = gtk_file_chooser_native_new ("Open file",
GTK_WINDOW (self),
GTK_FILE_CHOOSER_ACTION_OPEN,
"_Load",
"_Cancel");
gtk_native_dialog_set_modal (GTK_NATIVE_DIALOG (dialog), TRUE);
GFile *cwd = g_file_new_for_path (".");
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), cwd, NULL);
g_object_unref (cwd);
gtk_file_dialog_open (dialog, GTK_WINDOW (self), NULL, open_response_cb, self);
g_object_unref (dialog);
g_signal_connect (dialog, "response", G_CALLBACK (open_response_cb), self);
gtk_native_dialog_show (GTK_NATIVE_DIALOG (dialog));
}
static void
@@ -287,23 +294,22 @@ serialize_model (GListModel *list)
static void
save_response_cb (GObject *source,
GAsyncResult *result,
void *user_data)
save_response_cb (GtkNativeDialog *dialog,
int response,
ConstraintEditorWindow *self)
{
GtkFileDialog *dialog = GTK_FILE_DIALOG (source);
ConstraintEditorWindow *self = user_data;
GFile *file;
gtk_native_dialog_hide (dialog);
file = gtk_file_dialog_save_finish (dialog, result, NULL);
if (file)
if (response == GTK_RESPONSE_ACCEPT)
{
GListModel *model;
GFile *file;
char *text;
GError *error = NULL;
model = constraint_view_get_model (CONSTRAINT_VIEW (self->view));
text = serialize_model (model);
file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
g_file_replace_contents (file, text, strlen (text),
NULL, FALSE,
G_FILE_CREATE_NONE,
@@ -312,46 +318,54 @@ save_response_cb (GObject *source,
&error);
if (error != NULL)
{
GtkAlertDialog *alert;
GtkWidget *message_dialog;
alert = gtk_alert_dialog_new ("Saving failed");
gtk_alert_dialog_set_detail (alert, error->message);
gtk_alert_dialog_show (alert,
GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (self))));
g_object_unref (alert);
message_dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (self))),
GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO,
GTK_BUTTONS_OK,
"Saving failed");
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (message_dialog),
"%s", error->message);
g_signal_connect (message_dialog, "response", G_CALLBACK (gtk_window_destroy), NULL);
gtk_widget_show (message_dialog);
g_error_free (error);
}
g_free (text);
g_object_unref (file);
}
gtk_native_dialog_destroy (dialog);
}
static void
save_cb (GtkWidget *button,
ConstraintEditorWindow *self)
{
GtkFileDialog *dialog;
GFile *cwd;
GtkFileChooserNative *dialog;
dialog = gtk_file_dialog_new ();
gtk_file_dialog_set_title (dialog, "Save constraints");
cwd = g_file_new_for_path (".");
gtk_file_dialog_set_initial_folder (dialog, cwd);
dialog = gtk_file_chooser_native_new ("Save constraints",
GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (button))),
GTK_FILE_CHOOSER_ACTION_SAVE,
"_Save",
"_Cancel");
gtk_native_dialog_set_modal (GTK_NATIVE_DIALOG (dialog), TRUE);
GFile *cwd = g_file_new_for_path (".");
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), cwd, NULL);
g_object_unref (cwd);
gtk_file_dialog_save (dialog,
GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (button))),
NULL,
save_response_cb, self);
g_object_unref (dialog);
g_signal_connect (dialog, "response", G_CALLBACK (save_response_cb), self);
gtk_native_dialog_show (GTK_NATIVE_DIALOG (dialog));
}
static void
constraint_editor_window_dispose (GObject *object)
constraint_editor_window_finalize (GObject *object)
{
gtk_widget_dispose_template (GTK_WIDGET (object), CONSTRAINT_EDITOR_WINDOW_TYPE);
//ConstraintEditorWindow *self = (ConstraintEditorWindow *)object;
G_OBJECT_CLASS (constraint_editor_window_parent_class)->dispose (object);
G_OBJECT_CLASS (constraint_editor_window_parent_class)->finalize (object);
}
static int child_counter;
@@ -426,7 +440,7 @@ edit_constraint (ConstraintEditorWindow *win,
g_signal_connect (editor, "done", G_CALLBACK (constraint_editor_done), win);
gtk_window_present (GTK_WINDOW (window));
gtk_widget_show (window);
}
static void
@@ -459,7 +473,7 @@ edit_guide (ConstraintEditorWindow *win,
gtk_window_set_child (GTK_WINDOW (window), GTK_WIDGET (editor));
g_signal_connect (editor, "done", G_CALLBACK (guide_editor_done), win);
gtk_window_present (GTK_WINDOW (window));
gtk_widget_show (window);
}
static void
@@ -483,7 +497,7 @@ constraint_editor_window_class_init (ConstraintEditorWindowClass *class)
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
object_class->dispose = constraint_editor_window_dispose;
object_class->finalize = constraint_editor_window_finalize;
gtk_widget_class_set_template_from_resource (widget_class,
"/org/gtk/gtk4/constraint-editor/constraint-editor-window.ui");

View File

@@ -21,8 +21,6 @@
#include "constraint-editor.h"
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
struct _ConstraintEditor
{
GtkWidget parent_instance;
@@ -609,11 +607,10 @@ constraint_editor_dispose (GObject *object)
{
ConstraintEditor *self = (ConstraintEditor *)object;
g_clear_pointer (&self->grid, gtk_widget_unparent);
g_clear_object (&self->model);
g_clear_object (&self->constraint);
gtk_widget_dispose_template (GTK_WIDGET (object), CONSTRAINT_EDITOR_TYPE);
G_OBJECT_CLASS (constraint_editor_parent_class)->dispose (object);
}

View File

@@ -21,8 +21,6 @@
#include "guide-editor.h"
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
struct _GuideEditor
{
GtkWidget parent_instance;
@@ -296,10 +294,9 @@ guide_editor_dispose (GObject *object)
{
GuideEditor *self = (GuideEditor *)object;
g_clear_pointer (&self->grid, gtk_widget_unparent);
g_clear_object (&self->guide);
gtk_widget_dispose_template (GTK_WIDGET (self), GUIDE_EDITOR_TYPE);
G_OBJECT_CLASS (guide_editor_parent_class)->dispose (object);
}

View File

@@ -9,7 +9,7 @@ constraint_editor_sources = [
constraint_editor_resources = gnome.compile_resources('constraint_editor_resources',
'constraint-editor.gresource.xml',
source_dir: meson.current_source_dir(),
source_dir: '.',
)
executable('gtk4-constraint-editor',

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,287 @@
#include "fontcolors.h"
#include "rangeedit.h"
#include <gtk/gtk.h>
#include <hb-ot.h>
enum {
PROP_FONT_DESC = 1,
PROP_PALETTE,
NUM_PROPERTIES
};
static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
struct _FontColors
{
GtkWidget parent;
GtkGrid *label;
GtkGrid *grid;
Pango2FontDescription *font_desc;
GSimpleAction *reset_action;
gboolean has_colors;
char *palette;
GtkCheckButton *default_check;
};
struct _FontColorsClass
{
GtkWidgetClass parent_class;
};
G_DEFINE_TYPE (FontColors, font_colors, GTK_TYPE_WIDGET);
static Pango2Font *
get_font (FontColors *self)
{
Pango2Context *context;
context = gtk_widget_get_pango_context (GTK_WIDGET (self));
return pango2_context_load_font (context, self->font_desc);
}
static void
palette_changed (GtkCheckButton *button,
FontColors *self)
{
g_free (self->palette);
self->palette = g_strdup ((const char *) g_object_get_data (G_OBJECT (button), "palette"));
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_PALETTE]);
}
static void
update_colors (FontColors *self)
{
Pango2Font *font;
hb_font_t *hb_font;
hb_face_t *hb_face;
GtkWidget *child;
GtkWidget *check;
unsigned int n_colors;
hb_color_t *colors;
GtkWidget *box;
g_object_ref (self->label);
while ((child = gtk_widget_get_first_child (GTK_WIDGET (self->grid))))
gtk_grid_remove (self->grid, child);
gtk_grid_attach (self->grid, GTK_WIDGET (self->label), 0, -4, 2, 1);
g_object_unref (self->label);
self->default_check = NULL;
font = get_font (self);
hb_font = pango2_font_get_hb_font (font);
hb_face = hb_font_get_face (hb_font);
self->has_colors = hb_ot_color_has_palettes (hb_face);
gtk_widget_set_visible (GTK_WIDGET (self), self->has_colors);
if (!self->has_colors)
{
g_simple_action_set_enabled (self->reset_action, FALSE);
return;
}
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
gtk_grid_attach (self->grid, box, 0, -3, 2, 1);
check = gtk_check_button_new_with_label ("Default");
g_object_set_data (G_OBJECT (check), "palette", (gpointer)"default");
if (g_strcmp0 ("default", self->palette) == 0)
gtk_check_button_set_active (GTK_CHECK_BUTTON (check), TRUE);
g_signal_connect (check, "toggled", G_CALLBACK (palette_changed), self);
gtk_box_append (GTK_BOX (box), check);
self->default_check = GTK_CHECK_BUTTON (check);
check = gtk_check_button_new_with_label ("Light");
g_object_set_data (G_OBJECT (check), "palette", (gpointer)"light");
if (g_strcmp0 ("light", self->palette) == 0)
gtk_check_button_set_active (GTK_CHECK_BUTTON (check), TRUE);
g_signal_connect (check, "toggled", G_CALLBACK (palette_changed), self);
gtk_check_button_set_group (GTK_CHECK_BUTTON (check), self->default_check);
gtk_box_append (GTK_BOX (box), check);
check = gtk_check_button_new_with_label ("Dark");
g_object_set_data (G_OBJECT (check), "palette", (gpointer)"dark");
if (g_strcmp0 ("dark", self->palette) == 0)
gtk_check_button_set_active (GTK_CHECK_BUTTON (check), TRUE);
g_signal_connect (check, "toggled", G_CALLBACK (palette_changed), self);
gtk_check_button_set_group (GTK_CHECK_BUTTON (check), self->default_check);
gtk_box_append (GTK_BOX (box), check);
for (int i = 0; i < hb_ot_color_palette_get_count (hb_face); i++)
{
char *id = g_strdup_printf ("palette%d", i);
char *label = g_strdup_printf ("Palette %d", i);
GtkWidget *palette;
check = gtk_check_button_new_with_label (label);
g_object_set_data_full (G_OBJECT (check), "palette", id, g_free);
if (g_strcmp0 (id, self->palette) == 0)
gtk_check_button_set_active (GTK_CHECK_BUTTON (check), TRUE);
g_signal_connect (check, "toggled", G_CALLBACK (palette_changed), self);
gtk_check_button_set_group (GTK_CHECK_BUTTON (check), self->default_check);
gtk_grid_attach (self->grid, check, 0, i, 1, 1);
n_colors = hb_ot_color_palette_get_colors (hb_face, i, 0, NULL, NULL);
colors = g_new (hb_color_t, n_colors);
n_colors = hb_ot_color_palette_get_colors (hb_face, i, 0, &n_colors, colors);
palette = gtk_grid_new ();
gtk_widget_set_valign (palette, GTK_ALIGN_CENTER);
gtk_grid_attach (self->grid, palette, 1, i, 1, 1);
/* HACK - defeat first-child/last-child theming */
gtk_grid_attach (GTK_GRID (palette), gtk_picture_new (), -1, 0, 1, 1);
for (int k = 0; k < n_colors; k++)
{
GtkWidget *swatch;
swatch = g_object_new (g_type_from_name ("GtkColorSwatch"),
"rgba", &(GdkRGBA){ hb_color_get_red (colors[k])/255.,
hb_color_get_green (colors[k])/255.,
hb_color_get_blue (colors[k])/255.,
hb_color_get_alpha (colors[k])/255.},
"selectable", FALSE,
"has-menu", FALSE,
"can-drag", FALSE,
"width-request", 16,
"height-request", 16,
NULL);
gtk_grid_attach (GTK_GRID (palette), swatch, k % 6, k / 6, 1, 1);
}
/* HACK - defeat first-child/last-child theming */
gtk_grid_attach (GTK_GRID (palette), gtk_picture_new (), 6, 0, 1, 1);
}
}
static void
reset (GSimpleAction *action,
GVariant *parameter,
FontColors *self)
{
g_free (self->palette);
self->palette = g_strdup (PANGO2_COLOR_PALETTE_DEFAULT);
if (self->has_colors)
gtk_check_button_set_active (self->default_check, TRUE);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_PALETTE]);
g_simple_action_set_enabled (self->reset_action, FALSE);
}
static void
font_colors_init (FontColors *self)
{
self->palette = g_strdup (PANGO2_COLOR_PALETTE_DEFAULT);
gtk_widget_init_template (GTK_WIDGET (self));
self->reset_action = g_simple_action_new ("reset", NULL);
g_simple_action_set_enabled (self->reset_action, FALSE);
g_signal_connect (self->reset_action, "activate", G_CALLBACK (reset), self);
}
static void
font_colors_dispose (GObject *object)
{
gtk_widget_clear_template (GTK_WIDGET (object), FONT_COLORS_TYPE);
G_OBJECT_CLASS (font_colors_parent_class)->dispose (object);
}
static void
font_colors_finalize (GObject *object)
{
FontColors *self = FONT_COLORS (object);
g_clear_pointer (&self->font_desc, pango2_font_description_free);
g_free (self->palette);
G_OBJECT_CLASS (font_colors_parent_class)->finalize (object);
}
static void
font_colors_set_property (GObject *object,
unsigned int prop_id,
const GValue *value,
GParamSpec *pspec)
{
FontColors *self = FONT_COLORS (object);
switch (prop_id)
{
case PROP_FONT_DESC:
pango2_font_description_free (self->font_desc);
self->font_desc = pango2_font_description_copy (g_value_get_boxed (value));
update_colors (self);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
font_colors_get_property (GObject *object,
unsigned int prop_id,
GValue *value,
GParamSpec *pspec)
{
FontColors *self = FONT_COLORS (object);
switch (prop_id)
{
case PROP_PALETTE:
g_value_set_string (value, self->palette);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
font_colors_class_init (FontColorsClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
object_class->dispose = font_colors_dispose;
object_class->finalize = font_colors_finalize;
object_class->get_property = font_colors_get_property;
object_class->set_property = font_colors_set_property;
properties[PROP_FONT_DESC] =
g_param_spec_boxed ("font-desc", "", "",
PANGO2_TYPE_FONT_DESCRIPTION,
G_PARAM_WRITABLE);
properties[PROP_PALETTE] =
g_param_spec_string ("palette", "", "",
PANGO2_COLOR_PALETTE_DEFAULT,
G_PARAM_READABLE);
g_object_class_install_properties (G_OBJECT_CLASS (class), NUM_PROPERTIES, properties);
gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (class),
"/org/gtk/fontexplorer/fontcolors.ui");
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), FontColors, grid);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), FontColors, label);
gtk_widget_class_set_css_name (GTK_WIDGET_CLASS (class), "fontcolors");
}
FontColors *
font_colors_new (void)
{
return g_object_new (FONT_COLORS_TYPE, NULL);
}
GAction *
font_colors_get_reset_action (FontColors *self)
{
return G_ACTION (self->reset_action);
}

View File

@@ -0,0 +1,16 @@
#pragma once
#include <gtk/gtk.h>
#define FONT_COLORS_TYPE (font_colors_get_type ())
#define FONT_COLORS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FONT_COLORS_TYPE, FontColors))
typedef struct _FontColors FontColors;
typedef struct _FontColorsClass FontColorsClass;
GType font_colors_get_type (void);
FontColors * font_colors_new (void);
GAction * font_colors_get_reset_action (FontColors *self);

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="FontColors" parent="GtkWidget">
<property name="layout-manager"><object class="GtkBinLayout"/></property>
<child>
<object class="GtkGrid" id="grid">
<child>
<object class="GtkLabel" id="label">
<property name="label" translatable="yes">Colors</property>
<property name="margin-bottom">10</property>
<property name="xalign">0</property>
<style>
<class name="heading"/>
</style>
<layout>
<property name="row">-2</property>
<property name="column">0</property>
<property name="column-span">2</property>
</layout>
</object>
</child>
</object>
</child>
</template>
</interface>

View File

@@ -0,0 +1,271 @@
#include "fontcontrols.h"
#include "rangeedit.h"
#include <gtk/gtk.h>
#include <hb-ot.h>
enum {
PROP_SIZE = 1,
PROP_LETTERSPACING,
PROP_LINE_HEIGHT,
PROP_FOREGROUND,
PROP_BACKGROUND,
PROP_DISABLE_SIZE,
NUM_PROPERTIES
};
static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
struct _FontControls
{
GtkWidget parent;
GtkAdjustment *size_adjustment;
GtkAdjustment *letterspacing_adjustment;
GtkAdjustment *line_height_adjustment;
GtkColorButton *foreground;
GtkColorButton *background;
GSimpleAction *reset_action;
gboolean disable_size;
};
struct _FontControlsClass
{
GtkWidgetClass parent_class;
};
G_DEFINE_TYPE(FontControls, font_controls, GTK_TYPE_WIDGET);
static void
size_changed (GtkAdjustment *adjustment,
FontControls *self)
{
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SIZE]);
g_simple_action_set_enabled (self->reset_action, TRUE);
}
static void
letterspacing_changed (GtkAdjustment *adjustment,
FontControls *self)
{
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_LETTERSPACING]);
g_simple_action_set_enabled (self->reset_action, TRUE);
}
static void
line_height_changed (GtkAdjustment *adjustment,
FontControls *self)
{
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_LINE_HEIGHT]);
g_simple_action_set_enabled (self->reset_action, TRUE);
}
static void
color_set (GtkColorButton *button,
GParamSpec *pspec,
FontControls *self)
{
if (button == self->foreground)
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FOREGROUND]);
else
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_BACKGROUND]);
g_simple_action_set_enabled (self->reset_action, TRUE);
}
static void
swap_colors (GtkButton *button,
FontControls *self)
{
GdkRGBA fg;
GdkRGBA bg;
gtk_color_chooser_get_rgba (GTK_COLOR_CHOOSER (self->foreground), &fg);
gtk_color_chooser_get_rgba (GTK_COLOR_CHOOSER (self->background), &bg);
gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (self->foreground), &bg);
gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (self->background), &fg);
}
static void
reset (GSimpleAction *action,
GVariant *parameter,
FontControls *self)
{
gtk_adjustment_set_value (self->size_adjustment, 12.);
gtk_adjustment_set_value (self->letterspacing_adjustment, 0.);
gtk_adjustment_set_value (self->line_height_adjustment, 1.);
gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (self->foreground), &(GdkRGBA){0., 0., 0., 1.0 });
gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (self->background), &(GdkRGBA){1., 1., 1., 1.0 });
g_simple_action_set_enabled (self->reset_action, FALSE);
}
static void
font_controls_init (FontControls *self)
{
gtk_widget_init_template (GTK_WIDGET (self));
self->reset_action = g_simple_action_new ("reset", NULL);
g_simple_action_set_enabled (self->reset_action, FALSE);
g_signal_connect (self->reset_action, "activate", G_CALLBACK (reset), self);
}
static void
font_controls_dispose (GObject *object)
{
gtk_widget_clear_template (GTK_WIDGET (object), FONT_CONTROLS_TYPE);
G_OBJECT_CLASS (font_controls_parent_class)->dispose (object);
}
static void
font_controls_finalize (GObject *object)
{
//FontControls *self = FONT_CONTROLS (object);
G_OBJECT_CLASS (font_controls_parent_class)->finalize (object);
}
static void
font_controls_set_property (GObject *object,
unsigned int prop_id,
const GValue *value,
GParamSpec *pspec)
{
FontControls *self = FONT_CONTROLS (object);
switch (prop_id)
{
case PROP_SIZE:
gtk_adjustment_set_value (self->size_adjustment, g_value_get_float (value));
break;
case PROP_DISABLE_SIZE:
self->disable_size = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
font_controls_get_property (GObject *object,
unsigned int prop_id,
GValue *value,
GParamSpec *pspec)
{
FontControls *self = FONT_CONTROLS (object);
switch (prop_id)
{
case PROP_SIZE:
g_value_set_float (value, gtk_adjustment_get_value (self->size_adjustment));
break;
case PROP_LETTERSPACING:
g_value_set_int (value, (int) gtk_adjustment_get_value (self->letterspacing_adjustment));
break;
case PROP_LINE_HEIGHT:
g_value_set_float (value, gtk_adjustment_get_value (self->line_height_adjustment));
break;
case PROP_FOREGROUND:
{
GdkRGBA rgba;
gtk_color_chooser_get_rgba (GTK_COLOR_CHOOSER (self->foreground), &rgba);
g_value_set_boxed (value, &rgba);
}
break;
case PROP_BACKGROUND:
{
GdkRGBA rgba;
gtk_color_chooser_get_rgba (GTK_COLOR_CHOOSER (self->background), &rgba);
g_value_set_boxed (value, &rgba);
}
break;
case PROP_DISABLE_SIZE:
g_value_set_boolean (value, self->disable_size);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
font_controls_class_init (FontControlsClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
g_type_ensure (RANGE_EDIT_TYPE);
object_class->dispose = font_controls_dispose;
object_class->finalize = font_controls_finalize;
object_class->get_property = font_controls_get_property;
object_class->set_property = font_controls_set_property;
properties[PROP_SIZE] =
g_param_spec_float ("size", "", "",
0., 100., 12.,
G_PARAM_READABLE);
properties[PROP_LETTERSPACING] =
g_param_spec_int ("letterspacing", "", "",
-G_MAXINT, G_MAXINT, 0,
G_PARAM_READABLE);
properties[PROP_LINE_HEIGHT] =
g_param_spec_float ("line-height", "", "",
0., 100., 1.,
G_PARAM_READABLE);
properties[PROP_FOREGROUND] =
g_param_spec_boxed ("foreground", "", "",
GDK_TYPE_RGBA,
G_PARAM_READABLE);
properties[PROP_BACKGROUND] =
g_param_spec_boxed ("background", "", "",
GDK_TYPE_RGBA,
G_PARAM_READABLE);
properties[PROP_DISABLE_SIZE] =
g_param_spec_boolean ("disable-size", "", "",
FALSE,
G_PARAM_READWRITE);
g_object_class_install_properties (G_OBJECT_CLASS (class), NUM_PROPERTIES, properties);
gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (class),
"/org/gtk/fontexplorer/fontcontrols.ui");
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), FontControls, size_adjustment);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), FontControls, letterspacing_adjustment);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), FontControls, line_height_adjustment);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), FontControls, foreground);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), FontControls, background);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), size_changed);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), letterspacing_changed);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), line_height_changed);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), color_set);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), swap_colors);
gtk_widget_class_set_css_name (GTK_WIDGET_CLASS (class), "fontcontrols");
}
FontControls *
font_controls_new (void)
{
return g_object_new (FONT_CONTROLS_TYPE, NULL);
}
GAction *
font_controls_get_reset_action (FontControls *self)
{
return G_ACTION (self->reset_action);
}

View File

@@ -0,0 +1,16 @@
#pragma once
#include <gtk/gtk.h>
#define FONT_CONTROLS_TYPE (font_controls_get_type ())
#define FONT_CONTROLS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FONT_CONTROLS_TYPE, FontControls))
typedef struct _FontControls FontControls;
typedef struct _FontControlsClass FontControlsClass;
GType font_controls_get_type (void);
FontControls * font_controls_new (void);
GAction * font_controls_get_reset_action (FontControls *self);

View File

@@ -0,0 +1,175 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="FontControls" parent="GtkWidget">
<property name="layout-manager"><object class="GtkGridLayout"/></property>
<child>
<object class="GtkLabel">
<property name="sensitive" bind-source="FontControls" bind-property="disable-size" bind-flags="invert-boolean"/>
<property name="label">Size</property>
<property name="xalign">0</property>
<property name="valign">baseline</property>
<layout>
<property name="column">0</property>
<property name="row">0</property>
</layout>
</object>
</child>
<child>
<object class="RangeEdit">
<property name="sensitive" bind-source="FontControls" bind-property="disable-size" bind-flags="invert-boolean"/>
<property name="hexpand">1</property>
<property name="width-request">160</property>
<property name="valign">baseline</property>
<property name="adjustment">
<object class="GtkAdjustment" id="size_adjustment">
<property name="lower">7</property>
<property name="upper">100</property>
<property name="value">14</property>
<property name="step_increment">0.5</property>
<property name="page_increment">10</property>
<signal name="value-changed" handler="size_changed"/>
</object>
</property>
<property name="default-value">12</property>
<property name="n-chars">5</property>
<layout>
<property name="column">1</property>
<property name="row">0</property>
<property name="column-span">2</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">Letterspacing</property>
<property name="xalign">0</property>
<property name="valign">baseline</property>
<layout>
<property name="column">0</property>
<property name="row">1</property>
</layout>
</object>
</child>
<child>
<object class="RangeEdit">
<property name="hexpand">1</property>
<property name="width-request">160</property>
<property name="valign">baseline</property>
<property name="adjustment">
<object class="GtkAdjustment" id="letterspacing_adjustment">
<property name="lower">-1024</property>
<property name="upper">8192</property>
<property name="value">0</property>
<property name="step_increment">1</property>
<property name="page_increment">512</property>
<signal name="value-changed" handler="letterspacing_changed"/>
</object>
</property>
<property name="default-value">0</property>
<property name="n-chars">5</property>
<layout>
<property name="column">1</property>
<property name="row">1</property>
<property name="column-span">2</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">Line Height</property>
<property name="xalign">0</property>
<property name="valign">baseline</property>
<layout>
<property name="column">0</property>
<property name="row">2</property>
</layout>
</object>
</child>
<child>
<object class="RangeEdit">
<property name="hexpand">1</property>
<property name="width-request">160</property>
<property name="valign">baseline</property>
<property name="adjustment">
<object class="GtkAdjustment" id="line_height_adjustment">
<property name="lower">0.75</property>
<property name="upper">2.5</property>
<property name="value">1.0</property>
<property name="step_increment">0.1</property>
<property name="page_increment">1</property>
<signal name="value-changed" handler="line_height_changed"/>
</object>
</property>
<property name="default-value">1</property>
<property name="n-chars">5</property>
<layout>
<property name="column">1</property>
<property name="row">2</property>
<property name="column-span">2</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">Foreground</property>
<property name="xalign">0</property>
<property name="valign">baseline</property>
<layout>
<property name="column">0</property>
<property name="row">3</property>
</layout>
</object>
</child>
<child>
<object class="GtkColorButton" id="foreground">
<property name="rgba">black</property>
<signal name="notify::rgba" handler="color_set"/>
<layout>
<property name="column">1</property>
<property name="row">3</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">Background</property>
<property name="xalign">0</property>
<property name="valign">baseline</property>
<layout>
<property name="column">0</property>
<property name="row">4</property>
</layout>
</object>
</child>
<child>
<object class="GtkColorButton" id="background">
<property name="rgba">white</property>
<signal name="notify::rgba" handler="color_set"/>
<layout>
<property name="column">1</property>
<property name="row">4</property>
</layout>
</object>
</child>
<child>
<object class="GtkButton">
<property name="icon-name">object-flip-vertical-symbolic</property>
<property name="halign">start</property>
<property name="valign">center</property>
<style>
<class name="circular"/>
</style>
<signal name="clicked" handler="swap_colors"/>
<layout>
<property name="column">2</property>
<property name="row">3</property>
<property name="row-span">2</property>
</layout>
</object>
</child>
</template>
</interface>

View File

@@ -0,0 +1,20 @@
box.sidebar {
padding: 20px;
border-spacing: 20px;
}
fontcontrols {
border-spacing: 10px;
}
fontvariations > grid {
border-spacing: 10px;
}
fontcolors > grid {
border-spacing: 10px;
}
samplechooser {
border-spacing: 10px;
}
fontview {
padding: 10px;
border-spacing: 10px;
}

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/gtk/fontexplorer">
<file preprocess="xml-stripblanks">fontexplorerwin.ui</file>
<file preprocess="xml-stripblanks">fontview.ui</file>
<file preprocess="xml-stripblanks">fontcontrols.ui</file>
<file preprocess="xml-stripblanks">samplechooser.ui</file>
<file preprocess="xml-stripblanks">fontcolors.ui</file>
<file preprocess="xml-stripblanks">fontfeatures.ui</file>
<file preprocess="xml-stripblanks">fontvariations.ui</file>
<file preprocess="xml-stripblanks">rangeedit.ui</file>
<file>fontexplorer.css</file>
</gresource>
</gresources>

View File

@@ -0,0 +1,165 @@
#include "config.h"
#include <gtk/gtk.h>
#include "fontexplorerapp.h"
#include "fontexplorerwin.h"
#include "demo_conf.h"
struct _FontExplorerApp
{
GtkApplication parent;
};
struct _FontExplorerAppClass
{
GtkApplicationClass parent_class;
};
G_DEFINE_TYPE(FontExplorerApp, font_explorer_app, GTK_TYPE_APPLICATION);
static void
font_explorer_app_init (FontExplorerApp *app)
{
}
static void
quit_activated (GSimpleAction *action,
GVariant *parameter,
gpointer app)
{
g_application_quit (G_APPLICATION (app));
}
static void
inspector_activated (GSimpleAction *action,
GVariant *parameter,
gpointer app)
{
gtk_window_set_interactive_debugging (TRUE);
}
static void
about_activated (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
{
GtkApplication *app = user_data;
const char *authors[] = {
"The GTK Team",
NULL
};
char *icon_theme;
char *version;
GString *s;
char *os_name;
char *os_version;
g_object_get (gtk_settings_get_default (),
"gtk-icon-theme-name", &icon_theme,
NULL);
s = g_string_new ("");
os_name = g_get_os_info (G_OS_INFO_KEY_NAME);
os_version = g_get_os_info (G_OS_INFO_KEY_VERSION_ID);
if (os_name && os_version)
g_string_append_printf (s, "OS\t%s %s\n\n", os_name, os_version);
g_string_append (s, "System libraries\n");
g_string_append_printf (s, "\tGLib\t%d.%d.%d\n",
glib_major_version,
glib_minor_version,
glib_micro_version);
g_string_append_printf (s, "\tPango2\t%s\n",
pango2_version_string ());
g_string_append_printf (s, "\tGTK \t%d.%d.%d\n",
gtk_get_major_version (),
gtk_get_minor_version (),
gtk_get_micro_version ());
g_string_append_printf (s, "\nIcon theme\n\t%s", icon_theme);
version = g_strdup_printf ("%s%s%s\nRunning against GTK %d.%d.%d",
PACKAGE_VERSION,
g_strcmp0 (PROFILE, "devel") == 0 ? "-" : "",
g_strcmp0 (PROFILE, "devel") == 0 ? VCS_TAG : "",
gtk_get_major_version (),
gtk_get_minor_version (),
gtk_get_micro_version ());
gtk_show_about_dialog (GTK_WINDOW (gtk_application_get_active_window (app)),
"program-name", g_strcmp0 (PROFILE, "devel") == 0
? "GTK Font Explorer (Development)"
: "GTK Font Explorer",
"version", version,
"copyright", "©1997—2021 The GTK Team",
"license-type", GTK_LICENSE_LGPL_2_1,
"website", "http://www.gtk.org",
"comments", "Program to explore font features",
"authors", authors,
"logo-icon-name", "org.gtk.FontExplorer",
"title", "About GTK Font Explorer",
"system-information", s->str,
NULL);
g_string_free (s, TRUE);
g_free (version);
g_free (icon_theme);
g_free (os_name);
g_free (os_version);
}
static GActionEntry app_entries[] =
{
{ "quit", quit_activated, NULL, NULL, NULL },
{ "inspector", inspector_activated, NULL, NULL, NULL },
{ "about", about_activated, NULL, NULL, NULL }
};
static void
font_explorer_app_startup (GApplication *app)
{
const char *quit_accels[2] = { "<Ctrl>Q", NULL };
GtkCssProvider *provider;
G_APPLICATION_CLASS (font_explorer_app_parent_class)->startup (app);
g_action_map_add_action_entries (G_ACTION_MAP (app),
app_entries, G_N_ELEMENTS (app_entries),
app);
gtk_application_set_accels_for_action (GTK_APPLICATION (app),
"app.quit",
quit_accels);
provider = gtk_css_provider_new ();
gtk_css_provider_load_from_resource (provider, "/org/gtk/fontexplorer/fontexplorer.css");
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
GTK_STYLE_PROVIDER (provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
}
static void
font_explorer_app_activate (GApplication *app)
{
FontExplorerWindow *win;
win = font_explorer_window_new (FONT_EXPLORER_APP (app));
if (g_strcmp0 (PROFILE, "devel") == 0)
gtk_widget_add_css_class (GTK_WIDGET (win), "devel");
gtk_window_present (GTK_WINDOW (win));
}
static void
font_explorer_app_class_init (FontExplorerAppClass *class)
{
G_APPLICATION_CLASS (class)->startup = font_explorer_app_startup;
G_APPLICATION_CLASS (class)->activate = font_explorer_app_activate;
}
FontExplorerApp *
font_explorer_app_new (void)
{
return g_object_new (FONT_EXPLORER_APP_TYPE,
"application-id", "org.gtk.FontExplorer",
NULL);
}

View File

@@ -0,0 +1,15 @@
#pragma once
#include <gtk/gtk.h>
#define FONT_EXPLORER_APP_TYPE (font_explorer_app_get_type ())
#define FONT_EXPLORER_APP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FONT_EXPLORER_APP_TYPE, FontExplorerApp))
typedef struct _FontExplorerApp FontExplorerApp;
typedef struct _FontExplorerAppClass FontExplorerAppClass;
GType font_explorer_app_get_type (void);
FontExplorerApp * font_explorer_app_new (void);

View File

@@ -0,0 +1,131 @@
#include "fontexplorerapp.h"
#include "fontexplorerwin.h"
#include "fontview.h"
#include "fontcontrols.h"
#include "samplechooser.h"
#include "fontcolors.h"
#include "fontfeatures.h"
#include "fontvariations.h"
#include <gtk/gtk.h>
#include <string.h>
struct _FontExplorerWindow
{
GtkApplicationWindow parent;
GtkFontButton *fontbutton;
FontControls *controls;
FontFeatures *features;
FontVariations *variations;
FontColors *colors;
FontView *view;
};
struct _FontExplorerWindowClass
{
GtkApplicationWindowClass parent_class;
};
G_DEFINE_TYPE(FontExplorerWindow, font_explorer_window, GTK_TYPE_APPLICATION_WINDOW);
static void
reset (GSimpleAction *action,
GVariant *parameter,
FontExplorerWindow *win)
{
g_action_activate (font_controls_get_reset_action (win->controls), NULL);
g_action_activate (font_features_get_reset_action (win->features), NULL);
g_action_activate (font_variations_get_reset_action (win->variations), NULL);
g_action_activate (font_colors_get_reset_action (win->colors), NULL);
}
static void
update_reset (GSimpleAction *action,
GParamSpec *pspec,
FontExplorerWindow *win)
{
gboolean enabled;
GAction *reset_action;
enabled = g_action_get_enabled (font_controls_get_reset_action (win->controls)) ||
g_action_get_enabled (font_features_get_reset_action (win->features)) ||
g_action_get_enabled (font_variations_get_reset_action (win->variations)) ||
g_action_get_enabled (font_colors_get_reset_action (win->colors));
reset_action = g_action_map_lookup_action (G_ACTION_MAP (win), "reset");
g_simple_action_set_enabled (G_SIMPLE_ACTION (reset_action), enabled);
}
static void
font_explorer_window_init (FontExplorerWindow *win)
{
GSimpleAction *reset_action;
gtk_widget_init_template (GTK_WIDGET (win));
reset_action = g_simple_action_new ("reset", NULL);
g_signal_connect (reset_action, "activate", G_CALLBACK (reset), win);
g_signal_connect (font_controls_get_reset_action (win->controls),
"notify::enabled", G_CALLBACK (update_reset), win);
g_signal_connect (font_variations_get_reset_action (win->variations),
"notify::enabled", G_CALLBACK (update_reset), win);
g_signal_connect (font_colors_get_reset_action (win->colors),
"notify::enabled", G_CALLBACK (update_reset), win);
g_signal_connect (font_features_get_reset_action (win->features),
"notify::enabled", G_CALLBACK (update_reset), win);
g_action_map_add_action (G_ACTION_MAP (win), G_ACTION (reset_action));
update_reset (NULL, NULL, win);
}
static void
font_explorer_window_dispose (GObject *object)
{
gtk_widget_clear_template (GTK_WIDGET (object), FONT_EXPLORER_WINDOW_TYPE);
G_OBJECT_CLASS (font_explorer_window_parent_class)->dispose (object);
}
static void
font_explorer_window_finalize (GObject *object)
{
// FontExplorerWindow *win = FONT_EXPLORER_WINDOW (object);
G_OBJECT_CLASS (font_explorer_window_parent_class)->finalize (object);
}
static void
font_explorer_window_class_init (FontExplorerWindowClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
g_type_ensure (FONT_VIEW_TYPE);
g_type_ensure (FONT_CONTROLS_TYPE);
g_type_ensure (SAMPLE_CHOOSER_TYPE);
g_type_ensure (FONT_VARIATIONS_TYPE);
g_type_ensure (FONT_COLORS_TYPE);
g_type_ensure (FONT_FEATURES_TYPE);
object_class->dispose = font_explorer_window_dispose;
object_class->finalize = font_explorer_window_finalize;
gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (class),
"/org/gtk/fontexplorer/fontexplorerwin.ui");
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), FontExplorerWindow, fontbutton);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), FontExplorerWindow, controls);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), FontExplorerWindow, variations);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), FontExplorerWindow, colors);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), FontExplorerWindow, features);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), FontExplorerWindow, view);
}
FontExplorerWindow *
font_explorer_window_new (FontExplorerApp *app)
{
return g_object_new (FONT_EXPLORER_WINDOW_TYPE, "application", app, NULL);
}

View File

@@ -0,0 +1,16 @@
#pragma once
#include <gtk/gtk.h>
#include "fontexplorerapp.h"
#define FONT_EXPLORER_WINDOW_TYPE (font_explorer_window_get_type ())
#define FONT_EXPLORER_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FONT_EXPLORER_WINDOW_TYPE, FontExplorerWindow))
typedef struct _FontExplorerWindow FontExplorerWindow;
typedef struct _FontExplorerWindowClass FontExplorerWindowClass;
GType font_explorer_window_get_type (void);
FontExplorerWindow * font_explorer_window_new (FontExplorerApp *app);

View File

@@ -0,0 +1,100 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<menu id="gear_menu">
<section>
<item>
<attribute name="label" translatable="yes">_Inspector</attribute>
<attribute name="action">app.inspector</attribute>
</item>
<item>
<attribute name="label" translatable="yes">_About GTK Font Explorer</attribute>
<attribute name="action">app.about</attribute>
</item>
</section>
</menu>
<template class="FontExplorerWindow" parent="GtkApplicationWindow">
<property name="title" translatable="yes">Font Explorer</property>
<property name="default-width">1024</property>
<property name="default-height">768</property>
<child type="titlebar">
<object class="GtkHeaderBar">
<child>
<object class="GtkButton" id="reset">
<property name="receives-default">1</property>
<property name="tooltip-text">Reset</property>
<property name="icon-name">view-refresh-symbolic</property>
<property name="action-name">win.reset</property>
</object>
</child>
<child type="end">
<object class="GtkMenuButton" id="gear_menu_button">
<property name="focus-on-click">0</property>
<property name="valign">center</property>
<property name="menu-model">gear_menu</property>
<property name="icon-name">open-menu-symbolic</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox">
<child>
<object class="GtkScrolledWindow">
<property name="hscrollbar-policy">never</property>
<child>
<object class="GtkBox">
<property name="orientation">vertical</property>
<style>
<class name="sidebar"/>
</style>
<child>
<object class="GtkFontButton" id="fontbutton">
<property name="level">family|style</property>
</object>
</child>
<child>
<object class="FontControls" id="controls">
<property name="disable-size" bind-source="view" bind-property="ignore-size" bind-flags="sync-create"/>
</object>
</child>
<child>
<object class="SampleChooser" id="samplechooser"/>
</child>
<child>
<object class="FontVariations" id="variations">
<property name="font-desc" bind-source="fontbutton" bind-flags="sync-create"/>
</object>
</child>
<child>
<object class="FontFeatures" id="features">
<property name="font-desc" bind-source="fontbutton" bind-flags="sync-create"/>
<property name="language" bind-source="fontbutton" bind-flags="sync-create"/>
</object>
</child>
<child>
<object class="FontColors" id="colors">
<property name="font-desc" bind-source="fontbutton" bind-flags="sync-create"/>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="FontView" id="view">
<property name="font-desc" bind-source="fontbutton" bind-flags="sync-create"/>
<property name="size" bind-source="controls" bind-flags="sync-create"/>
<property name="letterspacing" bind-source="controls" bind-flags="sync-create"/>
<property name="line-height" bind-source="controls" bind-flags="sync-create"/>
<property name="foreground" bind-source="controls" bind-flags="sync-create"/>
<property name="background" bind-source="controls" bind-flags="sync-create"/>
<property name="sample-text" bind-source="samplechooser" bind-flags="sync-create"/>
<property name="features" bind-source="features" bind-flags="sync-create"/>
<property name="variations" bind-source="variations" bind-flags="sync-create"/>
<property name="palette" bind-source="colors" bind-flags="sync-create"/>
</object>
</child>
</object>
</child>
</template>
</interface>

View File

@@ -0,0 +1,727 @@
#include "fontfeatures.h"
#include <gtk/gtk.h>
#include <hb-ot.h>
#include <glib/gi18n.h>
#include "open-type-layout.h"
#include "language-names.h"
enum {
PROP_FONT_DESC = 1,
PROP_LANGUAGE,
PROP_FEATURES,
NUM_PROPERTIES
};
static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
typedef struct {
unsigned int tag;
const char *name;
GtkWidget *feat;
} FeatureItem;
struct _FontFeatures
{
GtkWidget parent;
GtkGrid *label;
GtkGrid *grid;
Pango2FontDescription *font_desc;
GSimpleAction *reset_action;
Pango2Language *lang;
GList *feature_items;
};
struct _FontFeaturesClass
{
GtkWidgetClass parent_class;
};
G_DEFINE_TYPE(FontFeatures, font_features, GTK_TYPE_WIDGET);
static Pango2Font *
get_font (FontFeatures *self)
{
Pango2Context *context;
context = gtk_widget_get_pango_context (GTK_WIDGET (self));
return pango2_context_load_font (context, self->font_desc);
}
static gboolean
is_ssNN (const char *buf)
{
return g_str_has_prefix (buf, "ss") && g_ascii_isdigit (buf[2]) && g_ascii_isdigit (buf[3]);
}
static gboolean
is_cvNN (const char *buf)
{
return g_str_has_prefix (buf, "cv") && g_ascii_isdigit (buf[2]) && g_ascii_isdigit (buf[3]);
}
static char *
get_feature_display_name (unsigned int tag)
{
int i;
static char buf[5] = { 0, };
if (tag == HB_TAG ('x', 'x', 'x', 'x'))
return g_strdup (_("Default"));
hb_tag_to_string (tag, buf);
if (is_ssNN (buf))
{
int num = (buf[2] - '0') * 10 + (buf[3] - '0');
return g_strdup_printf (g_dpgettext2 (NULL, "OpenType layout", "Stylistic Set %d"), num);
}
else if (is_cvNN (buf))
{
int num = (buf[2] - '0') * 10 + (buf[3] - '0');
return g_strdup_printf (g_dpgettext2 (NULL, "OpenType layout", "Character Variant %d"), num);
}
for (i = 0; i < G_N_ELEMENTS (open_type_layout_features); i++)
{
if (tag == open_type_layout_features[i].tag)
return g_strdup (g_dpgettext2 (NULL, "OpenType layout", open_type_layout_features[i].name));
}
g_warning ("unknown OpenType layout feature tag: %s", buf);
return g_strdup (buf);
}
static void
update_feature_label (FontFeatures *self,
FeatureItem *item,
hb_font_t *hb_font,
hb_tag_t script_tag,
hb_tag_t lang_tag)
{
hb_face_t *hb_face;
unsigned int script_index, lang_index, feature_index;
hb_ot_name_id_t id;
unsigned int len;
char *label;
char name[5] = { 0, };
hb_face = hb_font_get_face (hb_font);
hb_tag_to_string (item->tag, name);
if (!is_ssNN (name) && !is_cvNN (name))
return;
hb_ot_layout_table_find_script (hb_face, HB_OT_TAG_GSUB, script_tag, &script_index);
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
hb_ot_layout_script_find_language (hb_face, HB_OT_TAG_GSUB, script_index, lang_tag, &lang_index);
G_GNUC_END_IGNORE_DEPRECATIONS
if (hb_ot_layout_language_find_feature (hb_face, HB_OT_TAG_GSUB, script_index, lang_index, item->tag, &feature_index) &&
hb_ot_layout_feature_get_name_ids (hb_face, HB_OT_TAG_GSUB, feature_index, &id, NULL, NULL, NULL, NULL))
{
len = hb_ot_name_get_utf8 (hb_face, id, HB_LANGUAGE_INVALID, NULL, NULL);
len++;
label = g_new (char, len);
hb_ot_name_get_utf8 (hb_face, id, HB_LANGUAGE_INVALID, &len, label);
gtk_check_button_set_label (GTK_CHECK_BUTTON (item->feat), label);
g_free (label);
}
else
{
label = get_feature_display_name (item->tag);
gtk_check_button_set_label (GTK_CHECK_BUTTON (item->feat), label);
g_free (label);
}
}
static void
set_inconsistent (GtkCheckButton *button,
gboolean inconsistent)
{
gtk_check_button_set_inconsistent (GTK_CHECK_BUTTON (button), inconsistent);
gtk_widget_set_opacity (gtk_widget_get_first_child (GTK_WIDGET (button)), inconsistent ? 0.0 : 1.0);
}
static void
find_language_and_script (FontFeatures *self,
hb_face_t *hb_face,
hb_tag_t *lang_tag,
hb_tag_t *script_tag)
{
int i, j, k;
hb_tag_t scripts[80];
unsigned int n_scripts;
unsigned int count;
hb_tag_t table[2] = { HB_OT_TAG_GSUB, HB_OT_TAG_GPOS };
hb_language_t lang;
const char *langname, *p;
langname = pango2_language_to_string (self->lang);
p = strchr (langname, '-');
lang = hb_language_from_string (langname, p ? p - langname : -1);
n_scripts = 0;
for (i = 0; i < 2; i++)
{
count = G_N_ELEMENTS (scripts);
hb_ot_layout_table_get_script_tags (hb_face, table[i], n_scripts, &count, scripts);
n_scripts += count;
}
for (j = 0; j < n_scripts; j++)
{
hb_tag_t languages[80];
unsigned int n_languages;
n_languages = 0;
for (i = 0; i < 2; i++)
{
count = G_N_ELEMENTS (languages);
hb_ot_layout_script_get_language_tags (hb_face, table[i], j, n_languages, &count, languages);
n_languages += count;
}
for (k = 0; k < n_languages; k++)
{
if (lang == hb_ot_tag_to_language (languages[k]))
{
*script_tag = scripts[j];
*lang_tag = languages[k];
return;
}
}
}
*lang_tag = HB_OT_TAG_DEFAULT_LANGUAGE;
*script_tag = HB_OT_TAG_DEFAULT_SCRIPT;
}
static void
hide_feature_maybe (FeatureItem *item,
gboolean has_feature)
{
gtk_widget_set_visible (item->feat, has_feature);
if (has_feature)
gtk_widget_set_visible (gtk_widget_get_parent (item->feat), TRUE);
}
/* Make features insensitive if the font/langsys does not have them,
* and reset all others to their initial value
*/
static void
update_features (FontFeatures *self)
{
guint script_index, lang_index;
hb_tag_t lang_tag;
hb_tag_t script_tag;
Pango2Font *font;
hb_font_t *hb_font;
hb_face_t *hb_face;
font = get_font (self);
hb_font = pango2_font_get_hb_font (font);
hb_face = hb_font_get_face (hb_font);
{
hb_tag_t table[2] = { HB_OT_TAG_GSUB, HB_OT_TAG_GPOS };
hb_tag_t features[256];
unsigned int count;
unsigned int n_features = 0;
find_language_and_script (self, hb_face, &lang_tag, &script_tag);
/* Collect all features */
for (int i = 0; i < 2; i++)
{
hb_ot_layout_table_find_script (hb_face,
table[i],
script_tag,
&script_index);
hb_ot_layout_script_select_language (hb_face,
table[i],
script_index,
1,
&lang_tag,
&lang_index);
count = G_N_ELEMENTS (features);
hb_ot_layout_language_get_feature_tags (hb_face,
table[i],
script_index,
lang_index,
n_features,
&count,
features);
n_features += count;
}
/* Update all the features */
for (GList *l = self->feature_items; l; l = l->next)
{
FeatureItem *item = l->data;
gboolean has_feature = FALSE;
for (int j = 0; j < n_features; j++)
{
if (item->tag == features[j])
{
has_feature = TRUE;
break;
}
}
update_feature_label (self, item, hb_font, script_tag, lang_tag);
hide_feature_maybe (item, has_feature);
if (GTK_IS_CHECK_BUTTON (item->feat))
{
GtkWidget *def = GTK_WIDGET (g_object_get_data (G_OBJECT (item->feat), "default"));
if (def)
{
gtk_widget_show (def);
gtk_widget_show (gtk_widget_get_parent (def));
gtk_check_button_set_active (GTK_CHECK_BUTTON (def), TRUE);
}
else
set_inconsistent (GTK_CHECK_BUTTON (item->feat), TRUE);
}
}
}
/* Hide empty groups */
for (GList *l = self->feature_items; l; l = l->next)
{
FeatureItem *item = l->data;
GtkWidget *box;
box = gtk_widget_get_parent (item->feat);
if (gtk_widget_get_visible (box))
{
GtkWidget *c;
int count;
count = 0;
for (c = gtk_widget_get_first_child (box); c; c = gtk_widget_get_next_sibling (c))
{
if (gtk_widget_get_visible (c))
count++;
}
if (count == 1)
gtk_widget_hide (box);
else if (count == 2 &&
item->tag == HB_TAG ('x', 'x', 'x', 'x'))
gtk_widget_hide (box);
}
}
}
static void
script_changed (GtkComboBox *combo,
FontFeatures *self)
{
update_features (self);
}
static char *
get_features (FontFeatures *self)
{
GString *s;
char buf[128];
s = g_string_new ("");
for (GList *l = self->feature_items; l; l = l->next)
{
FeatureItem *item = l->data;
if (!gtk_widget_is_sensitive (item->feat))
continue;
if (GTK_IS_CHECK_BUTTON (item->feat) && g_object_get_data (G_OBJECT (item->feat), "default"))
{
if (gtk_check_button_get_active (GTK_CHECK_BUTTON (item->feat)) &&
item->tag != HB_TAG ('x', 'x', 'x', 'x'))
{
hb_feature_to_string (&(hb_feature_t) { item->tag, 1, 0, -1 }, buf, sizeof (buf));
if (s->len > 0)
g_string_append_c (s, ',');
g_string_append (s, buf);
}
}
else if (GTK_IS_CHECK_BUTTON (item->feat))
{
guint32 value;
if (gtk_check_button_get_inconsistent (GTK_CHECK_BUTTON (item->feat)))
continue;
value = gtk_check_button_get_active (GTK_CHECK_BUTTON (item->feat));
hb_feature_to_string (&(hb_feature_t) { item->tag, value, 0, -1 }, buf, sizeof (buf));
if (s->len > 0)
g_string_append_c (s, ',');
g_string_append (s, buf);
}
}
return g_string_free (s, FALSE);
}
static void
update_display (FontFeatures *self)
{
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FEATURES]);
g_simple_action_set_enabled (self->reset_action, TRUE);
}
static GtkWidget *
make_title_label (const char *title)
{
GtkWidget *label;
label = gtk_label_new (title);
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
gtk_widget_set_halign (label, GTK_ALIGN_START);
g_object_set (label, "margin-top", 10, "margin-bottom", 10, NULL);
gtk_widget_add_css_class (label, "heading");
return label;
}
static void
feat_toggled_cb (GtkCheckButton *check_button,
gpointer data)
{
set_inconsistent (check_button, FALSE);
}
static void
feat_pressed (GtkGestureClick *gesture,
int n_press,
double x,
double y,
GtkWidget *feat)
{
const guint button = gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture));
if (button == GDK_BUTTON_PRIMARY)
{
g_signal_handlers_block_by_func (feat, feat_pressed, NULL);
if (gtk_check_button_get_inconsistent (GTK_CHECK_BUTTON (feat)))
{
set_inconsistent (GTK_CHECK_BUTTON (feat), FALSE);
gtk_check_button_set_active (GTK_CHECK_BUTTON (feat), TRUE);
}
g_signal_handlers_unblock_by_func (feat, feat_pressed, NULL);
}
else if (button == GDK_BUTTON_SECONDARY)
{
gboolean inconsistent = gtk_check_button_get_inconsistent (GTK_CHECK_BUTTON (feat));
set_inconsistent (GTK_CHECK_BUTTON (feat), !inconsistent);
}
}
static void
add_check_group (FontFeatures *self,
const char *title,
const char **tags,
unsigned int n_tags,
int row)
{
GtkWidget *group;
int i;
group = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_widget_set_halign (group, GTK_ALIGN_START);
gtk_box_append (GTK_BOX (group), make_title_label (title));
for (i = 0; i < n_tags; i++)
{
unsigned int tag;
GtkWidget *feat;
FeatureItem *item;
GtkGesture *gesture;
char *name;
tag = hb_tag_from_string (tags[i], -1);
name = get_feature_display_name (tag);
feat = gtk_check_button_new_with_label (name);
g_free (name);
set_inconsistent (GTK_CHECK_BUTTON (feat), TRUE);
g_signal_connect_swapped (feat, "notify::active", G_CALLBACK (update_display), self);
g_signal_connect_swapped (feat, "notify::inconsistent", G_CALLBACK (update_display), self);
g_signal_connect (feat, "toggled", G_CALLBACK (feat_toggled_cb), NULL);
gesture = gtk_gesture_click_new ();
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture), GDK_BUTTON_SECONDARY);
g_signal_connect (gesture, "pressed", G_CALLBACK (feat_pressed), feat);
gtk_widget_add_controller (feat, GTK_EVENT_CONTROLLER (gesture));
gtk_box_append (GTK_BOX (group), feat);
item = g_new (FeatureItem, 1);
item->name = tags[i];
item->tag = tag;
item->feat = feat;
self->feature_items = g_list_prepend (self->feature_items, item);
}
gtk_grid_attach (self->grid, group, 0, row, 2, 1);
}
static void
add_radio_group (FontFeatures *self,
const char *title,
const char **tags,
unsigned int n_tags,
int row)
{
GtkWidget *group;
int i;
GtkWidget *group_button = NULL;
group = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_widget_set_halign (group, GTK_ALIGN_START);
gtk_box_append (GTK_BOX (group), make_title_label (title));
for (i = 0; i < n_tags; i++)
{
unsigned int tag;
GtkWidget *feat;
FeatureItem *item;
char *name;
tag = hb_tag_from_string (tags[i], -1);
name = get_feature_display_name (tag);
feat = gtk_check_button_new_with_label (name ? name : _("Default"));
g_free (name);
if (group_button == NULL)
group_button = feat;
else
gtk_check_button_set_group (GTK_CHECK_BUTTON (feat), GTK_CHECK_BUTTON (group_button));
g_signal_connect_swapped (feat, "notify::active", G_CALLBACK (update_display), self);
g_object_set_data (G_OBJECT (feat), "default", group_button);
gtk_box_append (GTK_BOX (group), feat);
item = g_new (FeatureItem, 1);
item->name = tags[i];
item->tag = tag;
item->feat = feat;
self->feature_items = g_list_prepend (self->feature_items, item);
}
gtk_grid_attach (self->grid, group, 0, row, 2, 1);
}
static void
setup_features (FontFeatures *self)
{
const char *kerning[] = { "kern" };
const char *ligatures[] = { "liga", "dlig", "hlig", "clig", "rlig" };
const char *letter_case[] = {
"smcp", "c2sc", "pcap", "c2pc", "unic", "cpsp", "case"
};
const char *number_case[] = { "xxxx", "lnum", "onum" };
const char *number_spacing[] = { "xxxx", "pnum", "tnum" };
const char *fractions[] = { "xxxx", "frac", "afrc" };
const char *num_extras[] = { "zero", "nalt", "sinf" };
const char *char_alt[] = {
"swsh", "cswh", "locl", "calt", "falt", "hist",
"salt", "jalt", "titl", "rand", "subs", "sups",
"ordn", "ltra", "ltrm", "rtla", "rtlm", "rclt"
};
const char *pos_alt[] = {
"init", "medi", "med2", "fina", "fin2", "fin3", "isol"
};
const char *width_var[] = {
"fwid", "hwid", "halt", "pwid", "palt", "twid", "qwid"
};
const char *style_alt[] = {
"ss01", "ss02", "ss03", "ss04", "ss05", "ss06",
"ss07", "ss08", "ss09", "ss10", "ss11", "ss12",
"ss13", "ss14", "ss15", "ss16", "ss17", "ss18",
"ss19", "ss20"
};
const char *char_var[] = {
"cv01", "cv02", "cv03", "cv04", "cv05", "cv06",
"cv07", "cv08", "cv09", "cv10", "cv11", "cv12",
"cv13", "cv14", "cv15", "cv16", "cv17", "cv18",
"cv19", "cv20"
};
const char *math[] = { "dtls", "flac", "mgrk", "ssty" };
const char *bounds[] = { "opbd", "lfbd", "rtbd" };
int row = 0;
add_check_group (self, _("Kerning"), kerning, G_N_ELEMENTS (kerning), row++);
add_check_group (self, _("Ligatures"), ligatures, G_N_ELEMENTS (ligatures), row++);
add_check_group (self, _("Letter Case"), letter_case, G_N_ELEMENTS (letter_case), row++);
add_radio_group (self, _("Number Case"), number_case, G_N_ELEMENTS (number_case), row++);
add_radio_group (self, _("Number Spacing"), number_spacing, G_N_ELEMENTS (number_spacing), row++);
add_radio_group (self, _("Fractions"), fractions, G_N_ELEMENTS (fractions), row++);
add_check_group (self, _("Numeric Extras"), num_extras, G_N_ELEMENTS (num_extras), row++);
add_check_group (self, _("Character Alternatives"), char_alt, G_N_ELEMENTS (char_alt), row++);
add_check_group (self, _("Positional Alternatives"), pos_alt, G_N_ELEMENTS (pos_alt), row++);
add_check_group (self, _("Width Variants"), width_var, G_N_ELEMENTS (width_var), row++);
add_check_group (self, _("Alternative Stylistic Sets"), style_alt, G_N_ELEMENTS (style_alt), row++);
add_check_group (self, _("Character Variants"), char_var, G_N_ELEMENTS (char_var), row++);
add_check_group (self, _("Mathematical"), math, G_N_ELEMENTS (math), row++);
add_check_group (self, _("Optical Bounds"), bounds, G_N_ELEMENTS (bounds), row++);
self->feature_items = g_list_reverse (self->feature_items);
}
static void
reset (GSimpleAction *action,
GVariant *parameter,
FontFeatures *self)
{
update_features (self);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FEATURES]);
g_simple_action_set_enabled (self->reset_action, FALSE);
}
static void
font_features_init (FontFeatures *self)
{
gtk_widget_init_template (GTK_WIDGET (self));
self->font_desc = pango2_font_description_from_string ("sans 12");
self->lang = pango2_language_get_default ();
setup_features (self);
self->reset_action = g_simple_action_new ("reset", NULL);
g_simple_action_set_enabled (self->reset_action, FALSE);
g_signal_connect (self->reset_action, "activate", G_CALLBACK (reset), self);
}
static void
font_features_dispose (GObject *object)
{
FontFeatures *self = FONT_FEATURES (object);
gtk_widget_clear_template (GTK_WIDGET (object), FONT_FEATURES_TYPE);
g_list_free_full (self->feature_items, g_free);
G_OBJECT_CLASS (font_features_parent_class)->dispose (object);
}
static void
font_features_finalize (GObject *object)
{
FontFeatures *self = FONT_FEATURES (object);
g_clear_pointer (&self->font_desc, pango2_font_description_free);
G_OBJECT_CLASS (font_features_parent_class)->finalize (object);
}
static void
font_features_set_property (GObject *object,
unsigned int prop_id,
const GValue *value,
GParamSpec *pspec)
{
FontFeatures *self = FONT_FEATURES (object);
switch (prop_id)
{
case PROP_FONT_DESC:
pango2_font_description_free (self->font_desc);
self->font_desc = pango2_font_description_copy (g_value_get_boxed (value));
update_features (self);
break;
case PROP_LANGUAGE:
self->lang = pango2_language_from_string (g_value_get_string (value));
update_features (self);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
font_features_get_property (GObject *object,
unsigned int prop_id,
GValue *value,
GParamSpec *pspec)
{
FontFeatures *self = FONT_FEATURES (object);
switch (prop_id)
{
case PROP_FEATURES:
g_value_take_string (value, get_features (self));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
font_features_class_init (FontFeaturesClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
object_class->dispose = font_features_dispose;
object_class->finalize = font_features_finalize;
object_class->get_property = font_features_get_property;
object_class->set_property = font_features_set_property;
properties[PROP_FONT_DESC] =
g_param_spec_boxed ("font-desc", "", "",
PANGO2_TYPE_FONT_DESCRIPTION,
G_PARAM_WRITABLE);
properties[PROP_LANGUAGE] =
g_param_spec_string ("language", "", "",
"en",
G_PARAM_WRITABLE);
properties[PROP_FEATURES] =
g_param_spec_string ("features", "", "",
"",
G_PARAM_READABLE);
g_object_class_install_properties (G_OBJECT_CLASS (class), NUM_PROPERTIES, properties);
gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (class),
"/org/gtk/fontexplorer/fontfeatures.ui");
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), FontFeatures, grid);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), FontFeatures, label);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), script_changed);
gtk_widget_class_set_css_name (GTK_WIDGET_CLASS (class), "fontfeatures");
}
FontFeatures *
font_features_new (void)
{
return g_object_new (FONT_FEATURES_TYPE, NULL);
}
GAction *
font_features_get_reset_action (FontFeatures *self)
{
return G_ACTION (self->reset_action);
}

View File

@@ -0,0 +1,16 @@
#pragma once
#include <gtk/gtk.h>
#define FONT_FEATURES_TYPE (font_features_get_type ())
#define FONT_FEATURES(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FONT_FEATURES_TYPE, FontFeatures))
typedef struct _FontFeatures FontFeatures;
typedef struct _FontFeaturesClass FontFeaturesClass;
GType font_features_get_type (void);
FontFeatures * font_features_new (void);
GAction * font_features_get_reset_action (FontFeatures *self);

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="FontFeatures" parent="GtkWidget">
<property name="layout-manager"><object class="GtkBinLayout"/></property>
<child>
<object class="GtkGrid" id="grid">
<child>
<object class="GtkLabel" id="label">
<property name="label" translatable="yes">Features</property>
<property name="margin-bottom">10</property>
<property name="xalign">0</property>
<style>
<class name="heading"/>
</style>
<layout>
<property name="row">-1</property>
<property name="column">0</property>
<property name="column-span">2</property>
</layout>
</object>
</child>
</object>
</child>
</template>
</interface>

View File

@@ -0,0 +1,488 @@
#include "fontvariations.h"
#include "rangeedit.h"
#include <gtk/gtk.h>
#include <hb-ot.h>
enum {
PROP_FONT_DESC = 1,
PROP_VARIATIONS,
NUM_PROPERTIES
};
static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
struct _FontVariations
{
GtkWidget parent;
GtkGrid *label;
GtkGrid *grid;
Pango2FontDescription *font_desc;
GSimpleAction *reset_action;
gboolean has_variations;
GtkWidget *instance_combo;
GHashTable *axes;
GHashTable *instances;
};
struct _FontVariationsClass
{
GtkWidgetClass parent_class;
};
G_DEFINE_TYPE(FontVariations, font_variations, GTK_TYPE_WIDGET);
static Pango2Font *
get_font (FontVariations *self)
{
Pango2Context *context;
context = gtk_widget_get_pango_context (GTK_WIDGET (self));
return pango2_context_load_font (context, self->font_desc);
}
typedef struct {
guint32 tag;
GtkAdjustment *adjustment;
double default_value;
} Axis;
static guint
axes_hash (gconstpointer v)
{
const Axis *p = v;
return p->tag;
}
static gboolean
axes_equal (gconstpointer v1, gconstpointer v2)
{
const Axis *p1 = v1;
const Axis *p2 = v2;
return p1->tag == p2->tag;
}
static void
unset_instance (GtkAdjustment *adjustment,
FontVariations *self)
{
if (self->instance_combo)
gtk_combo_box_set_active (GTK_COMBO_BOX (self->instance_combo), 0);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_VARIATIONS]);
g_simple_action_set_enabled (self->reset_action, TRUE);
}
static void
add_axis (FontVariations *self,
hb_face_t *hb_face,
hb_ot_var_axis_info_t *ax,
int i)
{
GtkWidget *axis_label;
GtkWidget *axis_scale;
GtkAdjustment *adjustment;
Axis *axis;
char name[20];
unsigned int name_len = 20;
hb_ot_name_get_utf8 (hb_face, ax->name_id, HB_LANGUAGE_INVALID, &name_len, name);
axis_label = gtk_label_new (name);
gtk_widget_set_halign (axis_label, GTK_ALIGN_START);
gtk_widget_set_valign (axis_label, GTK_ALIGN_BASELINE);
gtk_grid_attach (self->grid, axis_label, 0, i, 1, 1);
adjustment = gtk_adjustment_new (ax->default_value, ax->min_value, ax->max_value,
1.0, 10.0, 0.0);
axis_scale = g_object_new (RANGE_EDIT_TYPE,
"adjustment", adjustment,
"default-value", ax->default_value,
"n-chars", 5,
"hexpand", TRUE,
"halign", GTK_ALIGN_FILL,
"valign", GTK_ALIGN_BASELINE,
NULL);
gtk_grid_attach (self->grid, axis_scale, 1, i, 1, 1);
axis = g_new0 (Axis, 1);
axis->tag = ax->tag;
axis->adjustment = adjustment;
axis->default_value = ax->default_value;
g_hash_table_add (self->axes, axis);
g_signal_connect (adjustment, "value-changed", G_CALLBACK (unset_instance), self);
}
typedef struct {
char *name;
unsigned int index;
} Instance;
static guint
instance_hash (gconstpointer v)
{
const Instance *p = v;
return g_str_hash (p->name);
}
static gboolean
instance_equal (gconstpointer v1, gconstpointer v2)
{
const Instance *p1 = v1;
const Instance *p2 = v2;
return g_str_equal (p1->name, p2->name);
}
static void
free_instance (gpointer data)
{
Instance *instance = data;
g_free (instance->name);
g_free (instance);
}
static void
add_instance (FontVariations *self,
hb_face_t *face,
unsigned int index,
GtkWidget *combo,
int pos)
{
Instance *instance;
hb_ot_name_id_t name_id;
char name[20];
unsigned int name_len = 20;
instance = g_new0 (Instance, 1);
name_id = hb_ot_var_named_instance_get_subfamily_name_id (face, index);
hb_ot_name_get_utf8 (face, name_id, HB_LANGUAGE_INVALID, &name_len, name);
instance->name = g_strdup (name);
instance->index = index;
g_hash_table_add (self->instances, instance);
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), instance->name);
}
static void
instance_changed (GtkComboBox *combo,
FontVariations *self)
{
char *text;
Instance *instance;
Instance ikey;
int i;
unsigned int coords_length;
float *coords = NULL;
hb_ot_var_axis_info_t *ai = NULL;
unsigned int n_axes;
Pango2Font *font = NULL;
hb_font_t *hb_font;
hb_face_t *hb_face;
text = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (combo));
if (text[0] == '\0')
goto out;
ikey.name = text;
instance = g_hash_table_lookup (self->instances, &ikey);
if (!instance)
{
g_print ("did not find instance %s\n", text);
goto out;
}
font = get_font (self);
hb_font = pango2_font_get_hb_font (font);
hb_face = hb_font_get_face (hb_font);
n_axes = hb_ot_var_get_axis_infos (hb_face, 0, NULL, NULL);
ai = g_new (hb_ot_var_axis_info_t, n_axes);
hb_ot_var_get_axis_infos (hb_face, 0, &n_axes, ai);
coords = g_new (float, n_axes);
hb_ot_var_named_instance_get_design_coords (hb_face,
instance->index,
&coords_length,
coords);
for (i = 0; i < n_axes; i++)
{
Axis *axis;
Axis akey;
double value;
value = coords[ai[i].axis_index];
akey.tag = ai[i].tag;
axis = g_hash_table_lookup (self->axes, &akey);
if (axis)
{
g_signal_handlers_block_by_func (axis->adjustment, unset_instance, self);
gtk_adjustment_set_value (axis->adjustment, value);
g_signal_handlers_unblock_by_func (axis->adjustment, unset_instance, self);
}
}
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_VARIATIONS]);
g_simple_action_set_enabled (self->reset_action, TRUE);
out:
g_free (text);
g_clear_object (&font);
g_free (ai);
g_free (coords);
}
static void
update_variations (FontVariations *self)
{
GtkWidget *child;
Pango2Font *font;
hb_font_t *hb_font;
hb_face_t *hb_face;
unsigned int n_axes;
hb_ot_var_axis_info_t *ai = NULL;
int i;
font = get_font (self);
hb_font = pango2_font_get_hb_font (font);
hb_face = hb_font_get_face (hb_font);
g_object_ref (self->label);
while ((child = gtk_widget_get_first_child (GTK_WIDGET (self->grid))))
gtk_grid_remove (self->grid, child);
gtk_grid_attach (self->grid, GTK_WIDGET (self->label), 0, -2, 2, 1);
g_object_unref (self->label);
self->instance_combo = NULL;
g_hash_table_remove_all (self->axes);
g_hash_table_remove_all (self->instances);
n_axes = hb_ot_var_get_axis_infos (hb_face, 0, NULL, NULL);
self->has_variations = n_axes > 0;
gtk_widget_set_visible (GTK_WIDGET (self), self->has_variations);
if (!self->has_variations)
{
g_simple_action_set_enabled (self->reset_action, FALSE);
return;
}
if (hb_ot_var_get_named_instance_count (hb_face) > 0)
{
GtkWidget *label;
GtkWidget *combo;
label = gtk_label_new ("Instance");
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_widget_set_halign (label, GTK_ALIGN_START);
gtk_widget_set_valign (label, GTK_ALIGN_BASELINE);
gtk_grid_attach (self->grid, label, 0, -1, 1, 1);
combo = gtk_combo_box_text_new ();
gtk_widget_set_halign (combo, GTK_ALIGN_START);
gtk_widget_set_valign (combo, GTK_ALIGN_BASELINE);
gtk_widget_set_hexpand (combo, TRUE);
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "");
for (i = 0; i < hb_ot_var_get_named_instance_count (hb_face); i++)
add_instance (self, hb_face, i, combo, i);
gtk_grid_attach (GTK_GRID (self->grid), combo, 1, -1, 1, 1);
g_signal_connect (combo, "changed", G_CALLBACK (instance_changed), self);
self->instance_combo = combo;
}
ai = g_new (hb_ot_var_axis_info_t, n_axes);
hb_ot_var_get_axis_infos (hb_face, 0, &n_axes, ai);
for (i = 0; i < n_axes; i++)
add_axis (self, hb_face, &ai[i], i);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_VARIATIONS]);
g_clear_object (&font);
g_free (ai);
}
static char *
get_variations (FontVariations *self)
{
GHashTableIter iter;
Axis *axis;
char buf[G_ASCII_DTOSTR_BUF_SIZE];
const char *sep = "";
GString *s;
if (!self->has_variations)
return g_strdup ("");
s = g_string_new ("");
g_hash_table_iter_init (&iter, self->axes);
while (g_hash_table_iter_next (&iter, (gpointer *)NULL, (gpointer *)&axis))
{
char tag[5];
double value;
hb_tag_to_string (axis->tag, tag);
tag[4] = '\0';
value = gtk_adjustment_get_value (axis->adjustment);
g_string_append_printf (s, "%s%s=%s", sep, tag, g_ascii_dtostr (buf, sizeof (buf), value));
sep = ",";
}
return g_string_free (s, FALSE);
}
static void
reset (GSimpleAction *action,
GVariant *parameter,
FontVariations *self)
{
GHashTableIter iter;
Axis *axis;
if (self->instance_combo)
gtk_combo_box_set_active (GTK_COMBO_BOX (self->instance_combo), 0);
g_hash_table_iter_init (&iter, self->axes);
while (g_hash_table_iter_next (&iter, (gpointer *)NULL, (gpointer *)&axis))
{
g_signal_handlers_block_by_func (axis->adjustment, unset_instance, self);
gtk_adjustment_set_value (axis->adjustment, axis->default_value);
g_signal_handlers_unblock_by_func (axis->adjustment, unset_instance, self);
}
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_VARIATIONS]);
g_simple_action_set_enabled (self->reset_action, FALSE);
}
static void
font_variations_init (FontVariations *self)
{
gtk_widget_init_template (GTK_WIDGET (self));
self->reset_action = g_simple_action_new ("reset", NULL);
g_simple_action_set_enabled (self->reset_action, FALSE);
g_signal_connect (self->reset_action, "activate", G_CALLBACK (reset), self);
self->instances = g_hash_table_new_full (instance_hash, instance_equal,
NULL, free_instance);
self->axes = g_hash_table_new_full (axes_hash, axes_equal,
NULL, g_free);
}
static void
font_variations_dispose (GObject *object)
{
FontVariations *self = FONT_VARIATIONS (object);
gtk_widget_clear_template (GTK_WIDGET (object), FONT_VARIATIONS_TYPE);
g_hash_table_unref (self->instances);
g_hash_table_unref (self->axes);
G_OBJECT_CLASS (font_variations_parent_class)->dispose (object);
}
static void
font_variations_finalize (GObject *object)
{
FontVariations *self = FONT_VARIATIONS (object);
g_clear_pointer (&self->font_desc, pango2_font_description_free);
G_OBJECT_CLASS (font_variations_parent_class)->finalize (object);
}
static void
font_variations_set_property (GObject *object,
unsigned int prop_id,
const GValue *value,
GParamSpec *pspec)
{
FontVariations *self = FONT_VARIATIONS (object);
switch (prop_id)
{
case PROP_FONT_DESC:
pango2_font_description_free (self->font_desc);
self->font_desc = pango2_font_description_copy (g_value_get_boxed (value));
update_variations (self);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
font_variations_get_property (GObject *object,
unsigned int prop_id,
GValue *value,
GParamSpec *pspec)
{
FontVariations *self = FONT_VARIATIONS (object);
switch (prop_id)
{
case PROP_VARIATIONS:
g_value_take_string (value, get_variations (self));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
font_variations_class_init (FontVariationsClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
object_class->dispose = font_variations_dispose;
object_class->finalize = font_variations_finalize;
object_class->get_property = font_variations_get_property;
object_class->set_property = font_variations_set_property;
properties[PROP_FONT_DESC] =
g_param_spec_boxed ("font-desc", "", "",
PANGO2_TYPE_FONT_DESCRIPTION,
G_PARAM_WRITABLE);
properties[PROP_VARIATIONS] =
g_param_spec_string ("variations", "", "",
"",
G_PARAM_READABLE);
g_object_class_install_properties (G_OBJECT_CLASS (class), NUM_PROPERTIES, properties);
gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (class),
"/org/gtk/fontexplorer/fontvariations.ui");
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), FontVariations, grid);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), FontVariations, label);
gtk_widget_class_set_css_name (GTK_WIDGET_CLASS (class), "fontvariations");
}
FontVariations *
font_variations_new (void)
{
return g_object_new (FONT_VARIATIONS_TYPE, NULL);
}
GAction *
font_variations_get_reset_action (FontVariations *self)
{
return G_ACTION (self->reset_action);
}

View File

@@ -0,0 +1,16 @@
#pragma once
#include <gtk/gtk.h>
#define FONT_VARIATIONS_TYPE (font_variations_get_type ())
#define FONT_VARIATIONS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FONT_VARIATIONS_TYPE, FontVariations))
typedef struct _FontVariations FontVariations;
typedef struct _FontVariationsClass FontVariationsClass;
GType font_variations_get_type (void);
FontVariations * font_variations_new (void);
GAction * font_variations_get_reset_action (FontVariations *self);

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="FontVariations" parent="GtkWidget">
<property name="layout-manager"><object class="GtkBinLayout"/></property>
<child>
<object class="GtkGrid" id="grid">
<child>
<object class="GtkLabel" id="label">
<property name="label" translatable="yes">Variations</property>
<property name="margin-bottom">10</property>
<property name="xalign">0</property>
<style>
<class name="heading"/>
</style>
<layout>
<property name="row">-2</property>
<property name="column">0</property>
<property name="column-span">2</property>
</layout>
</object>
</child>
</object>
</child>
</template>
</interface>

View File

@@ -0,0 +1,413 @@
#include "fontview.h"
#include <gtk/gtk.h>
enum {
PROP_FONT_DESC = 1,
PROP_SIZE,
PROP_LETTERSPACING,
PROP_LINE_HEIGHT,
PROP_FOREGROUND,
PROP_BACKGROUND,
PROP_VARIATIONS,
PROP_FEATURES,
PROP_PALETTE,
PROP_SAMPLE_TEXT,
PROP_IGNORE_SIZE,
NUM_PROPERTIES
};
static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
struct _FontView
{
GtkWidget parent;
GtkStack *stack;
GtkTextView *edit;
GtkLabel *content;
GtkScrolledWindow *swin;
Pango2FontDescription *font_desc;
float size;
char *variations;
char *features;
char *palette;
int letterspacing;
float line_height;
GdkRGBA foreground;
GdkRGBA background;
GtkCssProvider *bg_provider;
char *sample_text;
gboolean do_waterfall;
};
struct _FontViewClass
{
GtkWidgetClass parent_class;
};
G_DEFINE_TYPE(FontView, font_view, GTK_TYPE_WIDGET);
static void
font_view_init (FontView *self)
{
self->font_desc = pango2_font_description_from_string ("sans 12");
self->size = 12.;
self->letterspacing = 0;
self->line_height = 1.;
self->variations = g_strdup ("");
self->features = g_strdup ("");
self->palette = g_strdup (PANGO2_COLOR_PALETTE_DEFAULT);
self->foreground = (GdkRGBA){0., 0., 0., 1. };
self->background = (GdkRGBA){1., 1., 1., 1. };
self->sample_text = g_strdup ("Some sample text is better than other sample text");
gtk_widget_set_layout_manager (GTK_WIDGET (self),
gtk_box_layout_new (GTK_ORIENTATION_VERTICAL));
gtk_widget_init_template (GTK_WIDGET (self));
self->bg_provider = gtk_css_provider_new ();
gtk_style_context_add_provider (gtk_widget_get_style_context (GTK_WIDGET (self->content)),
GTK_STYLE_PROVIDER (self->bg_provider), 800);
}
static void
font_view_dispose (GObject *object)
{
gtk_widget_clear_template (GTK_WIDGET (object), FONT_VIEW_TYPE);
G_OBJECT_CLASS (font_view_parent_class)->dispose (object);
}
static void
font_view_finalize (GObject *object)
{
FontView *self = FONT_VIEW (object);
pango2_font_description_free (self->font_desc);
g_free (self->variations);
g_free (self->features);
g_free (self->palette);
G_OBJECT_CLASS (font_view_parent_class)->finalize (object);
}
static void
update_view (FontView *self)
{
Pango2FontDescription *desc;
Pango2AttrList *attrs;
char *fg, *bg, *css;
desc = pango2_font_description_copy_static (self->font_desc);
pango2_font_description_set_size (desc, 12 * PANGO2_SCALE);
pango2_font_description_set_variations (desc, self->variations);
attrs = pango2_attr_list_new ();
pango2_attr_list_insert (attrs, pango2_attr_font_desc_new (desc));
pango2_attr_list_insert (attrs, pango2_attr_size_new (self->size * PANGO2_SCALE));
pango2_attr_list_insert (attrs, pango2_attr_letter_spacing_new (self->letterspacing));
pango2_attr_list_insert (attrs, pango2_attr_line_height_new (self->line_height));
pango2_attr_list_insert (attrs, pango2_attr_foreground_new (&(Pango2Color){65535 * self->foreground.red,
65535 * self->foreground.green,
65535 * self->foreground.blue,
65535 * self->foreground.alpha}));
pango2_attr_list_insert (attrs, pango2_attr_font_features_new (self->features));
pango2_attr_list_insert (attrs, pango2_attr_palette_new (self->palette));
pango2_font_description_free (desc);
gtk_scrolled_window_set_policy (self->swin,
self->do_waterfall ? GTK_POLICY_AUTOMATIC : GTK_POLICY_NEVER,
GTK_POLICY_AUTOMATIC);
gtk_label_set_wrap (self->content, !self->do_waterfall);
if (self->do_waterfall)
{
GString *str;
int sizes[] = { 7, 8, 9, 10, 12, 14, 16, 20, 24, 30, 40, 50, 60, 70, 90 };
int start, text_len;
str = g_string_new ("");
start = 0;
text_len = strlen (self->sample_text);
for (int i = 0; i < G_N_ELEMENTS (sizes); i++)
{
Pango2Attribute *attr;
g_string_append (str, self->sample_text);
g_string_append (str, ""); /* Unicode line separator */
attr = pango2_attr_size_new (sizes[i] * PANGO2_SCALE);
pango2_attribute_set_range (attr, start, start + text_len);
pango2_attr_list_insert (attrs, attr);
start += text_len + strlen ("");
}
gtk_label_set_text (self->content, str->str);
gtk_label_set_attributes (self->content, attrs);
g_string_free (str, TRUE);
}
else
{
gtk_label_set_label (self->content, self->sample_text);
gtk_label_set_attributes (self->content, attrs);
}
pango2_attr_list_unref (attrs);
fg = gdk_rgba_to_string (&self->foreground);
bg = gdk_rgba_to_string (&self->background);
css = g_strdup_printf (".view_background { caret-color: %s; background-color: %s; }", fg, bg);
gtk_css_provider_load_from_data (self->bg_provider, css, strlen (css));
g_free (css);
g_free (fg);
g_free (bg);
}
static void
toggle_edit (GtkToggleButton *button,
FontView *self)
{
GtkTextBuffer *buffer;
buffer = gtk_text_view_get_buffer (self->edit);
if (gtk_toggle_button_get_active (button))
{
gtk_text_buffer_set_text (buffer, self->sample_text, -1);
gtk_stack_set_visible_child_name (self->stack, "edit");
gtk_widget_grab_focus (GTK_WIDGET (self->edit));
}
else
{
GtkTextIter start, end;
g_free (self->sample_text);
gtk_text_buffer_get_bounds (buffer, &start, &end);
self->sample_text = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
update_view (self);
gtk_stack_set_visible_child_name (self->stack, "content");
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SAMPLE_TEXT]);
}
}
static void
waterfall_changed (GtkToggleButton *button,
GParamSpec *pspec,
FontView *self)
{
self->do_waterfall = gtk_toggle_button_get_active (button);
update_view (self);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_IGNORE_SIZE]);
}
static void
font_view_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
FontView *self = FONT_VIEW (object);
switch (prop_id)
{
case PROP_FONT_DESC:
pango2_font_description_free (self->font_desc);
self->font_desc = pango2_font_description_copy (g_value_get_boxed (value));
break;
case PROP_SIZE:
self->size = g_value_get_float (value);
break;
case PROP_LETTERSPACING:
self->letterspacing = g_value_get_int (value);
break;
case PROP_LINE_HEIGHT:
self->line_height = g_value_get_float (value);
break;
case PROP_FOREGROUND:
self->foreground = *(GdkRGBA *)g_value_get_boxed (value);
break;
case PROP_BACKGROUND:
self->background = *(GdkRGBA *)g_value_get_boxed (value);
break;
case PROP_VARIATIONS:
g_free (self->variations);
self->variations = g_strdup (g_value_get_string (value));
break;
case PROP_FEATURES:
g_free (self->features);
self->features = g_strdup (g_value_get_string (value));
break;
case PROP_PALETTE:
g_free (self->palette);
self->palette = g_strdup (g_value_get_string (value));
break;
case PROP_SAMPLE_TEXT:
g_free (self->sample_text);
self->sample_text = g_strdup (g_value_get_string (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
update_view (self);
}
static void
font_view_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
FontView *self = FONT_VIEW (object);
switch (prop_id)
{
case PROP_FONT_DESC:
g_value_set_boxed (value, self->font_desc);
break;
case PROP_SIZE:
g_value_set_float (value, self->size);
break;
case PROP_LETTERSPACING:
g_value_set_int (value, self->letterspacing);
break;
case PROP_LINE_HEIGHT:
g_value_set_float (value, self->line_height);
break;
case PROP_FOREGROUND:
g_value_set_boxed (value, &self->foreground);
break;
case PROP_BACKGROUND:
g_value_set_boxed (value, &self->background);
break;
case PROP_VARIATIONS:
g_value_set_string (value, self->variations);
break;
case PROP_FEATURES:
g_value_set_string (value, self->features);
break;
case PROP_PALETTE:
g_value_set_string (value, self->palette);
break;
case PROP_SAMPLE_TEXT:
g_value_set_string (value, self->sample_text);
break;
case PROP_IGNORE_SIZE:
g_value_set_boolean (value, self->do_waterfall);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
font_view_class_init (FontViewClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
object_class->dispose = font_view_dispose;
object_class->finalize = font_view_finalize;
object_class->get_property = font_view_get_property;
object_class->set_property = font_view_set_property;
properties[PROP_FONT_DESC] =
g_param_spec_boxed ("font-desc", "", "",
PANGO2_TYPE_FONT_DESCRIPTION,
G_PARAM_READWRITE);
properties[PROP_SIZE] =
g_param_spec_float ("size", "", "",
0., 100., 12.,
G_PARAM_READWRITE);
properties[PROP_LETTERSPACING] =
g_param_spec_int ("letterspacing", "", "",
-G_MAXINT, G_MAXINT, 0,
G_PARAM_READWRITE);
properties[PROP_LINE_HEIGHT] =
g_param_spec_float ("line-height", "", "",
0., 100., 1.,
G_PARAM_READWRITE);
properties[PROP_FOREGROUND] =
g_param_spec_boxed ("foreground", "", "",
GDK_TYPE_RGBA,
G_PARAM_READWRITE);
properties[PROP_BACKGROUND] =
g_param_spec_boxed ("background", "", "",
GDK_TYPE_RGBA,
G_PARAM_READWRITE);
properties[PROP_VARIATIONS] =
g_param_spec_string ("variations", "", "",
"",
G_PARAM_READWRITE);
properties[PROP_FEATURES] =
g_param_spec_string ("features", "", "",
"",
G_PARAM_READWRITE);
properties[PROP_PALETTE] =
g_param_spec_string ("palette", "", "",
PANGO2_COLOR_PALETTE_DEFAULT,
G_PARAM_READWRITE);
properties[PROP_SAMPLE_TEXT] =
g_param_spec_string ("sample-text", "", "",
"",
G_PARAM_READWRITE);
properties[PROP_IGNORE_SIZE] =
g_param_spec_boolean ("ignore-size", "", "",
FALSE,
G_PARAM_READWRITE);
g_object_class_install_properties (G_OBJECT_CLASS (class), NUM_PROPERTIES, properties);
gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (class),
"/org/gtk/fontexplorer/fontview.ui");
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), FontView, swin);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), FontView, content);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), FontView, stack);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), FontView, edit);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), toggle_edit);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), waterfall_changed);
gtk_widget_class_set_css_name (GTK_WIDGET_CLASS (class), "fontview");
}
FontView *
font_view_new (void)
{
return g_object_new (FONT_VIEW_TYPE, NULL);
}

View File

@@ -0,0 +1,15 @@
#pragma once
#include <gtk/gtk.h>
#define FONT_VIEW_TYPE (font_view_get_type ())
#define FONT_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FONT_VIEW_TYPE, FontView))
typedef struct _FontView FontView;
typedef struct _FontViewClass FontViewClass;
GType font_view_get_type (void);
FontView * font_view_new (void);

View File

@@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="FontView" parent="GtkWidget">
<property name="hexpand">1</property>
<property name="vexpand">1</property>
<style>
<class name="view"/>
</style>
<child>
<object class="GtkStack" id="stack">
<child>
<object class="GtkStackPage">
<property name="name">content</property>
<property name="child">
<object class="GtkScrolledWindow" id="swin">
<property name="hscrollbar-policy">never</property>
<property name="vscrollbar-policy">automatic</property>
<child>
<object class="GtkLabel" id="content">
<property name="label">ContentContent</property>
<property name="wrap">1</property>
<property name="wrap-mode">word-char</property>
<property name="xalign">0</property>
<property name="yalign">0</property>
<property name="hexpand">1</property>
<property name="vexpand">1</property>
<property name="halign">fill</property>
<property name="valign">fill</property>
<style>
<class name="view_background"/>
</style>
</object>
</child>
</object>
</property>
</object>
</child>
<child>
<object class="GtkStackPage">
<property name="name">edit</property>
<property name="child">
<object class="GtkScrolledWindow">
<property name="hscrollbar-policy">never</property>
<property name="vscrollbar-policy">automatic</property>
<child>
<object class="GtkTextView" id="edit">
<property name="wrap-mode">word-char</property>
</object>
</child>
</object>
</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox">
<child>
<object class="GtkBox">
<style>
<class name="linked"/>
</style>
<child>
<object class="GtkToggleButton" id="plain_toggle">
<property name="label" translatable="yes">Plain</property>
<property name="active">1</property>
</object>
</child>
<child>
<object class="GtkToggleButton" id="waterfall_toggle">
<property name="label" translatable="yes">Waterfall</property>
<property name="group">plain_toggle</property>
<signal name="notify::active" handler="waterfall_changed"/>
</object>
</child>
</object>
</child>
<child>
<object class="GtkToggleButton">
<property name="icon-name">document-edit-symbolic</property>
<property name="tooltip-text" translatable="yes">Edit the sample</property>
<property name="halign">end</property>
<property name="valign">end</property>
<property name="hexpand">1</property>
<signal name="clicked" handler="toggle_edit"/>
</object>
</child>
</object>
</child>
</template>
</interface>

View File

@@ -0,0 +1,336 @@
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <string.h>
#include <errno.h>
#include <locale.h>
#include <sys/stat.h>
#include <glib.h>
#include <glib/gi18n.h>
#include <glib/gstdio.h>
#include <hb-ot.h>
#include "language-names.h"
#ifdef G_OS_WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#else
#ifndef ISO_CODES_PREFIX
#define ISO_CODES_PREFIX "/usr"
#endif
#define ISO_CODES_DATADIR ISO_CODES_PREFIX "/share/xml/iso-codes"
#define ISO_CODES_LOCALESDIR ISO_CODES_PREFIX "/share/locale"
#endif
static GHashTable *language_map;
#ifdef G_OS_WIN32
/* if we are using native Windows use native Windows API for language names */
static BOOL CALLBACK
get_win32_all_locales_scripts (LPWSTR locale_w, DWORD flags, LPARAM param)
{
wchar_t *langname_w = NULL;
wchar_t locale_abbrev_w[9];
gchar *langname, *locale_abbrev, *locale, *p;
gint i;
const LCTYPE iso639_lctypes[] = { LOCALE_SISO639LANGNAME, LOCALE_SISO639LANGNAME2 };
GHashTable *ht_scripts_langs = (GHashTable *) param;
Pango2Language *lang;
gint langname_size, locale_abbrev_size;
langname_size = GetLocaleInfoEx (locale_w, LOCALE_SLOCALIZEDDISPLAYNAME, langname_w, 0);
if (langname_size == 0)
return FALSE;
langname_w = g_new0 (wchar_t, langname_size);
if (langname_size == 0)
return FALSE;
GetLocaleInfoEx (locale_w, LOCALE_SLOCALIZEDDISPLAYNAME, langname_w, langname_size);
langname = g_utf16_to_utf8 (langname_w, -1, NULL, NULL, NULL);
locale = g_utf16_to_utf8 (locale_w, -1, NULL, NULL, NULL);
p = strchr (locale, '-');
lang = pango2_language_from_string (locale);
if (g_hash_table_lookup (ht_scripts_langs, lang) == NULL)
g_hash_table_insert (ht_scripts_langs, lang, langname);
/*
* Track 3+-letter ISO639-2/3 language codes as well (these have a max length of 9 including terminating NUL)
* ISO639-2: iso639_lctypes[0] = LOCALE_SISO639LANGNAME
* ISO639-3: iso639_lctypes[1] = LOCALE_SISO639LANGNAME2
*/
for (i = 0; i < 2; i++)
{
locale_abbrev_size = GetLocaleInfoEx (locale_w, iso639_lctypes[i], locale_abbrev_w, 0);
if (locale_abbrev_size > 0)
{
GetLocaleInfoEx (locale_w, iso639_lctypes[i], locale_abbrev_w, locale_abbrev_size);
locale_abbrev = g_utf16_to_utf8 (locale_abbrev_w, -1, NULL, NULL, NULL);
lang = pango2_language_from_string (locale_abbrev);
if (g_hash_table_lookup (ht_scripts_langs, lang) == NULL)
g_hash_table_insert (ht_scripts_langs, lang, langname);
g_free (locale_abbrev);
}
}
g_free (locale);
g_free (langname_w);
return TRUE;
}
#else /* non-Windows */
static char *
get_first_item_in_semicolon_list (const char *list)
{
char **items;
char *item;
items = g_strsplit (list, "; ", 2);
item = g_strdup (items[0]);
g_strfreev (items);
return item;
}
static char *
capitalize_utf8_string (const char *str)
{
char first[8] = { 0 };
if (!str)
return NULL;
g_unichar_to_utf8 (g_unichar_totitle (g_utf8_get_char (str)), first);
return g_strconcat (first, g_utf8_offset_to_pointer (str, 1), NULL);
}
static char *
get_display_name (const char *language)
{
const char *translated;
char *tmp;
char *name;
translated = dgettext ("iso_639", language);
tmp = get_first_item_in_semicolon_list (translated);
name = capitalize_utf8_string (tmp);
g_free (tmp);
return name;
}
static void
languages_parse_start_tag (GMarkupParseContext *ctx,
const char *element_name,
const char **attr_names,
const char **attr_values,
gpointer user_data,
GError **error)
{
const char *ccode_longB;
const char *ccode_longT;
const char *ccode;
const char *ccode_id;
const char *lang_name;
char *display_name;
const char *long_names[] = {
"Dogri",
"Greek, Modern",
"Interlingua",
"Konkani",
"Tonga",
"Turkish, Ottoman",
};
int i;
if (!(g_str_equal (element_name, "iso_639_entry") ||
g_str_equal (element_name, "iso_639_3_entry")) ||
attr_names == NULL ||
attr_values == NULL)
return;
ccode = NULL;
ccode_longB = NULL;
ccode_longT = NULL;
ccode_id = NULL;
lang_name = NULL;
while (*attr_names && *attr_values)
{
if (g_str_equal (*attr_names, "iso_639_1_code"))
{
if (**attr_values)
{
if (strlen (*attr_values) != 2)
return;
ccode = *attr_values;
}
}
else if (g_str_equal (*attr_names, "iso_639_2B_code"))
{
if (**attr_values)
{
if (strlen (*attr_values) != 3)
return;
ccode_longB = *attr_values;
}
}
else if (g_str_equal (*attr_names, "iso_639_2T_code"))
{
if (**attr_values)
{
if (strlen (*attr_values) != 3)
return;
ccode_longT = *attr_values;
}
}
else if (g_str_equal (*attr_names, "id"))
{
if (**attr_values)
{
if (strlen (*attr_values) != 2 &&
strlen (*attr_values) != 3)
return;
ccode_id = *attr_values;
}
}
else if (g_str_equal (*attr_names, "name"))
{
lang_name = *attr_values;
}
++attr_names;
++attr_values;
}
if (lang_name == NULL)
return;
display_name = get_display_name (lang_name);
/* Fix up some egregious names */
for (i = 0; i < G_N_ELEMENTS (long_names); i++)
{
if (g_str_has_prefix (display_name, long_names[i]))
display_name[strlen (long_names[i])] = '\0';
}
if (ccode != NULL)
g_hash_table_insert (language_map,
pango2_language_from_string (ccode),
g_strdup (display_name));
if (ccode_longB != NULL)
g_hash_table_insert (language_map,
pango2_language_from_string (ccode_longB),
g_strdup (display_name));
if (ccode_longT != NULL)
g_hash_table_insert (language_map,
pango2_language_from_string (ccode_longT),
g_strdup (display_name));
if (ccode_id != NULL)
g_hash_table_insert (language_map,
pango2_language_from_string (ccode_id),
g_strdup (display_name));
g_free (display_name);
}
static void
languages_variant_init (const char *variant)
{
gboolean res;
gsize buf_len;
char *buf;
char *filename;
GError *error;
bindtextdomain (variant, ISO_CODES_LOCALESDIR);
bind_textdomain_codeset (variant, "UTF-8");
error = NULL;
filename = g_strconcat (ISO_CODES_DATADIR, "/", variant, ".xml", NULL);
res = g_file_get_contents (filename, &buf, &buf_len, &error);
if (res)
{
GMarkupParseContext *ctx = NULL;
GMarkupParser parser = { languages_parse_start_tag, NULL, NULL, NULL, NULL };
ctx = g_markup_parse_context_new (&parser, 0, NULL, NULL);
res = g_markup_parse_context_parse (ctx, buf, buf_len, &error);
g_free (ctx);
if (!res)
{
g_warning ("Failed to parse '%s': %s\n", filename, error->message);
g_error_free (error);
}
}
else
{
g_warning ("Failed to load '%s': %s\n", filename, error->message);
g_error_free (error);
}
g_free (filename);
g_free (buf);
}
#endif
static void
languages_init (void)
{
if (language_map)
return;
language_map = g_hash_table_new_full (NULL, NULL, NULL, g_free);
#ifdef G_OS_WIN32
g_return_if_fail (EnumSystemLocalesEx (&get_win32_all_locales_scripts, LOCALE_ALL, (LPARAM) language_map, NULL));
#else
languages_variant_init ("iso_639");
languages_variant_init ("iso_639_3");
#endif
}
const char *
get_language_name (Pango2Language *language)
{
languages_init ();
return (const char *) g_hash_table_lookup (language_map, language);
}
const char *
get_language_name_for_tag (guint32 tag)
{
hb_language_t lang;
const char *s;
lang = hb_ot_tag_to_language (tag);
s = hb_language_to_string (lang);
return get_language_name (pango2_language_from_string (s));
}

View File

@@ -0,0 +1,13 @@
#ifndef LANGUAGE_NAMES_H
#define LANGUAGE_NAMES_H
#include <pango2/pango.h>
G_BEGIN_DECLS
const char * get_language_name (Pango2Language *language);
const char * get_language_name_for_tag (guint32 tag);
G_END_DECLS
#endif

View File

@@ -0,0 +1,8 @@
#include <gtk/gtk.h>
#include <fontexplorerapp.h>
int
main (int argc, char *argv[])
{
return g_application_run (G_APPLICATION (font_explorer_app_new ()), argc, argv);
}

View File

@@ -0,0 +1,27 @@
fontexplorer_sources = [
'main.c',
'fontexplorerapp.c',
'fontexplorerwin.c',
'fontcontrols.c',
'samplechooser.c',
'fontcolors.c',
'fontfeatures.c',
'fontvariations.c',
'fontview.c',
'rangeedit.c',
'language-names.c',
]
fontexplorer_resources = gnome.compile_resources('fontexplorer_resources',
'fontexplorer.gresource.xml',
source_dir: '.',
)
executable('gtk4-font-explorer',
sources: [fontexplorer_sources, fontexplorer_resources],
c_args: common_cflags,
dependencies: [ libgtk_dep, demo_conf_h ],
include_directories: confinc,
link_args: extra_demo_ldflags,
install: true,
)

View File

@@ -0,0 +1,173 @@
#include "rangeedit.h"
#include <gtk/gtk.h>
#include <hb-ot.h>
enum {
PROP_ADJUSTMENT = 1,
PROP_DEFAULT_VALUE,
PROP_N_CHARS,
NUM_PROPERTIES
};
static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
struct _RangeEdit
{
GtkWidget parent;
GtkAdjustment *adjustment;
GtkScale *scale;
GtkEntry *entry;
double default_value;
int n_chars;
};
struct _RangeEditClass
{
GtkWidgetClass parent_class;
};
G_DEFINE_TYPE (RangeEdit, range_edit, GTK_TYPE_WIDGET);
static void
range_edit_init (RangeEdit *self)
{
gtk_widget_init_template (GTK_WIDGET (self));
}
static void
range_edit_dispose (GObject *object)
{
gtk_widget_clear_template (GTK_WIDGET (object), RANGE_EDIT_TYPE);
G_OBJECT_CLASS (range_edit_parent_class)->dispose (object);
}
static void
range_edit_get_property (GObject *object,
unsigned int prop_id,
GValue *value,
GParamSpec *pspec)
{
RangeEdit *self = RANGE_EDIT (object);
switch (prop_id)
{
case PROP_ADJUSTMENT:
g_value_set_object (value, self->adjustment);
break;
case PROP_DEFAULT_VALUE:
g_value_set_double (value, self->default_value);
break;
case PROP_N_CHARS:
g_value_set_int (value, self->n_chars);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
adjustment_changed (GtkAdjustment *adjustment,
RangeEdit *self)
{
char *str;
str = g_strdup_printf ("%.1f", gtk_adjustment_get_value (adjustment));
gtk_editable_set_text (GTK_EDITABLE (self->entry), str);
g_free (str);
}
static void
range_edit_set_property (GObject *object,
unsigned int prop_id,
const GValue *value,
GParamSpec *pspec)
{
RangeEdit *self = RANGE_EDIT (object);
switch (prop_id)
{
case PROP_ADJUSTMENT:
g_set_object (&self->adjustment, g_value_get_object (value));
g_signal_connect (self->adjustment, "value-changed", G_CALLBACK (adjustment_changed), self);
adjustment_changed (self->adjustment, self);
break;
case PROP_DEFAULT_VALUE:
self->default_value = g_value_get_double (value);
break;
case PROP_N_CHARS:
self->n_chars = g_value_get_int (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
range_edit_constructed (GObject *object)
{
RangeEdit *self = RANGE_EDIT (object);
gtk_scale_add_mark (self->scale, self->default_value, GTK_POS_TOP, NULL);
}
static void
entry_activated (GtkEntry *entry,
RangeEdit *self)
{
double value;
char *err = NULL;
value = g_strtod (gtk_editable_get_text (GTK_EDITABLE (entry)), &err);
if (err != NULL)
gtk_adjustment_set_value (self->adjustment, value);
}
static void
range_edit_class_init (RangeEditClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
object_class->dispose = range_edit_dispose;
object_class->get_property = range_edit_get_property;
object_class->set_property = range_edit_set_property;
object_class->constructed = range_edit_constructed;
properties[PROP_ADJUSTMENT] =
g_param_spec_object ("adjustment", "", "",
GTK_TYPE_ADJUSTMENT,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
properties[PROP_DEFAULT_VALUE] =
g_param_spec_double ("default-value", "", "",
-G_MAXDOUBLE, G_MAXDOUBLE, 0.,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
properties[PROP_N_CHARS] =
g_param_spec_int ("n-chars", "", "",
0, G_MAXINT, 10,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_properties (G_OBJECT_CLASS (class), NUM_PROPERTIES, properties);
gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (class),
"/org/gtk/fontexplorer/rangeedit.ui");
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), RangeEdit, scale);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), RangeEdit, entry);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), entry_activated);
gtk_widget_class_set_css_name (GTK_WIDGET_CLASS (class), "rangeedit");
}
RangeEdit *
range_edit_new (void)
{
return g_object_new (RANGE_EDIT_TYPE, NULL);
}

View File

@@ -0,0 +1,15 @@
#pragma once
#include <gtk/gtk.h>
#define RANGE_EDIT_TYPE (range_edit_get_type ())
#define RANGE_EDIT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), RANGE_EDIT_TYPE, RangeEdit))
typedef struct _RangeEdit RangeEdit;
typedef struct _RangeEditClass RangeEditClass;
GType range_edit_get_type (void);
RangeEdit * range_edit_new (void);

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="RangeEdit" parent="GtkWidget">
<property name="layout-manager">
<object class="GtkBoxLayout">
<property name="spacing">10</property>
</object>
</property>
<child>
<object class="GtkScale" id="scale">
<property name="orientation">horizontal</property>
<property name="hexpand">1</property>
<property name="adjustment" bind-source="RangeEdit" bind-flags="sync-create"/>
</object>
</child>
<child>
<object class="GtkEntry" id="entry">
<property name="width-chars" bind-source="RangeEdit" bind-property="n-chars" bind-flags="sync-create"/>
<property name="max-width-chars" bind-source="RangeEdit" bind-property="n-chars" bind-flags="sync-create"/>
<signal name="activate" handler="entry_activated"/>
</object>
</child>
</template>
</interface>

View File

@@ -0,0 +1,162 @@
#include "samplechooser.h"
#include <gtk/gtk.h>
#include <hb-ot.h>
enum {
PROP_SAMPLE_TEXT = 1,
NUM_PROPERTIES
};
static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
struct _SampleChooser
{
GtkWidget parent;
int sample;
const char *sample_text;
};
struct _SampleChooserClass
{
GtkWidgetClass parent_class;
};
G_DEFINE_TYPE(SampleChooser, sample_chooser, GTK_TYPE_WIDGET);
static const char *pangrams[] = {
"The quick brown fox jumps over the lazy dog.",
"Waltz, bad nymph, for quick jigs vex.",
"Quick zephyrs blow, vexing daft Jim.",
"Crazy Fredrick bought many very exquisite opal jewels.",
"Jaded zombies acted quaintly but kept driving their oxen forward.",
};
static const char *paragraphs[] = {
"Grumpy wizards make toxic brew for the evil Queen and Jack. A quick movement of the enemy will jeopardize six gunboats. The job of waxing linoleum frequently peeves chintzy kids. My girl wove six dozen plaid jackets before she quit. Twelve ziggurats quickly jumped a finch box.",
" Разъяренный чтец эгоистично бьёт пятью жердями шустрого фехтовальщика. Наш банк вчера же выплатил Ф.Я. Эйхгольду комиссию за ценные вещи. Эх, чужак, общий съём цен шляп (юфть) вдрызг! В чащах юга жил бы цитрус? Да, но фальшивый экземпляр!",
"Τάχιστη αλώπηξ βαφής ψημένη γη, δρασκελίζει υπέρ νωθρού κυνός",
};
static const char *alphabets[] = {
"abcdefghijklmnopqrstuvwxyz",
"ABCDEFGHIJKLMNOPQRSTUVWXYZ",
"0123456789",
"!@#$%^&*()?",
};
static const char *titles[] = {
"From My Cold Dead Hands",
"From Afar Upon the Back of a Tiger",
"Spontaneous Apple Creation",
"Big Bizness (Screwed & Chopped)",
"Pizza Shop Extended",
"Good News & Bad News",
};
static void
next_pangram (GtkButton *button,
SampleChooser *self)
{
self->sample++;
self->sample_text = pangrams[self->sample % G_N_ELEMENTS (pangrams)];
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SAMPLE_TEXT]);
}
static void
next_paragraph (GtkButton *button,
SampleChooser *self)
{
self->sample++;
self->sample_text = paragraphs[self->sample % G_N_ELEMENTS (paragraphs)];
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SAMPLE_TEXT]);
}
static void
next_alphabet (GtkButton *button,
SampleChooser *self)
{
self->sample++;
self->sample_text = alphabets[self->sample % G_N_ELEMENTS (alphabets)];
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SAMPLE_TEXT]);
}
static void
next_title (GtkButton *button,
SampleChooser *self)
{
self->sample++;
self->sample_text = titles[self->sample % G_N_ELEMENTS (titles)];
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SAMPLE_TEXT]);
}
static void
sample_chooser_init (SampleChooser *self)
{
self->sample_text = "Boring sample text";
gtk_widget_init_template (GTK_WIDGET (self));
}
static void
sample_chooser_dispose (GObject *object)
{
GtkWidget *child;
gtk_widget_clear_template (GTK_WIDGET (object), SAMPLE_CHOOSER_TYPE);
while ((child = gtk_widget_get_first_child (GTK_WIDGET (object))) != NULL)
gtk_widget_unparent (child);
G_OBJECT_CLASS (sample_chooser_parent_class)->dispose (object);
}
static void
sample_chooser_get_property (GObject *object,
unsigned int prop_id,
GValue *value,
GParamSpec *pspec)
{
SampleChooser *self = SAMPLE_CHOOSER (object);
switch (prop_id)
{
case PROP_SAMPLE_TEXT:
g_value_set_string (value, self->sample_text);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
sample_chooser_class_init (SampleChooserClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
object_class->dispose = sample_chooser_dispose;
object_class->get_property = sample_chooser_get_property;
properties[PROP_SAMPLE_TEXT] =
g_param_spec_string ("sample-text", "", "",
"",
G_PARAM_READABLE);
g_object_class_install_properties (G_OBJECT_CLASS (class), NUM_PROPERTIES, properties);
gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (class),
"/org/gtk/fontexplorer/samplechooser.ui");
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), next_pangram);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), next_paragraph);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), next_alphabet);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), next_title);
gtk_widget_class_set_css_name (GTK_WIDGET_CLASS (class), "samplechooser");
}
SampleChooser *
sample_chooser_new (void)
{
return g_object_new (SAMPLE_CHOOSER_TYPE, NULL);
}

View File

@@ -0,0 +1,15 @@
#pragma once
#include <gtk/gtk.h>
#define SAMPLE_CHOOSER_TYPE (sample_chooser_get_type ())
#define SAMPLE_CHOOSER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SAMPLE_CHOOSER_TYPE, SampleChooser))
typedef struct _SampleChooser SampleChooser;
typedef struct _SampleChooserClass SampleChooserClass;
GType sample_chooser_get_type (void);
SampleChooser * sample_chooser_new (void);

View File

@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="SampleChooser" parent="GtkWidget">
<property name="layout-manager"><object class="GtkGridLayout"/></property>
<child>
<object class="GtkButton">
<property name="label">Pangram</property>
<signal name="clicked" handler="next_pangram"/>
<layout>
<property name="row">0</property>
<property name="column">0</property>
</layout>
</object>
</child>
<child>
<object class="GtkButton">
<property name="label">Paragraph</property>
<signal name="clicked" handler="next_paragraph"/>
<layout>
<property name="row">0</property>
<property name="column">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkButton">
<property name="label">Alphabet</property>
<signal name="clicked" handler="next_alphabet"/>
<layout>
<property name="row">1</property>
<property name="column">0</property>
</layout>
</object>
</child>
<child>
<object class="GtkButton">
<property name="label">Title</property>
<signal name="clicked" handler="next_title"/>
<layout>
<property name="row">1</property>
<property name="column">1</property>
</layout>
</object>
</child>
</template>
</interface>

View File

@@ -2,8 +2,6 @@
#include <gtk/gtk.h>
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
typedef GtkApplication DemoApplication;
typedef GtkApplicationClass DemoApplicationClass;
@@ -35,12 +33,22 @@ static void create_window (GApplication *app, const char *contents);
static void
show_action_dialog (GSimpleAction *action)
{
GtkAlertDialog *dialog;
const char *name;
GtkWidget *dialog;
dialog = gtk_alert_dialog_new ("You activated action: \"%s\n",
g_action_get_name (G_ACTION (action)));
gtk_alert_dialog_show (dialog, NULL);
g_object_unref (dialog);
name = g_action_get_name (G_ACTION (action));
dialog = gtk_message_dialog_new (NULL,
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO,
GTK_BUTTONS_CLOSE,
"You activated action: \"%s\"",
name);
g_signal_connect (dialog, "response",
G_CALLBACK (gtk_window_destroy), NULL);
gtk_widget_show (dialog);
}
static void
@@ -59,7 +67,7 @@ show_action_infobar (GSimpleAction *action,
text = g_strdup_printf ("You activated radio action: \"%s\".\n"
"Current value: %s", name, value);
gtk_label_set_text (GTK_LABEL (window->message), text);
gtk_widget_set_visible (window->infobar, TRUE);
gtk_widget_show (window->infobar);
g_free (text);
}
@@ -82,38 +90,43 @@ activate_new (GSimpleAction *action,
}
static void
open_response_cb (GObject *source,
GAsyncResult *result,
gpointer user_data)
open_response_cb (GtkNativeDialog *dialog,
int response_id,
gpointer user_data)
{
GtkFileDialog *dialog = GTK_FILE_DIALOG (source);
GApplication *app = G_APPLICATION (user_data);
GtkFileChooserNative *native = user_data;
GApplication *app = g_object_get_data (G_OBJECT (native), "app");
GtkWidget *message_dialog;
GFile *file;
char *contents;
GError *error = NULL;
file = gtk_file_dialog_open_finish (dialog, result, &error);
if (file)
if (response_id == GTK_RESPONSE_ACCEPT)
{
char *contents;
file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (native));
if (g_file_load_contents (file, NULL, &contents, NULL, NULL, &error))
{
create_window (app, contents);
g_free (contents);
}
else
{
message_dialog = gtk_message_dialog_new (NULL,
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE,
"Error loading file: \"%s\"",
error->message);
g_signal_connect (message_dialog, "response",
G_CALLBACK (gtk_window_destroy), NULL);
gtk_widget_show (message_dialog);
g_error_free (error);
}
}
if (error)
{
GtkAlertDialog *alert;
alert = gtk_alert_dialog_new ("Error loading file: \"%s\"", error->message);
gtk_alert_dialog_show (alert, NULL);
g_object_unref (alert);
g_error_free (error);
}
g_object_unref (app);
gtk_native_dialog_destroy (GTK_NATIVE_DIALOG (native));
g_object_unref (native);
}
@@ -123,11 +136,21 @@ activate_open (GSimpleAction *action,
gpointer user_data)
{
GApplication *app = user_data;
GtkFileDialog *dialog;
GtkFileChooserNative *native;
dialog = gtk_file_dialog_new ();
gtk_file_dialog_open (dialog, NULL, NULL, open_response_cb, g_object_ref (app));
g_object_unref (dialog);
native = gtk_file_chooser_native_new ("Open File",
NULL,
GTK_FILE_CHOOSER_ACTION_OPEN,
"_Open",
"_Cancel");
g_object_set_data_full (G_OBJECT (native), "app", g_object_ref (app), g_object_unref);
g_signal_connect (native,
"response",
G_CALLBACK (open_response_cb),
native);
gtk_native_dialog_show (GTK_NATIVE_DIALOG (native));
}
static void
@@ -297,7 +320,7 @@ static GActionEntry win_entries[] = {
static void
clicked_cb (GtkWidget *widget, DemoApplicationWindow *window)
{
gtk_widget_set_visible (window->infobar, FALSE);
gtk_widget_hide (window->infobar);
}
static void
@@ -481,8 +504,6 @@ demo_application_window_dispose (GObject *object)
demo_application_window_store_state (window);
gtk_widget_dispose_template (GTK_WIDGET (window), demo_application_window_get_type ());
G_OBJECT_CLASS (demo_application_window_parent_class)->dispose (object);
}

View File

@@ -7,8 +7,6 @@
#include <gtk/gtk.h>
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
static GtkWidget *progress_bar = NULL;
static gboolean
@@ -142,6 +140,7 @@ create_page3 (GtkWidget *assistant)
label = gtk_label_new ("This is a confirmation page, press 'Apply' to apply changes");
gtk_widget_show (label);
gtk_assistant_append_page (GTK_ASSISTANT (assistant), label);
gtk_assistant_set_page_type (GTK_ASSISTANT (assistant), label, GTK_ASSISTANT_PAGE_CONFIRM);
gtk_assistant_set_page_complete (GTK_ASSISTANT (assistant), label, TRUE);
@@ -158,6 +157,7 @@ create_page4 (GtkWidget *assistant)
gtk_widget_set_margin_start (progress_bar, 40);
gtk_widget_set_margin_end (progress_bar, 40);
gtk_widget_show (progress_bar);
gtk_assistant_append_page (GTK_ASSISTANT (assistant), progress_bar);
gtk_assistant_set_page_type (GTK_ASSISTANT (assistant), progress_bar, GTK_ASSISTANT_PAGE_PROGRESS);
gtk_assistant_set_page_title (GTK_ASSISTANT (assistant), progress_bar, "Applying changes");
@@ -199,7 +199,7 @@ do_assistant (GtkWidget *do_widget)
}
if (!gtk_widget_get_visible (assistant))
gtk_widget_set_visible (assistant, TRUE);
gtk_widget_show (assistant);
else
gtk_window_destroy (GTK_WINDOW (assistant));

View File

@@ -116,8 +116,7 @@ effective_align (GtkAlign align,
return direction == GTK_TEXT_DIR_RTL ? GTK_ALIGN_START : GTK_ALIGN_END;
case GTK_ALIGN_FILL:
case GTK_ALIGN_CENTER:
case GTK_ALIGN_BASELINE_FILL:
case GTK_ALIGN_BASELINE_CENTER:
case GTK_ALIGN_BASELINE:
default:
return align;
}
@@ -259,8 +258,7 @@ blur_overlay_get_child_position (BlurOverlay *overlay,
case GTK_ALIGN_END:
alloc->x += width - alloc->width;
break;
case GTK_ALIGN_BASELINE_FILL:
case GTK_ALIGN_BASELINE_CENTER:
case GTK_ALIGN_BASELINE:
default:
g_assert_not_reached ();
break;
@@ -283,8 +281,7 @@ blur_overlay_get_child_position (BlurOverlay *overlay,
case GTK_ALIGN_END:
alloc->y += height - alloc->height;
break;
case GTK_ALIGN_BASELINE_FILL:
case GTK_ALIGN_BASELINE_CENTER:
case GTK_ALIGN_BASELINE:
default:
g_assert_not_reached ();
break;
@@ -300,13 +297,12 @@ blur_overlay_snapshot (GtkWidget *widget,
GtkWidget *main_widget;
GskRenderNode *main_widget_node = NULL;
GtkWidget *child;
int width, height;
GtkAllocation main_alloc;
cairo_region_t *clip = NULL;
int i;
main_widget = BLUR_OVERLAY (widget)->main_widget;
width = gtk_widget_get_width (widget);
height = gtk_widget_get_height (widget);
gtk_widget_get_allocation (widget, &main_alloc);
for (child = gtk_widget_get_first_child (widget);
child != NULL;
@@ -319,7 +315,7 @@ blur_overlay_snapshot (GtkWidget *widget,
if (blur > 0)
{
cairo_rectangle_int_t rect;
GtkAllocation alloc;
graphene_rect_t bounds;
if (main_widget_node == NULL)
@@ -331,8 +327,8 @@ blur_overlay_snapshot (GtkWidget *widget,
main_widget_node = gtk_snapshot_free_to_node (child_snapshot);
}
if (!gtk_widget_compute_bounds (child, gtk_widget_get_parent (child), &bounds))
graphene_rect_init (&bounds, 0, 0, 0, 0);
gtk_widget_get_allocation (child, &alloc);
graphene_rect_init (&bounds, alloc.x, alloc.y, alloc.width, alloc.height);
gtk_snapshot_push_blur (snapshot, blur);
gtk_snapshot_push_clip (snapshot, &bounds);
gtk_snapshot_append_node (snapshot, main_widget_node);
@@ -341,17 +337,13 @@ blur_overlay_snapshot (GtkWidget *widget,
if (clip == NULL)
{
cairo_rectangle_int_t rect;
rect.x = rect.y = 0;
rect.width = width;
rect.height = height;
rect.width = main_alloc.width;
rect.height = main_alloc.height;
clip = cairo_region_create_rectangle (&rect);
}
rect.x = floor (bounds.origin.x);
rect.y = floor (bounds.origin.y);
rect.width = ceil (bounds.origin.x + bounds.size.width - rect.x);
rect.height = ceil (bounds.origin.y + bounds.size.height - rect.y);
cairo_region_subtract_rectangle (clip, &rect);
cairo_region_subtract_rectangle (clip, (cairo_rectangle_int_t *)&alloc);
}
}

View File

@@ -51,11 +51,15 @@ struct _BlurOverlayClass
GtkAllocation *allocation);
};
GDK_AVAILABLE_IN_ALL
GType blur_overlay_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
GtkWidget *blur_overlay_new (void);
GDK_AVAILABLE_IN_ALL
void blur_overlay_add_overlay (BlurOverlay *overlay,
GtkWidget *widget,
double blur);
GDK_AVAILABLE_IN_ALL
void blur_overlay_set_child (BlurOverlay *overlay,
GtkWidget *widget);

View File

@@ -37,8 +37,6 @@ remove_timeout (gpointer data)
g_source_remove (id);
}
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
static gboolean
pop_status (gpointer data)
{
@@ -59,8 +57,6 @@ status_message (GtkStatusbar *status,
g_object_set_data_full (G_OBJECT (status), "timeout", GUINT_TO_POINTER (id), remove_timeout);
}
G_GNUC_END_IGNORE_DEPRECATIONS
static void
help_activate (GSimpleAction *action,
GVariant *parameter,
@@ -172,7 +168,7 @@ do_builder (GtkWidget *do_widget)
}
if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE);
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));

View File

@@ -1,5 +1,4 @@
/* Clipboard
* #Keywords: drag-and-drop, dnd
*
* GdkClipboard is used for clipboard handling. This demo shows how to
* copy and paste text, images, colors or files to and from the clipboard.
@@ -51,10 +50,10 @@ copy_button_clicked (GtkStack *source_stack,
}
else if (strcmp (visible_child_name, "Color") == 0)
{
const GdkRGBA *color;
GdkRGBA color;
color = gtk_color_dialog_button_get_rgba (GTK_COLOR_DIALOG_BUTTON (visible_child));
gdk_clipboard_set (clipboard, GDK_TYPE_RGBA, color);
gtk_color_chooser_get_rgba (GTK_COLOR_CHOOSER (visible_child), &color);
gdk_clipboard_set (clipboard, GDK_TYPE_RGBA, &color);
}
else if (strcmp (visible_child_name, "File") == 0)
{
@@ -216,71 +215,37 @@ file_button_set_file (GtkButton *button,
}
static void
file_chooser_response (GObject *source,
GAsyncResult *result,
gpointer user_data)
file_chooser_response (GtkNativeDialog *dialog,
int response,
GtkButton *button)
{
GtkFileDialog *dialog = GTK_FILE_DIALOG (source);
GtkButton *button = GTK_BUTTON (user_data);
GFile *file;
gtk_native_dialog_hide (dialog);
file = gtk_file_dialog_open_finish (dialog, result, NULL);
if (file)
if (response == GTK_RESPONSE_ACCEPT)
{
GFile *file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
file_button_set_file (button, file);
g_object_unref (file);
update_copy_button_sensitivity (gtk_widget_get_ancestor (GTK_WIDGET (button), GTK_TYPE_STACK));
}
gtk_native_dialog_destroy (dialog);
}
static void
open_file_cb (GtkWidget *button)
{
GtkFileDialog *dialog;
GtkFileChooserNative *chooser;
dialog = gtk_file_dialog_new ();
chooser = gtk_file_chooser_native_new ("Choose a file",
GTK_WINDOW (gtk_widget_get_ancestor (button, GTK_TYPE_WINDOW)),
GTK_FILE_CHOOSER_ACTION_OPEN,
"_Open",
"_Cancel");
gtk_file_dialog_open (dialog,
GTK_WINDOW (gtk_widget_get_ancestor (button, GTK_TYPE_WINDOW)),
NULL,
file_chooser_response, button);
g_object_unref (dialog);
}
static void
folder_chooser_response (GObject *source,
GAsyncResult *result,
gpointer user_data)
{
GtkFileDialog *dialog = GTK_FILE_DIALOG (source);
GtkButton *button = GTK_BUTTON (user_data);
GFile *file;
file = gtk_file_dialog_select_folder_finish (dialog, result, NULL);
if (file)
{
file_button_set_file (button, file);
g_object_unref (file);
update_copy_button_sensitivity (gtk_widget_get_ancestor (GTK_WIDGET (button), GTK_TYPE_STACK));
}
}
static void
open_folder_cb (GtkWidget *button)
{
GtkFileDialog *dialog;
dialog = gtk_file_dialog_new ();
gtk_file_dialog_select_folder (dialog,
GTK_WINDOW (gtk_widget_get_ancestor (button, GTK_TYPE_WINDOW)),
NULL,
folder_chooser_response, button);
g_object_unref (dialog);
g_signal_connect (chooser, "response", G_CALLBACK (file_chooser_response), button);
gtk_native_dialog_show (GTK_NATIVE_DIALOG (chooser));
}
static void
@@ -381,7 +346,6 @@ do_clipboard (GtkWidget *do_widget)
gtk_builder_cscope_add_callback (scope, source_changed_cb);
gtk_builder_cscope_add_callback (scope, text_changed_cb);
gtk_builder_cscope_add_callback (scope, open_file_cb);
gtk_builder_cscope_add_callback (scope, open_folder_cb);
gtk_builder_cscope_add_callback (scope, on_drop);
gtk_builder_cscope_add_callback (scope, drag_prepare);
builder = gtk_builder_new ();
@@ -405,7 +369,7 @@ do_clipboard (GtkWidget *do_widget)
}
if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE);
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));

View File

@@ -32,7 +32,6 @@
<item>Color</item>
<item>Image</item>
<item>File</item>
<item>Folder</item>
</items>
</object>
</property>
@@ -65,11 +64,7 @@
<object class="GtkStackPage">
<property name="name">Color</property>
<property name="child">
<object class="GtkColorDialogButton" id="source_color">
<property name="dialog">
<object class="GtkColorDialog">
</object>
</property>
<object class="GtkColorButton" id="source_color">
<property name="valign">center</property>
<property name="rgba">purple</property>
</object>
@@ -167,30 +162,6 @@
</property>
</object>
</child>
<child>
<object class="GtkStackPage">
<property name="name">Folder</property>
<property name="child">
<object class="GtkButton" id="source_folder">
<child>
<object class="GtkDragSource">
<property name="propagation-phase">capture</property>
<signal name="prepare" handler="drag_prepare"/>
</object>
</child>
<property name="valign">center</property>
<property name="child">
<object class="GtkLabel">
<property name="label">—</property>
<property name="xalign">0</property>
<property name="ellipsize">start</property>
</object>
</property>
<signal name="clicked" handler="open_folder_cb"/>
</object>
</property>
</object>
</child>
</object>
</child>
<child>

View File

@@ -11,8 +11,6 @@
#include <glib/gi18n.h>
#include <gtk/gtk.h>
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
enum
{
ICON_NAME_COL,
@@ -262,12 +260,13 @@ mask_entry_set_background (MaskEntry *entry)
{
if (!g_regex_match_simple (entry->mask, gtk_editable_get_text (GTK_EDITABLE (entry)), 0, 0))
{
PangoAttrList *attrs;
Pango2AttrList *attrs;
Pango2Color color = { 65535, 32767, 32767, 65535 };
attrs = pango_attr_list_new ();
pango_attr_list_insert (attrs, pango_attr_foreground_new (65535, 32767, 32767));
attrs = pango2_attr_list_new ();
pango2_attr_list_insert (attrs, pango2_attr_foreground_new (&color));
gtk_entry_set_attributes (GTK_ENTRY (entry), attrs);
pango_attr_list_unref (attrs);
pango2_attr_list_unref (attrs);
return;
}
}
@@ -449,7 +448,7 @@ do_combobox (GtkWidget *do_widget)
}
if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE);
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));

View File

@@ -277,7 +277,7 @@ do_constraints (GtkWidget *do_widget)
}
if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE);
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));

View File

@@ -66,7 +66,7 @@ do_constraints_builder (GtkWidget *do_widget)
}
if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE);
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));

View File

@@ -229,7 +229,7 @@ do_constraints_interactive (GtkWidget *do_widget)
}
if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE);
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));

View File

@@ -152,7 +152,7 @@ do_constraints_vfl (GtkWidget *do_widget)
}
if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE);
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));

View File

@@ -1,16 +1,20 @@
/* Theming/CSS Accordion
*
* A simple accordion demo written using CSS transitions and multiple backgrounds
*
*/
#include <gtk/gtk.h>
static void
destroy_provider (GtkWidget *window,
GtkStyleProvider *provider)
apply_css (GtkWidget *widget, GtkStyleProvider *provider)
{
gtk_style_context_remove_provider_for_display (gtk_widget_get_display (window), provider);
GtkWidget *child;
gtk_style_context_add_provider (gtk_widget_get_style_context (widget), provider, G_MAXUINT);
for (child = gtk_widget_get_first_child (widget);
child != NULL;
child = gtk_widget_get_next_sibling (child))
apply_css (child, provider);
}
GtkWidget *
@@ -20,8 +24,8 @@ do_css_accordion (GtkWidget *do_widget)
if (!window)
{
GtkWidget *container, *styled_box, *child;
GtkCssProvider *provider;
GtkWidget *container, *child;
GtkStyleProvider *provider;
window = gtk_window_new ();
gtk_window_set_title (GTK_WINDOW (window), "CSS Accordion");
@@ -29,13 +33,10 @@ do_css_accordion (GtkWidget *do_widget)
gtk_window_set_default_size (GTK_WINDOW (window), 600, 300);
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
styled_box = gtk_frame_new (NULL);
gtk_window_set_child (GTK_WINDOW (window), styled_box);
gtk_widget_add_css_class (styled_box, "accordion");
container = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_widget_set_halign (container, GTK_ALIGN_CENTER);
gtk_widget_set_valign (container, GTK_ALIGN_CENTER);
gtk_frame_set_child (GTK_FRAME (styled_box), container);
gtk_window_set_child (GTK_WINDOW (window), container);
child = gtk_button_new_with_label ("This");
gtk_box_append (GTK_BOX (container), child);
@@ -55,20 +56,14 @@ do_css_accordion (GtkWidget *do_widget)
child = gtk_button_new_with_label (":-)");
gtk_box_append (GTK_BOX (container), child);
provider = gtk_css_provider_new ();
gtk_css_provider_load_from_resource (provider, "/css_accordion/css_accordion.css");
provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
gtk_css_provider_load_from_resource (GTK_CSS_PROVIDER (provider), "/css_accordion/css_accordion.css");
gtk_style_context_add_provider_for_display (gtk_widget_get_display (window),
GTK_STYLE_PROVIDER (provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
g_signal_connect (window, "destroy",
G_CALLBACK (destroy_provider), provider);
g_object_unref (provider);
apply_css (window, provider);
}
if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE);
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));

View File

@@ -1,13 +1,13 @@
.accordion, .accordion * {
all: unset;
@import url("resource://css_accordion/reset.css");
* {
transition-property: color, background-color, border-color, background-image, padding, border-width;
transition-duration: 1s;
font: 20px Cantarell;
}
.accordion {
window {
background: linear-gradient(153deg, #151515, #151515 5px, transparent 5px) 0 0,
linear-gradient(333deg, #151515, #151515 5px, transparent 5px) 10px 5px,
linear-gradient(153deg, #222, #222 5px, transparent 5px) 0 5px,
@@ -18,7 +18,7 @@
background-size: 20px 20px;
}
.accordion button {
button {
color: black;
background-color: #bbb;
border-style: solid;
@@ -28,25 +28,25 @@
padding: 12px 4px;
}
.accordion button:first-child {
button:first-child {
border-radius: 5px 0 0 5px;
}
.accordion button:last-child {
button:last-child {
border-radius: 0 5px 5px 0;
border-width: 2px;
}
.accordion button:hover {
button:hover {
padding: 12px 48px;
background-color: #4870bc;
}
.accordion button *:hover {
button *:hover {
color: white;
}
.accordion button:hover:active,
.accordion button:active {
button:hover:active,
button:active {
background-color: #993401;
}

View File

@@ -6,8 +6,6 @@
#include <gtk/gtk.h>
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
static void
show_parsing_error (GtkCssProvider *provider,
GtkCssSection *section,
@@ -86,11 +84,11 @@ do_css_basics (GtkWidget *do_widget)
text = gtk_text_buffer_new (NULL);
gtk_text_buffer_create_tag (text,
"warning",
"underline", PANGO_UNDERLINE_SINGLE,
"underline", PANGO2_LINE_STYLE_SOLID,
NULL);
gtk_text_buffer_create_tag (text,
"error",
"underline", PANGO_UNDERLINE_ERROR,
"underline", PANGO2_LINE_STYLE_DOTTED,
NULL);
provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
@@ -115,7 +113,7 @@ do_css_basics (GtkWidget *do_widget)
}
if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE);
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));

View File

@@ -50,7 +50,7 @@ update_css_for_blend_mode (GtkCssProvider *provider,
blend_mode,
blend_mode);
gtk_css_provider_load_from_string (provider, css);
gtk_css_provider_load_from_data (provider, css, -1);
g_bytes_unref (bytes);
g_free (css);
@@ -139,7 +139,7 @@ do_css_blendmodes (GtkWidget *do_widget)
}
if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE);
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));

View File

@@ -6,8 +6,6 @@
#include <gtk/gtk.h>
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
static void
show_parsing_error (GtkCssProvider *provider,
GtkCssSection *section,
@@ -124,11 +122,11 @@ do_css_multiplebgs (GtkWidget *do_widget)
text = gtk_text_buffer_new (NULL);
gtk_text_buffer_create_tag (text,
"warning",
"underline", PANGO_UNDERLINE_SINGLE,
"underline", PANGO2_LINE_STYLE_SOLID,
NULL);
gtk_text_buffer_create_tag (text,
"error",
"underline", PANGO_UNDERLINE_ERROR,
"underline", PANGO2_LINE_STYLE_DOTTED,
NULL);
provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
@@ -155,7 +153,7 @@ do_css_multiplebgs (GtkWidget *do_widget)
}
if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE);
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));

View File

@@ -7,8 +7,6 @@
#include <gtk/gtk.h>
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
static void
show_parsing_error (GtkCssProvider *provider,
GtkCssSection *section,
@@ -95,11 +93,11 @@ do_css_pixbufs (GtkWidget *do_widget)
text = gtk_text_buffer_new (NULL);
gtk_text_buffer_create_tag (text,
"warning",
"underline", PANGO_UNDERLINE_SINGLE,
"underline", PANGO2_LINE_STYLE_SOLID,
NULL);
gtk_text_buffer_create_tag (text,
"error",
"underline", PANGO_UNDERLINE_ERROR,
"underline", PANGO2_LINE_STYLE_DOTTED,
NULL);
provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
@@ -124,7 +122,7 @@ do_css_pixbufs (GtkWidget *do_widget)
}
if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE);
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));

View File

@@ -5,8 +5,6 @@
#include <gtk/gtk.h>
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
static void
show_parsing_error (GtkCssProvider *provider,
GtkCssSection *section,
@@ -113,11 +111,11 @@ do_css_shadows (GtkWidget *do_widget)
text = gtk_text_buffer_new (NULL);
gtk_text_buffer_create_tag (text,
"warning",
"underline", PANGO_UNDERLINE_SINGLE,
"underline", PANGO2_LINE_STYLE_SOLID,
NULL);
gtk_text_buffer_create_tag (text,
"error",
"underline", PANGO_UNDERLINE_ERROR,
"underline", PANGO2_LINE_STYLE_DOTTED,
NULL);
provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
@@ -142,7 +140,7 @@ do_css_shadows (GtkWidget *do_widget)
}
if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE);
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));

View File

@@ -33,7 +33,7 @@ do_cursors (GtkWidget *do_widget)
}
if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE);
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));

View File

@@ -24,6 +24,7 @@
</gresource>
<gresource prefix="/css_accordion">
<file>css_accordion.css</file>
<file>reset.css</file>
</gresource>
<gresource prefix="/css_basics">
<file>css_basics.css</file>
@@ -43,7 +44,7 @@
<file>cssview.css</file>
<file>reset.css</file>
</gresource>
<gresource prefix="/listview_selections">
<gresource prefix="/dropdown">
<file>suggestionentry.h</file>
<file>suggestionentry.c</file>
<file>suggestionentry.css</file>
@@ -195,9 +196,6 @@
<gresource prefix="/listview_settings">
<file>listview_settings.ui</file>
</gresource>
<gresource prefix="/listview_settings2">
<file>listview_settings2.ui</file>
</gresource>
<gresource prefix="/listview_ucd_data/">
<file>ucdnames.data</file>
</gresource>
@@ -218,12 +216,6 @@
<file>demo3widget.h</file>
<file>demo3widget.ui</file>
</gresource>
<gresource prefix="/mask">
<file>demo4widget.c</file>
<file>demo4widget.h</file>
<file>hsla.h</file>
<file>hsla.c</file>
</gresource>
<gresource prefix="/paintable_svg">
<file>svgpaintable.h</file>
<file>svgpaintable.c</file>
@@ -277,6 +269,7 @@
<file>cursors.c</file>
<file>dialog.c</file>
<file>drawingarea.c</file>
<file>dropdown.c</file>
<file>dnd.c</file>
<file>editable_cells.c</file>
<file>entry_completion.c</file>
@@ -300,7 +293,6 @@
<file>iconscroll.c</file>
<file>iconview.c</file>
<file>iconview_edit.c</file>
<file>image_scaling.c</file>
<file>images.c</file>
<file>infobar.c</file>
<file>layoutmanager.c</file>
@@ -313,16 +305,14 @@
<file>listview_clocks.c</file>
<file>listview_filebrowser.c</file>
<file>listview_minesweeper.c</file>
<file>listview_selections.c</file>
<file>listview_settings.c</file>
<file>listview_settings2.c</file>
<file>listview_ucd.c</file>
<file>listview_weather.c</file>
<file>listview_words.c</file>
<file>list_store.c</file>
<file>main.c</file>
<file>markup.c</file>
<file>mask.c</file>
<file>menu.c</file>
<file>overlay.c</file>
<file>overlay_decorative.c</file>
<file>paint.c</file>
@@ -438,8 +428,6 @@
<file>icons/16x16/emotes/face-laugh-symbolic.symbolic.png</file>
<file>icons/16x16/status/battery-caution-charging-symbolic.symbolic.png</file>
<file>icons/16x16/categories/applications-other.png</file>
<file>icons/48x48/status/starred.png</file>
<file alias="icons/scalable/apps/org.gtk.Demo4.svg">data/scalable/apps/org.gtk.Demo4.svg</file>
</gresource>
<gresource prefix="/org/gtk/Demo4/gtk">
<file preprocess="xml-stripblanks">help-overlay.ui</file>

View File

@@ -3,20 +3,16 @@
enum
{
PROP_TEXTURE = 1,
PROP_FILTER,
PROP_SCALE,
PROP_ANGLE,
PROP_PAINTABLE = 1,
PROP_SCALE
};
struct _Demo3Widget
{
GtkWidget parent_instance;
GdkTexture *texture;
GdkPaintable *paintable;
float scale;
float angle;
GskScalingFilter filter;
GtkWidget *menu;
};
@@ -28,86 +24,10 @@ struct _Demo3WidgetClass
G_DEFINE_TYPE (Demo3Widget, demo3_widget, GTK_TYPE_WIDGET)
static gboolean
query_tooltip (GtkWidget *widget,
int x,
int y,
gboolean keyboard_mode,
GtkTooltip *tooltip,
gpointer data)
{
Demo3Widget *self = DEMO3_WIDGET (widget);
GtkWidget *grid;
GtkWidget *label;
char *s, *s2;
const char *filter[] = { "Linear", "Nearest", "Trilinear" };
int precision, l;
grid = gtk_grid_new ();
gtk_grid_set_column_spacing (GTK_GRID (grid), 12);
gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
label = gtk_label_new ("Texture");
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
s = g_strdup_printf ("%d\342\200\206\303\227\342\200\206%d",
gdk_texture_get_width (self->texture),
gdk_texture_get_height (self->texture));
label = gtk_label_new (s);
g_free (s);
gtk_label_set_xalign (GTK_LABEL (label), 1);
gtk_grid_attach (GTK_GRID (grid), label, 1, 0, 1, 1);
label = gtk_label_new ("Rotation");
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_grid_attach (GTK_GRID (grid), label, 0, 1, 1, 1);
s = g_strdup_printf ("%.1f", self->angle);
if (g_str_has_suffix (s, ".0"))
s[strlen (s) - 2] = '\0';
s2 = g_strconcat (s, "\302\260", NULL);
label = gtk_label_new (s2);
g_free (s2);
g_free (s);
gtk_label_set_xalign (GTK_LABEL (label), 1);
gtk_grid_attach (GTK_GRID (grid), label, 1, 1, 1, 1);
label = gtk_label_new ("Scale");
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_grid_attach (GTK_GRID (grid), label, 0, 2, 1, 1);
precision = 1;
do {
s = g_strdup_printf ("%.*f", precision, self->scale);
l = strlen (s) - 1;
while (s[l] == '0')
l--;
if (s[l] == '.')
s[l] = '\0';
precision++;
} while (strcmp (s, "0") == 0);
label = gtk_label_new (s);
g_free (s);
gtk_label_set_xalign (GTK_LABEL (label), 1);
gtk_grid_attach (GTK_GRID (grid), label, 1, 2, 1, 1);
label = gtk_label_new ("Filter");
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_grid_attach (GTK_GRID (grid), label, 0, 3, 1, 1);
label = gtk_label_new (filter[self->filter]);
gtk_label_set_xalign (GTK_LABEL (label), 1);
gtk_grid_attach (GTK_GRID (grid), label, 1, 3, 1, 1);
gtk_tooltip_set_custom (tooltip, grid);
return TRUE;
}
static void
demo3_widget_init (Demo3Widget *self)
{
self->scale = 1.f;
self->angle = 0.f;
self->filter = GSK_SCALING_FILTER_LINEAR;
gtk_widget_init_template (GTK_WIDGET (self));
}
@@ -116,9 +36,8 @@ demo3_widget_dispose (GObject *object)
{
Demo3Widget *self = DEMO3_WIDGET (object);
g_clear_object (&self->texture);
gtk_widget_dispose_template (GTK_WIDGET (self), DEMO3_TYPE_WIDGET);
g_clear_object (&self->paintable);
g_clear_pointer (&self->menu, gtk_widget_unparent);
G_OBJECT_CLASS (demo3_widget_parent_class)->dispose (object);
}
@@ -129,35 +48,21 @@ demo3_widget_snapshot (GtkWidget *widget,
{
Demo3Widget *self = DEMO3_WIDGET (widget);
int x, y, width, height;
double w, h, w2, h2;
double w, h;
width = gtk_widget_get_width (widget);
height = gtk_widget_get_height (widget);
w2 = w = self->scale * gdk_texture_get_width (self->texture);
h2 = h = self->scale * gdk_texture_get_height (self->texture);
w = self->scale * gdk_paintable_get_intrinsic_width (self->paintable);
h = self->scale * gdk_paintable_get_intrinsic_height (self->paintable);
if (G_APPROX_VALUE (self->angle, 90.f, FLT_EPSILON) ||
G_APPROX_VALUE (self->angle, 270.f, FLT_EPSILON))
{
double s = w2;
w2 = h2;
h2 = s;
}
x = (width - ceil (w2)) / 2;
y = (height - ceil (h2)) / 2;
x = MAX (0, (width - ceil (w)) / 2);
y = MAX (0, (height - ceil (h)) / 2);
gtk_snapshot_push_clip (snapshot, &GRAPHENE_RECT_INIT (0, 0, width, height));
gtk_snapshot_save (snapshot);
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (x, y));
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (w2 / 2, h2 / 2));
gtk_snapshot_rotate (snapshot, self->angle);
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (- w / 2, - h / 2));
gtk_snapshot_append_scaled_texture (snapshot,
self->texture,
self->filter,
&GRAPHENE_RECT_INIT (0, 0, w, h));
gdk_paintable_snapshot (self->paintable, snapshot, w, h);
gtk_snapshot_restore (snapshot);
gtk_snapshot_pop (snapshot);
}
@@ -172,26 +77,14 @@ demo3_widget_measure (GtkWidget *widget,
int *natural_baseline)
{
Demo3Widget *self = DEMO3_WIDGET (widget);
int width, height;
int size;
width = gdk_texture_get_width (self->texture);
height = gdk_texture_get_height (self->texture);
if (G_APPROX_VALUE (self->angle, 90.f, FLT_EPSILON) ||
G_APPROX_VALUE (self->angle, 270.f, FLT_EPSILON))
{
int s = width;
width = height;
height = s;
}
if (orientation == GTK_ORIENTATION_HORIZONTAL)
size = width;
size = gdk_paintable_get_intrinsic_width (self->paintable);
else
size = height;
size = gdk_paintable_get_intrinsic_height (self->paintable);
*minimum = *natural = (int) ceil (self->scale * size);
*minimum = *natural = self->scale * size;
}
static void
@@ -209,8 +102,6 @@ demo3_widget_size_allocate (GtkWidget *widget,
gtk_popover_present (GTK_POPOVER (self->menu));
}
static void update_actions (Demo3Widget *self);
static void
demo3_widget_set_property (GObject *object,
guint prop_id,
@@ -221,32 +112,14 @@ demo3_widget_set_property (GObject *object,
switch (prop_id)
{
case PROP_TEXTURE:
g_clear_object (&self->texture);
self->texture = g_value_dup_object (value);
self->scale = 1.f;
self->angle = 0.f;
self->filter = GSK_SCALING_FILTER_LINEAR;
update_actions (self);
case PROP_PAINTABLE:
g_clear_object (&self->paintable);
self->paintable = g_value_dup_object (value);
gtk_widget_queue_resize (GTK_WIDGET (object));
g_object_notify (object, "scale");
g_object_notify (object, "angle");
g_object_notify (object, "filter");
break;
case PROP_SCALE:
self->scale = g_value_get_float (value);
update_actions (self);
gtk_widget_queue_resize (GTK_WIDGET (object));
break;
case PROP_ANGLE:
self->angle = fmodf (g_value_get_float (value), 360.f);
gtk_widget_queue_resize (GTK_WIDGET (object));
break;
case PROP_FILTER:
self->filter = g_value_get_enum (value);
gtk_widget_queue_resize (GTK_WIDGET (object));
break;
@@ -266,22 +139,14 @@ demo3_widget_get_property (GObject *object,
switch (prop_id)
{
case PROP_TEXTURE:
g_value_set_object (value, self->texture);
case PROP_PAINTABLE:
g_value_set_object (value, self->paintable);
break;
case PROP_SCALE:
g_value_set_float (value, self->scale);
break;
case PROP_ANGLE:
g_value_set_float (value, self->angle);
break;
case PROP_FILTER:
g_value_set_enum (value, self->filter);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -303,14 +168,6 @@ pressed_cb (GtkGestureClick *gesture,
gtk_popover_popup (GTK_POPOVER (self->menu));
}
static void
update_actions (Demo3Widget *self)
{
gtk_widget_action_set_enabled (GTK_WIDGET (self), "zoom.in", self->scale < 1024.);
gtk_widget_action_set_enabled (GTK_WIDGET (self), "zoom.out", self->scale > 1./1024.);
gtk_widget_action_set_enabled (GTK_WIDGET (self), "zoom.reset", self->scale != 1.);
}
static void
zoom_cb (GtkWidget *widget,
const char *action_name,
@@ -320,30 +177,19 @@ zoom_cb (GtkWidget *widget,
float scale;
if (g_str_equal (action_name, "zoom.in"))
scale = MIN (1024., self->scale * M_SQRT2);
scale = MIN (10, self->scale * M_SQRT2);
else if (g_str_equal (action_name, "zoom.out"))
scale = MAX (1./1024., self->scale / M_SQRT2);
else if (g_str_equal (action_name, "zoom.reset"))
scale = 1.0;
scale = MAX (0.01, self->scale / M_SQRT2);
else
g_assert_not_reached ();
scale = 1.0;
gtk_widget_action_set_enabled (widget, "zoom.in", scale < 10);
gtk_widget_action_set_enabled (widget, "zoom.out", scale > 0.01);
gtk_widget_action_set_enabled (widget, "zoom.reset", scale != 1);
g_object_set (widget, "scale", scale, NULL);
}
static void
rotate_cb (GtkWidget *widget,
const char *action_name,
GVariant *parameter)
{
Demo3Widget *self = DEMO3_WIDGET (widget);
int angle;
g_variant_get (parameter, "i", &angle);
g_object_set (widget, "angle", fmodf (self->angle + angle, 360.f), NULL);
}
static void
demo3_widget_class_init (Demo3WidgetClass *class)
{
@@ -358,31 +204,20 @@ demo3_widget_class_init (Demo3WidgetClass *class)
widget_class->measure = demo3_widget_measure;
widget_class->size_allocate = demo3_widget_size_allocate;
g_object_class_install_property (object_class, PROP_TEXTURE,
g_param_spec_object ("texture", NULL, NULL,
GDK_TYPE_TEXTURE,
g_object_class_install_property (object_class, PROP_PAINTABLE,
g_param_spec_object ("paintable", "Paintable", "Paintable",
GDK_TYPE_PAINTABLE,
G_PARAM_READWRITE));
g_object_class_install_property (object_class, PROP_SCALE,
g_param_spec_float ("scale", NULL, NULL,
1./1024., 1024., 1.0,
g_param_spec_float ("scale", "Scale", "Scale",
0.0, 10.0, 1.0,
G_PARAM_READWRITE));
g_object_class_install_property (object_class, PROP_ANGLE,
g_param_spec_float ("angle", NULL, NULL,
0.0, 360.0, 0.0,
G_PARAM_READWRITE));
g_object_class_install_property (object_class, PROP_FILTER,
g_param_spec_enum ("filter", NULL, NULL,
GSK_TYPE_SCALING_FILTER, GSK_SCALING_FILTER_LINEAR,
G_PARAM_READWRITE));
/* These are the actions that we are using in the menu */
gtk_widget_class_install_action (widget_class, "zoom.in", NULL, zoom_cb);
gtk_widget_class_install_action (widget_class, "zoom.out", NULL, zoom_cb);
gtk_widget_class_install_action (widget_class, "zoom.reset", NULL, zoom_cb);
gtk_widget_class_install_action (widget_class, "rotate", "i", rotate_cb);
gtk_widget_class_set_template_from_resource (widget_class, "/menu/demo3widget.ui");
gtk_widget_class_bind_template_child (widget_class, Demo3Widget, menu);
@@ -393,18 +228,16 @@ GtkWidget *
demo3_widget_new (const char *resource)
{
Demo3Widget *self;
GdkTexture *texture;
GdkPixbuf *pixbuf;
GdkPaintable *paintable;
texture = gdk_texture_new_from_resource (resource);
pixbuf = gdk_pixbuf_new_from_resource (resource, NULL);
paintable = GDK_PAINTABLE (gdk_texture_new_for_pixbuf (pixbuf));
self = g_object_new (DEMO3_TYPE_WIDGET,
"texture", texture,
"has-tooltip", TRUE,
NULL);
self = g_object_new (DEMO3_TYPE_WIDGET, "paintable", paintable, NULL);
g_signal_connect (self, "query-tooltip", G_CALLBACK (query_tooltip), NULL);
g_object_unref (texture);
g_object_unref (pixbuf);
g_object_unref (paintable);
return GTK_WIDGET (self);
}

View File

@@ -12,11 +12,6 @@
<attribute name="label">11</attribute>
<attribute name="action">zoom.reset</attribute>
</item>
<item>
<attribute name="label">Rotate</attribute>
<attribute name="action">rotate</attribute>
<attribute name="target" type="i">90</attribute>
</item>
</menu>
<template class="Demo3Widget">
<child>

View File

@@ -1,226 +0,0 @@
#include <math.h>
#include "demo4widget.h"
#include "hsla.h"
enum
{
PROP_0,
PROP_PROGRESS,
};
struct _Demo4Widget
{
GtkWidget parent_instance;
PangoLayout *layout;
GskColorStop stops[8];
gsize n_stops;
double progress;
guint tick;
};
struct _Demo4WidgetClass
{
GtkWidgetClass parent_class;
};
G_DEFINE_TYPE (Demo4Widget, demo4_widget, GTK_TYPE_WIDGET)
static void
rotate_color (GdkRGBA *rgba)
{
GdkHSLA hsla;
_gdk_hsla_init_from_rgba (&hsla, rgba);
hsla.hue -= 1;
_gdk_rgba_init_from_hsla (rgba, &hsla);
}
static gboolean
rotate_colors (GtkWidget *widget,
GdkFrameClock *clock,
gpointer user_data)
{
Demo4Widget *self = DEMO4_WIDGET (widget);
for (unsigned int i = 0; i < self->n_stops; i++)
rotate_color (&self->stops[i].color);
gtk_widget_queue_draw (widget);
return G_SOURCE_CONTINUE;
}
static void
demo4_widget_init (Demo4Widget *self)
{
PangoFontDescription *desc;
self->progress = 0.5;
self->n_stops = 8;
self->stops[0].offset = 0;
self->stops[0].color = (GdkRGBA) { 1, 0, 0, 1 };
for (unsigned int i = 1; i < self->n_stops; i++)
{
GdkHSLA hsla;
self->stops[i].offset = i / (double)(self->n_stops - 1);
_gdk_hsla_init_from_rgba (&hsla, &self->stops[i - 1].color);
hsla.hue += 360.0 / (double)(self->n_stops - 1);
_gdk_rgba_init_from_hsla (&self->stops[i].color, &hsla);
}
self->layout = gtk_widget_create_pango_layout (GTK_WIDGET (self), "123");
desc = pango_font_description_from_string ("Cantarell Bold 210");
pango_layout_set_font_description (self->layout, desc);
pango_font_description_free (desc);
self->tick = gtk_widget_add_tick_callback (GTK_WIDGET (self), rotate_colors, NULL, NULL);
}
static void
demo4_widget_dispose (GObject *object)
{
Demo4Widget *self = DEMO4_WIDGET (object);
g_clear_object (&self->layout);
gtk_widget_remove_tick_callback (GTK_WIDGET (self), self->tick);
G_OBJECT_CLASS (demo4_widget_parent_class)->dispose (object);
}
static void
demo4_widget_snapshot_content (GtkWidget *widget,
GtkSnapshot *snapshot,
GskMaskMode mode)
{
Demo4Widget *self = DEMO4_WIDGET (widget);
int width, height, layout_width, layout_height;
double scale;
width = gtk_widget_get_width (widget);
height = gtk_widget_get_height (widget);
gtk_snapshot_push_mask (snapshot, mode);
pango_layout_get_pixel_size (self->layout, &layout_width, &layout_height);
scale = MIN ((double) width / layout_width, (double) height / layout_height);
gtk_snapshot_translate (snapshot,
&GRAPHENE_POINT_INIT ((width - scale * layout_width) / 2,
(height - scale * layout_height) / 2));
gtk_snapshot_scale (snapshot, scale, scale);
gtk_snapshot_append_layout (snapshot, self->layout, &(GdkRGBA) { 0, 0, 0, 1 });
gtk_snapshot_pop (snapshot);
gtk_snapshot_append_linear_gradient (snapshot,
&GRAPHENE_RECT_INIT (0, 0, width, height),
&GRAPHENE_POINT_INIT (0, 0),
&GRAPHENE_POINT_INIT (width, height),
self->stops,
self->n_stops);
gtk_snapshot_pop (snapshot);
}
static void
demo4_widget_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot)
{
Demo4Widget *self = DEMO4_WIDGET (widget);
int width, height;
width = gtk_widget_get_width (widget);
height = gtk_widget_get_height (widget);
gtk_snapshot_push_mask (snapshot, GSK_MASK_MODE_INVERTED_LUMINANCE);
gtk_snapshot_append_linear_gradient (snapshot,
&GRAPHENE_RECT_INIT (0, 0, width, height),
&GRAPHENE_POINT_INIT (0, 0),
&GRAPHENE_POINT_INIT (width, 0),
(GskColorStop[2]) {
{ MAX (0.0, self->progress - 5.0 / width), { 1, 1, 1, 1 } },
{ MIN (1.0, self->progress + 5.0 / width), { 0, 0, 0, 1 } }
}, 2);
gtk_snapshot_pop (snapshot);
demo4_widget_snapshot_content (widget, snapshot, GSK_MASK_MODE_INVERTED_ALPHA);
gtk_snapshot_pop (snapshot);
gtk_snapshot_push_mask (snapshot, GSK_MASK_MODE_LUMINANCE);
gtk_snapshot_append_linear_gradient (snapshot,
&GRAPHENE_RECT_INIT (0, 0, width, height),
&GRAPHENE_POINT_INIT (0, 0),
&GRAPHENE_POINT_INIT (width, 0),
(GskColorStop[2]) {
{ MAX (0.0, self->progress - 5.0 / width), { 1, 1, 1, 1 } },
{ MIN (1.0, self->progress + 5.0 / width), { 0, 0, 0, 1 } }
}, 2);
gtk_snapshot_pop (snapshot);
demo4_widget_snapshot_content (widget, snapshot, GSK_MASK_MODE_ALPHA);
gtk_snapshot_pop (snapshot);
}
static void
demo4_widget_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
Demo4Widget *self = DEMO4_WIDGET (object);
switch (prop_id)
{
case PROP_PROGRESS:
self->progress = g_value_get_double (value);
gtk_widget_queue_draw (GTK_WIDGET (object));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
demo4_widget_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
Demo4Widget *self = DEMO4_WIDGET (object);
switch (prop_id)
{
case PROP_PROGRESS:
g_value_set_double (value, self->progress);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
demo4_widget_class_init (Demo4WidgetClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
object_class->dispose = demo4_widget_dispose;
object_class->get_property = demo4_widget_get_property;
object_class->set_property = demo4_widget_set_property;
widget_class->snapshot = demo4_widget_snapshot;
g_object_class_install_property (object_class, PROP_PROGRESS,
g_param_spec_double ("progress", NULL, NULL,
0.0, 1.0, 0.5,
G_PARAM_READWRITE));
}
GtkWidget *
demo4_widget_new (void)
{
return g_object_new (DEMO4_TYPE_WIDGET, NULL);
}

View File

@@ -1,8 +0,0 @@
#pragma once
#include <gtk/gtk.h>
#define DEMO4_TYPE_WIDGET (demo4_widget_get_type ())
G_DECLARE_FINAL_TYPE (Demo4Widget, demo4_widget, DEMO4, WIDGET, GtkWidget)
GtkWidget * demo4_widget_new (void);

View File

@@ -8,8 +8,6 @@
#include <glib/gi18n.h>
#include <gtk/gtk.h>
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
static GtkWidget *window = NULL;
static GtkWidget *entry1 = NULL;
static GtkWidget *entry2 = NULL;
@@ -29,7 +27,7 @@ message_dialog_clicked (GtkButton *button,
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
ngettext ("Has been shown once", "Has been shown %d times", i), i);
g_signal_connect (dialog, "response", G_CALLBACK (gtk_window_destroy), NULL);
gtk_window_present (GTK_WINDOW (dialog));
gtk_widget_show (dialog);
i++;
}
@@ -116,7 +114,7 @@ interactive_dialog_clicked (GtkButton *button,
data, (GClosureNotify) g_free,
0);
gtk_window_present (GTK_WINDOW (dialog));
gtk_widget_show (dialog);
}
GtkWidget *
@@ -186,7 +184,7 @@ do_dialog (GtkWidget *do_widget)
}
if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE);
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));

View File

@@ -11,7 +11,6 @@
#include <gtk/gtk.h>
G_DECLARE_FINAL_TYPE (CanvasItem, canvas_item, CANVAS, ITEM, GtkWidget)
struct _CanvasItem {
@@ -25,9 +24,6 @@ struct _CanvasItem {
double delta;
GtkWidget *editor;
GtkStyleProvider *provider;
char *css_class;
};
struct _CanvasItemClass {
@@ -38,41 +34,32 @@ G_DEFINE_TYPE (CanvasItem, canvas_item, GTK_TYPE_WIDGET)
static int n_items = 0;
static void
unstyle_item (CanvasItem *item)
{
if (item->provider)
{
gtk_style_context_remove_provider_for_display (gtk_widget_get_display (item->label), item->provider);
g_clear_object (&item->provider);
}
if (item->css_class)
{
gtk_widget_remove_css_class (item->label, item->css_class);
g_clear_pointer (&item->css_class, g_free);
}
}
static void
set_color (CanvasItem *item,
GdkRGBA *color)
{
char *css;
char *str;
GtkStyleContext *context;
GtkCssProvider *provider;
const char *name;
unstyle_item (item);
const char *old_class;
str = gdk_rgba_to_string (color);
name = gtk_widget_get_name (item->label);
css = g_strdup_printf ("#%s { background: %s; }", name, str);
css = g_strdup_printf ("* { background: %s; }", str);
context = gtk_widget_get_style_context (item->label);
provider = g_object_get_data (G_OBJECT (context), "style-provider");
if (provider)
gtk_style_context_remove_provider (context, GTK_STYLE_PROVIDER (provider));
old_class = (const char *)g_object_get_data (G_OBJECT (item->label), "css-class");
if (old_class)
gtk_widget_remove_css_class (item->label, old_class);
provider = gtk_css_provider_new ();
gtk_css_provider_load_from_string (provider, css);
gtk_style_context_add_provider_for_display (gtk_widget_get_display (item->label), GTK_STYLE_PROVIDER (provider), 700);
item->provider = GTK_STYLE_PROVIDER (provider);
gtk_css_provider_load_from_data (provider, css, -1);
gtk_style_context_add_provider (gtk_widget_get_style_context (item->label), GTK_STYLE_PROVIDER (provider), 800);
g_object_set_data_full (G_OBJECT (context), "style-provider", provider, g_object_unref);
g_free (str);
g_free (css);
@@ -82,10 +69,21 @@ static void
set_css (CanvasItem *item,
const char *class)
{
unstyle_item (item);
GtkStyleContext *context;
GtkCssProvider *provider;
const char *old_class;
context = gtk_widget_get_style_context (item->label);
provider = g_object_get_data (G_OBJECT (context), "style-provider");
if (provider)
gtk_style_context_remove_provider (context, GTK_STYLE_PROVIDER (provider));
old_class = (const char *)g_object_get_data (G_OBJECT (item->label), "css-class");
if (old_class)
gtk_widget_remove_css_class (item->label, old_class);
g_object_set_data_full (G_OBJECT (item->label), "css-class", g_strdup (class), g_free);
gtk_widget_add_css_class (item->label, class);
item->css_class = g_strdup (class);
}
static gboolean
@@ -109,21 +107,15 @@ static void
apply_transform (CanvasItem *item)
{
GskTransform *transform;
graphene_rect_t bounds;
double x, y;
/* Add css padding and margin */
if (!gtk_widget_compute_bounds (item->label, item->label, &bounds))
return;
x = bounds.size.width / 2.;
y = bounds.size.height / 2.;
item->r = sqrt (x * x + y * y);
x = gtk_widget_get_allocated_width (item->label) / 2.0;
y = gtk_widget_get_allocated_height (item->label) / 2.0;
item->r = sqrt (x*x + y*y);
transform = gsk_transform_translate (NULL, &(graphene_point_t) { item->r, item->r });
transform = gsk_transform_rotate (transform, item->angle + item->delta);
transform = gsk_transform_translate (transform, &GRAPHENE_POINT_INIT (-x, -y));
transform = gsk_transform_translate (transform, &(graphene_point_t) { -x, -y });
gtk_fixed_set_child_transform (GTK_FIXED (item->fixed), item->label, transform);
gsk_transform_unref (transform);
@@ -330,7 +322,7 @@ canvas_item_start_editing (CanvasItem *item)
GtkWidget *canvas = gtk_widget_get_parent (GTK_WIDGET (item));
GtkWidget *entry;
GtkWidget *scale;
graphene_point_t p;
double x, y;
if (item->editor)
return;
@@ -356,17 +348,12 @@ canvas_item_start_editing (CanvasItem *item)
gtk_box_append (GTK_BOX (item->editor), scale);
if (!gtk_widget_compute_point (GTK_WIDGET (item), canvas, &GRAPHENE_POINT_INIT (0, 0), &p))
graphene_point_init (&p, 0, 0);
gtk_fixed_put (GTK_FIXED (canvas), item->editor, p.x, p.y + 2 * item->r);
gtk_widget_translate_coordinates (GTK_WIDGET (item), canvas, 0, 0, &x, &y);
gtk_fixed_put (GTK_FIXED (canvas), item->editor, x, y + 2 * item->r);
gtk_widget_grab_focus (entry);
}
typedef struct {
double x, y;
} Hotspot;
static GdkContentProvider *
prepare (GtkDragSource *source,
double x,
@@ -374,8 +361,6 @@ prepare (GtkDragSource *source,
{
GtkWidget *canvas;
GtkWidget *item;
Hotspot *hotspot;
graphene_point_t p;
canvas = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (source));
item = gtk_widget_pick (canvas, x, y, GTK_PICK_DEFAULT);
@@ -386,13 +371,6 @@ prepare (GtkDragSource *source,
g_object_set_data (G_OBJECT (canvas), "dragged-item", item);
hotspot = g_new (Hotspot, 1);
if (!gtk_widget_compute_point (canvas, item, &GRAPHENE_POINT_INIT (x, y), &p))
graphene_point_init (&p, x, y);
hotspot->x = p.x;
hotspot->y = p.y;
g_object_set_data_full (G_OBJECT (canvas), "hotspot", hotspot, g_free);
return gdk_content_provider_new_typed (GTK_TYPE_WIDGET, item);
}
@@ -403,14 +381,12 @@ drag_begin (GtkDragSource *source,
GtkWidget *canvas;
CanvasItem *item;
GdkPaintable *paintable;
Hotspot *hotspot;
canvas = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (source));
item = CANVAS_ITEM (g_object_get_data (G_OBJECT (canvas), "dragged-item"));
hotspot = (Hotspot *) g_object_get_data (G_OBJECT (canvas), "hotspot");
paintable = canvas_item_get_drag_icon (item);
gtk_drag_source_set_icon (source, paintable, hotspot->x, hotspot->y);
gtk_drag_source_set_icon (source, paintable, item->r, item->r);
g_object_unref (paintable);
gtk_widget_set_opacity (GTK_WIDGET (item), 0.3);
@@ -746,11 +722,8 @@ do_dnd (GtkWidget *do_widget)
int i;
int x, y;
GtkCssProvider *provider;
GString *css;
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
button = gtk_color_button_new ();
G_GNUC_END_IGNORE_DEPRECATIONS
g_object_unref (g_object_ref_sink (button));
provider = gtk_css_provider_new ();
@@ -760,18 +733,6 @@ G_GNUC_END_IGNORE_DEPRECATIONS
800);
g_object_unref (provider);
css = g_string_new ("");
for (i = 0; colors[i]; i++)
g_string_append_printf (css, ".canvasitem.%s { background: %s; }\n", colors[i], colors[i]);
provider = gtk_css_provider_new ();
gtk_css_provider_load_from_string (provider, css->str);
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
GTK_STYLE_PROVIDER (provider),
800);
g_object_unref (provider);
g_string_free (css, TRUE);
window = gtk_window_new ();
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
@@ -824,7 +785,7 @@ G_GNUC_END_IGNORE_DEPRECATIONS
}
if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE);
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));

View File

@@ -362,7 +362,7 @@ do_drawingarea (GtkWidget *do_widget)
G_CALLBACK (scribble_resize), NULL);
drag = gtk_gesture_drag_new ();
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (drag), 0);
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (drag), GDK_BUTTON_PRIMARY);
gtk_widget_add_controller (da, GTK_EVENT_CONTROLLER (drag));
g_signal_connect (drag, "drag-begin", G_CALLBACK (drag_begin), da);
@@ -372,7 +372,7 @@ do_drawingarea (GtkWidget *do_widget)
}
if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE);
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));

View File

@@ -164,14 +164,14 @@ strings_bind_item (GtkSignalListItemFactory *factory,
popup = gtk_widget_get_ancestor (title, GTK_TYPE_POPOVER);
if (popup && gtk_widget_is_ancestor (popup, GTK_WIDGET (dropdown)))
{
gtk_widget_set_visible (checkmark, TRUE);
gtk_widget_show (checkmark);
g_signal_connect (dropdown, "notify::selected-item",
G_CALLBACK (selected_item_changed), item);
selected_item_changed (dropdown, NULL, item);
}
else
{
gtk_widget_set_visible (checkmark, FALSE);
gtk_widget_hide (checkmark);
}
}
@@ -263,7 +263,7 @@ drop_down_new_from_strings (const char *const *titles,
static char *
get_family_name (gpointer item)
{
return g_strdup (pango_font_family_get_name (PANGO_FONT_FAMILY (item)));
return g_strdup (pango2_font_family_get_name (PANGO2_FONT_FAMILY (item)));
}
static char *
@@ -326,8 +326,8 @@ bind_highlight_item (GtkSignalListItemFactory *factory,
{
MatchObject *obj;
GtkWidget *label;
PangoAttrList *attrs;
PangoAttribute *attr;
Pango2AttrList *attrs;
Pango2Attribute *attr;
const char *str;
obj = MATCH_OBJECT (gtk_list_item_get_item (item));
@@ -336,13 +336,14 @@ bind_highlight_item (GtkSignalListItemFactory *factory,
str = match_object_get_string (obj);
gtk_label_set_label (GTK_LABEL (label), str);
attrs = pango_attr_list_new ();
attr = pango_attr_weight_new (PANGO_WEIGHT_BOLD);
attr->start_index = match_object_get_match_start (obj);
attr->end_index = match_object_get_match_end (obj);
pango_attr_list_insert (attrs, attr);
attrs = pango2_attr_list_new ();
attr = pango2_attr_weight_new (PANGO2_WEIGHT_BOLD);
pango2_attribute_set_range (attr,
match_object_get_match_start (obj),
match_object_get_match_end (obj));
pango2_attr_list_insert (attrs, attr);
gtk_label_set_attributes (GTK_LABEL (label), attrs);
pango_attr_list_unref (attrs);
pango2_attr_list_unref (attrs);
}
static void
@@ -369,7 +370,7 @@ match_func (MatchObject *obj,
}
GtkWidget *
do_listview_selections (GtkWidget *do_widget)
do_dropdown (GtkWidget *do_widget)
{
static GtkWidget *window = NULL;
GtkWidget *button, *box, *spin, *check, *hbox, *label, *entry;
@@ -434,7 +435,7 @@ do_listview_selections (GtkWidget *do_widget)
button = gtk_drop_down_new (NULL, NULL);
model = G_LIST_MODEL (pango_cairo_font_map_get_default ());
model = G_LIST_MODEL (pango2_font_map_get_default ());
gtk_drop_down_set_model (GTK_DROP_DOWN (button), model);
gtk_drop_down_set_selected (GTK_DROP_DOWN (button), 0);
@@ -563,7 +564,7 @@ do_listview_selections (GtkWidget *do_widget)
}
if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE);
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));

View File

@@ -14,8 +14,6 @@
#include <string.h>
#include <stdlib.h>
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
typedef struct
{
int number;
@@ -409,7 +407,7 @@ do_editable_cells (GtkWidget *do_widget)
}
if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE);
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));

View File

@@ -8,8 +8,6 @@
#include <glib/gi18n.h>
#include <gtk/gtk.h>
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
/* Creates a tree model containing the completions */
static GtkTreeModel *
create_completion_model (void)
@@ -115,7 +113,7 @@ do_entry_completion (GtkWidget *do_widget)
}
if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE);
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));

View File

@@ -46,7 +46,7 @@ do_entry_undo (GtkWidget *do_widget)
}
if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE);
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));

View File

@@ -42,12 +42,12 @@ mode_switch_state_set (GtkSwitch *sw,
if (!state ||
(gtk_range_get_value (GTK_RANGE (scale)) > 50))
{
gtk_widget_set_visible (label, FALSE);
gtk_widget_hide (label);
gtk_switch_set_state (sw, state);
}
else
{
gtk_widget_set_visible (label, TRUE);
gtk_widget_show (label);
}
return TRUE;
@@ -65,7 +65,7 @@ level_scale_value_changed (GtkRange *range,
!gtk_switch_get_state (GTK_SWITCH (sw)) &&
(gtk_range_get_value (range) > 50))
{
gtk_widget_set_visible (label, FALSE);
gtk_widget_hide (label);
gtk_switch_set_state (GTK_SWITCH (sw), TRUE);
}
else if (gtk_switch_get_state (GTK_SWITCH (sw)) &&
@@ -113,7 +113,7 @@ do_errorstates (GtkWidget *do_widget)
}
if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE);
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));

View File

@@ -10,8 +10,6 @@
#include <glib/gi18n.h>
#include <gtk/gtk.h>
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
static GtkWidget *window = NULL;
static void
@@ -122,7 +120,7 @@ do_expander (GtkWidget *do_widget)
}
if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE);
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));

View File

@@ -9,8 +9,6 @@
#include <gtk/gtk.h>
#include <stdlib.h>
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
enum {
WIDTH_COLUMN,
HEIGHT_COLUMN,
@@ -199,7 +197,7 @@ do_filtermodel (GtkWidget *do_widget)
}
if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE);
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));

View File

@@ -68,13 +68,11 @@ create_blurred_button (void)
return w;
}
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
static GtkWidget *
create_font_button (void)
{
return gtk_font_button_new ();
}
G_GNUC_END_IGNORE_DEPRECATIONS
static GtkWidget *
create_level_bar (void)
@@ -301,7 +299,7 @@ do_fishbowl (GtkWidget *do_widget)
if (provider == NULL)
{
provider = gtk_css_provider_new ();
gtk_css_provider_load_from_string (provider, css);
gtk_css_provider_load_from_data (provider, css, -1);
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
GTK_STYLE_PROVIDER (provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
@@ -329,7 +327,7 @@ do_fishbowl (GtkWidget *do_widget)
}
if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE);
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));

View File

@@ -160,7 +160,7 @@ do_fixed (GtkWidget *do_widget)
demo_window = create_demo_window (do_widget);
if (!gtk_widget_get_visible (demo_window))
gtk_widget_set_visible (demo_window, TRUE);
gtk_widget_show (demo_window);
else
gtk_window_destroy (GTK_WINDOW (demo_window));

View File

@@ -742,7 +742,7 @@ do_flowbox (GtkWidget *do_widget)
}
if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE);
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,65 @@
--- demos/gtk-demo/font_features.c
+++ demos/gtk-demo/font_features.c
@@ -434,7 +434,7 @@ static void
update_display (void)
{
GString *s;
- const char *text;
+ char *text;
gboolean has_feature;
GtkTreeIter iter;
GtkTreeModel *model;
@@ -452,8 +452,12 @@ update_display (void)
gboolean do_waterfall;
GString *waterfall;
char *palette;
+ GtkTextBuffer *buffer;
+ GtkTextIter start_iter, end_iter;
- text = gtk_editable_get_text (GTK_EDITABLE (demo->the_entry));
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (demo->the_entry));
+ gtk_text_buffer_get_bounds (buffer, &start_iter, &end_iter);
+ text = gtk_text_buffer_get_text (buffer, &start_iter, &end_iter, FALSE);
text_len = strlen (text);
do_waterfall = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (demo->waterfall_toggle));
@@ -631,6 +635,8 @@ update_display (void)
pango2_font_description_free (desc);
g_free (features);
pango2_attr_list_unref (attrs);
+
+ g_free (text);
}
static Pango2Font *
@@ -1603,8 +1609,12 @@ font_features_toggle_edit (void)
{
if (strcmp (gtk_stack_get_visible_child_name (GTK_STACK (demo->stack)), "entry") != 0)
{
+ GtkTextBuffer *buffer;
+ GtkTextIter start, end;
g_free (demo->text);
- demo->text = g_strdup (gtk_editable_get_text (GTK_EDITABLE (demo->the_entry)));
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (demo->the_entry));
+ gtk_text_buffer_get_bounds (buffer, &start, &end);
+ demo->text = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
gtk_stack_set_visible_child_name (GTK_STACK (demo->stack), "entry");
gtk_widget_grab_focus (demo->the_entry);
gtk_adjustment_set_value (gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (demo->swin)), 0);
@@ -1632,7 +1642,7 @@ entry_key_press (GtkEventController *controller,
{
if (keyval == GDK_KEY_Escape)
{
- gtk_editable_set_text (GTK_EDITABLE (entry), demo->text);
+ gtk_text_buffer_set_text (gtk_text_view_get_buffer (GTK_TEXT_VIEW (demo->the_entry)), demo->text, -1);
return GDK_EVENT_STOP;
}
@@ -1701,7 +1711,6 @@ do_font_features (GtkWidget *do_widget)
basic_value_changed (demo->line_height_adjustment, demo->line_height_entry);
controller = gtk_event_controller_key_new ();
- g_object_set_data_full (G_OBJECT (demo->the_entry), "controller", g_object_ref (controller), g_object_unref);
g_signal_connect (controller, "key-pressed", G_CALLBACK (entry_key_press), demo->the_entry);
gtk_widget_add_controller (demo->the_entry, controller);

View File

@@ -38,6 +38,7 @@
<signal name="clicked" handler="font_features_reset_basic" swapped="no"/>
<signal name="clicked" handler="font_features_reset_features" swapped="no"/>
<signal name="clicked" handler="font_features_reset_variations" swapped="no"/>
<signal name="clicked" handler="font_features_reset_colors" swapped="no"/>
</object>
</child>
</object>
@@ -58,14 +59,11 @@
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkFontDialogButton" id="font">
<property name="dialog">
<object class="GtkFontDialog">
</object>
</property>
<object class="GtkFontButton" id="font">
<property name="receives-default">1</property>
<property name="level">face</property>
<signal name="notify::font-desc" handler="font_features_font_changed" swapped="no"/>
<property name="font">Sans 12</property>
<property name="level">family|style</property>
<signal name="font-set" handler="font_features_font_changed" swapped="no"/>
</object>
</child>
<child>
@@ -195,11 +193,7 @@
</object>
</child>
<child>
<object class="GtkColorDialogButton" id="foreground">
<property name="dialog">
<object class="GtkColorDialog">
</object>
</property>
<object class="GtkColorButton" id="foreground">
<property name="valign">baseline</property>
<property name="rgba">black</property>
<signal name="notify::rgba" handler="color_set_cb"/>
@@ -221,11 +215,7 @@
</object>
</child>
<child>
<object class="GtkColorDialogButton" id="background">
<property name="dialog">
<object class="GtkColorDialog">
</object>
</property>
<object class="GtkColorButton" id="background">
<property name="valign">baseline</property>
<property name="rgba">white</property>
<signal name="notify::rgba" handler="color_set_cb"/>
@@ -270,10 +260,16 @@
<object class="GtkBox" id="feature_list">
<property name="orientation">vertical</property>
<child>
<object class="GtkDropDown" id="script_lang">
<object class="GtkComboBox" id="script_lang">
<property name="tooltip-text" translatable="yes">Language System</property>
<property name="margin-top">10</property>
<signal name="notify::selected" handler="font_features_script_changed" swapped="no"/>
<signal name="changed" handler="font_features_script_changed" swapped="no"/>
<child>
<object class="GtkCellRendererText"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
</child>
</object>
@@ -301,6 +297,27 @@
</child>
</object>
</child>
<child>
<object class="GtkExpander">
<child type="label">
<object class="GtkLabel">
<property name="label" translatable="yes">Color Palettes</property>
<property name="xalign">0</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<style>
<class name="title-4"/>
</style>
</object>
</child>
<child>
<object class="GtkGrid" id="colors_grid">
<property name="column-spacing">10</property>
<property name="row-spacing">10</property>
</object>
</child>
</object>
</child>
</object>
</child>
<style>

View File

@@ -19,7 +19,7 @@
*/
static void
insert_tags_for_attributes (GtkTextBuffer *buffer,
PangoAttrIterator *iter,
Pango2AttrIterator *iter,
GtkTextIter *start,
GtkTextIter *end)
{
@@ -27,13 +27,12 @@ insert_tags_for_attributes (GtkTextBuffer *buffer,
GSList *attrs, *l;
GtkTextTag *tag;
char name[256];
float fg_alpha, bg_alpha;
table = gtk_text_buffer_get_tag_table (buffer);
#define LANGUAGE_ATTR(attr_name) \
{ \
const char *language = pango_language_to_string (((PangoAttrLanguage*)attr)->value); \
const char *language = pango2_language_to_string (pango2_attribute_get_language (attr)); \
g_snprintf (name, 256, "language=%s", language); \
tag = gtk_text_tag_table_lookup (table, name); \
if (!tag) \
@@ -48,7 +47,7 @@ insert_tags_for_attributes (GtkTextBuffer *buffer,
#define STRING_ATTR(attr_name) \
{ \
const char *string = ((PangoAttrString*)attr)->value; \
const char *string = pango2_attribute_get_string (attr); \
g_snprintf (name, 256, #attr_name "=%s", string); \
tag = gtk_text_tag_table_lookup (table, name); \
if (!tag) \
@@ -63,7 +62,7 @@ insert_tags_for_attributes (GtkTextBuffer *buffer,
#define INT_ATTR(attr_name) \
{ \
int value = ((PangoAttrInt*)attr)->value; \
int value = pango2_attribute_get_int (attr); \
g_snprintf (name, 256, #attr_name "=%d", value); \
tag = gtk_text_tag_table_lookup (table, name); \
if (!tag) \
@@ -78,8 +77,8 @@ insert_tags_for_attributes (GtkTextBuffer *buffer,
#define FONT_ATTR(attr_name) \
{ \
PangoFontDescription *desc = ((PangoAttrFontDesc*)attr)->desc; \
char *str = pango_font_description_to_string (desc); \
Pango2FontDescription *desc = pango2_attribute_get_font_desc (attr); \
char *str = pango2_font_description_to_string (desc); \
g_snprintf (name, 256, "font-desc=%s", str); \
g_free (str); \
tag = gtk_text_tag_table_lookup (table, name); \
@@ -95,7 +94,7 @@ insert_tags_for_attributes (GtkTextBuffer *buffer,
#define FLOAT_ATTR(attr_name) \
{ \
float value = ((PangoAttrFloat*)attr)->value; \
float value = pango2_attribute_get_float (attr); \
g_snprintf (name, 256, #attr_name "=%g", value); \
tag = gtk_text_tag_table_lookup (table, name); \
if (!tag) \
@@ -108,15 +107,14 @@ insert_tags_for_attributes (GtkTextBuffer *buffer,
gtk_text_buffer_apply_tag (buffer, tag, start, end); \
}
#define RGBA_ATTR(attr_name, alpha_value) \
#define RGBA_ATTR(attr_name) \
{ \
PangoColor *color; \
Pango2Color *color = pango2_attribute_get_color (attr); \
GdkRGBA rgba; \
color = &((PangoAttrColor*)attr)->color; \
rgba.red = color->red / 65535.; \
rgba.green = color->green / 65535.; \
rgba.blue = color->blue / 65535.; \
rgba.alpha = alpha_value; \
rgba.alpha = color->alpha / 65535.; \
char *str = gdk_rgba_to_string (&rgba); \
g_snprintf (name, 256, #attr_name "=%s", str); \
g_free (str); \
@@ -144,173 +142,157 @@ insert_tags_for_attributes (GtkTextBuffer *buffer,
gtk_text_buffer_apply_tag (buffer, tag, start, end); \
}
fg_alpha = bg_alpha = 1.;
attrs = pango_attr_iterator_get_attrs (iter);
attrs = pango2_attr_iterator_get_attrs (iter);
for (l = attrs; l; l = l->next)
{
PangoAttribute *attr = l->data;
Pango2Attribute *attr = l->data;
switch ((int)attr->klass->type)
switch (pango2_attribute_type (attr))
{
case PANGO_ATTR_FOREGROUND_ALPHA:
fg_alpha = ((PangoAttrInt*)attr)->value / 65535.;
break;
case PANGO_ATTR_BACKGROUND_ALPHA:
bg_alpha = ((PangoAttrInt*)attr)->value / 65535.;
break;
default:
break;
}
}
for (l = attrs; l; l = l->next)
{
PangoAttribute *attr = l->data;
switch (attr->klass->type)
{
case PANGO_ATTR_LANGUAGE:
case PANGO2_ATTR_LANGUAGE:
LANGUAGE_ATTR (language);
break;
case PANGO_ATTR_FAMILY:
case PANGO2_ATTR_FAMILY:
STRING_ATTR (family);
break;
case PANGO_ATTR_STYLE:
case PANGO2_ATTR_STYLE:
INT_ATTR (style);
break;
case PANGO_ATTR_WEIGHT:
case PANGO2_ATTR_WEIGHT:
INT_ATTR (weight);
break;
case PANGO_ATTR_VARIANT:
case PANGO2_ATTR_VARIANT:
INT_ATTR (variant);
break;
case PANGO_ATTR_STRETCH:
case PANGO2_ATTR_STRETCH:
INT_ATTR (stretch);
break;
case PANGO_ATTR_SIZE:
case PANGO2_ATTR_SIZE:
INT_ATTR (size);
break;
case PANGO_ATTR_FONT_DESC:
case PANGO2_ATTR_FONT_DESC:
FONT_ATTR (font-desc);
break;
case PANGO_ATTR_FOREGROUND:
RGBA_ATTR (foreground_rgba, fg_alpha);
case PANGO2_ATTR_FOREGROUND:
RGBA_ATTR (foreground_rgba);
break;
case PANGO_ATTR_BACKGROUND:
RGBA_ATTR (background_rgba, bg_alpha);
case PANGO2_ATTR_BACKGROUND:
RGBA_ATTR (background_rgba);
break;
case PANGO_ATTR_UNDERLINE:
case PANGO2_ATTR_UNDERLINE:
INT_ATTR (underline);
break;
case PANGO_ATTR_UNDERLINE_COLOR:
RGBA_ATTR (underline_rgba, fg_alpha);
case PANGO2_ATTR_UNDERLINE_COLOR:
RGBA_ATTR (underline_rgba);
break;
case PANGO_ATTR_OVERLINE:
case PANGO2_ATTR_OVERLINE:
INT_ATTR (overline);
break;
case PANGO_ATTR_OVERLINE_COLOR:
RGBA_ATTR (overline_rgba, fg_alpha);
case PANGO2_ATTR_OVERLINE_COLOR:
RGBA_ATTR (overline_rgba);
break;
case PANGO_ATTR_STRIKETHROUGH:
case PANGO2_ATTR_STRIKETHROUGH:
INT_ATTR (strikethrough);
break;
case PANGO_ATTR_STRIKETHROUGH_COLOR:
RGBA_ATTR (strikethrough_rgba, fg_alpha);
case PANGO2_ATTR_STRIKETHROUGH_COLOR:
RGBA_ATTR (strikethrough_rgba);
break;
case PANGO_ATTR_RISE:
case PANGO2_ATTR_RISE:
INT_ATTR (rise);
break;
case PANGO_ATTR_SCALE:
case PANGO2_ATTR_SCALE:
FLOAT_ATTR (scale);
break;
case PANGO_ATTR_FALLBACK:
case PANGO2_ATTR_FALLBACK:
INT_ATTR (fallback);
break;
case PANGO_ATTR_LETTER_SPACING:
case PANGO2_ATTR_LETTER_SPACING:
INT_ATTR (letter_spacing);
break;
case PANGO_ATTR_FONT_FEATURES:
case PANGO2_ATTR_FONT_FEATURES:
STRING_ATTR (font_features);
break;
case PANGO_ATTR_ALLOW_BREAKS:
case PANGO2_ATTR_ALLOW_BREAKS:
INT_ATTR (allow_breaks);
break;
case PANGO_ATTR_SHOW:
case PANGO2_ATTR_SHOW:
INT_ATTR (show_spaces);
break;
case PANGO_ATTR_INSERT_HYPHENS:
case PANGO2_ATTR_INSERT_HYPHENS:
INT_ATTR (insert_hyphens);
break;
case PANGO_ATTR_LINE_HEIGHT:
case PANGO2_ATTR_LINE_HEIGHT:
FLOAT_ATTR (line_height);
break;
case PANGO_ATTR_ABSOLUTE_LINE_HEIGHT:
case PANGO2_ATTR_ABSOLUTE_LINE_HEIGHT:
break;
case PANGO_ATTR_WORD:
case PANGO2_ATTR_LINE_SPACING:
INT_ATTR (pixels_inside_wrap);
break;
case PANGO2_ATTR_WORD:
VOID_ATTR (word);
break;
case PANGO_ATTR_SENTENCE:
case PANGO2_ATTR_SENTENCE:
VOID_ATTR (sentence);
break;
case PANGO_ATTR_BASELINE_SHIFT:
case PANGO2_ATTR_PARAGRAPH:
VOID_ATTR (paragraph);
break;
case PANGO2_ATTR_BASELINE_SHIFT:
INT_ATTR (baseline_shift);
break;
case PANGO_ATTR_FONT_SCALE:
case PANGO2_ATTR_FONT_SCALE:
INT_ATTR (font_scale);
break;
case PANGO_ATTR_SHAPE:
case PANGO_ATTR_ABSOLUTE_SIZE:
case PANGO_ATTR_GRAVITY:
case PANGO_ATTR_GRAVITY_HINT:
case PANGO_ATTR_FOREGROUND_ALPHA:
case PANGO_ATTR_BACKGROUND_ALPHA:
case PANGO2_ATTR_ABSOLUTE_SIZE:
case PANGO2_ATTR_GRAVITY:
case PANGO2_ATTR_GRAVITY_HINT:
break;
case PANGO_ATTR_TEXT_TRANSFORM:
case PANGO2_ATTR_TEXT_TRANSFORM:
INT_ATTR (text_transform);
break;
case PANGO_ATTR_INVALID:
case PANGO2_ATTR_INVALID:
default:
g_assert_not_reached ();
break;
}
}
g_slist_free_full (attrs, (GDestroyNotify)pango_attribute_destroy);
g_slist_free_full (attrs, (GDestroyNotify)pango2_attribute_destroy);
#undef LANGUAGE_ATTR
#undef STRING_ATTR
@@ -329,9 +311,9 @@ typedef struct
GtkTextBuffer *buffer;
GtkTextIter iter;
GtkTextMark *mark;
PangoAttrList *attributes;
Pango2AttrList *attributes;
char *text;
PangoAttrIterator *attr;
Pango2AttrIterator *attr;
} MarkupData;
static void
@@ -340,8 +322,8 @@ free_markup_data (MarkupData *mdata)
g_free (mdata->markup);
g_clear_pointer (&mdata->parser, g_markup_parse_context_free);
gtk_text_buffer_delete_mark (mdata->buffer, mdata->mark);
g_clear_pointer (&mdata->attr, pango_attr_iterator_destroy);
g_clear_pointer (&mdata->attributes, pango_attr_list_unref);
g_clear_pointer (&mdata->attr, pango2_attr_iterator_destroy);
g_clear_pointer (&mdata->attributes, pango2_attr_list_unref);
g_free (mdata->text);
g_object_unref (mdata->buffer);
g_free (mdata);
@@ -367,7 +349,7 @@ insert_markup_idle (gpointer data)
return G_SOURCE_REMOVE;
}
pango_attr_iterator_range (mdata->attr, &start, &end);
pango2_attr_iterator_range (mdata->attr, &start, &end);
if (end == G_MAXINT) /* last chunk */
end = start - 1; /* resulting in -1 to be passed to _insert */
@@ -380,7 +362,7 @@ insert_markup_idle (gpointer data)
gtk_text_buffer_get_iter_at_mark (mdata->buffer, &mdata->iter, mdata->mark);
}
while (pango_attr_iterator_next (mdata->attr));
while (pango2_attr_iterator_next (mdata->attr));
free_markup_data (mdata);
return G_SOURCE_REMOVE;
@@ -416,7 +398,7 @@ parse_markup_idle (gpointer data)
mdata->pos += 4096;
} while (mdata->pos < mdata->len);
if (!pango_markup_parser_finish (mdata->parser,
if (!pango2_markup_parser_finish (mdata->parser,
&mdata->attributes,
&mdata->text,
NULL,
@@ -435,7 +417,7 @@ parse_markup_idle (gpointer data)
return G_SOURCE_REMOVE;
}
mdata->attr = pango_attr_list_get_iterator (mdata->attributes);
mdata->attr = pango2_attr_list_get_iterator (mdata->attributes);
insert_markup_idle (data);
return G_SOURCE_REMOVE;
@@ -461,7 +443,7 @@ insert_markup (GtkTextBuffer *buffer,
data->markup = markup;
data->len = len;
data->parser = pango_markup_parser_new (0);
data->parser = pango2_markup_parser_new (0);
data->pos = 0;
/* create mark with right gravity */

View File

@@ -42,8 +42,8 @@ val_to_xy (GtkFontPlane *plane,
double u, v;
int width, height;
width = gtk_widget_get_width (GTK_WIDGET (plane));
height = gtk_widget_get_height (GTK_WIDGET (plane));
width = gtk_widget_get_allocated_width (GTK_WIDGET (plane));
height = gtk_widget_get_allocated_height (GTK_WIDGET (plane));
u = adjustment_get_normalized_value (plane->width_adj);
v = adjustment_get_normalized_value (plane->weight_adj);
@@ -62,8 +62,8 @@ plane_snapshot (GtkWidget *widget,
cairo_t *cr;
val_to_xy (plane, &x, &y);
width = gtk_widget_get_width (widget);
height = gtk_widget_get_height (widget);
width = gtk_widget_get_allocated_width (widget);
height = gtk_widget_get_allocated_height (widget);
cr = gtk_snapshot_append_cairo (snapshot,
&GRAPHENE_RECT_INIT (0, 0, width, height));
@@ -131,8 +131,8 @@ update_value (GtkFontPlane *plane,
GtkWidget *widget = GTK_WIDGET (plane);
double u, v;
u = CLAMP (x * (1.0 / gtk_widget_get_width (widget)), 0, 1);
v = CLAMP (1 - y * (1.0 / gtk_widget_get_height (widget)), 0, 1);
u = CLAMP (x * (1.0 / gtk_widget_get_allocated_width (widget)), 0, 1);
v = CLAMP (1 - y * (1.0 / gtk_widget_get_allocated_height (widget)), 0, 1);
adjustment_set_normalized_value (plane->width_adj, u);
adjustment_set_normalized_value (plane->weight_adj, v);

View File

@@ -25,7 +25,7 @@ static GtkWidget *show_extents = NULL;
static GtkWidget *show_pixels = NULL;
static GtkWidget *show_outlines = NULL;
static PangoContext *context;
static Pango2Context *context;
static int scale = 7;
static double pixel_alpha = 1.0;
@@ -35,15 +35,15 @@ static void
update_image (void)
{
const char *text;
PangoFontDescription *desc;
PangoLayout *layout;
PangoRectangle ink, logical;
Pango2FontDescription *desc;
Pango2Layout *layout;
Pango2Rectangle ink, logical;
int baseline;
cairo_surface_t *surface;
cairo_t *cr;
GdkPixbuf *pixbuf;
GdkPixbuf *pixbuf2;
GdkTexture *texture;
const char *hint;
cairo_font_options_t *fopt;
cairo_hint_style_t hintstyle;
cairo_hint_metrics_t hintmetrics;
@@ -54,27 +54,22 @@ update_image (void)
context = gtk_widget_create_pango_context (image);
text = gtk_editable_get_text (GTK_EDITABLE (entry));
desc = gtk_font_dialog_button_get_font_desc (GTK_FONT_DIALOG_BUTTON (font_button));
desc = gtk_font_chooser_get_font_desc (GTK_FONT_CHOOSER (font_button));
fopt = cairo_font_options_copy (pango_cairo_context_get_font_options (context));
fopt = cairo_font_options_copy (pango2_cairo_context_get_font_options (context));
switch (gtk_drop_down_get_selected (GTK_DROP_DOWN (hinting)))
hint = gtk_combo_box_get_active_id (GTK_COMBO_BOX (hinting));
hintstyle = CAIRO_HINT_STYLE_DEFAULT;
if (hint)
{
case 0:
hintstyle = CAIRO_HINT_STYLE_NONE;
break;
case 1:
hintstyle = CAIRO_HINT_STYLE_SLIGHT;
break;
case 2:
hintstyle = CAIRO_HINT_STYLE_MEDIUM;
break;
case 3:
hintstyle = CAIRO_HINT_STYLE_FULL;
break;
default:
hintstyle = CAIRO_HINT_STYLE_DEFAULT;
break;
if (strcmp (hint, "none") == 0)
hintstyle = CAIRO_HINT_STYLE_NONE;
else if (strcmp (hint, "slight") == 0)
hintstyle = CAIRO_HINT_STYLE_SLIGHT;
else if (strcmp (hint, "medium") == 0)
hintstyle = CAIRO_HINT_STYLE_MEDIUM;
else if (strcmp (hint, "full") == 0)
hintstyle = CAIRO_HINT_STYLE_FULL;
}
cairo_font_options_set_hint_style (fopt, hintstyle);
@@ -90,20 +85,20 @@ update_image (void)
antialias = CAIRO_ANTIALIAS_NONE;
cairo_font_options_set_antialias (fopt, antialias);
pango_context_set_round_glyph_positions (context, hintmetrics == CAIRO_HINT_METRICS_ON);
pango_cairo_context_set_font_options (context, fopt);
pango2_context_set_round_glyph_positions (context, hintmetrics == CAIRO_HINT_METRICS_ON);
pango2_cairo_context_set_font_options (context, fopt);
cairo_font_options_destroy (fopt);
pango_context_changed (context);
pango2_context_changed (context);
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (text_radio)))
{
layout = pango_layout_new (context);
pango_layout_set_font_description (layout, desc);
pango_layout_set_text (layout, text, -1);
pango_layout_get_extents (layout, &ink, &logical);
baseline = pango_layout_get_baseline (layout);
layout = pango2_layout_new (context);
pango2_layout_set_font_description (layout, desc);
pango2_layout_set_text (layout, text, -1);
pango2_lines_get_extents (pango2_layout_get_lines (layout), &ink, &logical);
baseline = pango2_lines_get_baseline (pango2_layout_get_lines (layout));
pango_extents_to_pixels (&ink, NULL);
pango2_extents_to_pixels (&ink, NULL);
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, ink.width + 20, ink.height + 20);
cr = cairo_create (surface);
@@ -113,25 +108,16 @@ update_image (void)
cairo_set_source_rgba (cr, 0, 0, 0, pixel_alpha);
cairo_move_to (cr, 10, 10);
pango_cairo_show_layout (cr, layout);
pango2_cairo_show_layout (cr, layout);
pango_cairo_layout_path (cr, layout);
pango2_cairo_layout_path (cr, layout);
path = cairo_copy_path (cr);
cairo_destroy (cr);
g_object_unref (layout);
pixbuf = gdk_pixbuf_new_from_data (cairo_image_surface_get_data (surface),
GDK_COLORSPACE_RGB, TRUE, 8,
cairo_image_surface_get_width (surface),
cairo_image_surface_get_height (surface),
cairo_image_surface_get_stride (surface),
NULL, NULL);
pixbuf2 = gdk_pixbuf_scale_simple (pixbuf,
gdk_pixbuf_get_width (pixbuf) * scale,
gdk_pixbuf_get_height (pixbuf) * scale,
GDK_INTERP_NEAREST);
pixbuf = gdk_pixbuf_get_from_surface (surface, 0, 0, cairo_image_surface_get_width (surface), cairo_image_surface_get_height (surface));
pixbuf2 = gdk_pixbuf_scale_simple (pixbuf, gdk_pixbuf_get_width (pixbuf) * scale, gdk_pixbuf_get_height (pixbuf) * scale, GDK_INTERP_NEAREST);
g_object_unref (pixbuf);
cairo_surface_destroy (surface);
@@ -168,15 +154,15 @@ update_image (void)
cairo_set_source_rgb (cr, 0, 0, 1);
cairo_rectangle (cr,
scale * (10 + pango_units_to_double (logical.x)) - 0.5,
scale * (10 + pango_units_to_double (logical.y)) - 0.5,
scale * pango_units_to_double (logical.width) + 1,
scale * pango_units_to_double (logical.height) + 1);
scale * (10 + pango2_units_to_double (logical.x)) - 0.5,
scale * (10 + pango2_units_to_double (logical.y)) - 0.5,
scale * pango2_units_to_double (logical.width) + 1,
scale * pango2_units_to_double (logical.height) + 1);
cairo_stroke (cr);
cairo_move_to (cr, scale * (10 + pango_units_to_double (logical.x)) - 0.5,
scale * (10 + pango_units_to_double (baseline)) - 0.5);
cairo_line_to (cr, scale * (10 + pango_units_to_double (logical.x + logical.width)) + 1,
scale * (10 + pango_units_to_double (baseline)) - 0.5);
cairo_move_to (cr, scale * (10 + pango2_units_to_double (logical.x)) - 0.5,
scale * (10 + pango2_units_to_double (baseline)) - 0.5);
cairo_line_to (cr, scale * (10 + pango2_units_to_double (logical.x + logical.width)) + 1,
scale * (10 + pango2_units_to_double (baseline)) - 0.5);
cairo_stroke (cr);
cairo_set_source_rgb (cr, 1, 0, 0);
cairo_rectangle (cr,
@@ -220,9 +206,10 @@ update_image (void)
}
else
{
PangoLayoutIter *iter;
PangoLayoutRun *run;
PangoGlyphInfo *g;
Pango2LineIter *iter;
Pango2Run *run;
Pango2GlyphString *glyphs;
Pango2GlyphInfo *g;
int i, j;
GString *str;
gunichar ch;
@@ -231,82 +218,66 @@ update_image (void)
text = " ";
ch = g_utf8_get_char (text);
str = g_string_new ("");
layout = pango_layout_new (context);
retry:
str = g_string_new ("");
for (i = 0; i < 4; i++)
{
g_string_append_unichar (str, ch);
g_string_append_unichar (str, 0x200c);
}
pango_layout_set_font_description (layout, desc);
pango_layout_set_text (layout, str->str, -1);
pango_layout_get_extents (layout, &ink, &logical);
pango_extents_to_pixels (&logical, NULL);
iter = pango_layout_get_iter (layout);
run = pango_layout_iter_get_run (iter);
if (run->glyphs->num_glyphs < 8)
{
/* not a good char to use */
g_string_truncate (str, 0);
ch = 'a';
goto retry;
}
layout = pango2_layout_new (context);
pango2_layout_set_font_description (layout, desc);
pango2_layout_set_text (layout, str->str, -1);
g_string_free (str, TRUE);
pango2_lines_get_extents (pango2_layout_get_lines (layout), &ink, &logical);
pango2_extents_to_pixels (&logical, NULL);
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, logical.width * 3 / 2, 4*logical.height);
cr = cairo_create (surface);
cairo_set_source_rgb (cr, 1, 1, 1);
cairo_paint (cr);
iter = pango2_layout_get_iter (layout);
run = pango2_line_iter_get_run (iter);
glyphs = pango2_run_get_glyphs (run);
cairo_set_source_rgb (cr, 0, 0, 0);
for (i = 0; i < 4; i++)
{
g = &(run->glyphs->glyphs[2*i]);
g->geometry.width = PANGO_UNITS_ROUND (g->geometry.width * 3 / 2);
g = &(glyphs->glyphs[2*i]);
g->geometry.width = PANGO2_UNITS_ROUND (g->geometry.width * 3 / 2);
}
for (j = 0; j < 4; j++)
{
for (i = 0; i < 4; i++)
{
g = &(run->glyphs->glyphs[2*i]);
g->geometry.x_offset = i * (PANGO_SCALE / 4);
g->geometry.y_offset = j * (PANGO_SCALE / 4);
g = &(glyphs->glyphs[2*i]);
g->geometry.x_offset = i * (PANGO2_SCALE / 4);
g->geometry.y_offset = j * (PANGO2_SCALE / 4);
}
cairo_move_to (cr, 0, j * logical.height);
pango_cairo_show_layout (cr, layout);
pango2_cairo_show_layout (cr, layout);
}
cairo_destroy (cr);
pango_layout_iter_free (iter);
pango2_line_iter_free (iter);
g_object_unref (layout);
pixbuf = gdk_pixbuf_new_from_data (cairo_image_surface_get_data (surface),
GDK_COLORSPACE_RGB, TRUE, 8,
cairo_image_surface_get_width (surface),
cairo_image_surface_get_height (surface),
cairo_image_surface_get_stride (surface),
NULL, NULL);
pixbuf2 = gdk_pixbuf_scale_simple (pixbuf,
gdk_pixbuf_get_width (pixbuf) * scale,
gdk_pixbuf_get_height (pixbuf) * scale,
GDK_INTERP_NEAREST);
pixbuf = gdk_pixbuf_get_from_surface (surface, 0, 0, cairo_image_surface_get_width (surface), cairo_image_surface_get_height (surface));
pixbuf2 = gdk_pixbuf_scale_simple (pixbuf, gdk_pixbuf_get_width (pixbuf) * scale, gdk_pixbuf_get_height (pixbuf) * scale, GDK_INTERP_NEAREST);
g_object_unref (pixbuf);
cairo_surface_destroy (surface);
}
texture = gdk_texture_new_for_pixbuf (pixbuf2);
gtk_picture_set_paintable (GTK_PICTURE (image), GDK_PAINTABLE (texture));
g_object_unref (pixbuf2);
gtk_picture_set_pixbuf (GTK_PICTURE (image), pixbuf2);
g_object_unref (pixbuf2);
pango2_font_description_free (desc);
}
static gboolean fading = FALSE;
@@ -440,7 +411,7 @@ do_fontrendering (GtkWidget *do_widget)
g_signal_connect (down_button, "clicked", G_CALLBACK (scale_down), NULL);
g_signal_connect (entry, "notify::text", G_CALLBACK (update_image), NULL);
g_signal_connect (font_button, "notify::font-desc", G_CALLBACK (update_image), NULL);
g_signal_connect (hinting, "notify::selected", G_CALLBACK (update_image), NULL);
g_signal_connect (hinting, "notify::active", G_CALLBACK (update_image), NULL);
g_signal_connect (anti_alias, "notify::active", G_CALLBACK (update_image), NULL);
g_signal_connect (hint_metrics, "notify::active", G_CALLBACK (update_image), NULL);
g_signal_connect (text_radio, "notify::active", G_CALLBACK (update_image), NULL);
@@ -455,7 +426,7 @@ do_fontrendering (GtkWidget *do_widget)
}
if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE);
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));

Some files were not shown because too many files have changed in this diff Show More