Compare commits

..

1 Commits

Author SHA1 Message Date
Matthias Clasen
4ab0e7956e css: Reshuffle the inner loop of value computation
The loop over all properties in gtk_css_static_style_compute_values
is the inner loop of the css value computation, we hit it thousands
of times per frame. Rearrange things to make this faster, by avoiding
function calls, pulling the section handling out of the separate loop,
and handling the border-width special case in a neater way.

Before: 50 runs, min 12.45, max 20.419, avg 15.9414
After:  50 runs, min 12.622, max 21.195, avg 15.0449
2020-01-25 01:20:17 -05:00
4944 changed files with 1512621 additions and 691273 deletions

View File

@@ -1,11 +0,0 @@
# See https://wiki.apertis.org/Guidelines/Coding_conventions#Code_formatting
BasedOnStyle: GNU
AlwaysBreakAfterDefinitionReturnType: All
BreakBeforeBinaryOperators: None
BinPackParameters: false
SpaceAfterCStyleCast: true
# 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
# existing hanging indents.
ColumnLimit: 0

View File

@@ -1,32 +0,0 @@
# SPDX-FileCopyrightText: 2021 The GTK Authors
# SPDX-License-Identifier: CC0-1.0
root = true
[*]
charset = utf-8
end_of_line = lf
trim_trailing_whitespace = true
[*.[ch]]
indent_size = 2
indent_style = space
insert_final_newline = true
# For the legacy tabs which still exist in the code:
tab_width = 8
[*.ui]
indent_size = 2
indent_style = space
insert_final_newline = true
[*.xml]
indent_size = 2
indent_style = space
[meson.build]
indent_size = 2
indent_style = space
[*.md]
max_line_length = 80

View File

@@ -1,14 +1,7 @@
include:
- project: 'gnome/citemplates'
file: 'flatpak/flatpak_ci_initiative.yml'
stages:
- build
- analysis
- docs
- flatpak
- publish
- deploy
# - deploy
.cache-paths: &cache-paths
paths:
@@ -19,338 +12,114 @@ stages:
- subprojects/libepoxy/
- subprojects/pango/
# Common variables
variables:
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"
MESON_TEST_TIMEOUT_MULTIPLIER: 3
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v38"
FLATPAK_IMAGE: "registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:master"
.only-default:
only:
- branches
except:
- tags
style-check-diff:
extends: .only-default
image: $FEDORA_IMAGE
stage: .pre
allow_failure: true
fedora-x86_64: &fedora-x86_64-defaults
image: registry.gitlab.gnome.org/gnome/gtk/master:v9
stage: build
script:
- .gitlab-ci/run-style-check-diff.sh
.build-fedora-default:
extends: .only-default
image: $FEDORA_IMAGE
- bash -x ./.gitlab-ci/test-docker.sh
artifacts:
when: always
reports:
junit:
- "${CI_PROJECT_DIR}/_build/report-x11.xml"
- "${CI_PROJECT_DIR}/_build/report-wayland.xml"
- "${CI_PROJECT_DIR}/_build/report-broadway.xml"
- "${CI_PROJECT_DIR}/_build/report.xml"
name: "gtk-${CI_COMMIT_REF_NAME}"
paths:
- "${CI_PROJECT_DIR}/_build/meson-logs"
- "${CI_PROJECT_DIR}/_build/report*.xml"
- "${CI_PROJECT_DIR}/_build/report*.html"
- "${CI_PROJECT_DIR}/_build/testsuite/reftests/output/*/*.png"
- "${CI_PROJECT_DIR}/_build/testsuite/reftests/output/*/*.node"
- "${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_hello/meson-logs"
- "${CI_PROJECT_DIR}/_build/report.xml"
- "${CI_PROJECT_DIR}/_build/report.html"
- "${CI_PROJECT_DIR}/_build/testsuite/reftests/output/*.png"
- "${CI_PROJECT_DIR}/_build/testsuite/gsk/compare/*/*.png"
- "${CI_PROJECT_DIR}/_build/testsuite/css/output/*.syscap"
cache:
key: "$CI_JOB_NAME"
paths:
- _ccache/
- subprojects/gdk-pixbuf/
- subprojects/glib/
- subprojects/graphene/
- subprojects/libepoxy/
- subprojects/pango/
<<: *cache-paths
fedora-x86_64:
extends: .build-fedora-default
stage: build
needs: []
fedora-x86_64-staticlibs:
variables:
EXTRA_MESON_FLAGS: "--buildtype=debug --default-library=both"
script:
- .gitlab-ci/show-info-linux.sh
- 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 waylandgles
- .gitlab-ci/run-tests.sh _build broadway
EXTRA_MESON_FLAGS: "-Ddefault_library=both"
<<: *fedora-x86_64-defaults
release-build:
extends: .build-fedora-default
stage: build
needs: []
variables:
EXTRA_MESON_FLAGS: "--buildtype=release"
script:
- .gitlab-ci/show-info-linux.sh
- meson subprojects update
- meson ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS} ${BACKEND_FLAGS} ${FEATURE_FLAGS}
_build
- ninja -C _build
- .gitlab-ci/run-tests.sh _build x11
installed-tests:
extends: .build-fedora-default
stage: build
needs: []
variables:
EXTRA_MESON_FLAGS: "--prefix=/usr --libdir=/usr/lib64 -Dinstall-tests=true"
G_TEST_ACCESSIBLE: 1
script:
- .gitlab-ci/show-info-linux.sh
- meson subprojects update
- meson ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS} ${BACKEND_FLAGS} ${FEATURE_FLAGS}
_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/"
.mingw-defaults:
extends: .only-default
.mingw-defaults: &mingw-defaults
stage: build
tags:
- win32-ps
- win32
script:
- C:\msys64\usr\bin\pacman --noconfirm -Syyuu
- C:\msys64\usr\bin\bash -lc "bash -x ./.gitlab-ci/test-msys2.sh"
cache:
key: "$CI_JOB_NAME"
paths:
- _ccache/
- subprojects/gdk-pixbuf/
- subprojects/glib/
- subprojects/graphene/
- subprojects/libepoxy/
- subprojects/pango/
key: "%CI_JOB_NAME%"
<<: *cache-paths
msys2-mingw64:
extends: .mingw-defaults
needs: []
msys2-mingw32:
variables:
MSYSTEM: "MINGW64"
MSYSTEM: "MINGW32"
CHERE_INVOKING: "yes"
artifacts:
when: always
expose_as: 'Windows_DLL_MSYS2_64_bit_toolchain'
paths:
- "${CI_PROJECT_DIR}/_build/gtkdll.tar.gz"
<<: *mingw-defaults
macos:
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==0.60.3
- pip3 install --user ninja
- export PATH=/Users/gitlabrunner/Library/Python/3.7/bin:$PATH
- export MESON_FORCE_BACKTRACE=1
script:
- meson -Dx11-backend=false
-Dbroadway-backend=true
-Dmacos-backend=true
-Dmedia-gstreamer=disabled
-Dintrospection=disabled
-Dcpp_std=c++11
-Dpixman:tests=disabled
_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.
#only:
# - branches@GNOME/gtk
stage: build
tags:
- win32-ps
needs: []
script:
- .gitlab-ci/test-msvc.bat
artifacts:
when: always
paths:
- "${CI_PROJECT_DIR}/_build/meson-logs"
.flatpak-defaults:
image: $FLATPAK_IMAGE
.flatpak-defaults: &flatpak-defaults
image: registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:master
stage: flatpak
allow_failure: true
tags:
- flatpak
artifacts:
paths:
- "${APPID}-dev.flatpak"
- 'repo.tar'
expire_in: 1 day
script:
- bash -x ./.gitlab-ci/flatpak-build.sh "${APPID}"
# Manual jobs, for branches and MRs
.flatpak-manual:
extends: .flatpak-defaults
.flatpak-manual: &flatpak-manual
<<: *flatpak-defaults
when: manual
# Only build Flatpak bundles automatically on main
.flatpak-main:
extends: .flatpak-defaults
# Only build Flatpak bundles automatically on master
.flatpak-master: &flatpak-master
<<: *flatpak-defaults
only:
- main
- master
flatpak-manual:demo:
extends: .flatpak-manual
needs: []
variables:
APPID: org.gtk.Demo4
<<: *flatpak-manual
flatpak-main:demo:
extends: .flatpak-main
needs: []
flatpak-master:demo:
variables:
APPID: org.gtk.Demo4
<<: *flatpak-master
flatpak-manual:widget-factory:
extends: .flatpak-manual
needs: []
variables:
APPID: org.gtk.WidgetFactory4
<<: *flatpak-manual
flatpak-main:widget-factory:
extends: .flatpak-main
needs: []
flatpak-master:widget-factory:
variables:
APPID: org.gtk.WidgetFactory4
<<: *flatpak-master
flatpak-manual:icon-browser:
extends: .flatpak-manual
needs: []
variables:
APPID: org.gtk.IconBrowser4
<<: *flatpak-manual
flatpak-main:icon-browser:
extends: .flatpak-main
needs: []
flatpak-master:icon-browser:
variables:
APPID: org.gtk.IconBrowser4
<<: *flatpak-master
# 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'
dependencies: ['flatpak-main:demo']
needs: ['flatpak-main:demo']
nightly factory:
extends: '.publish_nightly'
dependencies: ['flatpak-main:widget-factory']
needs: ['flatpak-main:widget-factory']
nightly icon-browser:
extends: '.publish_nightly'
dependencies: ['flatpak-main:icon-browser']
needs: ['flatpak-main:icon-browser']
static-scan:
image: $FEDORA_IMAGE
stage: analysis
needs: []
variables:
EXTRA_MESON_FLAGS: "--buildtype=debug"
script:
- 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,
# since it is incompatible with asan
asan-build:
image: $FEDORA_IMAGE
tags: [ asan ]
stage: analysis
needs: []
variables:
script:
- 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:
paths:
- _build/meson-logs
allow_failure: true
reference:
image: $FEDORA_IMAGE
stage: docs
needs: []
variables:
EXTRA_MESON_FLAGS: "--buildtype=release --force-fallback-for=gdk-pixbuf,pango"
script:
- 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/
- mv _build/docs/reference/gdk/gdk4-x11/ _reference/gdk4-x11/
- mv _build/docs/reference/gdk/gdk4-wayland/ _reference/gdk4-wayland/
- mv _build/docs/reference/gsk/gsk4/ _reference/gsk4/
- mv _build/docs/reference/gtk/gtk4/ _reference/gtk4/
- mv _build/subprojects/pango/docs/Pango/ _reference/Pango/
- mv _build/subprojects/pango/docs/PangoCairo/ _reference/PangoCairo/
- mv _build/subprojects/pango/docs/PangoFc/ _reference/PangoFc/
- mv _build/subprojects/pango/docs/PangoFT2/ _reference/PangoFT2/
- mv _build/subprojects/pango/docs/PangoOT/ _reference/PangoOT/
- mv _build/subprojects/pango/docs/PangoXft/ _reference/PangoXft/
- mv _build/subprojects/gdk-pixbuf/docs/gdk-pixbuf/ _reference/gdk-pixbuf/
- mv _build/subprojects/gdk-pixbuf/docs/gdk-pixdata/ _reference/gdk-pixdata/
artifacts:
paths:
- _reference
publish-docs:
image: fedora:latest
stage: publish
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"
only:
refs:
- main
#pages:
# image: registry.gitlab.gnome.org/gnome/gtk/master:v6
# stage: deploy
# script:
# - meson -Dgtk_doc=true _build .
# - ninja -C _build
# - ninja -C _build gdk4-doc gsk4-doc gtk4-doc
# - mkdir -p public/
# - mv _build/docs/reference/gtk/html/ public/gtk/
# - mv _build/docs/reference/gdk/html/ public/gdk/
# - mv _build/docs/reference/gsk/html/ public/gsk/
# artifacts:
# paths:
# - public
# only:
# - master

88
.gitlab-ci/Dockerfile Normal file
View File

@@ -0,0 +1,88 @@
FROM fedora:31
RUN dnf -y install \
adwaita-icon-theme \
atk-devel \
at-spi2-atk-devel \
avahi-gobject-devel \
cairo-devel \
cairo-gobject-devel \
ccache \
colord-devel \
cups-devel \
dbus-daemon \
dejavu-sans-mono-fonts \
desktop-file-utils \
diffutils \
elfutils-libelf-devel \
fribidi-devel \
gcc \
gcc-c++ \
gdk-pixbuf2-devel \
gdk-pixbuf2-modules \
gettext \
git \
glib2-devel \
glibc-devel \
glibc-headers \
gobject-introspection-devel \
graphene-devel \
gstreamer1-devel \
gstreamer1-plugins-good \
gstreamer1-plugins-bad-free-devel \
gstreamer1-plugins-base-devel \
gtk-doc \
hicolor-icon-theme \
iso-codes \
itstool \
json-glib-devel \
lcov \
libattr-devel \
libepoxy-devel \
libffi-devel \
libmount-devel \
librsvg2 \
libselinux-devel \
libXcomposite-devel \
libXcursor-devel \
libXcursor-devel \
libXdamage-devel \
libXfixes-devel \
libXi-devel \
libXinerama-devel \
libxkbcommon-devel \
libXrandr-devel \
libXrender-devel \
libXtst-devel \
libxslt \
mesa-dri-drivers \
mesa-libEGL-devel \
mesa-libwayland-egl-devel \
ninja-build \
pango-devel \
pcre-devel \
python3 \
python3-jinja2 \
python3-pip \
python3-wheel \
redhat-rpm-config \
sassc \
sysprof-devel \
systemtap-sdt-devel \
vulkan-devel \
wayland-devel \
wayland-protocols-devel \
which \
xorg-x11-server-Xvfb \
&& dnf clean all
RUN pip3 install meson==0.50.1
ARG HOST_USER_ID=5555
ENV HOST_USER_ID ${HOST_USER_ID}
RUN useradd -u $HOST_USER_ID -ms /bin/bash user
USER user
WORKDIR /home/user
ENV LANG C.UTF-8

View File

@@ -1,50 +0,0 @@
## GTK CI infrastructure
GTK uses different CI images depending on platform and jobs.
The CI images are Docker containers, generated either using `docker` or
`podman`, and pushed to the GitLab [container registry][registry].
Each Docker image has a tag composed of two parts:
- `${image}`: the base image for a given platform, like "fedora" or
"debian-stable"
- `${number}`: an incremental version number, or `latest`
See the [container registry][registry] for the available images for each
branch, as well as their available versions.
Note that using `latest` as version number will overwrite the most
recently uploaded image in the registry.
### Checklist for Updating a CI image
- [ ] Update the `${image}.Dockerfile` file with the dependencies
- [ ] Run `./run-docker.sh build --base ${image} --version ${number}`
- [ ] Run `./run-docker.sh push --base ${image} --version ${number}`
once the Docker image is built; you may need to log in by using
`docker login` or `podman login`
- [ ] Update the `image` keys in the `.gitlab-ci.yml` file with the new
image tag
- [ ] Open a merge request with your changes and let it run
### Checklist for Adding a new CI image
- [ ] Write a new `${image}.Dockerfile` with the instructions to set up
a build environment
- [ ] Add the `pip3 install meson` incantation
- [ ] Run `./run-docker.sh build --base ${image} --version ${number}`
- [ ] Run `./run-docker.sh push --base ${image} --version ${number}`
- [ ] Add the new job to `.gitlab-ci.yml` referencing the image
- [ ] Open a merge request with your changes and let it run
### Checklist for Adding a new dependency to a CI image
Our images are layered, and the base (called fedora-base) contains
all the rpm payload. Therefore, adding a new dependency is a 2-step
process:
1. [ ] Build and upload fedora-base:$version+1
1. [ ] Build and upload fedora:$version+1 based on fedora-base:version+1
[registry]: https://gitlab.gnome.org/GNOME/gtk/container_registry

View File

@@ -1,133 +0,0 @@
#!/usr/bin/env python3
#
# === clang-format-diff.py - ClangFormat Diff Reformatter ---*- python -*-=== #
#
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
# ===---------------------------------------------------------------------=== #
"""
This script reads input from a unified diff and reformats all the changed
lines. This is useful to reformat all the lines touched by a specific patch.
Example usage for git/svn users:
git diff -U0 --no-color HEAD^ | clang-format-diff.py -p1 -i
svn diff --diff-cmd=diff -x-U0 | clang-format-diff.py -i
"""
from __future__ import absolute_import, division, print_function
import argparse
import difflib
import re
import subprocess
import sys
if sys.version_info.major >= 3:
from io import StringIO
else:
from io import BytesIO as StringIO
def main():
parser = argparse.ArgumentParser(
description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('-i', action='store_true', default=False,
help='apply edits to files instead of displaying a '
'diff')
parser.add_argument('-p', metavar='NUM', default=0,
help='strip the smallest prefix containing P slashes')
parser.add_argument('-regex', metavar='PATTERN', default=None,
help='custom pattern selecting file paths to reformat '
'(case sensitive, overrides -iregex)')
parser.add_argument('-iregex', metavar='PATTERN',
default=r'.*\.(cpp|cc|c\+\+|cxx|c|cl|h|hh|hpp|m|mm|inc'
r'|js|ts|proto|protodevel|java|cs)',
help='custom pattern selecting file paths to reformat '
'(case insensitive, overridden by -regex)')
parser.add_argument('-sort-includes', action='store_true', default=False,
help='let clang-format sort include blocks')
parser.add_argument('-v', '--verbose', action='store_true',
help='be more verbose, ineffective without -i')
parser.add_argument('-style',
help='formatting style to apply (LLVM, Google, '
'Chromium, Mozilla, WebKit)')
parser.add_argument('-binary', default='clang-format',
help='location of binary to use for clang-format')
args = parser.parse_args()
# Extract changed lines for each file.
filename = None
lines_by_file = {}
for line in sys.stdin:
match = re.search(r'^\+\+\+\ (.*?/){%s}(\S*)' % args.p, line)
if match:
filename = match.group(2)
if filename is None:
continue
if args.regex is not None:
if not re.match('^%s$' % args.regex, filename):
continue
else:
if not re.match('^%s$' % args.iregex, filename, re.IGNORECASE):
continue
match = re.search(r'^@@.*\+(\d+)(,(\d+))?', line)
if match:
start_line = int(match.group(1))
line_count = 1
if match.group(3):
line_count = int(match.group(3))
if line_count == 0:
continue
end_line = start_line + line_count - 1
lines_by_file.setdefault(filename, []).extend(
['-lines', str(start_line) + ':' + str(end_line)])
# Reformat files containing changes in place.
# We need to count amount of bytes generated in the output of
# clang-format-diff. If clang-format-diff doesn't generate any bytes it
# means there is nothing to format.
format_line_counter = 0
for filename, lines in lines_by_file.items():
if args.i and args.verbose:
print('Formatting {}'.format(filename))
command = [args.binary, filename]
if args.i:
command.append('-i')
if args.sort_includes:
command.append('-sort-includes')
command.extend(lines)
if args.style:
command.extend(['-style', args.style])
p = subprocess.Popen(command,
stdout=subprocess.PIPE,
stderr=None,
stdin=subprocess.PIPE,
universal_newlines=True)
stdout, _ = p.communicate()
if p.returncode != 0:
sys.exit(p.returncode)
if not args.i:
with open(filename) as f:
code = f.readlines()
formatted_code = StringIO(stdout).readlines()
diff = difflib.unified_diff(code, formatted_code,
filename, filename,
'(before formatting)',
'(after formatting)')
diff_string = ''.join(diff)
if diff_string:
format_line_counter += sys.stdout.write(diff_string)
if format_line_counter > 0:
sys.exit(1)
if __name__ == '__main__':
main()

View File

@@ -1,111 +0,0 @@
FROM fedora:36
RUN dnf -y install \
adwaita-icon-theme \
atk-devel \
at-spi2-atk-devel \
avahi-gobject-devel \
cairo-devel \
cairo-gobject-devel \
ccache \
clang \
clang-analyzer \
clang-tools-extra \
colord-devel \
cups-devel \
dbus-daemon \
dbus-x11 \
dejavu-sans-mono-fonts \
desktop-file-utils \
diffutils \
elfutils-libelf-devel \
fribidi-devel \
gcc \
gcc-c++ \
gdk-pixbuf2-devel \
gdk-pixbuf2-modules \
gettext \
git \
glib2-devel \
glib2-static \
glibc-devel \
glibc-headers \
gnome-desktop-testing \
gobject-introspection-devel \
graphene-devel \
graphviz \
gstreamer1-devel \
gstreamer1-plugins-good \
gstreamer1-plugins-bad-free-devel \
gstreamer1-plugins-base-devel \
hicolor-icon-theme \
iso-codes \
itstool \
json-glib-devel \
lcov \
libasan \
libattr-devel \
libcloudproviders-devel \
libepoxy-devel \
libffi-devel \
libjpeg-turbo-devel \
libmount-devel \
libpng-devel \
librsvg2 \
libselinux-devel \
libtiff-devel \
libubsan \
libXcomposite-devel \
libXcursor-devel \
libXcursor-devel \
libXdamage-devel \
libXfixes-devel \
libXi-devel \
libXinerama-devel \
libxkbcommon-devel \
libXrandr-devel \
libXrender-devel \
libXtst-devel \
libxslt \
mesa-dri-drivers \
mesa-libEGL-devel \
mesa-libGLES-devel \
meson \
ninja-build \
pango-devel \
pcre-devel \
pcre-static \
python3 \
python3-docutils \
python3-gobject \
python3-jinja2 \
python3-markdown \
python3-pip \
python3-pygments \
python3-toml \
python3-typogrify \
python3-wheel \
redhat-rpm-config \
sassc \
vulkan-devel \
wayland-devel \
wayland-protocols-devel \
weston \
weston-libs \
which \
xorg-x11-server-Xvfb \
&& dnf install -y 'dnf-command(builddep)' \
&& dnf builddep -y wayland \
&& dnf clean all
# Enable sudo for wheel users
RUN sed -i -e 's/# %wheel/%wheel/' -e '0,/%wheel/{s/%wheel/# %wheel/}' /etc/sudoers
ARG HOST_USER_ID=5555
ENV HOST_USER_ID ${HOST_USER_ID}
RUN useradd -u $HOST_USER_ID -G wheel -ms /bin/bash user
USER user
WORKDIR /home/user
ENV LANG C.UTF-8

View File

@@ -4,33 +4,34 @@ set -e
appid=$1
builddir=flatpak_app
builddir=app
repodir=repo
flatpak-builder \
--user --disable-rofiles-fuse \
--stop-at=gtk \
${builddir} \
build-aux/flatpak/${appid}.json
flatpak build ${builddir} meson \
--prefix=/app \
--libdir=/app/lib \
--buildtype=release \
flatpak-builder \
--run ${builddir} build-aux/flatpak/${appid}.json \
meson \
--prefix /app \
--libdir /app/lib \
--buildtype debug \
-Dx11-backend=true \
-Dwayland-backend=true \
-Dprint-backends=file \
-Dbuild-tests=false \
-Dbuild-examples=false \
-Dintrospection=disabled \
-Dintrospection=false \
-Ddemos=true \
-Dprofile=devel \
_flatpak_build
flatpak build ${builddir} ninja -C _flatpak_build install
_build .
flatpak-builder \
--run ${builddir} build-aux/flatpak/${appid}.json \
ninja -C _build install
flatpak-builder \
--user --disable-rofiles-fuse \
--finish-only \
--repo=${repodir} \
${builddir} \
@@ -39,10 +40,5 @@ flatpak-builder \
flatpak build-bundle \
${repodir} \
${appid}-dev.flatpak \
--runtime-repo=https://nightly.gnome.org/gnome-nightly.flatpakrepo \
--runtime-repo=https://flathub.org/repo/flathub.flatpakrepo \
${appid}
# to be consumed by the nightly publish jobs
if [[ $CI_COMMIT_BRANCH == main ]]; then
tar cf repo.tar ${repodir}
fi

View File

@@ -138,26 +138,22 @@ ul.images li {
</head>
<body>
<header>
<h1>{{ report.project_name }}/{{ report.backend }}/{{ report.branch_name }} :: Test Reports</h1>
<h1>{{ report.project_name }} :: Test Reports</h1>
<div class="report-meta">
<p><strong>Branch:</strong> {{ report.branch_name }}</p>
<p><strong>Date:</strong> <time datetime="{{ report.date.isoformat() }}">{{ report.locale_date }}</time></p>
{% if report.job_id %}<p><strong>Job ID:</strong> {{ report.job_id }}</p>{% endif %}
</div>
</header>
<article>
<section>
<div class="report-meta">
<p><strong>Backend:</strong> {{ report.backend }}</p>
<p><strong>Branch:</strong> {{ report.branch_name }}</p>
<p><strong>Date:</strong> <time datetime="{{ report.date.isoformat() }}">{{ report.locale_date }}</time></p>
{% if report.job_id %}<p><strong>Job ID:</strong> {{ report.job_id }}</p>{% endif %}
</div>
</section>
<section>
<div class="summary">
<h3><a name="summary">Summary</a></h3>
<ul>
<li><strong>Total units:</strong> {{ report.total_units }}</li>
<li><strong>Failed:</strong> {{ report.total_failures }}</li>
<li><strong>Passed:</strong> {{ report.total_successes }}</li>
<li><strong>Passed:</strong> <a href="#passed">{{ report.total_successes }}</a></li>
<li><strong>Failed:</strong> <a href="#failures">{{ report.total_failures }}</a></li>
</ul>
</div>
</section>
@@ -168,49 +164,30 @@ ul.images li {
<h3><a name="results">Suite: {{ suite_result.suite_name }}</a></h3>
<ul>
<li><strong>Units:</strong> {{ suite_result.n_units }}</li>
<li><strong>Failed:</strong> <a href="#{{ suite_result.suite_name }}-failed">{{ suite_result.n_failures }}</a></li>
<li><strong>Passed:</strong> <a href="#{{ suite_result.suite_name }}-passed">{{ suite_result.n_successes }}</a></li>
<li><strong>Passed:</strong> {{ suite_result.n_successes }}</li>
<li><strong>Failed:</strong> {{ suite_result.n_failures }}</li>
</ul>
<div class="failures">
<h4><a name="{{ suite_result.suite_name }}-failed">Failures</a></h4>
<ul class="failed">
{% for failure in suite_result.failures if failure.result in [ 'ERROR', 'FAIL', 'UNEXPECTEDPASS' ] %}
<li><a name="{{ failure.name }}">{{ failure.name }}</a> - result: <span class="result fail">{{ failure.result }}</span><br/>
{% if failure.stdout %}
Output: <pre>{{ failure.stdout }}</pre>
{% endif %}
{% if failure.image_data is defined %}
<ul class="images">
<li><img alt="ref" src="{{ failure.image_data.ref }}" /></li>
<li><img alt="out" src="{{ failure.image_data.out }}" /></li>
<li><img alt="diff" src="{{ failure.image_data.diff }}" /></li>
<li><a href="{{ failure.image_data.refnode }}">ref node</a></li>
<li><a href="{{ failure.image_data.outnode }}">out node</a></li>
</ul>
{% endif %}
</li>
{% else %}
<li>None</li>
{% endfor %}
</ul>
<h4><a name="{{ suite_result.suite_name }}-timed-out">Timed out</a></h4>
<ul class="failed">
{% for failure in suite_result.failures if failure.result == 'TIMEOUT' %}
<li><a name="{{ failure.name }}">{{ failure.name }}</a> - result: <span class="result fail">{{ failure.result }}</span><br/>
{% if failure.stdout %}
Output: <pre>{{ failure.stdout }}</pre>
{% endif %}
</li>
{% else %}
<li>None</li>
{% endfor %}
</ul>
</div>
<div class="successes">
<h4><a name="{{ suite_result.suite_name }}-expected-fail">Expected failures</a></h4>
<h4><a name="passed">Passed</a></h4>
<ul class="passed">
{% for success in suite_result.successes if success.result == 'OK' %}
<li>{{ success.name }} - result: <span class="result pass">{{ success.result }}</li>
{% else %}
<li>None</li>
{% endfor %}
</ul>
<h4><a name="skipped">Skipped</a></h4>
<ul>
{% for success in suite_result.successes if success.result == 'SKIP' %}
<li>{{ success.name }} - result: <span class="result skip">{{ success.result }}</li>
{% else %}
<li>None</li>
{% endfor %}
</ul>
<h4><a name="expected-fail">Expected failures</a></h4>
<ul>
{% for success in suite_result.successes if success.result == 'EXPECTEDFAIL' %}
<li><a name="{{ success.name }}">{{ success.name }}</a> - result: <span class="result xfail">{{ success.result }}</span><br/>
@@ -229,20 +206,37 @@ ul.images li {
<li>None</li>
{% endfor %}
</ul>
</div>
<h4><a name="{{ suite_result.suite_name }}-skipped">Skipped</a></h4>
<ul>
{% for success in suite_result.successes if success.result == 'SKIP' %}
<li>{{ success.name }} - result: <span class="result skip">{{ success.result }}</li>
<div class="failures">
<h4><a name="failed">Failed</a></h4>
<ul class="failed">
{% for failure in suite_result.failures if failure.result == 'FAIL' %}
<li><a name="{{ failure.name }}">{{ failure.name }}</a> - result: <span class="result fail">{{ failure.result }}</span><br/>
{% if failure.stdout %}
Output: <pre>{{ failure.stdout }}</pre>
{% endif %}
{% if failure.image_data is defined %}
<ul class="images">
<li><img alt="ref" src="{{ failure.image_data.ref }}" /></li>
<li><img alt="out" src="{{ failure.image_data.out }}" /></li>
<li><img alt="diff" src="{{ failure.image_data.diff }}" /></li>
</ul>
{% endif %}
</li>
{% else %}
<li>None</li>
{% endfor %}
</ul>
<h4><a name="{{ suite_result.suite_name }}-passed">Passed</a></h4>
<ul class="passed">
{% for success in suite_result.successes if success.result == 'OK' %}
<li>{{ success.name }} - result: <span class="result pass">{{ success.result }}</li>
<h4><a name="timed-out">Timed out</a></h4>
<ul class="failed">
{% for failure in suite_result.failures if failure.result == 'TIMEOUT' %}
<li><a name="{{ failure.name }}">{{ failure.name }}</a> - result: <span class="result fail">{{ failure.result }}</span><br/>
{% if failure.stdout %}
Output: <pre>{{ failure.stdout }}</pre>
{% endif %}
</li>
{% else %}
<li>None</li>
{% endfor %}
@@ -262,15 +256,12 @@ aparser = argparse.ArgumentParser(description='Turns a Meson test log into an HT
aparser.add_argument('--project-name', metavar='NAME',
help='The project name',
default='Unknown')
aparser.add_argument('--backend', metavar='NAME',
help='The used backend',
default='unknown')
aparser.add_argument('--job-id', metavar='ID',
help='The job ID for the report',
default=None)
aparser.add_argument('--branch', metavar='NAME',
help='Branch of the project being tested',
default='main')
default='master')
aparser.add_argument('--output', metavar='FILE',
help='The output HTML file, stdout by default',
type=argparse.FileType('w', encoding='UTF-8'),
@@ -313,8 +304,6 @@ for line in args.infile:
image_data = {
'ref': os.path.join(args.reftest_output_dir, '{}.ref.png'.format(basename)),
'out': os.path.join(args.reftest_output_dir, '{}.out.png'.format(basename)),
'refnode': os.path.join(args.reftest_output_dir, '{}.ref.node'.format(basename)),
'outnode': os.path.join(args.reftest_output_dir, '{}.out.node'.format(basename)),
'diff': os.path.join(args.reftest_output_dir, '{}.diff.png'.format(basename)),
}
@@ -327,7 +316,6 @@ report = {}
report['date'] = datetime.datetime.utcnow()
report['locale_date'] = report['date'].strftime("%c")
report['project_name'] = args.project_name
report['backend'] = args.backend
report['job_id'] = args.job_id
report['branch_name'] = args.branch
report['total_successes'] = 0
@@ -340,7 +328,7 @@ for name, units in suites.items():
print('Processing {} suite {}:'.format(project_name, suite_name))
def if_failed(unit):
if unit['result'] in ['FAIL', 'UNEXPECTEDPASS', 'TIMEOUT', 'ERROR',]:
if unit['result'] in ['FAIL', 'TIMEOUT']:
return True
return False

View File

@@ -19,15 +19,12 @@ aparser = argparse.ArgumentParser(description='Turns a Meson test log into a JUn
aparser.add_argument('--project-name', metavar='NAME',
help='The project name',
default='unknown')
aparser.add_argument('--backend', metavar='NAME',
help='The used backend',
default='unknown')
aparser.add_argument('--job-id', metavar='ID',
help='The job ID for the report',
default='Unknown')
aparser.add_argument('--branch', metavar='NAME',
help='Branch of the project being tested',
default='main')
default='master')
aparser.add_argument('--output', metavar='FILE',
help='The output file, stdout by default',
type=argparse.FileType('w', encoding='UTF-8'),
@@ -54,7 +51,6 @@ for line in args.infile:
duration = data['duration']
return_code = data['returncode']
result = data['result']
log = data['stdout']
unit = {
@@ -62,7 +58,6 @@ for line in args.infile:
'name': unit_name,
'duration': duration,
'returncode': return_code,
'result': result,
'stdout': log,
}
@@ -73,12 +68,12 @@ for name, units in suites.items():
print('Processing suite {} (units: {})'.format(name, len(units)))
def if_failed(unit):
if unit['result'] in ['ERROR', 'FAIL', 'UNEXPECTEDPASS', 'TIMEOUT']:
if unit['returncode'] != 0:
return True
return False
def if_succeded(unit):
if unit['result'] in ['OK', 'EXPECTEDFAIL', 'SKIP']:
if unit['returncode'] == 0:
return True
return False
@@ -95,18 +90,18 @@ for name, units in suites.items():
for unit in successes:
testcase = ET.SubElement(testsuite, 'testcase')
testcase.set('classname', '{}/{}'.format(args.project_name, unit['suite']))
testcase.set('name', '{}/{}'.format(args.backend, unit['name']))
testcase.set('name', unit['name'])
testcase.set('time', str(unit['duration']))
for unit in failures:
testcase = ET.SubElement(testsuite, 'testcase')
testcase.set('classname', '{}/{}'.format(args.project_name, unit['suite']))
testcase.set('name', '{}/{}'.format(args.backend, unit['name']))
testcase.set('name', unit['name'])
testcase.set('time', str(unit['duration']))
failure = ET.SubElement(testcase, 'failure')
failure.set('classname', '{}/{}'.format(args.project_name, unit['suite']))
testcase.set('name', '{}/{}'.format(args.backend, unit['name']))
failure.set('name', unit['name'])
failure.set('type', 'error')
failure.text = unit['stdout']

View File

@@ -1,154 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 GNOME Foundation
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
/**
* RedHat Fonts taken from https://github.com/RedHatOfficial/RedHatFont
* License: SIL Open Font License 1.1 http://scripts.sil.org/OFL
*/
@import url('https://fonts.googleapis.com/css2?family=Noto+Serif:ital,wght@0,400;0,700;1,400;1,700&family=Red+Hat+Display:ital,wght@0,400;0,500;0,700;0,900;1,400;1,500;1,700;1,900&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Noto+Serif:ital,wght@0,400;0,700;1,400;1,700&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Source+Code+Pro:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500;1,600&display=swap');
@font-face {
font-family: "RedHatDisplayWeb";
src: local('RedHatDisplayWeb'),
url("RedHatDisplay-Regular.woff2") format("woff2"),
url("RedHatDisplay-Regular.woff") format("woff");
font-style: normal;
font-weight: 400;
font-display: fallback;
}
@font-face {
font-family: "RedHatDisplayWeb";
src: local('RedHatDisplayWeb'),
url("RedHatDisplay-RegularItalic.woff2") format("woff2"),
url("RedHatDisplay-RegularItalic.woff") format("woff");
font-style: italic;
font-weight: 400;
font-display: fallback;
}
@font-face {
font-family: "RedHatDisplayWeb";
src: local('RedHatDisplayWeb'),
url("RedHatDisplay-Medium.woff2") format("woff2"),
url("RedHatDisplay-Medium.woff") format("woff");
font-style: normal;
font-weight: 500;
font-display: fallback;
}
@font-face {
font-family: "RedHatDisplayWeb";
src: local('RedHatDisplayWeb'),
url("RedHatDisplay-MediumItalic.woff2") format("woff2"),
url("RedHatDisplay-MediumItalic.woff") format("woff");
font-style: italic;
font-weight: 500;
font-display: fallback;
}
@font-face {
font-family: "RedHatDisplayWeb";
src: local('RedHatDisplayWeb'),
url("RedHatDisplay-Bold.woff2") format("woff2"),
url("RedHatDisplay-Bold.woff") format("woff");
font-style: normal;
font-weight: 700;
font-display: fallback;
}
@font-face {
font-family: "RedHatDisplayWeb";
src: local('RedHatDisplayWeb'),
url("RedHatDisplay-BoldItalic.woff2") format("woff2"),
url("RedHatDisplay-BoldItalic.woff") format("woff");
font-style: italic;
font-weight: 700;
font-display: fallback;
}
@font-face {
font-family: "RedHatDisplayWeb";
src: local('RedHatDisplayWeb'),
url("RedHatDisplay-Black.woff2") format("woff2"),
url("RedHatDisplay-Black.woff") format("woff");
font-style: normal;
font-weight: 900;
font-display: fallback;
}
@font-face {
font-family: "RedHatDisplayWeb";
src: local('RedHatDisplayWeb'),
url("RedHatDisplay-BlackItalic.woff2") format("woff2"),
url("RedHatDisplay-BlackItalic.woff") format("woff");
font-style: italic;
font-weight: 900;
font-display: fallback;
}
@font-face {
font-family: "RedHatTextWeb";
src: local('RedHatTextWeb'),
url("RedHatText-Regular.woff2") format("woff2"),
url("RedHatText-Regular.woff") format("woff");
font-style: normal;
font-weight: 400;
font-display: fallback;
}
@font-face {
font-family: "RedHatTextWeb";
src: local('RedHatTextWeb'),
url("RedHatText-RegularItalic.woff2") format("woff2"),
url("RedHatText-RegularItalic.woff") format("woff");
font-style: italic;
font-weight: 400;
font-display: fallback;
}
@font-face {
font-family: "RedHatTextWeb";
src: local('RedHatTextWeb'),
url("RedHatText-Medium.woff2") format("woff2"),
url("RedHatText-Medium.woff") format("woff");
font-style: normal;
font-weight: 700;
font-display: fallback;
}
@font-face {
font-family: "RedHatTextWeb";
src: local('RedHatTextWeb'),
url("RedHatText-MediumItalic.woff2") format("woff2"),
url("RedHatText-MediumItalic.woff") format("woff");
font-style: italic;
font-weight: 700;
font-display: fallback;
}
@font-face {
font-family: "RedHatTextWeb";
src: local('RedHatTextWeb'),
url("RedHatText-Bold.woff2") format("woff2"),
url("RedHatText-Bold.woff") format("woff");
font-style: normal;
font-weight: 900;
font-display: fallback;
}
@font-face {
font-family: "RedHatTextWeb";
src: local('RedHatTextWeb'),
url("RedHatText-BoldItalic.woff2") format("woff2"),
url("RedHatText-BoldItalic.woff") format("woff");
font-style: italic;
font-weight: 900;
font-display: fallback;
}

View File

@@ -1,138 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="128"
height="128"
id="svg6843"
sodipodi:version="0.32"
inkscape:version="0.92.4 5da689c313, 2019-01-14"
version="1.0"
sodipodi:docname="gtk-logo.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
inkscape:export-filename="/home/ebassi/Pictures/gtk-logo-256.png"
inkscape:export-xdpi="192"
inkscape:export-ydpi="192">
<defs
id="defs6845">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="-50 : 600 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="700 : 600 : 1"
inkscape:persp3d-origin="300 : 400 : 1"
id="perspective13" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="2.8284271"
inkscape:cx="69.874353"
inkscape:cy="64.313526"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:document-units="px"
inkscape:grid-bbox="true"
width="128px"
height="128px"
showguides="true"
inkscape:guide-bbox="true"
inkscape:window-width="1920"
inkscape:window-height="1016"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
id="grid7947" />
</sodipodi:namedview>
<metadata
id="metadata6848">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
<dc:date />
<dc:creator>
<cc:Agent>
<dc:title />
</cc:Agent>
</dc:creator>
<dc:rights>
<cc:Agent>
<dc:title />
</cc:Agent>
</dc:rights>
<dc:publisher>
<cc:Agent>
<dc:title />
</cc:Agent>
</dc:publisher>
<dc:identifier />
<dc:source />
<dc:relation />
<dc:language />
<dc:subject>
<rdf:Bag />
</dc:subject>
<dc:coverage />
<dc:description />
<dc:contributor>
<cc:Agent>
<dc:title />
</cc:Agent>
</dc:contributor>
<cc:license
rdf:resource="" />
</cc:Work>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<path
sodipodi:nodetypes="ccccc"
id="path6976"
d="M 20.88413,30.82696 L 53.816977,55.527708 L 107.33282,39.060543 L 70.587303,17.177763 L 20.88413,30.82696 z"
style="fill:#729fcf;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:2.12364459;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline" />
<path
id="path6978"
d="M 22.94243,82.287118 L 20.88413,30.82696 L 53.816977,55.527708 L 53.816977,111.10486 L 22.94243,82.287118 z"
style="fill:#e40000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:2.12364459;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline" />
<path
id="path6980"
d="M 53.816977,111.10486 L 103.21619,90.5207 L 107.33282,39.060543 L 53.816977,55.527708 L 53.816977,111.10486 z"
style="fill:#7fe719;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:2.12364459;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline" />
<path
sodipodi:nodetypes="ccc"
id="path6982"
d="M 23.216626,81.319479 L 70.48573,67.361442 L 103.38422,90.444516"
style="opacity:1;fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
sodipodi:nodetypes="cc"
id="path6984"
d="M 70.434539,17.875593 L 70.434539,66.984877"
style="opacity:1;fill:#babdb6;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 4.8 KiB

View File

@@ -1,149 +0,0 @@
<!--
SPDX-FileCopyrightText: 2021 GNOME Foundation
SPDX-License-Identifier: LGPL-2.1-or-later
-->
<!DOCTYPE html>
<html lang="en">
<head>
<title>GTK Documentation</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="utf-8" />
<meta property="og:site_name" content="https://docs.gtk.org"/>
<meta property="og:title" content="GTK Documentation"/>
<meta property="og:url" content="https://docs.gtk.org"/>
<meta property="og:type" content="website"/>
<meta property="og:description" content="API reference for GTK"/>
<meta name="twitter:title" content="GTK Documentation"/>
<meta name="twitter:url" content="https://docs.gtk.org"/>
<meta name="twitter:card" content="summary"/>
<link rel="canonical" href="https://docs.gtk.org"/>
<link rel="stylesheet" href="style.css" type="text/css" />
<script src="main.js"></script>
<!--[if IE]><script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script><![endif]-->
</head>
<body>
<div id="body-wrapper" tabindex="-1">
<nav class="sidebar">
<div class="section">
<img src="gtk-logo.svg" class="logo"/>
</div>
<div class="section">
<h5>Sections</h5>
<div class="links">
<a href="#user-interface">User interface</a>
<a href="#core-libraries">Core libraries</a>
</div>
</div>
</nav>
<button id="btn-to-top" class="hidden"><span class="up-arrow"></span></button>
<section id="main" class="content">
<header>
<h1>GTK Documentation</h1>
</header>
<div class="toggle-wrapper">
<h4 id="user-interface">
User interface
<a href="#user-interface" class="anchor"></a>
</h4>
<div class="docblock">
<h5 id="gdk">GTK</h5>
<p>GTK is the primary library used to construct user interfaces. It
provides user interface controls and signal callbacks to respond to
user actions.</p>
<p><a href="https://docs.gtk.org/gtk4/">GTK API reference</a></p>
</div>
<div class="docblock">
<h5 id="gdk">GSK</h5>
<p>An intermediate layer which provides a rendering API implemented using Cairo, OpenGL or Vulkan.</p>
<p><a href="https://docs.gtk.org/gsk4/">GSK API reference</a></p>
</div>
<div class="docblock">
<h5 id="gdk">GDK</h5>
<p>An intermediate layer which isolates GTK from the details of the windowing system.</p>
<p><a href="https://docs.gtk.org/gdk4/">GDK API reference</a></p>
</div>
<div class="docblock">
<h5 id="pango">Pango</h5>
<p>Pango is the core text and font handling library used in GTK
applications. It has extensive support for the different writing
systems used throughout the world.</p>
<p><a href="https://docs.gtk.org/Pango/">Pango API reference</a></p>
</div>
<div class="docblock">
<h5 id="gdk-pixbuf">GdkPixbuf</h5>
<p>GdkPixbuf is a library for image loading and manipulation.</p>
<p><a href="https://docs.gtk.org/gdk-pixbuf/">GdkPixbuf API reference</a></p>
</div>
<div class="docblock">
<h5 id="cairo">Cairo</h5>
<p>Cairo is a 2D graphics library with support for multiple output
devices. It is designed to produce consistent, high quality output
on all media.</p>
<p><a href="https://www.cairographics.org/manual/" class="external">Cairo API reference</a></p>
</div>
</div>
<div class="toggle-wrapper">
<h4 id="core-libraries" style="display:flex;">
Core libraries
<a href="#core-libraries" class="anchor"></a>
</h4>
<div class="docblock">
<h5 id="glib">GLib</h5>
<p>GLib provides the core application building blocks for libraries
and applications written in C. It provides common data types
used in GTK, the main loop implementation, and a large set of
utility functions for strings and general portability across
different platforms.</p>
<p><a href="https://developer.gnome.org/glib/" class="external">GLib API reference</a></p>
</div>
<div class="docblock">
<h5 id="gobject">GObject</h5>
<p>GObject provides the object system used by GTK.</p>
<p><a href="https://developer.gnome.org/gobject/" class="external">GObject API reference</a></p>
</div>
<div class="docblock">
<h5 id="gio">GIO</h5>
<p>GIO provides a portable, modern and easy-to-use file system
abstraction API for accessing local and remote files; a set of
low and high level abstractions over the <a href="https://www.freedesktop.org/wiki/Software/dbus/" class="external">DBus</a>
IPC specification; an application settings API; portable networking
abstractions; and additional utilities for writing asynchronous
operations without blocking the user interface of your application.</p>
<p><a href="https://developer.gnome.org/gio/" class="external">GIO API reference</a></p>
</div>
</div>
</section>
<footer>
</footer>
</div>
</body>
</html>

View File

@@ -1,140 +0,0 @@
// SPDX-FileCopyrightText: 2021 GNOME Foundation
//
// SPDX-License-Identifier: LGPL-2.1-or-later
// eslint-disable-next-line no-unused-vars
function hasClass(elem, className) {
return elem && elem.classList && elem.classList.contains(className);
}
// eslint-disable-next-line no-unused-vars
function addClass(elem, className) {
if (!elem || !elem.classList) {
return;
}
elem.classList.add(className);
}
// eslint-disable-next-line no-unused-vars
function removeClass(elem, className) {
if (!elem || !elem.classList) {
return;
}
elem.classList.remove(className);
}
function insertAfter(newNode, referenceNode) {
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
}
function onEach(arr, func, reversed) {
if (arr && arr.length > 0 && func) {
var length = arr.length;
var i;
if (reversed !== true) {
for (i = 0; i < length; ++i) {
if (func(arr[i]) === true) {
return true;
}
}
} else {
for (i = length - 1; i >= 0; --i) {
if (func(arr[i]) === true) {
return true;
}
}
}
}
return false;
}
function onEachLazy(lazyArray, func, reversed) {
return onEach(
Array.prototype.slice.call(lazyArray),
func,
reversed);
}
// eslint-disable-next-line no-unused-vars
function hasOwnProperty(obj, property) {
return Object.prototype.hasOwnProperty.call(obj, property);
}
window.addEventListener("load", function() {
"use strict;"
var main = document.getElementById("main");
var btnToTop = document.getElementById("btn-to-top");
function labelForToggleButton(isCollapsed) {
if (isCollapsed) {
return "+";
}
return "\u2212";
}
function createToggle(isCollapsed) {
var toggle = document.createElement("a");
toggle.href = "javascript:void(0)";
toggle.className = "collapse-toggle";
toggle.innerHTML = "[<span class=\"inner\">"
+ labelForToggleButton(isCollapsed)
+ "</span>]";
return toggle;
}
function toggleClicked() {
if (hasClass(this, "collapsed")) {
removeClass(this, "collapsed");
this.innerHTML = "[<span class=\"inner\">"
+ labelForToggleButton(false)
+ "</span>]";
onEachLazy(this.parentNode.getElementsByClassName("docblock"), function(e) {
removeClass(e, "hidden");
});
} else {
addClass(this, "collapsed");
this.innerHTML = "[<span class=\"inner\">"
+ labelForToggleButton(true)
+ "</span>]";
onEachLazy(this.parentNode.getElementsByClassName("docblock"), function(e) {
addClass(e, "hidden");
});
}
}
onEachLazy(document.getElementsByClassName("toggle-wrapper"), function(e) {
let sectionHeader = e.querySelector(".section-header");
let fragmentMatches = sectionHeader !== null && location.hash === "#" + sectionHeader.getAttribute('id');
collapsedByDefault = hasClass(e, "default-hide") && !fragmentMatches;
var toggle = createToggle(collapsedByDefault);
toggle.onclick = toggleClicked;
e.insertBefore(toggle, e.firstChild);
if (collapsedByDefault) {
addClass(toggle, "collapsed");
onEachLazy(e.getElementsByClassName("docblock"), function(d) {
addClass(d, "hidden");
});
}
});
function scrollBackTop(e) {
e.preventDefault();
window.scroll({
top: 0,
behavior: 'smooth',
});
}
function toggleScrollButton() {
if (window.scrollY < 400) {
addClass(btnToTop, "hidden");
} else {
removeClass(btnToTop, "hidden");
}
}
window.onscroll = toggleScrollButton;
btnToTop.onclick = scrollBackTop;
}, false);

View File

@@ -1,747 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 GNOME Foundation
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
@import url("fonts.css");
/*********************************
* LIGHT THEME
*********************************/
:root {
/* colors */
--text-color: #333;
--text-color-muted: #999;
--primary: rgb(28, 118, 228);
--body-bg: #fff;
--sidebar-primary: rgb(144, 194, 255);
--sidebar-bg: #151515;
--sidebar-selected-bg: var(--primary);
--sidebar-text-color: #fafafa;
--sidebar-padding: 1.5em;
/* boxes, e.g. code blocks */
--box-bg: rgba(135, 135, 135, 0.085);
--box-radius: 0.35rem;
--box-padding: 0.75rem;
--box-margin: 0.75rem 0;
--box-text-color: #111;
/* typography */
--body-font-family: "Noto Serif",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";
--body-font-scale: 0.95;
--body-font-size: calc(var(--body-font-scale) * clamp(16px, 1vw, 20px));
--body-font-weight: normal;
--monospace-font-family: "Source Code Pro", monospace;
--monospace-font-size: calc(0.86 * var(--body-font-size)); /* Monospace fonts are very different in terms of font-sizes. Adjust this value to scale it */
--heading-font-family: "Red Hat Display", var(--body-font-family);
--heading-weight: 900;
--heading-font-scale: 1.05;
--heading-small-font-family: var(--heading-font-family);
--heading-small-weight: 600;
--heading-small-font-scale: 1;
--heading-table-font-family: var(--heading-font-family);
--heading-table-weight: 600;
--heading-docblock-color: #6d6d6d; /* docblocks have headings from source comments. we want them to differ.*/
--heading-docblock-scale: 0.9; /* docblocks have headings from source comments. we want them to differ.*/
--symbol-font-family: var(--heading-font-family);
--symbol-font-weight: 500;
--symbol-font-scale: 1;
--table-font-size: 0.92em; /* Tables often contain lots information. It's better to scale them down a big to get more sutff fitted inside */
/* misc */
--prefered-content-width: 90ch; /* The preferred width for the readable content */
--anchor-sign: "#";
}
/*********************************
* DARK THEME (overrides)
*********************************/
@media (prefers-color-scheme: dark) {
:root {
--primary: rgb(144, 194, 255);
--text-color: #f6f6f6;
--text-color-muted: #686868;
--body-bg: #121212;
--sidebar-primary: rgb(144, 194, 255);
--sidebar-bg: #1e1e1e;
--sidebar-selected-bg: rgb(17, 112, 228);
--sidebar-text-color: #fafafa;
--box-bg: rgba(135, 135, 135, 0.1);
--box-text-color: #fff;
--heading-docblock-color: #b7b7b7;
}
/* fix dark theme syntax highlighting with a filter (for now) */
.highlight pre span {
filter: brightness(6);
}
}
/*********************************
* GENERAL STYLING
*********************************/
*,
*:before,
*:after {
box-sizing: border-box;
}
::-moz-selection {
color: white;
background: var(--primary);
}
::selection {
color: white;
background: var(--primary);
}
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-thumb {
border-radius: 10px;
background: rgba(128, 128, 128, 0.6);
}
::-webkit-scrollbar-thumb:hover {
background: rgba(128, 128, 128, 1);
}
::-webkit-scrollbar-track {
background: rgba(128, 128, 128, 0.15);
}
* {
scrollbar-width: initial;
}
body {
font: 16px/1.5 var(--body-font-family);
font-weight: var(--body-font-weight);
font-size: var(--body-font-size);
margin: 0;
padding: 0;
position: relative;
-webkit-font-feature-settings: "kern", "liga";
-moz-font-feature-settings: "kern", "liga";
font-feature-settings: "kern", "liga";
color: var(--text-color);
background: var(--body-bg);
}
h1, h2, h3, h4, h5, h6 {
font-family: var(--heading-font-family);
font-weight: var(--heading-weight);
margin: 1.75em 0 0.75em 0;
display: flex;
align-items: center;
}
h1 {
font-size: calc(1.75em * var(--heading-font-scale));
}
header h1 {
margin-top: 0;
}
h2 {
font-size: calc(1.4em * var(--heading-font-scale));
}
h3 {
font-size: calc(1.2em * var(--heading-font-scale));
}
header h3 {
color: var(--text-color-muted);
margin-bottom: 0;
}
h4, h5 {
font-size: calc(1em * var(--heading-font-scale));
}
h6 {
font-size: calc(1em * var(--heading-small-font-scale));
font-family: var(--heading-small-font-family);
font-weight: var(--heading-small-weight);
}
ol, ul {
padding-left: 1rem;
}
ul ul, ol ul, ul ol, ol ol {
margin-bottom: .6em;
}
p {
margin: 0 0 .6em 0;
}
a {
color: var(--primary);
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
summary {
outline: none;
}
blockquote {
border-left: 3px solid var(--primary);
background: var(--box-bg);
padding: var(--box-padding);
border-radius: var(--box-radius);
margin: var(--box--margin);
}
code,
pre {
font-family: var(--monospace-font-family);
font-size: var(--monospace-font-size);
color: var(--box-text-color);
}
pre {
background: var(--box-bg);
padding: var(--box-padding);
border-radius: var(--box-radius);
overflow: auto;
}
code {
background: var(--box-bg);
padding: 0 0.35em;
border-radius: 0.35rem;
word-break: break-word;
}
a > code {
color: var(--primary);
}
pre pre,
pre code {
padding: 0;
margin: 0;
font-size: 1em;
background: none;
color: inherit;
}
h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {
font-family: inherit;
font-weight: inherit;
font-size: 0.85em;
}
strong, b {
font-weight: 600;
}
/* fix unwanted margins in tables, code, lists and blockquotes */
li > *:first-child,
li > *:first-child > *:first-child,
li > *:first-child > *:first-child > *:first-child,
td > *:first-child,
td > *:first-child > *:first-child,
td > *:first-child > *:first-child > *:first-child,
pre > *:first-child,
pre > *:first-child > *:first-child,
pre > *:first-child > *:first-child > *:first-child,
blockquote > *:first-child,
blockquote > *:first-child > *:first-child,
blockquote > *:first-child > *:first-child > *:first-child {
margin-top: 0;
}
li > *:last-child,
li > *:last-child > *:last-child,
li > *:last-child > *:last-child > *:last-child,
td > *:last-child,
td > *:last-child > *:last-child,
td > *:last-child > *:last-child > *:last-child,
pre > *:last-child,
pre > *:last-child > *:last-child,
pre > *:last-child > *:last-child > *:last-child,
blockquote > *:last-child,
blockquote > *:last-child > *:last-child,
blockquote > *:last-child > *:last-child > *:last-child {
margin-bottom: 0;
}
/*********************************
* PAGE STRUCTURE
*********************************/
#body-wrapper {
display: flex;
flex-wrap: nowrap;
flex-direction: row;
}
#body-wrapper:focus {
outline: none;
}
#main {
position: relative;
flex-grow: 1;
min-width: 0;
box-shadow: 0 0 134px rgba(0, 0, 0, 0.1);
}
footer {
width: 100%;
display: none;
}
/*********************************
* Button
*********************************/
#btn-to-top {
position: fixed;
bottom: 12px;
right: 32px;
z-index: 1000;
border-radius: 50%;
width: 42px;
height: 42px;
border: 1px solid var(--primary);
background: var(--box-bg);
color: var(--text-color);
cursor: pointer;
text-transform: none;
}
#btn-to-top > .up-arrow:after {
content: "🡅"
}
/*********************************
* SIDEBAR
*********************************/
.sidebar {
scrollbar-width: thin;
background: var(--sidebar-bg);
border-right: 1px solid var(--sidebar-bg);
min-width: 40ch;
padding: var(--sidebar-padding);
color: var(--sidebar-text-color);
position: sticky;
top: 0;
z-index: 2;
height: 100vh;
overflow-y: auto;
}
.sidebar a,
.sidebar a:hover {
text-decoration: none;
}
.sidebar .logo {
display: block;
margin: 2rem auto 0 auto;
width: 70%;
}
.sidebar .section > ul > li {
margin-right: -10px;
}
.sidebar .section h3, .sidebar .section h5 {
text-align: left;
padding-left: 0.5rem;
padding-right: 0.5rem;
font-weight: var(--heading-weight);
}
.sidebar .section h5 {
font-size: 1em;
margin-bottom: 0.5em;
}
.sidebar .namespace > h3 {
margin-bottom: 0;
padding: 0;
font-size: 1.5em;
text-transform: uppercase;
font-weight: 900;
}
.sidebar .namespace > p {
font-size: 0.9em;
opacity: 0.8;
padding-left: 0.5rem;
}
.sidebar .section {
padding-left: 0.5rem;
padding-right: 0.5rem;
}
.sidebar .links {
margin-bottom: 1rem;
}
.sidebar .section a {
display: block;
text-overflow: ellipsis;
overflow: hidden;
transition: background-color 150ms ease;
color: var(--sidebar-primary);
border-radius: var(--box-radius);
padding: 0.2rem 0.5rem;
margin-bottom: 0.15rem;
}
.sidebar .section a:hover {
background-color: rgba(127, 127, 127, 0.2);
color: var(--sidebar-text-color);
}
.sidebar .section a.current {
background-color: var(--sidebar-selected-bg);
color: white;
}
.sidebar .search {
box-sizing: border-box;
text-align: center;
}
.sidebar .search input[type="text"] {
border-color: transparent;
width: 100%;
border: 1px solid #ccc;
border-radius: 50px;
padding: 6px 12px;
display: inline-block;
font-size: 80%;
box-shadow: inset 0 1px 3px #ddd;
transition: border .3s linear;
}
/*********************************
* ANCHORS & TOGGLERS
*********************************/
.anchor,
.md-anchor {
position: relative;
z-index: 1;
text-decoration: none;
padding: 0 0.5em;
color: var(--text-color-muted);
}
.anchor:hover,
.md-anchor:hover {
color: var(--primary);
}
.anchor:not([href]),
.md-anchor:not([href]) {
display: none;
}
.anchor:before,
.md-anchor:before {
content: var(--anchor-sign); /*'§'*/
}
.toggle-wrapper {
position: relative;
}
.collapse-toggle {
position: absolute;
right: 0;
left: -2em;
white-space: nowrap;
text-decoration: none;
font-size: 0.8em;
color: transparent;
}
.collapse-toggle > .inner {
width: 1rem;
height: 1rem;
border-radius: calc(0.75 * var(--box-radius));
display: inline-flex;
justify-content: center;
align-items: center;
text-align: center;
vertical-align: middle;
color: var(--box-text-color);
position: relative;
left: -0.25rem;
font-family: monospace;
font-size: 0.7rem;
font-weight: bold;
background: var(--box-bg);
}
/*********************************
* UTILITY
*********************************/
.deprecated > h6 > a {
opacity: 0.65;
}
.hidden {
display: none !important;
}
/*********************************
* CONTENT STYLING
*********************************/
.content {
padding: 2em 4em;
overflow: visible;
max-width: calc(var(--prefered-content-width) + 8em);
}
.content table:not(.table-display) {
border-spacing: 0 0.25rem;
}
.content td {
vertical-align: top;
}
.content td:first-child {
padding-right: 1rem;
}
.content td p:first-child {
margin-top: 0;
}
.content td h1, .content td h2 {
margin-left: 0;
font-size: 1.1em;
}
.content tr:first-child td {
border-top: 0;
}
kbd {
display: inline-block;
padding: 3px 5px;
font: 15px monospace;
line-height: 10px;
vertical-align: middle;
border: solid 1px;
border-radius: 3px;
box-shadow: inset 0 -1px 0;
cursor: default;
}
.content tr:first-child {
border-bottom: 1px solid rgba(0, 0, 0, 0.35);
}
.content td {
vertical-align: top;
}
.content td:first-child {
padding-right: 1rem;
}
.content td p:first-child {
margin-top: 0;
}
.content td h4, .content td h5 {
margin-left: 0;
font-size: 1.1em;
}
.content tr:first-child td {
border-top: 0;
}
.srclink {
color: var(--text-color-muted);
font-size: 1rem;
font-weight: var(--body-font-weight);
flex-grow: 0;
text-decoration: none;
margin-left: auto;
position: relative;
z-index: 1;
}
.meta tr > td:not(:first-child) {
width: 100%;
}
.meta tr > td:first-child {
white-space: nowrap;
}
/*********************************
* DOCBLOCK STYLING
*********************************/
.docblock {
position: relative;
text-align: left;
}
.docblock h1 {
font-size: calc(1.3em * var(--heading-docblock-scale) * var(--heading-font-scale));
}
.docblock h2 {
font-size: calc(1.2em * var(--heading-docblock-scale) * var(--heading-font-scale));
}
.docblock h3 {
font-size: calc(1.1em * var(--heading-docblock-scale) * var(--heading-font-scale));
}
.docblock h4 {
font-size: calc(1.05em * var(--heading-docblock-scale) * var(--heading-font-scale));
}
.docblock h1,
.docblock h2,
.docblock h3,
.docblock h4,
.docblock h5,
.docblock h6 {
color: var(--heading-docblock-color)
}
.docblock table {
margin: .25em 0;
max-width: 100%;
font-size: var(--table-font-size);
}
.docblock table td {
padding: .25em;
}
.docblock table th {
padding: .25em;
text-align: left;
font-family: var(--heading-table-font-family);
font-weight: var(--heading-table-weight);
}
.docblock table tr th:first-child,
.docblock table tr td:first-child {
padding-left: 0;
}
.docblock table tr th:last-child,
.docblock table tr td:last-child {
padding-right: 0;
}
table.enum-members,
table.results {
border-radius: var(--box-radius);
border: 1px solid var(--text-color-muted);
border-spacing: 0 0 !important;
font-size: 80%;
}
table.enum-members tr th,
table.results tr th {
border-top-color: var(--body-bg);
background-color: var(--box-bg);
border-bottom: 1px solid var(--text-color-muted);
}
table.enum-members tr th:first-child,
table.enum-members tr td:first-child {
min-width: 25em;
padding-left: .5em;
}
table.results tr th:first-child,
table.results tr td:first-child {
padding-left: .5em;
}
table.enum-members tr th:last-child,
table.enum-members tr td:last-child,
table.results tr th:last-child,
table.results tr td:last-child {
max-width: 35em;
padding-right: .5em;
}
table.results tr td code {
font-size: 100%;
}
.docblock ul li,
.docblock ol li {
padding-top: 0.15rem;
padding-bottom: 0.15rem;
}
.docblock ul.type {
list-style: none;
}
.docblock ul.type li::before {
content: "»";
color: var(--text-color);
display: inline-block;
width: 1em;
margin-left: -1em;
}
/**************************
RESPONSIVENESS
**************************/
@media (max-width: 700px) {
body {
padding-top: 0px;
}
#body-wrapper {
flex-direction: column;
overflow: hidden;
}
#main {
width: 100%;
padding: 2rem;
}
.sidebar {
position: static;
height: initial;
order: 1;
}
}

View File

@@ -1,135 +1,11 @@
#!/bin/bash
read_arg() {
# $1 = arg name
# $2 = arg value
# $3 = arg parameter
local rematch='^[^=]*=(.*)$'
if [[ $2 =~ $rematch ]]; then
read "$1" <<< "${BASH_REMATCH[1]}"
else
read "$1" <<< "$3"
# There is no way to shift our callers args, so
# return 1 to indicate they should do it instead.
return 1
fi
}
set -e
build=0
run=0
push=0
list=0
print_help=0
no_login=0
TAG="registry.gitlab.gnome.org/gnome/gtk/master:v7"
while (($# > 0)); do
case "${1%%=*}" in
build) build=1;;
run) run=1;;
push) push=1;;
list) list=1;;
help) print_help=1;;
--base|-b) read_arg base "$@" || shift;;
--version|-v) read_arg base_version "$@" || shift;;
--no-login) no_login=1;;
*) echo -e "\e[1;31mERROR\e[0m: Unknown option '$1'"; exit 1;;
esac
shift
done
if [ $print_help == 1 ]; then
echo "$0 - Build and run Docker images"
echo ""
echo "Usage: $0 <command> [options] [basename]"
echo ""
echo "Available commands"
echo ""
echo " build --base=<BASENAME> - Build Docker image <BASENAME>.Dockerfile"
echo " run --base=<BASENAME> - Run Docker image <BASENAME>"
echo " push --base=<BASENAME> - Push Docker image <BASENAME> to the registry"
echo " list - List available images"
echo " help - This help message"
echo ""
exit 0
fi
cd "$(dirname "$0")"
if [ $list == 1 ]; then
echo "Available Docker images:"
for f in *.Dockerfile; do
filename=$( basename -- "$f" )
basename="${filename%.*}"
echo -e " \e[1;39m$basename\e[0m"
done
exit 0
fi
# All commands after this require --base to be set
if [ -z $base ]; then
echo "Usage: $0 <command>"
exit 1
fi
if [ ! -f "$base.Dockerfile" ]; then
echo -e "\e[1;31mERROR\e[0m: Dockerfile for '$base' not found"
exit 1
fi
if [ -z $base_version ]; then
base_version="latest"
elif [ $base_version != "latest" ]; then
base_version="v$base_version"
fi
if [ ! -x "$(command -v docker)" ] || [ docker --help |& grep -q podman ]; then
# Docker is actually implemented by podman, and its OCI output
# is incompatible with some of the dockerd instances on GitLab
# CI runners.
echo "Using: Podman"
format="--format docker"
CMD="podman"
else
echo "Using: Docker"
format=""
CMD="sudo docker"
fi
REGISTRY="registry.gitlab.gnome.org"
TAG="${REGISTRY}/gnome/gtk/${base}:${base_version}"
if [ $build == 1 ]; then
echo -e "\e[1;32mBUILDING\e[0m: ${base} as ${TAG}"
${CMD} build \
${format} \
--build-arg HOST_USER_ID="$UID" \
--tag "${TAG}" \
--file "${base}.Dockerfile" .
exit $?
fi
if [ $push == 1 ]; then
echo -e "\e[1;32mPUSHING\e[0m: ${base} as ${TAG}"
if [ $no_login == 0 ]; then
${CMD} login ${REGISTRY}
fi
${CMD} push ${TAG}
exit $?
fi
if [ $run == 1 ]; then
echo -e "\e[1;32mRUNNING\e[0m: ${base} as ${TAG}"
${CMD} run \
--rm \
--volume "$(pwd)/..:/home/user/app" \
--workdir "/home/user/app" \
--tty \
--interactive "${TAG}" \
bash
exit $?
fi
sudo docker build --build-arg HOST_USER_ID="$UID" --tag "${TAG}" \
--file "Dockerfile" .
sudo docker run --rm --security-opt label=disable \
--volume "$(pwd)/..:/home/user/app" --workdir "/home/user/app" \
--tty --interactive "${TAG}" bash

View File

@@ -1,44 +0,0 @@
#!/bin/bash
set -e
# 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/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=$?
# The style check is not infallible. The clang-format configuration cannot
# perfectly describe GTKs coding style: in particular, it cannot align
# function arguments. The documented coding style for GTK takes priority over
# clang-format suggestions. Hopefully we can eventually improve clang-format to
# be configurable enough for our coding style. Thats why this CI check is OK
# to fail: the idea is that people can look through the output and ignore it if
# its wrong. (That situation can also happen if someone touches pre-existing
# badly formatted code and it doesnt make sense to tidy up the wider coding
# style with the changes theyre making.)
echo ""
echo "Note that clang-format output is advisory and cannot always match the"
echo "GTK coding style, documented at:"
echo " https://gitlab.gnome.org/GNOME/gtk/blob/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."
exit ${exit_status}

View File

@@ -1,107 +0,0 @@
#!/bin/bash
set +x
set +e
srcdir=$( pwd )
builddir=$1
backend=$2
# Ignore memory leaks lower in dependencies
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} \
--timeout-multiplier "${MESON_TEST_TIMEOUT_MULTIPLIER}" \
--print-errorlogs \
--setup=${backend} \
--suite=gtk \
--no-suite=gsk-compare-broadway
# Store the exit code for the CI run, but always
# generate the reports
exit_code=$?
;;
wayland)
export XDG_RUNTIME_DIR="$(mktemp -p $(pwd) -d xdg-runtime-XXXXXX)"
weston --backend=headless-backend.so --socket=wayland-5 --idle-time=0 &
compositor=$!
export WAYLAND_DISPLAY=wayland-5
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}
;;
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}
;;
broadway)
export XDG_RUNTIME_DIR="$(mktemp -p $(pwd) -d xdg-runtime-XXXXXX)"
${builddir}/gdk/broadway/gtk4-broadwayd :5 &
server=$!
export BROADWAY_DISPLAY=:5
meson test -C ${builddir} \
--timeout-multiplier "${MESON_TEST_TIMEOUT_MULTIPLIER}" \
--print-errorlogs \
--setup=${backend} \
--suite=gtk \
--no-suite=gsk-compare-opengl
# don't let Broadway failures fail the run, for now
exit_code=0
kill ${server}
;;
*)
echo "Failed to add ${backend} to .gitlab-ci/run-tests.sh"
exit 1
;;
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
$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
exit $exit_code

View File

@@ -1,5 +0,0 @@
#! /bin/sh
. /etc/os-release
echo $PRETTY_NAME

View File

@@ -1,8 +0,0 @@
#!/bin/bash
set -eux -o pipefail
xcodebuild -version || :
xcodebuild -showsdks || :
system_profiler SPSoftwareDataType || :

View File

@@ -15,7 +15,7 @@ meson \
-Dx11-backend=true \
-Dwayland-backend=true \
-Dbroadway-backend=true \
-Dvulkan=enabled \
-Dvulkan=yes \
-Dprofiler=true \
--werror \
${EXTRA_MESON_FLAGS:-} \

View File

@@ -1,14 +0,0 @@
@echo on
:: vcvarsall.bat sets various env vars like PATH, INCLUDE, LIB, LIBPATH for the
:: specified build architecture
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" x64
@echo on
:: FIXME: make warnings fatal
pip3 install --upgrade --user meson==0.60.3 || goto :error
meson -Ddebug=false -Dmedia-gstreamer=disabled _build || goto :error
ninja -C _build || goto :error
goto :EOF
:error
exit /b 1

View File

@@ -15,9 +15,9 @@ pacman --noconfirm -Suy
pacman --noconfirm -S --needed \
base-devel \
git \
mingw-w64-$MSYS2_ARCH-cc \
mingw-w64-$MSYS2_ARCH-toolchain \
mingw-w64-$MSYS2_ARCH-ccache \
mingw-w64-$MSYS2_ARCH-pkgconf \
mingw-w64-$MSYS2_ARCH-pkg-config \
mingw-w64-$MSYS2_ARCH-gobject-introspection \
mingw-w64-$MSYS2_ARCH-meson \
mingw-w64-$MSYS2_ARCH-adwaita-icon-theme \
@@ -28,35 +28,19 @@ pacman --noconfirm -S --needed \
mingw-w64-$MSYS2_ARCH-graphene \
mingw-w64-$MSYS2_ARCH-json-glib \
mingw-w64-$MSYS2_ARCH-libepoxy \
mingw-w64-$MSYS2_ARCH-pango2 \
mingw-w64-$MSYS2_ARCH-pango \
mingw-w64-$MSYS2_ARCH-fribidi \
mingw-w64-$MSYS2_ARCH-gst-plugins-bad-libs \
mingw-w64-$MSYS2_ARCH-shared-mime-info \
mingw-w64-$MSYS2_ARCH-python-gobject
mingw-w64-$MSYS2_ARCH-gst-plugins-bad \
mingw-w64-$MSYS2_ARCH-shared-mime-info
# https://gitlab.gnome.org/GNOME/gtk/issues/2243
wget "https://gitlab.gnome.org/creiter/gitlab-ci-win32-runner/raw/master/pango/mingw-w64-$MSYS2_ARCH-pango-1.44.7-1-any.pkg.tar.xz"
pacman --noconfirm -U "mingw-w64-$MSYS2_ARCH-pango-1.44.7-1-any.pkg.tar.xz"
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
@@ -65,13 +49,10 @@ meson \
-Dx11-backend=false \
-Dwayland-backend=false \
-Dwin32-backend=true \
-Dvulkan=disabled \
-Dintrospection=enabled \
-Dgtk:werror=true \
-Dvulkan=no \
--werror \
_build
unset CCACHE_DISABLE
ninja -C _build
ccache --show-stats
tar zcf _build/gtkdll.tar.gz _build/gtk/libgtk*.dll

View File

@@ -1,13 +1,4 @@
<!--
Please, read the CONTRIBUTING.md guide on how to file a new issue.
https://gitlab.gnome.org/GNOME/gtk/-/blob/main/CONTRIBUTING.md
-->
## Steps to reproduce
<!--
Please, explain the sequence of actions necessary to reproduce the
bug
-->
1. ...
2. ...
@@ -41,8 +32,5 @@
## Additional information
<!--
- Screenshots or screen recordings are useful for visual errors
- Attaching a screenshot or a video without explaining the current
behavior and the actions necessary to reproduce the bug will lead
to the bug being closed
- Please report any warning or message printed on the terminal
-->

View File

@@ -1,14 +1,4 @@
<!--
Please, read the CONTRIBUTING.md guide on how to file a new issue.
https://gitlab.gnome.org/GNOME/gtk/-/blob/main/CONTRIBUTING.md
-->
## Steps to reproduce
<!--
Please, explain the sequence of actions necessary to reproduce the
crash
-->
1. ...
2. ...

30
AUTHORS
View File

@@ -1,5 +1,5 @@
Please do not mail any of the authors listed here
asking questions about this version of GTK.
Please do not mail any of the authors listed here
asking questions about this version of GTK+.
Original Authors
----------------
@@ -7,8 +7,8 @@ Peter Mattis <petm@xcf.berkeley.edu>
Spencer Kimball <spencer@xcf.berkeley.edu>
Josh MacDonald <jmacd@xcf.berkeley.edu>
The Team that build GTK 2 (in alphabetical order)
-------------------------------------------------
The GTK+ Team (in alphabetical order)
-------------------------------------
Shawn T. Amundson <amundson@gtk.org>
Jerome Bolliet <bolliet@gtk.org>
Damon Chaplin <damon@gtk.org>
@@ -28,24 +28,11 @@ Jay Painter <jpaint@gtk.org>
Manish Singh <manish@gtk.org>
Owen Taylor <otaylor@gtk.org>
The current team (GTK 3 and 4)
------------------------------
Jonas Ådahl <jadahl@gmail.com>
Tim Bäder <mail@baedert.org>
Emmanuele Bassi <ebassi@gnome.org>
Chun-wei Fan <fanchunwei@src.gnome.org>
Matthias Clasen <mclasen@redhat.com>
Carlos Garnacho <mrgarnacho@gmail.com>
Alexander Larsson <alexl@redhat.com>
Benjamin Otte <otte@gnome.org>
There are many others who have contributed patches; we thank them,
GTK is much better because of them.
GTK+ is much better because of them.
Over time, GTK has incorporated some pieces of software which
Over time, GTK+ has incorporated some pieces of software which
started as independent projects. We list the original authors here:
@@ -76,8 +63,3 @@ DirectFB backend
Denis Oliver Kropp
Sven Neumann
Mike Emmel
gtkparasite
-----------
Christian Hammond

View File

@@ -22,7 +22,12 @@ 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` IRC channel on irc.gnome.org
- the [gtk tag on the GNOME Discourse instance](https://discourse.gnome.org/tag/gtk)
- the [gtk](https://mail.gnome.org/mailman/listinfo/gtk-list) mailing list,
for general questions on GTK
- the [gtk-app-devel](https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list)
mailing list, for questions on application development with GTK
- the [gtk-devel](https://mail.gnome.org/mailman/listinfo/gtk-devel-list)
mailing list, for questions on developing GTK itself
You can also look at the GTK tag on [Stack
Overflow](https://stackoverflow.com/questions/tagged/gtk).
@@ -56,12 +61,6 @@ If the issue includes a crash, you should also include:
0. the eventual warnings printed on the terminal
0. a backtrace, obtained with tools such as GDB or LLDB
It is fine to include screenshots of screen recordings to demonstrate
an issue that is best to understand visually, but please don't just
dump screen recordings without further details into issues. It is
essential that the problem is described in enough detail to reproduce
it without watching a video.
For small issues, such as:
- spelling/grammar fixes in the documentation
@@ -256,7 +255,7 @@ people committing to GTK to follow a few rules:
0. Always write a meaningful commit message. Changes without a sufficient
commit message will be reverted.
0. Never push to the `main` branch, or any stable branches, directly; you
0. Never push to the `master` branch, or any stable branches, directly; you
should always go through a merge request, to ensure that the code is
tested on the CI infrastructure at the very least. A merge request is
also the proper place to get a comprehensive code review from the core

8892
NEWS

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
GTK — The GTK toolkit
=====================
[![Build status](https://gitlab.gnome.org/GNOME/gtk/badges/main/pipeline.svg)](https://gitlab.gnome.org/GNOME/gtk/-/commits/main)
[![Build Status](https://gitlab.gnome.org/GNOME/gtk/badges/master/build.svg)](https://gitlab.gnome.org/GNOME/gtk/pipelines)
General information
-------------------
@@ -10,16 +10,14 @@ GTK is a multi-platform toolkit for creating graphical user interfaces.
Offering a complete set of widgets, GTK is suitable for projects ranging
from small one-off projects to complete application suites.
GTK is a free and open-source software project. The licensing terms
for GTK, the GNU LGPL, allow it to be used by all developers, including those
developing proprietary software, without any license fees or royalties.
GTK is hosted by the GNOME project (thanks!) and used by a wide variety
of applications and projects.
GTK is free software and part of the GNU Project. However, the
licensing terms for GTK, the GNU LGPL, allow it to be used by all
developers, including those developing proprietary software, without any
license fees or royalties.
The official download location
- https://download.gnome.org/sources/gtk/
- https://download.gnome.org/sources/gtk+
The official web site
@@ -29,21 +27,14 @@ The official developers blog
- https://blog.gtk.org
Discussion forum
Information about mailing lists can be found at
- https://discourse.gnome.org/c/platform/core/
- http://www.gtk.org/mailing-lists.php
Nightly documentation can be found at
- Gtk: https://gnome.pages.gitlab.gnome.org/gtk/gtk4/
- Gdk: https://gnome.pages.gitlab.gnome.org/gtk/gdk4/
- Gsk: https://gnome.pages.gitlab.gnome.org/gtk/gsk4/
Nightly flatpaks of our demos can be installed from the
[GNOME Nightly](https://wiki.gnome.org/Apps/Nightly) repository:
- `flatpak remote-add --if-not-exists gnome-nightly https://nightly.gnome.org/gnome-nightly.flatpakrepo`
- `flatpak install gnome-nightly org.gtk.Demo4`
- `flatpak install gnome-nightly org.gtk.WidgetFactory4`
- `flatpak install gnome-nightly org.gtk.IconBrowser4`
- Gtk: https://gnome.pages.gitlab.gnome.org/gtk/gtk/
- Gdk: https://gnome.pages.gitlab.gnome.org/gtk/gdk/
- Gsk: https://gnome.pages.gitlab.gnome.org/gtk/gsk/
Building and installing
-----------------------
@@ -58,13 +49,14 @@ In order to build GTK you will need:
You will also need various dependencies, based on the platform you are
building for:
- [GLib](https://download.gnome.org/sources/glib/)
- [GdkPixbuf](https://download.gnome.org/sources/gdk-pixbuf/)
- [GObject-Introspection](https://download.gnome.org/sources/gobject-introspection/)
- [Cairo](https://www.cairographics.org/)
- [Pango](https://download.gnome.org/sources/pango/)
- [GLib](https://download.gnome.org/sources/glib)
- [GdkPixbuf](https://download.gnome.org/sources/gdk-pixbuf)
- [GObject-Introspection](https://download.gnome.org/sources/gobject-introspection)
- [Cairo](https://www.cairographics.org)
- [Pango](https://download.gnome.org/sources/pango)
- [Epoxy](https://github.com/anholt/libepoxy)
- [Graphene](https://github.com/ebassi/graphene)
- [ATK](https://download.gnome.org/sources/atk)
- [Xkb-common](https://github.com/xkbcommon/libxkbcommon)
If you are building the X11 backend, you will also need:
@@ -78,6 +70,7 @@ If you are building the X11 backend, you will also need:
- xcursor
- xdamage
- xcomposite
- [atk-bridge-2.0](https://download.gnome.org/sources/at-spi2-atk)
If you are building the Wayland backend, you will also need:
@@ -107,28 +100,14 @@ And, finally, you can install GTK using:
$ sudo ninja install
```
Complete information about installing GTK and related libraries
Complete information about installing GTK+ and related libraries
can be found in the file:
```
docs/reference/gtk/html/gtk-building.html
```
Or [online](https://docs.gtk.org/gtk4/building.html)
Default branch renamed to `main`
--------------------------------
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
```
Or [online](https://developer.gnome.org/gtk4/stable/gtk-building.html)
How to report bugs
------------------
@@ -161,23 +140,14 @@ In the bug report please include:
* Further information such as stack traces may be useful, but
is not necessary.
Contributing to GTK
-------------------
Please, follow the [contribution guide](./CONTRIBUTING.md) to know how to
start contributing to GTK.
If you want to support GTK financially, please consider donating to
the GNOME project, which runs the infrastructure hosting GTK.
Release notes
-------------
The release notes for GTK are part of the migration guide in the API
reference. See:
- [3.x release notes](https://developer.gnome.org/gtk3/stable/gtk-migrating-2-to-3.html)
- [4.x release notes](https://docs.gtk.org/gtk4/migrating-3to4.html)
- [3.x release notes](https://developer.gnome.org/gtk3/unstable/gtk-migrating-2-to-3.html)
- [4.x release notes](https://developer.gnome.org/gtk4/unstable/gtk-migrating-3-to-4.html)
Licensing terms
---------------
@@ -186,8 +156,4 @@ GTK is released under the terms of the GNU Lesser General Public License,
version 2.1 or, at your option, any later version, as published by the Free
Software Foundation.
Please, see the [`COPYING`](./COPYING) file for further information.
GTK includes a small number of source files under the Apache license:
- A fork of the roaring bitmaps implementation in [gtk/roaring](./gtk/roaring)
- An adaptation of timsort from python in [gtk/timsort](./gtk/timsort)
Please, see the `COPYING` file for further information.

View File

@@ -1,43 +0,0 @@
diff -ur lua-5.1.4/src/Makefile lua-5.1.4-new/src/Makefile
--- lua-5.1.4/src/Makefile 2008-01-19 20:37:58.000000000 +0100
+++ lua-5.1.4-new/src/Makefile 2012-02-23 18:26:43.000000000 +0100
@@ -23,6 +23,7 @@
PLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris
LUA_A= liblua.a
+LUA_SO= liblua.so
CORE_O= lapi.o lcode.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o \
lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o \
lundump.o lvm.o lzio.o
@@ -36,7 +37,7 @@
LUAC_O= luac.o print.o
ALL_O= $(CORE_O) $(LIB_O) $(LUA_O) $(LUAC_O)
-ALL_T= $(LUA_A) $(LUA_T) $(LUAC_T)
+ALL_T= $(LUA_A) $(LUA_SO) $(LUA_T) $(LUAC_T)
ALL_A= $(LUA_A)
default: $(PLAT)
@@ -51,6 +52,11 @@
$(AR) $@ $?
$(RANLIB) $@
+$(LUA_SO): $(CORE_O) $(LIB_O)
+ $(CC) -shared -ldl -Wl,-soname,$(LUA_SO).$(V) -o $@.$(R) $? -lm $(MYLDFLAGS)
+ ln -sf $(LUA_SO).$(R) $(LUA_SO).$(V)
+ ln -sf $(LUA_SO).$(R) $(LUA_SO)
+
$(LUA_T): $(LUA_O) $(LUA_A)
$(CC) -o $@ $(MYLDFLAGS) $(LUA_O) $(LUA_A) $(LIBS)
--- lua-5.1.4/Makefile 2008-08-12 02:40:48.000000000 +0200
+++ lua-5.1.4-new/Makefile 2012-02-23 19:06:32.000000000 +0100
@@ -53,7 +53,7 @@
all: $(PLAT)
$(PLATS) clean:
- cd src && $(MAKE) $@
+ cd src && $(MAKE) $@ V=$(V) R=$(R)
test: dummy
src/lua test/hello.lua

View File

@@ -1,207 +1,72 @@
{
"app-id" : "org.gtk.Demo4",
"runtime" : "org.gnome.Platform",
"runtime-version" : "master",
"sdk" : "org.gnome.Sdk",
"command" : "gtk4-demo",
"tags" : [
"devel",
"development",
"nightly"
],
"desktop-file-name-prefix" : "(Development) ",
"finish-args" : [
"app-id": "org.gtk.Demo4",
"runtime": "org.gnome.Platform",
"runtime-version": "master",
"sdk": "org.gnome.Sdk",
"command": "gtk4-demo",
"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.*"
"--talk-name=org.gtk.vfs", "--talk-name=org.gtk.vfs.*"
],
"cleanup" : [
"cleanup": [
"/include",
"/lib/pkgconfig",
"/share/pkgconfig",
"/lib/pkgconfig", "/share/pkgconfig",
"/share/aclocal",
"/man",
"/share/man",
"/share/gtk-doc",
"*.la",
".a",
"/man", "/share/man", "/share/gtk-doc",
"*.la", ".a",
"/lib/girepository-1.0",
"/share/gir-1.0",
"/share/doc"
],
"modules" : [
"modules": [
{
"name" : "wayland",
"buildsystem" : "meson",
"buildsystem" : "autotools",
"builddir" : true,
"config-opts" : [
"-Ddocumentation=false"
"--disable-documentation"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.freedesktop.org/wayland/wayland.git",
"branch" : "main"
"url" : "https://github.com/wayland-project/wayland.git"
}
]
},
{
"name" : "graphene",
"buildsystem" : "meson",
"builddir" : true,
"config-opts" : [
"name": "graphene",
"buildsystem": "meson",
"builddir": true,
"config-opts": [
"--libdir=/app/lib",
"-Dtests=false",
"-Dbenchmarks=false"
],
"sources" : [
"sources": [
{
"type" : "git",
"url" : "https://github.com/ebassi/graphene.git"
"type": "git",
"url": "https://github.com/ebassi/graphene.git"
}
]
},
{
"name" : "libsass",
"buildsystem" : "meson",
"builddir" : true,
"config-opts" : [
"name": "gtk",
"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": "boost",
"buildsystem": "simple",
"build-commands": [
"./bootstrap.sh --prefix=/app --with-libraries=date_time,filesystem,iostreams,locale,regex,system,thread,python,program_options,test,serialization",
"./b2 --build-type=minimal link=shared -j $FLATPAK_BUILDER_N_JOBS",
"./b2 --build-type=minimal link=shared install"
],
"sources": [
{
"type": "archive",
"url": "https://boostorg.jfrog.io/artifactory/main/release/1.69.0/source/boost_1_69_0.tar.bz2",
"sha256": "8f32d4617390d1c2d16f26a27ab60d97807b35440d45891fa340fc2648b04406"
}
]
},
{
"name": "lua-5.1",
"buildsystem": "simple",
"build-commands": [
"make -j $FLATPAK_BUILDER_N_JOBS CFLAGS=\"$CFLAGS -fPIC -DLUA_USE_LINUX\" linux",
"make INSTALL_TOP=$FLATPAK_DEST TO_LIB='liblua.a liblua.so.5.1.5' install",
"ln -sf liblua.so.5.1.5 $FLATPAK_DEST/lib/liblua.so",
"ln -sf liblua.so.5.1.5 $FLATPAK_DEST/lib/liblua.so.5.1",
"install -Dm0644 etc/lua.pc $FLATPAK_DEST/lib/pkgconfig/lua.pc",
"ln -sf lua.pc $FLATPAK_DEST/lib/pkgconfig/lua51.pc",
"ln -sf lua.pc $FLATPAK_DEST/lib/pkgconfig/lua5.1.pc",
"ln -sf lua.pc $FLATPAK_DEST/lib/pkgconfig/lua-5.1.pc"
],
"sources": [
{
"type": "archive",
"url": "https://www.lua.org/ftp/lua-5.1.5.tar.gz",
"sha256": "2640fc56a795f29d28ef15e13c34a47e223960b0240e8cb0a82d9b0738695333"
},
{
"type": "patch",
"path": "lua-5.1.5-so.patch"
},
{
"type": "shell",
"commands": [
"sed -i \"s|/usr/local|$FLATPAK_DEST|\" etc/lua.pc src/luaconf.h"
]
}
],
"cleanup": [
"*.a",
"/bin",
"/include",
"/lib/pkgconfig",
"/man"
]
},
{
"name" : "highlight",
"buildsystem" : "simple",
"builddir" : true,
"build-commands" : [
"sed -i -e 's#^PREFIX = /usr#PREFIX = /app#' makefile",
"make",
"make install"
],
"sources" : [
{
"type" : "archive",
"url" : "http://www.andre-simon.de/zip/highlight-4.0.tar.bz2",
"sha256" : "f40dcba26e011a2c67df874f4d9b0238c2c6b065163ce8de3d8371b9dfce864d"
}
]
},
{
"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",
"-Denable_vulkan=no",
"-Dbuildtype=debugoptimized",
"-Dprofile=devel"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/gtk.git",
"branch" : "main"
"type": "git",
"url": "https://gitlab.gnome.org/GNOME/gtk.git"
}
]
}
],
"build-options" : {
"env" : {
"GSK_RENDERER" : "opengl"
}
}
]
}

View File

@@ -1,135 +1,72 @@
{
"app-id" : "org.gtk.IconBrowser4",
"runtime" : "org.gnome.Platform",
"runtime-version" : "master",
"sdk" : "org.gnome.Sdk",
"command" : "gtk4-icon-browser",
"tags" : [
"devel",
"development",
"nightly"
],
"desktop-file-name-prefix" : "(Development) ",
"finish-args" : [
"app-id": "org.gtk.IconBrowser4",
"runtime": "org.gnome.Platform",
"runtime-version": "master",
"sdk": "org.gnome.Sdk",
"command": "gtk4-icon-browser",
"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.*"
"--talk-name=org.gtk.vfs", "--talk-name=org.gtk.vfs.*"
],
"cleanup" : [
"cleanup": [
"/include",
"/lib/pkgconfig",
"/share/pkgconfig",
"/lib/pkgconfig", "/share/pkgconfig",
"/share/aclocal",
"/man",
"/share/man",
"/share/gtk-doc",
"*.la",
".a",
"/man", "/share/man", "/share/gtk-doc",
"*.la", ".a",
"/lib/girepository-1.0",
"/share/gir-1.0",
"/share/doc"
],
"modules" : [
"modules": [
{
"name" : "wayland",
"buildsystem" : "meson",
"buildsystem" : "autotools",
"builddir" : true,
"config-opts" : [
"-Ddocumentation=false"
"--disable-documentation"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.freedesktop.org/wayland/wayland.git",
"branch" : "main"
"url" : "https://github.com/wayland-project/wayland.git"
}
]
},
{
"name" : "graphene",
"buildsystem" : "meson",
"builddir" : true,
"config-opts" : [
"name": "graphene",
"buildsystem": "meson",
"builddir": true,
"config-opts": [
"--libdir=/app/lib",
"-Dtests=false",
"-Dbenchmarks=false"
],
"sources" : [
"sources": [
{
"type" : "git",
"url" : "https://github.com/ebassi/graphene.git"
"type": "git",
"url": "https://github.com/ebassi/graphene.git"
}
]
},
{
"name" : "libsass",
"buildsystem" : "meson",
"builddir" : true,
"config-opts" : [
"name": "gtk",
"buildsystem": "meson",
"builddir": true,
"config-opts": [
"--libdir=/app/lib"
],
"sources" : [
"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",
"-Denable_vulkan=no",
"-Dbuildtype=debugoptimized",
"-Dprofile=devel"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/gtk.git",
"branch" : "main"
"type": "git",
"url": "https://gitlab.gnome.org/GNOME/gtk.git"
}
]
}
],
"build-options" : {
"env" : {
}
}
]
}

View File

@@ -1,139 +1,72 @@
{
"app-id" : "org.gtk.WidgetFactory4",
"runtime" : "org.gnome.Platform",
"runtime-version" : "master",
"sdk" : "org.gnome.Sdk",
"command" : "gtk4-widget-factory",
"tags" : [
"devel",
"development",
"nightly"
],
"desktop-file-name-prefix" : "(Development) ",
"finish-args" : [
"app-id": "org.gtk.WidgetFactory4",
"runtime": "org.gnome.Platform",
"runtime-version": "master",
"sdk": "org.gnome.Sdk",
"command": "gtk4-widget-factory",
"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.*"
"--talk-name=org.gtk.vfs", "--talk-name=org.gtk.vfs.*"
],
"cleanup" : [
"cleanup": [
"/include",
"/lib/pkgconfig",
"/share/pkgconfig",
"/lib/pkgconfig", "/share/pkgconfig",
"/share/aclocal",
"/man",
"/share/man",
"/share/gtk-doc",
"*.la",
".a",
"/man", "/share/man", "/share/gtk-doc",
"*.la", ".a",
"/lib/girepository-1.0",
"/share/gir-1.0",
"/share/doc"
],
"modules" : [
"modules": [
{
"name" : "wayland",
"buildsystem" : "meson",
"buildsystem" : "autotools",
"builddir" : true,
"config-opts" : [
"-Ddocumentation=false"
"--disable-documentation"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.freedesktop.org/wayland/wayland.git",
"branch" : "main"
"url" : "https://github.com/wayland-project/wayland.git"
}
]
},
{
"name" : "graphene",
"buildsystem" : "meson",
"builddir" : true,
"config-opts" : [
"name": "graphene",
"buildsystem": "meson",
"builddir": true,
"config-opts": [
"--libdir=/app/lib",
"-Dtests=false",
"-Dbenchmarks=false"
],
"sources" : [
"sources": [
{
"type" : "git",
"url" : "https://github.com/ebassi/graphene.git"
"type": "git",
"url": "https://github.com/ebassi/graphene.git"
}
]
},
{
"name" : "libsass",
"buildsystem" : "meson",
"builddir" : true,
"config-opts" : [
"name": "gtk",
"buildsystem": "meson",
"builddir": true,
"config-opts": [
"--libdir=/app/lib"
],
"sources" : [
"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",
"-Denable_vulkan=no",
"-Dbuildtype=debugoptimized",
"-Dprofile=devel"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/gtk.git",
"branch" : "main"
"type": "git",
"url": "https://gitlab.gnome.org/GNOME/gtk.git"
}
]
}
],
"build-options" : {
"env" : {
"DBUS_SESSION_BUS_ADDRESS" : "''",
"GSK_RENDERER" : "opengl",
"GDK_DEBUG" : "vulkan-disable",
"G_ENABLE_DEBUG" : "true"
}
}
]
}

View File

@@ -1,39 +0,0 @@
#!/usr/bin/env python3
import os
import shutil
import subprocess
from pathlib import PurePath
stylesheets = [
'gtk/theme/Default/Default-light.css',
'gtk/theme/Default/Default-dark.css',
'gtk/theme/Default/Default-hc.css',
'gtk/theme/Default/Default-hc-dark.css',
]
references = [
'docs/reference/gtk/gtk4',
'docs/reference/gsk/gsk4',
'docs/reference/gdk/gdk4',
'docs/reference/gdk/gdk4-wayland',
'docs/reference/gdk/gdk4-x11',
]
sourceroot = os.environ.get('MESON_SOURCE_ROOT')
buildroot = os.environ.get('MESON_BUILD_ROOT')
distroot = os.environ.get('MESON_DIST_ROOT')
for stylesheet in stylesheets:
stylesheet_path = PurePath(stylesheet)
src = PurePath(sourceroot, stylesheet_path.with_suffix('.scss'))
dst = PurePath(distroot, stylesheet_path)
subprocess.call(['sassc', '-a', '-M', '-t', 'compact', src, dst])
for reference in references:
src_path = os.path.join(buildroot, reference)
if os.path.isdir(src_path):
dst_path = os.path.join(distroot, reference)
shutil.copytree(src_path, dst_path)

View File

@@ -1,26 +0,0 @@
#!/usr/bin/env python3
import os
import subprocess
import sys
repodir = sys.argv[1]
profile = sys.argv[2]
sys.stdout.write("/* This file is auto-generated. Do not edit. */\n")
sys.stdout.write("#pragma once\n")
sys.stdout.write("\n")
sys.stdout.write(f"#define PROFILE \"{profile}\"\n")
short_sha = os.environ.get('CI_COMMIT_SHORT_SHA')
if short_sha is None:
cmd = ["git", "-C", repodir, "rev-parse", "--short", "HEAD"]
try:
with subprocess.Popen(cmd, stdout=subprocess.PIPE) as p:
short_sha = p.stdout.read().decode('utf-8').rstrip("\n")
except FileNotFoundError:
short_sha = ''
if profile != 'default':
short_sha = 'devel'
sys.stdout.write(f"#define VCS_TAG \"{short_sha}\"\n")

View File

@@ -1,45 +1,31 @@
#!/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]
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...')
gtk_moduledir = os.path.join(gtk_libdir, 'gtk-' + gtk_api_version, gtk_abi_version)
gtk_printmodule_dir = os.path.join(gtk_moduledir, 'printbackends')
gtk_immodule_dir = os.path.join(gtk_moduledir, 'immodules')
print('Compiling GSettings schemas...')
subprocess.call(['glib-compile-schemas',
os.path.join(gtk_datadir, 'glib-2.0', 'schemas')])
print('Updating icon cache...')
subprocess.call(['gtk4-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])
subprocess.call(['gio-querymodules', gtk_printmodule_dir])
print('Updating module cache for input methods...')
os.makedirs(gtk_immodule_dir, exist_ok=True)
subprocess.call(['gio-querymodules', gtk_immodule_dir])

297
config.h.meson Normal file
View File

@@ -0,0 +1,297 @@
/* config.h.in. Generated from configure.ac by autoheader. */
/* always defined to indicate that i18n is enabled */
#define ENABLE_NLS 1
/* The prefix for our gettext translation domains. */
#mesondefine GETTEXT_PACKAGE
/* Disable deprecation warnings from glib */
#mesondefine GLIB_DISABLE_DEPRECATION_WARNINGS
/* Define the location where the catalogs will be installed */
#mesondefine GTK_LOCALEDIR
/* Define to 1 if you have the `bind_textdomain_codeset' function. */
#mesondefine HAVE_BIND_TEXTDOMAIN_CODESET
/* Have the cloudproviders library */
#mesondefine HAVE_CLOUDPROVIDERS
/* define if we have colord */
#mesondefine HAVE_COLORD
/* Define to 1 if you have the <crt_externs.h> header file. */
#mesondefine HAVE_CRT_EXTERNS_H
/* Define to 1 if you have the `dcgettext' function. */
#mesondefine HAVE_DCGETTEXT
/* Define to 1 if you have the declaration of `isinf', and to 0 if you don't.
*/
#mesondefine HAVE_DECL_ISINF
/* Define to 1 if you have the declaration of `isnan', and to 0 if you don't.
*/
#mesondefine HAVE_DECL_ISNAN
/* Define to 1 if you have the <dlfcn.h> header file. */
#mesondefine HAVE_DLFCN_H
/* Have the ffmpeg library */
#mesondefine HAVE_FFMPEG
/* Define to 1 if you have the <ftw.h> header file. */
#mesondefine HAVE_FTW_H
/* Define to 1 if you have the `getpagesize' function. */
#mesondefine HAVE_GETPAGESIZE
/* Define to 1 if you have the `getresuid' function. */
#mesondefine HAVE_GETRESUID
/* Define if gio-unix is available */
#mesondefine HAVE_GIO_UNIX
/* Define if GStreamer support is available */
#mesondefine HAVE_GSTREAMER
/* Define to 1 if you have the <inttypes.h> header file. */
#mesondefine HAVE_INTTYPES_H
/* Define to 1 if the system has the type `IPrintDialogCallback'. */
#mesondefine HAVE_IPRINTDIALOGCALLBACK
/* Define to 1 if you have the <locale.h> header file. */
#mesondefine HAVE_LOCALE_H
/* Define to 1 if you have the `lstat' function. */
#mesondefine HAVE_LSTAT
/* Define to 1 if you have the `mallinfo' function. */
#mesondefine HAVE_MALLINFO
/* Define to 1 if you have the <memory.h> header file. */
#mesondefine HAVE_MEMORY_H
/* Define to 1 if you have the `mkstemp' function. */
#mesondefine HAVE_MKSTEMP
/* Define to 1 if you have a working `mmap' system call. */
#mesondefine HAVE_MMAP
/* Define to 1 if you have the `nearbyint' function. */
#mesondefine HAVE_NEARBYINT
/* Define to 1 if you have the `posix_fallocate' function. */
#mesondefine HAVE_POSIX_FALLOCATE
/* Have the Xrandr extension library */
#mesondefine HAVE_RANDR
/* Have the Xrandr 1.5 extension library */
#mesondefine HAVE_RANDR15
/* Define to 1 if you have the `rint' function. */
#mesondefine HAVE_RINT
/* Define to 1 if you have the `round' function. */
#mesondefine HAVE_ROUND
/* Define to 1 if you have the `sincos' function. */
#mesondefine HAVE_SINCOS
/* Define to 1 if you have the `log2` function */
#mesondefine HAVE_LOG2
/* Define to 1 if you ahve the `exp2` function */
#mesondefine HAVE_EXP2
/* Define to 1 if you have the <stdint.h> header file. */
#mesondefine HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#mesondefine HAVE_STDLIB_H
/* Define to 1 if you have the <strings.h> header file. */
#mesondefine HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#mesondefine HAVE_STRING_H
/* Define to 1 if you have the <sys/mman.h> header file. */
#mesondefine HAVE_SYS_MMAN_H
/* Define to 1 if you have the <sys/param.h> header file. */
#mesondefine HAVE_SYS_PARAM_H
/* Have the sysprof-capture library */
#mesondefine HAVE_SYSPROF_CAPTURE
/* Define to 1 if you have the <sys/stat.h> header file. */
#mesondefine HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/time.h> header file. */
#mesondefine HAVE_SYS_TIME_H
/* Define to 1 if you have the <sys/types.h> header file. */
#mesondefine HAVE_SYS_TYPES_H
/* Define to 1 if you have the <unistd.h> header file. */
#mesondefine HAVE_UNISTD_H
/* Have the XCOMPOSITE X extension */
#mesondefine HAVE_XCOMPOSITE
/* Have the Xcursor library */
#mesondefine HAVE_XCURSOR
/* Have the XDAMAGE X extension */
#mesondefine HAVE_XDAMAGE
/* Have the XFIXES X extension */
#mesondefine HAVE_XFIXES
/* Define to 1 if XFree Xinerama is available */
#mesondefine HAVE_XFREE_XINERAMA
/* Have XGenericEvent */
#mesondefine HAVE_XGENERICEVENTS
/* Define to use XKB extension */
#mesondefine HAVE_XKB
/* Have the SYNC extension library */
#mesondefine HAVE_XSYNC
/* Define to 1 if you have the `_lock_file' function */
#mesondefine HAVE__LOCK_FILE
/* Define to 1 if you have the `flockfile' function */
#mesondefine HAVE_FLOCKFILE
/* Define if _NL_MEASUREMENT_MEASUREMENT is available */
#mesondefine HAVE__NL_MEASUREMENT_MEASUREMENT
/* Define if _NL_PAPER_HEIGHT is available */
#mesondefine HAVE__NL_PAPER_HEIGHT
/* Define if _NL_PAPER_WIDTH is available */
#mesondefine HAVE__NL_PAPER_WIDTH
/* Define if _NL_TIME_FIRST_WEEKDAY is available */
#mesondefine HAVE__NL_TIME_FIRST_WEEKDAY
/* Define to the sub-directory where libtool stores uninstalled libraries. */
#mesondefine LT_OBJDIR
/* Define to 1 if your C compiler doesn't accept -c and -o together. */
#mesondefine NO_MINUS_C_MINUS_O
/* Define to the address where bug reports for this package should be sent. */
#mesondefine PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#mesondefine PACKAGE_NAME
/* Define to the full name and version of this package. */
#mesondefine PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#mesondefine PACKAGE_TARNAME
/* Define to the home page for this package. */
#mesondefine PACKAGE_URL
/* Define to the version of this package. */
#mesondefine PACKAGE_VERSION
/* Use NSBundle functions to determine load paths for libraries, translations,
etc. */
#mesondefine QUARTZ_RELOCATION
/* Define to 1 if you have the ANSI C header files. */
#mesondefine STDC_HEADERS
/* Enable extensions on AIX 3, Interix. */
#ifndef _ALL_SOURCE
# undef _ALL_SOURCE
#endif
/* Enable GNU extensions on systems that have them. */
#ifndef _GNU_SOURCE
# undef _GNU_SOURCE
#endif
/* Enable threading extensions on Solaris. */
#ifndef _POSIX_PTHREAD_SEMANTICS
# undef _POSIX_PTHREAD_SEMANTICS
#endif
/* Enable extensions on HP NonStop. */
#ifndef _TANDEM_SOURCE
# undef _TANDEM_SOURCE
#endif
/* Enable general extensions on Solaris. */
#ifndef __EXTENSIONS__
# undef __EXTENSIONS__
#endif
/* Define to 1 if XInput 2.2 is available */
#mesondefine XINPUT_2_2
/* Define to 1 if the X Window System is missing or not being used. */
#mesondefine X_DISPLAY_MISSING
/* Enable large inode numbers on Mac OS X 10.5. */
#ifndef _DARWIN_USE_64_BIT_INODE
# define _DARWIN_USE_64_BIT_INODE 1
#endif
/* Number of bits in a file offset, on hosts where this is settable. */
#mesondefine _FILE_OFFSET_BITS
/* defines how to decorate public symbols while building */
#mesondefine _GDK_EXTERN
/* Define for large files, on AIX-style hosts. */
#mesondefine _LARGE_FILES
/* Define to 1 if on MINIX. */
#mesondefine _MINIX
/* Define to 2 if the system does not provide POSIX.1 features except with
this defined. */
#mesondefine _POSIX_1_SOURCE
/* Define to 1 if you need to in order for `stat' and other things to work. */
#mesondefine _POSIX_SOURCE
/* Define to `int' if <sys/types.h> doesn't define. */
#mesondefine gid_t
/* Define to `int' if <sys/types.h> doesn't define. */
#mesondefine uid_t
/* Define to 1 if linux/memfd.h exists */
#mesondefine HAVE_LINUX_MEMFD_H
#mesondefine HAVE_LINUX_INPUT_H
#mesondefine HAVE_DEV_EVDEV_INPUT_H
#mesondefine GTK_SYSCONFDIR
#mesondefine GTK_LOCALEDIR
#mesondefine GTK_DATADIR
#mesondefine GTK_LIBDIR
#mesondefine GTK_PRINT_BACKENDS
#mesondefine HAVE_CAIRO_SCRIPT_INTERPRETER
#mesondefine HAVE_HARFBUZZ
#mesondefine HAVE_PANGOFT
#mesondefine ISO_CODES_PREFIX

View File

@@ -81,11 +81,11 @@ constraint_editor_application_activate (GApplication *app)
static void
constraint_editor_application_open (GApplication *app,
GFile **files,
int n_files,
const char *hint)
gint n_files,
const gchar *hint)
{
ConstraintEditorWindow *win;
int i;
gint i;
for (i = 0; i < n_files; i++)
{

View File

@@ -36,7 +36,7 @@ struct _ConstraintEditorWindow
G_DEFINE_TYPE(ConstraintEditorWindow, constraint_editor_window, GTK_TYPE_APPLICATION_WINDOW);
static GtkConstraintTarget *
find_target (GListModel *model,
find_target (GListModel *model,
GtkConstraintTarget *orig)
{
const char *name;
@@ -163,30 +163,20 @@ constraint_editor_window_load (ConstraintEditorWindow *self,
GtkConstraint *clone;
GtkConstraintTarget *target;
GtkConstraintTarget *source;
GtkConstraintAttribute source_attr;
item = g_list_model_get_item (list, i);
constraint = GTK_CONSTRAINT (item);
target = gtk_constraint_get_target (constraint);
source = gtk_constraint_get_source (constraint);
source_attr = gtk_constraint_get_source_attribute (constraint);
if (source == NULL && source_attr == GTK_CONSTRAINT_ATTRIBUTE_NONE)
clone = gtk_constraint_new_constant (find_target (constraint_view_get_model (CONSTRAINT_VIEW (self->view)), target),
clone = gtk_constraint_new (find_target (constraint_view_get_model (CONSTRAINT_VIEW (self->view)), target),
gtk_constraint_get_target_attribute (constraint),
gtk_constraint_get_relation (constraint),
find_target (constraint_view_get_model (CONSTRAINT_VIEW (self->view)), source),
gtk_constraint_get_target_attribute (constraint),
gtk_constraint_get_multiplier (constraint),
gtk_constraint_get_constant (constraint),
gtk_constraint_get_strength (constraint));
else
clone = gtk_constraint_new (find_target (constraint_view_get_model (CONSTRAINT_VIEW (self->view)), target),
gtk_constraint_get_target_attribute (constraint),
gtk_constraint_get_relation (constraint),
find_target (constraint_view_get_model (CONSTRAINT_VIEW (self->view)), source),
source_attr,
gtk_constraint_get_multiplier (constraint),
gtk_constraint_get_constant (constraint),
gtk_constraint_get_strength (constraint));
constraint_view_add_constraint (CONSTRAINT_VIEW (self->view), clone);
@@ -203,7 +193,7 @@ constraint_editor_window_load (ConstraintEditorWindow *self,
static void
open_response_cb (GtkNativeDialog *dialog,
int response,
gint response,
ConstraintEditorWindow *self)
{
gtk_native_dialog_hide (dialog);
@@ -231,12 +221,9 @@ open_cb (GtkWidget *button,
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_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), ".");
g_signal_connect (dialog, "response", G_CALLBACK (open_response_cb), self);
gtk_native_dialog_show (GTK_NATIVE_DIALOG (dialog));
}
@@ -295,7 +282,7 @@ serialize_model (GListModel *list)
static void
save_response_cb (GtkNativeDialog *dialog,
int response,
gint response,
ConstraintEditorWindow *self)
{
gtk_native_dialog_hide (dialog);
@@ -303,37 +290,29 @@ save_response_cb (GtkNativeDialog *dialog,
if (response == GTK_RESPONSE_ACCEPT)
{
GListModel *model;
GFile *file;
char *text;
char *text, *filename;
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,
NULL,
NULL,
&error);
if (error != NULL)
{
GtkWidget *message_dialog;
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),
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
if (!g_file_set_contents (filename, text, -1, &error))
{
GtkWidget *dialog;
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 (dialog),
"%s", error->message);
g_signal_connect (message_dialog, "response", G_CALLBACK (gtk_window_destroy), NULL);
gtk_widget_show (message_dialog);
g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
gtk_widget_show (dialog);
g_error_free (error);
}
g_free (text);
g_object_unref (file);
g_free (filename);
}
gtk_native_dialog_destroy (dialog);
@@ -350,12 +329,9 @@ save_cb (GtkWidget *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_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), ".");
g_signal_connect (dialog, "response", G_CALLBACK (save_response_cb), self);
gtk_native_dialog_show (GTK_NATIVE_DIALOG (dialog));
}
@@ -413,7 +389,7 @@ constraint_editor_done (ConstraintEditor *editor,
g_clear_object (&old_constraint);
gtk_window_destroy (GTK_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (editor), GTK_TYPE_WINDOW)));
gtk_widget_destroy (gtk_widget_get_ancestor (GTK_WIDGET (editor), GTK_TYPE_WINDOW));
}
static void
@@ -424,7 +400,7 @@ edit_constraint (ConstraintEditorWindow *win,
ConstraintEditor *editor;
GListModel *model;
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (win));
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
if (constraint)
@@ -436,7 +412,7 @@ edit_constraint (ConstraintEditorWindow *win,
editor = constraint_editor_new (model, constraint);
gtk_window_set_child (GTK_WINDOW (window), GTK_WIDGET (editor));
gtk_container_add (GTK_CONTAINER (window), GTK_WIDGET (editor));
g_signal_connect (editor, "done", G_CALLBACK (constraint_editor_done), win);
@@ -454,7 +430,7 @@ guide_editor_done (GuideEditor *editor,
GtkConstraintGuide *guide,
ConstraintEditorWindow *win)
{
gtk_window_destroy (GTK_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (editor), GTK_TYPE_WINDOW)));
gtk_widget_destroy (gtk_widget_get_ancestor (GTK_WIDGET (editor), GTK_TYPE_WINDOW));
}
static void
@@ -464,13 +440,13 @@ edit_guide (ConstraintEditorWindow *win,
GtkWidget *window;
GuideEditor *editor;
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (win));
gtk_window_set_title (GTK_WINDOW (window), "Edit Guide");
editor = guide_editor_new (guide);
gtk_window_set_child (GTK_WINDOW (window), GTK_WIDGET (editor));
gtk_container_add (GTK_CONTAINER (window), GTK_WIDGET (editor));
g_signal_connect (editor, "done", G_CALLBACK (guide_editor_done), win);
gtk_widget_show (window);
@@ -497,6 +473,8 @@ constraint_editor_window_class_init (ConstraintEditorWindowClass *class)
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
g_type_ensure (CONSTRAINT_VIEW_TYPE);
object_class->finalize = constraint_editor_window_finalize;
gtk_widget_class_set_template_from_resource (widget_class,
@@ -609,33 +587,30 @@ create_widget_func (gpointer item,
g_object_bind_property (item, "name",
label, "label",
G_BINDING_DEFAULT);
gtk_widget_set_margin_start (label, 10);
gtk_widget_set_margin_end (label, 10);
gtk_widget_set_margin_top (label, 10);
gtk_widget_set_margin_bottom (label, 10);
g_object_set (label, "margin", 10, NULL);
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
gtk_widget_set_hexpand (label, TRUE);
gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (row), box);
gtk_box_append (GTK_BOX (box), label);
gtk_container_add (GTK_CONTAINER (row), box);
gtk_container_add (GTK_CONTAINER (box), label);
if (GTK_IS_CONSTRAINT (item) || GTK_IS_CONSTRAINT_GUIDE (item))
{
button = gtk_button_new_from_icon_name ("document-edit-symbolic");
gtk_button_set_has_frame (GTK_BUTTON (button), FALSE);
gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
g_signal_connect (button, "clicked", G_CALLBACK (row_edit), win);
g_object_set_data (G_OBJECT (row), "edit", button);
gtk_box_append (GTK_BOX (box), button);
gtk_container_add (GTK_CONTAINER (box), button);
button = gtk_button_new_from_icon_name ("edit-delete-symbolic");
gtk_button_set_has_frame (GTK_BUTTON (button), FALSE);
gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
g_signal_connect (button, "clicked", G_CALLBACK (row_delete), win);
gtk_box_append (GTK_BOX (box), button);
gtk_container_add (GTK_CONTAINER (box), button);
}
else if (GTK_IS_WIDGET (item))
{
button = gtk_button_new_from_icon_name ("edit-delete-symbolic");
gtk_button_set_has_frame (GTK_BUTTON (button), FALSE);
gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
g_signal_connect (button, "clicked", G_CALLBACK (row_delete), win);
gtk_box_append (GTK_BOX (box), button);
gtk_container_add (GTK_CONTAINER (box), button);
}
g_free (freeme);

View File

@@ -1,11 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="ConstraintEditorWindow" parent="GtkApplicationWindow">
<style>
<class name="devel"/>
</style>
<property name="title" translatable="yes">GTK Constraint Editor</property>
<property name="default-width">1024</property>
<property name="default-height">768</property>
<child type="titlebar">
<object class="GtkHeaderBar" id="header">
<property name="title" translatable="yes">GTK Constraint Editor</property>
<property name="show-title-buttons">1</property>
<child type="start">
<object class="GtkButton">
<property name="icon-name">document-open-symbolic</property>

View File

@@ -142,9 +142,6 @@ get_target (GListModel *model,
{
int i;
if (id == NULL)
return NULL;
if (strcmp ("super", id) == 0)
return NULL;
@@ -215,22 +212,6 @@ get_relation_nick (GtkConstraintRelation relation)
return nick;
}
static const char *
get_relation_display_name (GtkConstraintRelation relation)
{
switch (relation)
{
case GTK_CONSTRAINT_RELATION_LE:
return "";
case GTK_CONSTRAINT_RELATION_EQ:
return "=";
case GTK_CONSTRAINT_RELATION_GE:
return "";
default:
return "?";
}
}
static GtkConstraintStrength
get_strength (const char *id)
{
@@ -350,7 +331,6 @@ source_attr_changed (ConstraintEditor *editor)
{
gtk_widget_set_sensitive (editor->source, TRUE);
gtk_widget_set_sensitive (editor->multiplier, TRUE);
gtk_editable_set_text (GTK_EDITABLE (editor->multiplier), "1");
}
}
@@ -367,7 +347,7 @@ constraint_editor_constraint_to_string (GtkConstraint *constraint)
name = get_target_name (gtk_constraint_get_target (constraint));
attr = get_attr_nick (gtk_constraint_get_target_attribute (constraint));
relation = get_relation_display_name (gtk_constraint_get_relation (constraint));
relation = get_relation_nick (gtk_constraint_get_relation (constraint));
if (name == NULL)
name = "[ ]";
@@ -461,12 +441,8 @@ update_preview (ConstraintEditor *editor)
static void
update_button (ConstraintEditor *editor)
{
const char *target = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->target));
const char *source = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->source));
const char *source_attr = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->source_attr));
if (target &&
(source || (source_attr && get_target_attr (source_attr) == GTK_CONSTRAINT_ATTRIBUTE_NONE)))
if (gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->target)) != NULL &&
gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->source)) != NULL)
gtk_widget_set_sensitive (editor->button, TRUE);
else
gtk_widget_set_sensitive (editor->button, FALSE);

View File

@@ -3,18 +3,15 @@
<template class="ConstraintEditor" parent="GtkWidget">
<child>
<object class="GtkGrid" id="grid">
<property name="margin-start">20</property>
<property name="margin-end">20</property>
<property name="margin-top">20</property>
<property name="margin-bottom">20</property>
<property name="margin">20</property>
<property name="row-spacing">10</property>
<property name="column-spacing">10</property>
<child>
<object class="GtkLabel">
<property name="label">Target</property>
<layout>
<property name="column">0</property>
<property name="row">1</property>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</layout>
</object>
</child>
@@ -23,8 +20,8 @@
<signal name="changed" handler="update_preview" swapped="yes"/>
<signal name="changed" handler="update_button" swapped="yes"/>
<layout>
<property name="column">1</property>
<property name="row">1</property>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
</layout>
</object>
</child>
@@ -32,8 +29,8 @@
<object class="GtkComboBoxText" id="target_attr">
<signal name="changed" handler="update_preview" swapped="yes"/>
<layout>
<property name="column">2</property>
<property name="row">1</property>
<property name="left-attach">2</property>
<property name="top-attach">1</property>
</layout>
</object>
</child>
@@ -41,8 +38,8 @@
<object class="GtkLabel">
<property name="label">Relation</property>
<layout>
<property name="column">0</property>
<property name="row">2</property>
<property name="left-attach">0</property>
<property name="top-attach">2</property>
</layout>
</object>
</child>
@@ -50,8 +47,8 @@
<object class="GtkComboBoxText" id="relation">
<signal name="changed" handler="update_preview" swapped="yes"/>
<layout>
<property name="column">1</property>
<property name="row">2</property>
<property name="left-attach">1</property>
<property name="top-attach">2</property>
</layout>
</object>
</child>
@@ -59,8 +56,8 @@
<object class="GtkLabel">
<property name="label">Source</property>
<layout>
<property name="column">0</property>
<property name="row">3</property>
<property name="left-attach">0</property>
<property name="top-attach">3</property>
</layout>
</object>
</child>
@@ -69,8 +66,8 @@
<signal name="changed" handler="update_preview" swapped="yes"/>
<signal name="changed" handler="update_button" swapped="yes"/>
<layout>
<property name="column">1</property>
<property name="row">3</property>
<property name="left-attach">1</property>
<property name="top-attach">3</property>
</layout>
</object>
</child>
@@ -78,10 +75,9 @@
<object class="GtkComboBoxText" id="source_attr">
<signal name="changed" handler="update_preview" swapped="yes"/>
<signal name="changed" handler="source_attr_changed" swapped="yes"/>
<signal name="changed" handler="update_button" swapped="yes"/>
<layout>
<property name="column">2</property>
<property name="row">3</property>
<property name="left-attach">2</property>
<property name="top-attach">3</property>
</layout>
</object>
</child>
@@ -89,8 +85,8 @@
<object class="GtkLabel">
<property name="label">Multiplier</property>
<layout>
<property name="column">0</property>
<property name="row">4</property>
<property name="left-attach">0</property>
<property name="top-attach">4</property>
</layout>
</object>
</child>
@@ -98,8 +94,8 @@
<object class="GtkEntry" id="multiplier">
<signal name="changed" handler="update_preview" swapped="yes"/>
<layout>
<property name="column">1</property>
<property name="row">4</property>
<property name="left-attach">1</property>
<property name="top-attach">4</property>
</layout>
</object>
</child>
@@ -107,8 +103,8 @@
<object class="GtkLabel">
<property name="label">Constant</property>
<layout>
<property name="column">0</property>
<property name="row">5</property>
<property name="left-attach">0</property>
<property name="top-attach">5</property>
</layout>
</object>
</child>
@@ -116,8 +112,8 @@
<object class="GtkEntry" id="constant">
<signal name="changed" handler="update_preview" swapped="yes"/>
<layout>
<property name="column">1</property>
<property name="row">5</property>
<property name="left-attach">1</property>
<property name="top-attach">5</property>
</layout>
</object>
</child>
@@ -125,16 +121,16 @@
<object class="GtkLabel">
<property name="label">Strength</property>
<layout>
<property name="column">0</property>
<property name="row">6</property>
<property name="left-attach">0</property>
<property name="top-attach">6</property>
</layout>
</object>
</child>
<child>
<object class="GtkComboBoxText" id="strength">
<layout>
<property name="column">1</property>
<property name="row">6</property>
<property name="left-attach">1</property>
<property name="top-attach">6</property>
</layout>
</object>
</child>
@@ -142,8 +138,8 @@
<object class="GtkLabel" id="preview">
<property name="xalign">0</property>
<layout>
<property name="column">1</property>
<property name="row">7</property>
<property name="left-attach">1</property>
<property name="top-attach">7</property>
<property name="column-span">2</property>
</layout>
<attributes>
@@ -156,8 +152,8 @@
<property name="label">Create</property>
<signal name="clicked" handler="create_constraint"/>
<layout>
<property name="column">2</property>
<property name="row">8</property>
<property name="left-attach">2</property>
<property name="top-attach">8</property>
</layout>
</object>
</child>

View File

@@ -77,7 +77,7 @@ update_weak_position (ConstraintView *self,
GTK_CONSTRAINT_RELATION_EQ,
x,
GTK_CONSTRAINT_STRENGTH_WEAK);
g_object_set_data (G_OBJECT (constraint), "internal", (char *)"yes");
g_object_set_data (G_OBJECT (constraint), "internal", "yes");
gtk_constraint_layout_add_constraint (GTK_CONSTRAINT_LAYOUT (manager),
constraint);
g_object_set_data (G_OBJECT (child), "x-constraint", constraint);
@@ -97,7 +97,7 @@ update_weak_position (ConstraintView *self,
GTK_CONSTRAINT_RELATION_EQ,
y,
GTK_CONSTRAINT_STRENGTH_WEAK);
g_object_set_data (G_OBJECT (constraint), "internal", (char *)"yes");
g_object_set_data (G_OBJECT (constraint), "internal", "yes");
gtk_constraint_layout_add_constraint (GTK_CONSTRAINT_LAYOUT (manager),
constraint);
g_object_set_data (G_OBJECT (child), "y-constraint", constraint);
@@ -169,30 +169,28 @@ constraint_view_init (ConstraintView *self)
GListModel *guides;
GListModel *children;
GListModel *constraints;
GtkFilter *filter;
manager = gtk_constraint_layout_new ();
gtk_widget_set_layout_manager (GTK_WIDGET (self), manager);
guides = gtk_constraint_layout_observe_guides (GTK_CONSTRAINT_LAYOUT (manager));
all_constraints = gtk_constraint_layout_observe_constraints (GTK_CONSTRAINT_LAYOUT (manager));
filter = GTK_FILTER (gtk_custom_filter_new (omit_internal, NULL, NULL));
constraints = (GListModel *)gtk_filter_list_model_new (all_constraints, filter);
all_children = gtk_widget_observe_children (GTK_WIDGET (self));
filter = GTK_FILTER (gtk_custom_filter_new (omit_internal, NULL, NULL));
children = (GListModel *)gtk_filter_list_model_new (all_children, filter);
all_constraints = gtk_constraint_layout_observe_constraints (GTK_CONSTRAINT_LAYOUT (manager));
guides = gtk_constraint_layout_observe_guides (GTK_CONSTRAINT_LAYOUT (manager));
constraints = (GListModel *)gtk_filter_list_model_new (all_constraints, omit_internal, NULL, NULL);
children = (GListModel *)gtk_filter_list_model_new (all_children, omit_internal, NULL, NULL);
list = g_list_store_new (G_TYPE_LIST_MODEL);
g_list_store_append (list, children);
g_list_store_append (list, guides);
g_list_store_append (list, constraints);
self->model = G_LIST_MODEL (gtk_flatten_list_model_new (G_TYPE_OBJECT, G_LIST_MODEL (list)));
g_object_unref (children);
g_object_unref (guides);
g_object_unref (constraints);
g_object_unref (all_children);
g_object_unref (all_constraints);
g_object_unref (list);
self->model = G_LIST_MODEL (gtk_flatten_list_model_new (G_LIST_MODEL (list)));
controller = (GtkEventController *)gtk_gesture_drag_new ();
g_signal_connect (controller, "drag-begin", G_CALLBACK (drag_begin), self);
@@ -216,9 +214,9 @@ constraint_view_add_child (ConstraintView *view,
label = gtk_label_new (name);
frame = gtk_frame_new (NULL);
gtk_widget_add_css_class (frame, "child");
gtk_style_context_add_class (gtk_widget_get_style_context (frame), "child");
gtk_widget_set_name (frame, name);
gtk_frame_set_child (GTK_FRAME (frame), label);
gtk_container_add (GTK_CONTAINER (frame), label);
gtk_widget_set_parent (frame, GTK_WIDGET (view));
update_weak_position (view, frame, 100, 100);
@@ -259,9 +257,9 @@ constraint_view_add_guide (ConstraintView *view,
G_BINDING_DEFAULT);
frame = gtk_frame_new (NULL);
gtk_widget_add_css_class (frame, "guide");
g_object_set_data (G_OBJECT (frame), "internal", (char *)"yes");
gtk_frame_set_child (GTK_FRAME (frame), label);
gtk_style_context_add_class (gtk_widget_get_style_context (frame), "guide");
g_object_set_data (G_OBJECT (frame), "internal", "yes");
gtk_container_add (GTK_CONTAINER (frame), label);
gtk_widget_insert_after (frame, GTK_WIDGET (view), NULL);
g_object_set_data (G_OBJECT (guide), "frame", frame);
@@ -278,7 +276,7 @@ constraint_view_add_guide (ConstraintView *view,
names[i].attr,
1.0, 0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED);
g_object_set_data (G_OBJECT (constraint), "internal", (char *)"yes");
g_object_set_data (G_OBJECT (constraint), "internal", "yes");
gtk_constraint_layout_add_constraint (layout, constraint);
g_object_set_data (G_OBJECT (guide), names[i].name, constraint);
}

View File

@@ -23,7 +23,6 @@
#define CONSTRAINT_VIEW_TYPE (constraint_view_get_type ())
G_MODULE_EXPORT
G_DECLARE_FINAL_TYPE (ConstraintView, constraint_view, CONSTRAINT, VIEW, GtkWidget)
ConstraintView * constraint_view_new (void);

View File

@@ -78,7 +78,7 @@ get_strength (const char *id)
return strength;
}
static const char *
const char *
get_strength_nick (GtkConstraintStrength strength)
{
GEnumClass *class = g_type_class_ref (GTK_TYPE_CONSTRAINT_STRENGTH);
@@ -184,6 +184,58 @@ max_input (GtkSpinButton *spin_button,
return FALSE;
}
static gboolean
min_output (GtkSpinButton *spin_button)
{
GtkAdjustment *adjustment;
double value;
GtkWidget *box, *text;
adjustment = gtk_spin_button_get_adjustment (spin_button);
value = gtk_adjustment_get_value (adjustment);
box = gtk_widget_get_first_child (GTK_WIDGET (spin_button));
text = gtk_widget_get_first_child (box);
if (value == 0.0)
{
gtk_editable_set_text (GTK_EDITABLE (spin_button), "");
gtk_text_set_placeholder_text (GTK_TEXT (text), "unset");
return TRUE;
}
else
{
gtk_text_set_placeholder_text (GTK_TEXT (text), "");
return FALSE;
}
}
static gboolean
max_output (GtkSpinButton *spin_button)
{
GtkAdjustment *adjustment;
double value;
GtkWidget *box, *text;
adjustment = gtk_spin_button_get_adjustment (spin_button);
value = gtk_adjustment_get_value (adjustment);
box = gtk_widget_get_first_child (GTK_WIDGET (spin_button));
text = gtk_widget_get_first_child (box);
if (value == (double)G_MAXINT)
{
gtk_editable_set_text (GTK_EDITABLE (spin_button), "");
gtk_text_set_placeholder_text (GTK_TEXT (text), "unset");
return TRUE;
}
else
{
gtk_text_set_placeholder_text (GTK_TEXT (text), "");
return FALSE;
}
}
static void
guide_editor_constructed (GObject *object)
{
@@ -192,12 +244,16 @@ guide_editor_constructed (GObject *object)
guide_strength_combo (editor->strength);
g_signal_connect (editor->min_width, "input", G_CALLBACK (min_input), NULL);
g_signal_connect (editor->min_width, "output", G_CALLBACK (min_output), NULL);
g_signal_connect (editor->min_height, "input", G_CALLBACK (min_input), NULL);
g_signal_connect (editor->min_height, "output", G_CALLBACK (min_output), NULL);
g_signal_connect (editor->max_width, "input", G_CALLBACK (max_input), NULL);
g_signal_connect (editor->max_width, "output", G_CALLBACK (max_output), NULL);
g_signal_connect (editor->max_height, "input", G_CALLBACK (max_input), NULL);
g_signal_connect (editor->max_height, "output", G_CALLBACK (max_output), NULL);
if (editor->guide)
{

View File

@@ -45,18 +45,15 @@
<template class="GuideEditor" parent="GtkWidget">
<child>
<object class="GtkGrid" id="grid">
<property name="margin-start">20</property>
<property name="margin-end">20</property>
<property name="margin-top">20</property>
<property name="margin-bottom">20</property>
<property name="margin">20</property>
<property name="row-spacing">10</property>
<property name="column-spacing">10</property>
<child>
<object class="GtkLabel">
<property name="label">Name</property>
<layout>
<property name="column">0</property>
<property name="row">0</property>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</layout>
</object>
</child>
@@ -64,8 +61,8 @@
<object class="GtkEntry" id="name">
<property name="max-width-chars">20</property>
<layout>
<property name="column">1</property>
<property name="row">0</property>
<property name="left-attach">1</property>
<property name="top-attach">0</property>
<property name="column-span">2</property>
</layout>
</object>
@@ -74,8 +71,8 @@
<object class="GtkLabel">
<property name="label">Min Size</property>
<layout>
<property name="column">0</property>
<property name="row">1</property>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</layout>
</object>
</child>
@@ -84,8 +81,8 @@
<property name="adjustment">min_width_adj</property>
<property name="max-width-chars">5</property>
<layout>
<property name="column">1</property>
<property name="row">1</property>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
</layout>
</object>
</child>
@@ -94,8 +91,8 @@
<property name="adjustment">min_height_adj</property>
<property name="max-width-chars">5</property>
<layout>
<property name="column">2</property>
<property name="row">1</property>
<property name="left-attach">2</property>
<property name="top-attach">1</property>
</layout>
</object>
</child>
@@ -103,8 +100,8 @@
<object class="GtkLabel">
<property name="label">Nat Size</property>
<layout>
<property name="column">0</property>
<property name="row">2</property>
<property name="left-attach">0</property>
<property name="top-attach">2</property>
</layout>
</object>
</child>
@@ -113,8 +110,8 @@
<property name="adjustment">nat_width_adj</property>
<property name="max-width-chars">5</property>
<layout>
<property name="column">1</property>
<property name="row">2</property>
<property name="left-attach">1</property>
<property name="top-attach">2</property>
</layout>
</object>
</child>
@@ -123,8 +120,8 @@
<property name="adjustment">nat_height_adj</property>
<property name="max-width-chars">5</property>
<layout>
<property name="column">2</property>
<property name="row">2</property>
<property name="left-attach">2</property>
<property name="top-attach">2</property>
</layout>
</object>
</child>
@@ -132,8 +129,8 @@
<object class="GtkLabel">
<property name="label">Max Size</property>
<layout>
<property name="column">0</property>
<property name="row">3</property>
<property name="left-attach">0</property>
<property name="top-attach">3</property>
</layout>
</object>
</child>
@@ -142,8 +139,8 @@
<property name="adjustment">max_width_adj</property>
<property name="max-width-chars">5</property>
<layout>
<property name="column">1</property>
<property name="row">3</property>
<property name="left-attach">1</property>
<property name="top-attach">3</property>
</layout>
</object>
</child>
@@ -152,8 +149,8 @@
<property name="adjustment">max_height_adj</property>
<property name="max-width-chars">5</property>
<layout>
<property name="column">2</property>
<property name="row">3</property>
<property name="left-attach">2</property>
<property name="top-attach">3</property>
</layout>
</object>
</child>
@@ -161,16 +158,16 @@
<object class="GtkLabel">
<property name="label">Strength</property>
<layout>
<property name="column">0</property>
<property name="row">4</property>
<property name="left-attach">0</property>
<property name="top-attach">4</property>
</layout>
</object>
</child>
<child>
<object class="GtkComboBoxText" id="strength">
<layout>
<property name="column">1</property>
<property name="row">4</property>
<property name="left-attach">1</property>
<property name="top-attach">4</property>
<property name="column-span">2</property>
</layout>
</object>
@@ -180,8 +177,8 @@
<property name="label">Create</property>
<signal name="clicked" handler="create_guide"/>
<layout>
<property name="column">2</property>
<property name="row">5</property>
<property name="left-attach">2</property>
<property name="top-attach">5</property>
</layout>
</object>
</child>

View File

@@ -8,16 +8,13 @@ constraint_editor_sources = [
]
constraint_editor_resources = gnome.compile_resources('constraint_editor_resources',
'constraint-editor.gresource.xml',
source_dir: '.',
)
'constraint-editor.gresource.xml',
source_dir: '.')
executable('gtk4-constraint-editor',
sources: [ constraint_editor_sources, constraint_editor_resources, ],
c_args: common_cflags,
dependencies: libgtk_dep,
include_directories: confinc,
win_subsystem: 'windows',
link_args: extra_demo_ldflags,
install: false,
)
constraint_editor_sources, constraint_editor_resources,
dependencies: libgtk_dep,
include_directories: confinc,
gui_app: true,
link_args: extra_demo_ldflags,
install: false)

View File

@@ -1,303 +0,0 @@
#include "fontcolors.h"
#include <gtk/gtk.h>
#include <hb-ot.h>
#include "rangeedit.h"
enum {
PROP_FONT_MAP = 1,
PROP_FONT_DESC,
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;
Pango2FontMap *font_map;
};
struct _FontColorsClass
{
GtkWidgetClass parent_class;
};
G_DEFINE_TYPE (FontColors, font_colors, GTK_TYPE_WIDGET);
static Pango2Font *
get_font (FontColors *self)
{
Pango2Context *context;
Pango2Font *font;
context = pango2_context_new_with_font_map (self->font_map);
font = pango2_context_load_font (context, self->font_desc);
g_object_unref (context);
return font;
}
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->font_map = g_object_ref (pango2_font_map_get_default ());
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_clear_object (&self->font_map);
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_MAP:
g_set_object (&self->font_map, g_value_get_object (value));
break;
case PROP_FONT_DESC:
pango2_font_description_free (self->font_desc);
self->font_desc = pango2_font_description_copy (g_value_get_boxed (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
update_colors (self);
}
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_MAP] =
g_param_spec_object ("font-map", "", "",
PANGO2_TYPE_FONT_MAP,
G_PARAM_READWRITE);
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");
}
GAction *
font_colors_get_reset_action (FontColors *self)
{
return G_ACTION (self->reset_action);
}

View File

@@ -1,15 +0,0 @@
#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);
GAction * font_colors_get_reset_action (FontColors *self);

View File

@@ -1,25 +0,0 @@
<?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

@@ -1,257 +0,0 @@
#include "fontcontrols.h"
#include <gtk/gtk.h>
#include <hb-ot.h>
#include "rangeedit.h"
enum {
PROP_SIZE = 1,
PROP_LETTERSPACING,
PROP_LINE_HEIGHT,
PROP_FOREGROUND,
PROP_BACKGROUND,
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;
};
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;
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;
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);
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

@@ -1,16 +0,0 @@
#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

@@ -1,173 +0,0 @@
<?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="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="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

@@ -1,43 +0,0 @@
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;
}
plainview .content {
padding: 20px;
}
waterfallview .content {
padding: 20px;
}
styleview .content {
padding: 20px;
}
glyphsview .content {
padding: 20px;
}
infoview .content {
padding: 20px;
border-spacing: 10px;
}
gridview > child {
padding: 0;
}
glyphview {
padding: 0;
border: 0.6px solid gray;
}
.viewcontrols {
padding: 20px;
border-spacing: 10px;
}

View File

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

View File

@@ -1,186 +0,0 @@
#include "config.h"
#include "fontexplorerapp.h"
#include <gtk/gtk.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_open (GApplication *app,
GFile **files,
int n_files,
const char *hint)
{
FontExplorerWindow *win;
int i;
for (i = 0; i < n_files; i++)
{
win = font_explorer_window_new (FONT_EXPLORER_APP (app));
font_explorer_window_load (win, files[i]);
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;
G_APPLICATION_CLASS (class)->open = font_explorer_app_open;
}
FontExplorerApp *
font_explorer_app_new (void)
{
return g_object_new (FONT_EXPLORER_APP_TYPE,
"application-id", "org.gtk.FontExplorer",
"flags", G_APPLICATION_HANDLES_OPEN,
NULL);
}

View File

@@ -1,15 +0,0 @@
#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

@@ -1,269 +0,0 @@
#include "fontexplorerwin.h"
#include <gtk/gtk.h>
#include <string.h>
#include "fontcolors.h"
#include "fontcontrols.h"
#include "fontexplorerapp.h"
#include "fontfeatures.h"
#include "fontvariations.h"
#include "glyphsview.h"
#include "infoview.h"
#include "plainview.h"
#include "samplechooser.h"
#include "sampleeditor.h"
#include "styleview.h"
#include "waterfallview.h"
struct _FontExplorerWindow
{
GtkApplicationWindow parent;
Pango2FontMap *font_map;
GtkFontButton *fontbutton;
GtkLabel *path;
FontControls *controls;
FontFeatures *features;
FontVariations *variations;
FontColors *colors;
GtkStack *stack;
GtkToggleButton *plain_toggle;
GtkToggleButton *waterfall_toggle;
GtkToggleButton *style_toggle;
GtkToggleButton *glyphs_toggle;
GtkToggleButton *info_toggle;
GtkToggleButton *edit_toggle;
};
struct _FontExplorerWindowClass
{
GtkApplicationWindowClass parent_class;
};
enum {
PROP_FONT_MAP = 1,
NUM_PROPERTIES
};
static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
G_DEFINE_TYPE(FontExplorerWindow, font_explorer_window, GTK_TYPE_APPLICATION_WINDOW);
static void
reset (GSimpleAction *action,
GVariant *parameter,
FontExplorerWindow *self)
{
g_action_activate (font_controls_get_reset_action (self->controls), NULL);
g_action_activate (font_features_get_reset_action (self->features), NULL);
g_action_activate (font_variations_get_reset_action (self->variations), NULL);
g_action_activate (font_colors_get_reset_action (self->colors), NULL);
}
static void
update_reset (GSimpleAction *action,
GParamSpec *pspec,
FontExplorerWindow *self)
{
gboolean enabled;
GAction *reset_action;
enabled = g_action_get_enabled (font_controls_get_reset_action (self->controls)) ||
g_action_get_enabled (font_features_get_reset_action (self->features)) ||
g_action_get_enabled (font_variations_get_reset_action (self->variations)) ||
g_action_get_enabled (font_colors_get_reset_action (self->colors));
reset_action = g_action_map_lookup_action (G_ACTION_MAP (self), "reset");
g_simple_action_set_enabled (G_SIMPLE_ACTION (reset_action), enabled);
}
static void
font_explorer_window_init (FontExplorerWindow *self)
{
GSimpleAction *reset_action;
self->font_map = g_object_ref (pango2_font_map_get_default ());
gtk_widget_init_template (GTK_WIDGET (self));
reset_action = g_simple_action_new ("reset", NULL);
g_signal_connect (reset_action, "activate", G_CALLBACK (reset), self);
g_signal_connect (font_controls_get_reset_action (self->controls),
"notify::enabled", G_CALLBACK (update_reset), self);
g_signal_connect (font_variations_get_reset_action (self->variations),
"notify::enabled", G_CALLBACK (update_reset), self);
g_signal_connect (font_colors_get_reset_action (self->colors),
"notify::enabled", G_CALLBACK (update_reset), self);
g_signal_connect (font_features_get_reset_action (self->features),
"notify::enabled", G_CALLBACK (update_reset), self);
g_action_map_add_action (G_ACTION_MAP (self), G_ACTION (reset_action));
update_reset (NULL, NULL, self);
}
static void
update_view (GtkToggleButton *button,
FontExplorerWindow *self)
{
if (gtk_toggle_button_get_active (self->edit_toggle))
gtk_stack_set_visible_child_name (self->stack, "edit");
else if (gtk_toggle_button_get_active (self->plain_toggle))
gtk_stack_set_visible_child_name (self->stack, "plain");
else if (gtk_toggle_button_get_active (self->waterfall_toggle))
gtk_stack_set_visible_child_name (self->stack, "waterfall");
else if (gtk_toggle_button_get_active (self->style_toggle))
gtk_stack_set_visible_child_name (self->stack, "style");
else if (gtk_toggle_button_get_active (self->glyphs_toggle))
gtk_stack_set_visible_child_name (self->stack, "glyphs");
else if (gtk_toggle_button_get_active (self->info_toggle))
gtk_stack_set_visible_child_name (self->stack, "info");
}
static void
font_explorer_window_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
FontExplorerWindow *self = FONT_EXPLORER_WINDOW (object);
switch (prop_id)
{
case PROP_FONT_MAP:
g_set_object (&self->font_map, g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
font_explorer_window_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
FontExplorerWindow *self = FONT_EXPLORER_WINDOW (object);
switch (prop_id)
{
case PROP_FONT_MAP:
g_value_set_object (value, self->font_map);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
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 *self = FONT_EXPLORER_WINDOW (object);
g_clear_object (&self->font_map);
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_COLORS_TYPE);
g_type_ensure (FONT_CONTROLS_TYPE);
g_type_ensure (FONT_FEATURES_TYPE);
g_type_ensure (FONT_VARIATIONS_TYPE);
g_type_ensure (GLYPHS_VIEW_TYPE);
g_type_ensure (INFO_VIEW_TYPE);
g_type_ensure (PLAIN_VIEW_TYPE);
g_type_ensure (SAMPLE_CHOOSER_TYPE);
g_type_ensure (SAMPLE_EDITOR_TYPE);
g_type_ensure (STYLE_VIEW_TYPE);
g_type_ensure (WATERFALL_VIEW_TYPE);
object_class->set_property = font_explorer_window_set_property;
object_class->get_property = font_explorer_window_get_property;
object_class->dispose = font_explorer_window_dispose;
object_class->finalize = font_explorer_window_finalize;
properties[PROP_FONT_MAP] =
g_param_spec_object ("font-map", "", "",
PANGO2_TYPE_FONT_MAP,
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/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, path);
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, stack);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), FontExplorerWindow, plain_toggle);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), FontExplorerWindow, waterfall_toggle);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), FontExplorerWindow, style_toggle);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), FontExplorerWindow, glyphs_toggle);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), FontExplorerWindow, info_toggle);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), FontExplorerWindow, edit_toggle);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), update_view);
}
FontExplorerWindow *
font_explorer_window_new (FontExplorerApp *app)
{
return g_object_new (FONT_EXPLORER_WINDOW_TYPE, "application", app, NULL);
}
void
font_explorer_window_load (FontExplorerWindow *self,
GFile *file)
{
const char *path;
Pango2FontMap *map;
Pango2HbFace *face;
Pango2FontDescription *desc;
char *basename;
path = g_file_peek_path (file);
basename = g_path_get_basename (path);
face = pango2_hb_face_new_from_file (path, 0, -2, NULL, NULL);
desc = pango2_font_face_describe (PANGO2_FONT_FACE (face));
map = pango2_font_map_new ();
pango2_font_map_add_face (map, PANGO2_FONT_FACE (face));
pango2_font_map_set_fallback (map, pango2_font_map_get_default ());
g_set_object (&self->font_map, map);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FONT_MAP]);
g_object_unref (map);
gtk_font_chooser_set_font_desc (GTK_FONT_CHOOSER (self->fontbutton), desc);
gtk_widget_hide (GTK_WIDGET (self->fontbutton));
gtk_widget_show (GTK_WIDGET (self->path));
gtk_label_set_label (self->path, basename);
pango2_font_description_free (desc);
g_free (basename);
}

View File

@@ -1,18 +0,0 @@
#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);
void font_explorer_window_load (FontExplorerWindow *self,
GFile *file);

View File

@@ -1,252 +0,0 @@
<?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="title">
<object class="GtkBox">
<property name="orientation">horizontal</property>
<style>
<class name="linked"/>
</style>
<child>
<object class="GtkToggleButton" id="plain_toggle">
<property name="label">Plain</property>
<property name="active">1</property>
<signal name="toggled" handler="update_view"/>
</object>
</child>
<child>
<object class="GtkToggleButton" id="waterfall_toggle">
<property name="label">Waterfall</property>
<property name="group">plain_toggle</property>
<signal name="toggled" handler="update_view"/>
</object>
</child>
<child>
<object class="GtkToggleButton" id="style_toggle">
<property name="label">Styles</property>
<property name="group">plain_toggle</property>
<property name="sensitive" bind-source="styleview" bind-property="has-styles" bind-flags="sync-create"/>
<signal name="toggled" handler="update_view"/>
</object>
</child>
<child>
<object class="GtkToggleButton" id="glyphs_toggle">
<property name="label">Glyphs</property>
<property name="group">plain_toggle</property>
<signal name="toggled" handler="update_view"/>
</object>
</child>
<child>
<object class="GtkToggleButton" id="info_toggle">
<property name="label">Info</property>
<property name="group">plain_toggle</property>
<signal name="toggled" handler="update_view"/>
</object>
</child>
</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>
<child type="end">
<object class="GtkToggleButton" id="edit_toggle">
<property name="hexpand">1</property>
<property name="halign">end</property>
<property name="icon-name">document-edit-symbolic</property>
<property name="tooltip-text" translatable="yes">Edit the sample</property>
<signal name="toggled" handler="update_view"/>
</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="GtkLabel" id="path">
<property name="visible">0</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
</child>
<child>
<object class="FontControls" id="controls">
</object>
</child>
<child>
<object class="SampleChooser" id="samplechooser"/>
</child>
<child>
<object class="FontVariations" id="variations">
<property name="font-map" bind-source="FontExplorerWindow" bind-flags="sync-create"/>
<property name="font-desc" bind-source="fontbutton" bind-flags="sync-create"/>
</object>
</child>
<child>
<object class="FontFeatures" id="features">
<property name="font-map" bind-source="FontExplorerWindow" bind-flags="sync-create"/>
<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-map" bind-source="FontExplorerWindow" bind-flags="sync-create"/>
<property name="font-desc" bind-source="fontbutton" bind-flags="sync-create"/>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkStack" id="stack">
<property name="hexpand">1</property>
<child>
<object class="GtkStackPage">
<property name="name">plain</property>
<property name="child">
<object class="PlainView">
<property name="font-map" bind-source="FontExplorerWindow" bind-flags="sync-create"/>
<property name="font-desc" bind-source="fontbutton" bind-flags="sync-create"/>
<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="sampleeditor" 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>
</property>
</object>
</child>
<child>
<object class="GtkStackPage">
<property name="name">waterfall</property>
<property name="child">
<object class="WaterfallView">
<property name="font-map" bind-source="FontExplorerWindow" bind-flags="sync-create"/>
<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="sampleeditor" 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>
</property>
</object>
</child>
<child>
<object class="GtkStackPage">
<property name="name">style</property>
<property name="child">
<object class="StyleView" id="styleview">
<property name="font-map" bind-source="FontExplorerWindow" bind-flags="sync-create"/>
<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="sampleeditor" 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>
</property>
</object>
</child>
<child>
<object class="GtkStackPage">
<property name="name">glyphs</property>
<property name="child">
<object class="GlyphsView">
<property name="font-map" bind-source="FontExplorerWindow" bind-flags="sync-create"/>
<property name="font-desc" bind-source="fontbutton" 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>
</property>
</object>
</child>
<child>
<object class="GtkStackPage">
<property name="name">info</property>
<property name="child">
<object class="InfoView">
<property name="font-map" bind-source="FontExplorerWindow" bind-flags="sync-create"/>
<property name="font-desc" bind-source="fontbutton" bind-flags="sync-create"/>
<property name="size" bind-source="controls" bind-flags="sync-create"/>
<property name="variations" bind-source="variations" bind-flags="sync-create"/>
</object>
</property>
</object>
</child>
<child>
<object class="GtkStackPage">
<property name="name">edit</property>
<property name="child">
<object class="SampleEditor" id="sampleeditor">
<property name="sample-text" bind-source="samplechooser" bind-flags="sync-create"/>
<property name="editing" bind-source="edit_toggle" bind-property="active" bind-flags="sync-create"/>
</object>
</property>
</object>
</child>
</object>
</child>
</object>
</child>
</template>
</interface>

View File

@@ -1,744 +0,0 @@
#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_MAP = 1,
PROP_FONT_DESC,
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;
Pango2FontMap *font_map;
};
struct _FontFeaturesClass
{
GtkWidgetClass parent_class;
};
G_DEFINE_TYPE(FontFeatures, font_features, GTK_TYPE_WIDGET);
static Pango2Font *
get_font (FontFeatures *self)
{
Pango2Context *context;
Pango2Font *font;
context = pango2_context_new_with_font_map (self->font_map);
font = pango2_context_load_font (context, self->font_desc);
g_object_unref (context);
return font;
}
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)
{
self->font_map = g_object_ref (pango2_font_map_get_default ());
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_clear_object (&self->font_map);
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_MAP:
g_set_object (&self->font_map, g_value_get_object (value));
break;
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_LANGUAGE:
self->lang = pango2_language_from_string (g_value_get_string (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
update_features (self);
}
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_FONT_MAP:
g_value_set_object (value, self->font_map);
break;
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_MAP] =
g_param_spec_object ("font-map", "", "",
PANGO2_TYPE_FONT_MAP,
G_PARAM_READWRITE);
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");
}
GAction *
font_features_get_reset_action (FontFeatures *self)
{
return G_ACTION (self->reset_action);
}

View File

@@ -1,15 +0,0 @@
#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);
GAction * font_features_get_reset_action (FontFeatures *self);

View File

@@ -1,25 +0,0 @@
<?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

@@ -1,508 +0,0 @@
#include "fontvariations.h"
#include <gtk/gtk.h>
#include <hb-ot.h>
#include "rangeedit.h"
enum {
PROP_FONT_MAP = 1,
PROP_FONT_DESC,
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;
Pango2FontMap *font_map;
};
struct _FontVariationsClass
{
GtkWidgetClass parent_class;
};
G_DEFINE_TYPE(FontVariations, font_variations, GTK_TYPE_WIDGET);
static Pango2Font *
get_font (FontVariations *self)
{
Pango2Context *context;
Pango2Font *font;
context = pango2_context_new_with_font_map (self->font_map);
font = pango2_context_load_font (context, self->font_desc);
g_object_unref (context);
return font;
}
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)
{
self->font_map = g_object_ref (pango2_font_map_get_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);
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_clear_object (&self->font_map);
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_MAP:
g_set_object (&self->font_map, g_value_get_object (value));
break;
case PROP_FONT_DESC:
pango2_font_description_free (self->font_desc);
self->font_desc = pango2_font_description_copy (g_value_get_boxed (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
update_variations (self);
}
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_FONT_MAP:
g_value_set_object (value, self->font_map);
break;
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_MAP] =
g_param_spec_object ("font-map", "", "",
PANGO2_TYPE_FONT_MAP,
G_PARAM_READWRITE);
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");
}
GAction *
font_variations_get_reset_action (FontVariations *self)
{
return G_ACTION (self->reset_action);
}

View File

@@ -1,15 +0,0 @@
#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);
GAction * font_variations_get_reset_action (FontVariations *self);

View File

@@ -1,25 +0,0 @@
<?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

@@ -1,56 +0,0 @@
#include "glyphitem.h"
struct _GlyphItem {
GObject parent;
Pango2Font *font;
hb_codepoint_t glyph;
};
struct _GlyphItemClass {
GObjectClass parent_class;
};
G_DEFINE_TYPE (GlyphItem, glyph_item, G_TYPE_OBJECT)
static void
glyph_item_init (GlyphItem *self)
{
}
static void
glyph_item_finalize (GObject *object)
{
GlyphItem *item = GLYPH_ITEM (object);
g_object_unref (item->font);
G_OBJECT_CLASS (glyph_item_parent_class)->finalize (object);
}
static void
glyph_item_class_init (GlyphItemClass *class)
{
G_OBJECT_CLASS (class)->finalize = glyph_item_finalize;
}
GlyphItem *
glyph_item_new (Pango2Font *font,
hb_codepoint_t glyph)
{
GlyphItem *item = g_object_new (GLYPH_ITEM_TYPE, NULL);
item->font = g_object_ref (font);
item->glyph = glyph;
return item;
}
Pango2Font *
glyph_item_get_font (GlyphItem *item)
{
return item->font;
}
hb_codepoint_t
glyph_item_get_glyph (GlyphItem *item)
{
return item->glyph;
}

View File

@@ -1,17 +0,0 @@
#pragma once
#include <gtk/gtk.h>
#define GLYPH_ITEM_TYPE (glyph_item_get_type ())
#define GLYPH_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GLYPH_ITEM_TYPE, GlyphItem))
typedef struct _GlyphItem GlyphItem;
typedef struct _GlyphItemClass GlyphItemClass;
GType glyph_item_get_type (void);
GlyphItem * glyph_item_new (Pango2Font *font,
hb_codepoint_t glyph);
hb_codepoint_t glyph_item_get_glyph (GlyphItem *item);
Pango2Font * glyph_item_get_font (GlyphItem *item);

View File

@@ -1,97 +0,0 @@
#include "glyphmodel.h"
#include "glyphitem.h"
struct _GlyphModel {
GObject parent;
Pango2Font *font;
unsigned int num_glyphs;
GlyphItem **glyphs;
};
struct _GlyphModelClass {
GObjectClass parent_class;
};
static GType
glyph_model_get_item_type (GListModel *model)
{
return GLYPH_ITEM_TYPE;
}
static guint
glyph_model_get_n_items (GListModel *model)
{
GlyphModel *self = GLYPH_MODEL (model);
return self->num_glyphs;
}
static gpointer
glyph_model_get_item (GListModel *model,
guint position)
{
GlyphModel *self = GLYPH_MODEL (model);
if (position >= self->num_glyphs)
return NULL;
if (self->glyphs[position] == NULL)
self->glyphs[position] = glyph_item_new (self->font, position);
return g_object_ref (self->glyphs[position]);
}
static void
glyph_model_list_model_init (GListModelInterface *iface)
{
iface->get_item_type = glyph_model_get_item_type;
iface->get_n_items = glyph_model_get_n_items;
iface->get_item = glyph_model_get_item;
}
G_DEFINE_TYPE_WITH_CODE (GlyphModel, glyph_model, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, glyph_model_list_model_init))
static void
glyph_model_init (GlyphModel *self)
{
}
static void
glyph_model_finalize (GObject *object)
{
GlyphModel *self = GLYPH_MODEL (object);
g_object_unref (self->font);
for (int i = 0; i < self->num_glyphs; i++)
{
if (self->glyphs[i])
g_object_unref (self->glyphs[i]);
}
g_free (self->glyphs);
G_OBJECT_CLASS (glyph_model_parent_class)->finalize (object);
}
static void
glyph_model_class_init (GlyphModelClass *class)
{
G_OBJECT_CLASS (class)->finalize = glyph_model_finalize;
}
GlyphModel *
glyph_model_new (Pango2Font *font)
{
GlyphModel *self;
hb_face_t *hb_face;
self = g_object_new (GLYPH_MODEL_TYPE, NULL);
self->font = g_object_ref (font);
hb_face = pango2_hb_face_get_hb_face (PANGO2_HB_FACE (pango2_font_get_face (font)));
self->num_glyphs = hb_face_get_glyph_count (hb_face);
self->glyphs = g_new0 (GlyphItem *, self->num_glyphs);
return self;
}

View File

@@ -1,14 +0,0 @@
#pragma once
#include <gtk/gtk.h>
#define GLYPH_MODEL_TYPE (glyph_model_get_type ())
#define GLYPH_MODEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GLYPH_MODEL_TYPE, GlyphModel))
typedef struct _GlyphModel GlyphModel;
typedef struct _GlyphModelClass GlyphModelClass;
GType glyph_model_get_type (void);
GlyphModel * glyph_model_new (Pango2Font *font);

View File

@@ -1,239 +0,0 @@
#include "glyphsview.h"
#include <gtk/gtk.h>
#include <hb-ot.h>
#include "glyphitem.h"
#include "glyphmodel.h"
#include "glyphview.h"
enum {
PROP_FONT_MAP = 1,
PROP_FONT_DESC,
PROP_VARIATIONS,
PROP_PALETTE,
NUM_PROPERTIES
};
static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
struct _GlyphsView
{
GtkWidget parent;
Pango2FontMap *font_map;
GtkGridView *glyphs;
Pango2FontDescription *font_desc;
char *variations;
char *palette;
GQuark palette_quark;
};
struct _GlyphsViewClass
{
GtkWidgetClass parent_class;
};
G_DEFINE_TYPE(GlyphsView, glyphs_view, GTK_TYPE_WIDGET);
static void
glyphs_view_init (GlyphsView *self)
{
self->font_map = g_object_ref (pango2_font_map_get_default ());
self->font_desc = pango2_font_description_from_string ("sans 12");
self->variations = g_strdup ("");
self->palette = g_strdup (PANGO2_COLOR_PALETTE_DEFAULT);
self->palette_quark = g_quark_from_string (self->palette);
gtk_widget_set_layout_manager (GTK_WIDGET (self),
gtk_box_layout_new (GTK_ORIENTATION_VERTICAL));
gtk_widget_init_template (GTK_WIDGET (self));
}
static void
glyphs_view_dispose (GObject *object)
{
gtk_widget_clear_template (GTK_WIDGET (object), GLYPHS_VIEW_TYPE);
G_OBJECT_CLASS (glyphs_view_parent_class)->dispose (object);
}
static void
glyphs_view_finalize (GObject *object)
{
GlyphsView *self = GLYPHS_VIEW (object);
g_clear_object (&self->font_map);
pango2_font_description_free (self->font_desc);
g_free (self->variations);
g_free (self->palette);
G_OBJECT_CLASS (glyphs_view_parent_class)->finalize (object);
}
static Pango2Font *
get_font (GlyphsView *self,
int size)
{
Pango2Context *context;
Pango2FontDescription *desc;
Pango2Font *font;
context = pango2_context_new_with_font_map (self->font_map);
desc = pango2_font_description_copy_static (self->font_desc);
pango2_font_description_set_variations (desc, self->variations);
pango2_font_description_set_size (desc, size);
font = pango2_context_load_font (context, desc);
pango2_font_description_free (desc);
g_object_unref (context);
return font;
}
static void
update_glyph_model (GlyphsView *self)
{
Pango2Font *font = get_font (self, 60 * PANGO2_SCALE);
GlyphModel *gm;
GtkSelectionModel *model;
gm = glyph_model_new (font);
model = GTK_SELECTION_MODEL (gtk_no_selection_new (G_LIST_MODEL (gm)));
gtk_grid_view_set_model (self->glyphs, model);
g_object_unref (model);
g_object_unref (font);
}
static void
setup_glyph (GtkSignalListItemFactory *factory,
GObject *listitem)
{
gtk_list_item_set_child (GTK_LIST_ITEM (listitem), GTK_WIDGET (glyph_view_new ()));
}
static void
bind_glyph (GtkSignalListItemFactory *factory,
GObject *listitem,
GlyphsView *self)
{
GlyphView *view;
GObject *item;
view = GLYPH_VIEW (gtk_list_item_get_child (GTK_LIST_ITEM (listitem)));
item = gtk_list_item_get_item (GTK_LIST_ITEM (listitem));
glyph_view_set_font (view, glyph_item_get_font (GLYPH_ITEM (item)));
glyph_view_set_glyph (view, glyph_item_get_glyph (GLYPH_ITEM (item)));
glyph_view_set_palette (view, self->palette_quark);
}
static void
glyphs_view_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GlyphsView *self = GLYPHS_VIEW (object);
switch (prop_id)
{
case PROP_FONT_MAP:
g_set_object (&self->font_map, g_value_get_object (value));
break;
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_VARIATIONS:
g_free (self->variations);
self->variations = g_strdup (g_value_get_string (value));
break;
case PROP_PALETTE:
g_free (self->palette);
self->palette = g_strdup (g_value_get_string (value));
self->palette_quark = g_quark_from_string (self->palette);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
update_glyph_model (self);
}
static void
glyphs_view_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GlyphsView *self = GLYPHS_VIEW (object);
switch (prop_id)
{
case PROP_FONT_MAP:
g_value_set_object (value, self->font_map);
break;
case PROP_FONT_DESC:
g_value_set_boxed (value, self->font_desc);
break;
case PROP_VARIATIONS:
g_value_set_string (value, self->variations);
break;
case PROP_PALETTE:
g_value_set_string (value, self->palette);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
glyphs_view_class_init (GlyphsViewClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
object_class->dispose = glyphs_view_dispose;
object_class->finalize = glyphs_view_finalize;
object_class->get_property = glyphs_view_get_property;
object_class->set_property = glyphs_view_set_property;
properties[PROP_FONT_MAP] =
g_param_spec_object ("font-map", "", "",
PANGO2_TYPE_FONT_MAP,
G_PARAM_READWRITE);
properties[PROP_FONT_DESC] =
g_param_spec_boxed ("font-desc", "", "",
PANGO2_TYPE_FONT_DESCRIPTION,
G_PARAM_READWRITE);
properties[PROP_VARIATIONS] =
g_param_spec_string ("variations", "", "",
"",
G_PARAM_READWRITE);
properties[PROP_PALETTE] =
g_param_spec_string ("palette", "", "",
PANGO2_COLOR_PALETTE_DEFAULT,
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/glyphsview.ui");
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), GlyphsView, glyphs);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), setup_glyph);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), bind_glyph);
gtk_widget_class_set_css_name (GTK_WIDGET_CLASS (class), "glyphsview");
}

View File

@@ -1,14 +0,0 @@
#pragma once
#include <gtk/gtk.h>
#define GLYPHS_VIEW_TYPE (glyphs_view_get_type ())
#define GLYPHS_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GLYPHS_VIEW_TYPE, GlyphsView))
typedef struct _GlyphsView GlyphsView;
typedef struct _GlyphsViewClass GlyphsViewClass;
GType glyphs_view_get_type (void);

View File

@@ -1,29 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="GlyphsView" parent="GtkWidget">
<style>
<class name="view"/>
</style>
<child>
<object class="GtkScrolledWindow">
<property name="hexpand">1</property>
<property name="vexpand">1</property>
<property name="hscrollbar-policy">never</property>
<property name="vscrollbar-policy">automatic</property>
<child>
<object class="GtkGridView" id="glyphs">
<style>
<class name="content"/>
</style>
<property name="factory">
<object class="GtkSignalListItemFactory">
<signal name="setup" handler="setup_glyph"/>
<signal name="bind" handler="bind_glyph"/>
</object>
</property>
</object>
</child>
</object>
</child>
</template>
</interface>

View File

@@ -1,321 +0,0 @@
#include "glyphview.h"
#include <gtk/gtk.h>
#include <hb-ot.h>
struct _GlyphView
{
GtkWidget parent;
Pango2Font *font;
GQuark palette;
int palette_index;
hb_codepoint_t glyph;
int n_layers;
int layer;
};
struct _GlyphViewClass
{
GtkWidgetClass parent_class;
};
G_DEFINE_TYPE(GlyphView, glyph_view, GTK_TYPE_WIDGET);
static void
click_cb (GtkGestureClick *gesture,
int n_press,
double x,
double y,
GlyphView *self)
{
if (self->n_layers == 0)
return;
self->layer++;
if (self->layer == self->n_layers)
self->layer = -1;
gtk_widget_queue_draw (GTK_WIDGET (self));
}
static void
glyph_view_init (GlyphView *self)
{
GtkGesture *click;
self->n_layers = 0;
self->layer = -1;
click = gtk_gesture_click_new ();
g_signal_connect (click, "pressed", G_CALLBACK (click_cb), self);
gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (click));
}
static void
glyph_view_dispose (GObject *object)
{
GlyphView *self = GLYPH_VIEW (object);
g_clear_object (&self->font);
G_OBJECT_CLASS (glyph_view_parent_class)->dispose (object);
}
static void
glyph_view_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot)
{
GlyphView *self = GLYPH_VIEW (widget);
Pango2GlyphString *glyphs;
Pango2Rectangle ink, logical;
cairo_t *cr;
int width, height;
char name[80];
pango2_font_get_glyph_extents (self->font, self->glyph, &ink, &logical);
width = gtk_widget_get_width (widget);
height = gtk_widget_get_height (widget);
cr = gtk_snapshot_append_cairo (snapshot, &GRAPHENE_RECT_INIT (0, 0, width, height));
glyphs = pango2_glyph_string_new ();
pango2_glyph_string_set_size (glyphs, 1);
glyphs->glyphs[0].geometry.width = ink.width;
glyphs->glyphs[0].geometry.x_offset = ink.x;
glyphs->glyphs[0].geometry.y_offset = -ink.y;
if (self->layer == -1)
{
glyphs->glyphs[0].glyph = self->glyph;
cairo_set_source_rgb (cr, 0, 0, 0);
}
else
{
hb_face_t *face = hb_font_get_face (pango2_font_get_hb_font (self->font));
hb_ot_color_layer_t *layers;
unsigned int count;
layers = g_newa (hb_ot_color_layer_t, self->n_layers);
count = self->n_layers;
hb_ot_color_glyph_get_layers (face,
self->glyph,
0,
&count,
layers);
glyphs->glyphs[0].glyph = layers[self->layer].glyph;
if (layers[self->layer].color_index == 0xffff)
{
cairo_set_source_rgb (cr, 0, 0, 0);
}
else
{
hb_color_t *colors;
unsigned int n_colors;
hb_color_t color;
n_colors = hb_ot_color_palette_get_colors (face,
self->palette_index,
0,
NULL,
NULL);
colors = g_newa (hb_color_t, n_colors);
hb_ot_color_palette_get_colors (face,
self->palette_index,
0,
&n_colors,
colors);
color = colors[layers[self->layer].color_index];
cairo_set_source_rgba (cr, hb_color_get_red (color)/255.,
hb_color_get_green (color)/255.,
hb_color_get_blue (color)/255.,
hb_color_get_alpha (color)/255.);
}
}
cairo_move_to (cr, (width - logical.width/1024.)/2, (height - logical.height/1024.)/2);
pango2_cairo_show_color_glyph_string (cr, self->font, self->palette, glyphs);
{
Pango2Layout *layout;
Pango2FontDescription *desc;
char gid[20];
hb_font_t *hb_font;
hb_face_t *hb_face;
g_snprintf (gid, sizeof (gid), "%d", self->glyph);
layout = gtk_widget_create_pango_layout (widget, gid);
desc = pango2_font_description_from_string ("Cantarell 8");
pango2_layout_set_font_description (layout, desc);
pango2_font_description_free (desc);
gtk_snapshot_save (snapshot);
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (5, 5));
gtk_snapshot_append_layout (snapshot, layout, &(GdkRGBA){ 0.,0.,0.,0.7});
gtk_snapshot_restore (snapshot);
hb_font = pango2_font_get_hb_font (self->font);
hb_face = hb_font_get_face (hb_font);
if (hb_ot_layout_has_glyph_classes (hb_face))
{
hb_ot_layout_glyph_class_t class;
const char *class_names[] = {
NULL, "Base", "Ligature", "Mark", "Component"
};
int w, h;
class = hb_ot_layout_get_glyph_class (hb_face, self->glyph);
if (class != HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED)
{
pango2_layout_set_text (layout, class_names[class], -1);
pango2_lines_get_size (pango2_layout_get_lines (layout), &w, &h);
gtk_snapshot_save (snapshot);
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (width - w/1024. - 5, 5));
gtk_snapshot_append_layout (snapshot, layout, &(GdkRGBA){ 0.,0.,0.,.7});
gtk_snapshot_restore (snapshot);
}
}
if (hb_font_get_glyph_name (hb_font, self->glyph, name, sizeof (name)))
{
int w, h;
pango2_layout_set_text (layout, name, -1);
pango2_lines_get_size (pango2_layout_get_lines (layout), &w, &h);
gtk_snapshot_save (snapshot);
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (5, height - h/1024. - 5));
gtk_snapshot_append_layout (snapshot, layout, &(GdkRGBA){ 0.,0.,0.,.7});
gtk_snapshot_restore (snapshot);
}
if (self->n_layers > 0)
{
char buf[128];
int w, h;
if (self->layer == -1)
g_snprintf (buf, sizeof (buf), "%d Layers", self->n_layers);
else
g_snprintf (buf, sizeof (buf), "Layer %d", self->layer);
pango2_layout_set_text (layout, buf, -1);
pango2_lines_get_size (pango2_layout_get_lines (layout), &w, &h);
gtk_snapshot_save (snapshot);
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (width - w/1024. - 5, height - h/1024. - 5));
gtk_snapshot_append_layout (snapshot, layout, &(GdkRGBA){ 0.,0.,0.,.7});
gtk_snapshot_restore (snapshot);
}
g_object_unref (layout);
}
}
static void
glyph_view_measure (GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline)
{
GlyphView *self = GLYPH_VIEW (widget);
Pango2Rectangle ink, logical;
pango2_font_get_glyph_extents (self->font, self->glyph, &ink, &logical);
if (orientation == GTK_ORIENTATION_HORIZONTAL)
*minimum = *natural = 2 * logical.width / PANGO2_SCALE;
else
*minimum = *natural = 2 * logical.height / PANGO2_SCALE;
}
static void
glyph_view_class_init (GlyphViewClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
object_class->dispose = glyph_view_dispose;
widget_class->snapshot = glyph_view_snapshot;
widget_class->measure = glyph_view_measure;
gtk_widget_class_set_css_name (widget_class, "glyphview");
}
GlyphView *
glyph_view_new (void)
{
return g_object_new (GLYPH_VIEW_TYPE, NULL);
}
void
glyph_view_set_font (GlyphView *self,
Pango2Font *font)
{
if (g_set_object (&self->font, font))
gtk_widget_queue_resize (GTK_WIDGET (self));
}
static unsigned int
find_palette_index_by_flag (hb_face_t *hbface,
hb_ot_color_palette_flags_t flag)
{
unsigned int n_palettes;
n_palettes = hb_ot_color_palette_get_count (hbface);
for (unsigned int i = 0; i < n_palettes; i++)
{
if (hb_ot_color_palette_get_flags (hbface, i) & flag)
return i;
}
return 0;
}
void
glyph_view_set_palette (GlyphView *self,
GQuark palette)
{
if (self->palette == palette)
return;
self->palette = palette;
if (palette == g_quark_from_string (PANGO2_COLOR_PALETTE_DEFAULT))
self->palette_index = 0;
else if (palette == g_quark_from_string (PANGO2_COLOR_PALETTE_LIGHT))
self->palette_index = find_palette_index_by_flag (hb_font_get_face (pango2_font_get_hb_font (self->font)), HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_LIGHT_BACKGROUND);
else if (palette == g_quark_from_string (PANGO2_COLOR_PALETTE_DARK))
self->palette_index = find_palette_index_by_flag (hb_font_get_face (pango2_font_get_hb_font (self->font)), HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_DARK_BACKGROUND);
else
{
const char *str = g_quark_to_string (palette);
char *endp;
if (g_str_has_prefix (str, "palette"))
self->palette_index = g_ascii_strtoll (str + strlen ("palette"), &endp, 10);
}
gtk_widget_queue_resize (GTK_WIDGET (self));
}
void
glyph_view_set_glyph (GlyphView *self,
hb_codepoint_t glyph)
{
if (self->glyph == glyph)
return;
self->glyph = glyph;
self->n_layers = hb_ot_color_glyph_get_layers (hb_font_get_face (pango2_font_get_hb_font (self->font)), glyph, 0, NULL, NULL);
self->layer = -1;
gtk_widget_queue_resize (GTK_WIDGET (self));
}

View File

@@ -1,21 +0,0 @@
#pragma once
#include <gtk/gtk.h>
#define GLYPH_VIEW_TYPE (glyph_view_get_type ())
#define GLYPH_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GLYPH_VIEW_TYPE, GlyphView))
typedef struct _GlyphView GlyphView;
typedef struct _GlyphViewClass GlyphViewClass;
GType glyph_view_get_type (void);
GlyphView * glyph_view_new (void);
void glyph_view_set_font (GlyphView *view,
Pango2Font *font);
void glyph_view_set_palette (GlyphView *view,
GQuark palette);
void glyph_view_set_glyph (GlyphView *view,
hb_codepoint_t glyph);

View File

@@ -1,423 +0,0 @@
#include "infoview.h"
#include <gtk/gtk.h>
#include <hb-ot.h>
enum {
PROP_FONT_MAP = 1,
PROP_FONT_DESC,
PROP_SIZE,
PROP_VARIATIONS,
NUM_PROPERTIES
};
static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
struct _InfoView
{
GtkWidget parent;
GtkGrid *info;
Pango2FontMap *font_map;
Pango2FontDescription *font_desc;
float size;
char *variations;
};
struct _InfoViewClass
{
GtkWidgetClass parent_class;
};
G_DEFINE_TYPE(InfoView, info_view, GTK_TYPE_WIDGET);
static void
info_view_init (InfoView *self)
{
self->font_map = g_object_ref (pango2_font_map_get_default ());
self->font_desc = pango2_font_description_from_string ("sans 12");
self->size = 12.;
self->variations = g_strdup ("");
gtk_widget_set_layout_manager (GTK_WIDGET (self),
gtk_box_layout_new (GTK_ORIENTATION_VERTICAL));
gtk_widget_init_template (GTK_WIDGET (self));
}
static void
info_view_dispose (GObject *object)
{
gtk_widget_clear_template (GTK_WIDGET (object), INFO_VIEW_TYPE);
G_OBJECT_CLASS (info_view_parent_class)->dispose (object);
}
static void
info_view_finalize (GObject *object)
{
InfoView *self = INFO_VIEW (object);
g_clear_object (&self->font_map);
pango2_font_description_free (self->font_desc);
g_free (self->variations);
G_OBJECT_CLASS (info_view_parent_class)->finalize (object);
}
static Pango2Font *
get_font (InfoView *self,
int size)
{
Pango2Context *context;
Pango2FontDescription *desc;
Pango2Font *font;
context = pango2_context_new_with_font_map (self->font_map);
desc = pango2_font_description_copy_static (self->font_desc);
pango2_font_description_set_variations (desc, self->variations);
pango2_font_description_set_size (desc, size);
font = pango2_context_load_font (context, desc);
pango2_font_description_free (desc);
g_object_unref (context);
return font;
}
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
add_misc_line (InfoView *self,
const char *title,
const char *value,
int row)
{
GtkWidget *label;
label = gtk_label_new (title);
gtk_widget_set_halign (label, GTK_ALIGN_START);
gtk_widget_set_valign (label, GTK_ALIGN_START);
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_widget_set_hexpand (label, TRUE);
gtk_grid_attach (self->info, label, 0, row, 1, 1);
label = gtk_label_new (value);
gtk_widget_set_halign (label, GTK_ALIGN_END);
gtk_widget_set_valign (label, GTK_ALIGN_START);
gtk_label_set_xalign (GTK_LABEL (label), 1);
gtk_label_set_wrap (GTK_LABEL (label), TRUE);
gtk_label_set_width_chars (GTK_LABEL (label), 40);
gtk_label_set_max_width_chars (GTK_LABEL (label), 40);
gtk_label_set_selectable (GTK_LABEL (label), TRUE);
gtk_grid_attach (self->info, label, 1, row, 1, 1);
}
static void
add_info_line (InfoView *self,
hb_face_t *face,
hb_ot_name_id_t name_id,
const char *title,
int row)
{
char info[256];
unsigned int len = sizeof (info);
if (hb_ot_name_get_utf8 (face, name_id, HB_LANGUAGE_INVALID, &len, info) > 0)
add_misc_line (self, title, info, row);
}
static void
add_metrics_line (InfoView *self,
hb_font_t *font,
hb_ot_metrics_tag_t metrics_tag,
const char *title,
int row)
{
hb_position_t pos;
if (hb_ot_metrics_get_position (font, metrics_tag, &pos))
{
char buf[128];
g_snprintf (buf, sizeof (buf), "%d", pos);
add_misc_line (self, title, buf, row);
}
}
static void
add_style_line (InfoView *self,
hb_font_t *font,
hb_style_tag_t style_tag,
const char *title,
int row)
{
float value;
char buf[16];
value = hb_style_get_value (font, style_tag);
g_snprintf (buf, sizeof (buf), "%.2f", value);
add_misc_line (self, title, buf, row);
}
static void
update_info (InfoView *self)
{
GtkWidget *child;
int size = pango2_font_description_get_size (self->font_desc);
Pango2Font *pango_font = get_font (self, MAX (size, 10 * PANGO2_SCALE));
hb_font_t *font1 = pango2_font_get_hb_font (pango_font);
hb_face_t *face = hb_font_get_face (font1);
hb_font_t *font = hb_font_create_sub_font (font1);
int row = 0;
char buf[128];
unsigned int count;
GString *s;
hb_tag_t *tables;
const char *path;
hb_font_set_scale (font, hb_face_get_upem (face), hb_face_get_upem (face));
while ((child = gtk_widget_get_first_child (GTK_WIDGET (self->info))) != NULL)
gtk_widget_unparent (child);
gtk_grid_attach (self->info, make_title_label ("General Info"), 0, row++, 2, 1);
path = pango2_hb_face_get_file (PANGO2_HB_FACE (pango2_font_get_face (pango_font)));
if (path)
add_misc_line (self, "File ", path, row++);
add_info_line (self, face, HB_OT_NAME_ID_FONT_FAMILY, "Font Family Name", row++);
add_info_line (self, face, HB_OT_NAME_ID_FONT_SUBFAMILY, "Font Subfamily Name", row++);
add_info_line (self, face, HB_OT_NAME_ID_UNIQUE_ID, "Unique Font Identifier", row++);
add_info_line (self, face, HB_OT_NAME_ID_FULL_NAME, "Full Name", row++);
add_info_line (self, face, HB_OT_NAME_ID_VERSION_STRING, "Version", row++);
add_info_line (self, face, HB_OT_NAME_ID_POSTSCRIPT_NAME, "Postscript Name", row++);
add_info_line (self, face, HB_OT_NAME_ID_TYPOGRAPHIC_FAMILY, "Typographic Family Name", row++);
add_info_line (self, face, HB_OT_NAME_ID_TYPOGRAPHIC_SUBFAMILY, "Typographic Subfamily Name", row++);
add_info_line (self, face, HB_OT_NAME_ID_MANUFACTURER, "Vendor ID", row++);
add_info_line (self, face, HB_OT_NAME_ID_DESIGNER, "Designer", row++);
add_info_line (self, face, HB_OT_NAME_ID_DESCRIPTION, "Description", row++);
add_info_line (self, face, HB_OT_NAME_ID_COPYRIGHT, "Copyright", row++);
gtk_grid_attach (self->info, make_title_label ("Metrics"), 0, row++, 2, 1);
g_snprintf (buf, sizeof (buf), "%d", hb_face_get_upem (face));
add_misc_line (self, "Units per Em", buf, row++);
add_metrics_line (self, font, HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER, "Ascender", row++);
add_metrics_line (self, font, HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER, "Descender", row++);
add_metrics_line (self, font, HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP, "Line Gap", row++);
add_metrics_line (self, font, HB_OT_METRICS_TAG_HORIZONTAL_CARET_RISE, "Caret Rise", row++);
add_metrics_line (self, font, HB_OT_METRICS_TAG_HORIZONTAL_CARET_RUN, "Caret Run", row++);
add_metrics_line (self, font, HB_OT_METRICS_TAG_HORIZONTAL_CARET_OFFSET, "Caret Offset", row++);
add_metrics_line (self, font, HB_OT_METRICS_TAG_X_HEIGHT, "x Height", row++);
add_metrics_line (self, font, HB_OT_METRICS_TAG_CAP_HEIGHT, "Cap Height", row++);
add_metrics_line (self, font, HB_OT_METRICS_TAG_STRIKEOUT_SIZE, "Strikeout Size", row++);
add_metrics_line (self, font, HB_OT_METRICS_TAG_STRIKEOUT_OFFSET, "Strikeout Offset", row++);
add_metrics_line (self, font, HB_OT_METRICS_TAG_STRIKEOUT_SIZE, "Underline Size", row++);
add_metrics_line (self, font, HB_OT_METRICS_TAG_STRIKEOUT_OFFSET, "Underline Offset", row++);
gtk_grid_attach (self->info, make_title_label ("Style"), 0, row++, 2, 1);
add_style_line (self, font, HB_STYLE_TAG_ITALIC, "Italic", row++);
add_style_line (self, font, HB_STYLE_TAG_OPTICAL_SIZE, "Optical Size", row++);
add_style_line (self, font, HB_STYLE_TAG_SLANT_ANGLE, "Slant Angle", row++);
add_style_line (self, font, HB_STYLE_TAG_WIDTH, "Width", row++);
add_style_line (self, font, HB_STYLE_TAG_WEIGHT, "Weight", row++);
gtk_grid_attach (self->info, make_title_label ("Miscellaneous"), 0, row++, 2, 1);
count = hb_face_get_glyph_count (face);
g_snprintf (buf, sizeof (buf), "%d", count);
add_misc_line (self, "Glyph Count", buf, row++);
if (hb_ot_var_get_axis_count (face) > 0)
{
s = g_string_new ("");
hb_ot_var_axis_info_t *axes;
axes = g_newa (hb_ot_var_axis_info_t, hb_ot_var_get_axis_count (face));
count = hb_ot_var_get_axis_count (face);
hb_ot_var_get_axis_infos (face, 0, &count, axes);
for (int i = 0; i < count; i++)
{
char name[256];
unsigned int len;
len = sizeof (buf);
hb_ot_name_get_utf8 (face, axes[i].name_id, HB_LANGUAGE_INVALID, &len, name);
if (s->len > 0)
g_string_append (s, ", ");
g_string_append (s, name);
}
add_misc_line (self, "Axes", s->str, row++);
g_string_free (s, TRUE);
}
if (hb_ot_var_get_named_instance_count (face) > 0)
{
s = g_string_new ("");
for (int i = 0; i < hb_ot_var_get_named_instance_count (face); i++)
{
hb_ot_name_id_t name_id;
char name[256];
unsigned int len;
name_id = hb_ot_var_named_instance_get_subfamily_name_id (face, i);
len = sizeof (buf);
hb_ot_name_get_utf8 (face, name_id, HB_LANGUAGE_INVALID, &len, name);
if (s->len > 0)
g_string_append (s, ", ");
g_string_append (s, name);
}
add_misc_line (self, "Named Instances", s->str, row++);
g_string_free (s, TRUE);
}
s = g_string_new ("");
count = hb_face_get_table_tags (face, 0, NULL, NULL);
tables = g_newa (hb_tag_t, count);
hb_face_get_table_tags (face, 0, &count, tables);
for (int i = 0; i < count; i++)
{
memset (buf, 0, sizeof (buf));
hb_tag_to_string (tables[i], buf);
if (s->len > 0)
g_string_append (s, ", ");
g_string_append (s, buf);
}
add_misc_line (self, "Tables", s->str, row++);
g_string_free (s, TRUE);
s = g_string_new ("");
if (hb_ot_color_has_palettes (face))
g_string_append_printf (s, "%s", "Palettes");
if (hb_ot_color_has_layers (face))
g_string_append_printf (s, "%s%s", s->len > 0 ? ", " : "", "Layers");
if (hb_ot_color_has_svg (face))
g_string_append_printf (s, "%s%s", s->len > 0 ? ", " : "", "SVG");
if (hb_ot_color_has_png (face))
g_string_append_printf (s, "%s%s", s->len > 0 ? ", " : "", "PNG");
if (s->len > 0)
add_misc_line (self, "Color", s->str, row++);
g_string_free (s, TRUE);
hb_font_destroy (font);
}
static void
info_view_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
InfoView *self = INFO_VIEW (object);
switch (prop_id)
{
case PROP_FONT_MAP:
g_set_object (&self->font_map, g_value_get_object (value));
break;
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_VARIATIONS:
g_free (self->variations);
self->variations = g_strdup (g_value_get_string (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
update_info (self);
}
static void
info_view_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
InfoView *self = INFO_VIEW (object);
switch (prop_id)
{
case PROP_FONT_MAP:
g_value_set_object (value, self->font_map);
break;
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_VARIATIONS:
g_value_set_string (value, self->variations);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
info_view_class_init (InfoViewClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
object_class->dispose = info_view_dispose;
object_class->finalize = info_view_finalize;
object_class->get_property = info_view_get_property;
object_class->set_property = info_view_set_property;
properties[PROP_FONT_MAP] =
g_param_spec_object ("font-map", "", "",
PANGO2_TYPE_FONT_MAP,
G_PARAM_READWRITE);
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_VARIATIONS] =
g_param_spec_string ("variations", "", "",
"",
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/infoview.ui");
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), InfoView, info);
gtk_widget_class_set_css_name (GTK_WIDGET_CLASS (class), "infoview");
}

View File

@@ -1,14 +0,0 @@
#pragma once
#include <gtk/gtk.h>
#define INFO_VIEW_TYPE (info_view_get_type ())
#define INFO_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INFO_VIEW_TYPE, InfoView))
typedef struct _InfoView InfoView;
typedef struct _InfoViewClass InfoViewClass;
GType info_view_get_type (void);

View File

@@ -1,23 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="InfoView" parent="GtkWidget">
<style>
<class name="view"/>
</style>
<child>
<object class="GtkScrolledWindow">
<property name="hscrollbar-policy">never</property>
<property name="vscrollbar-policy">automatic</property>
<property name="hexpand">1</property>
<property name="vexpand">1</property>
<child>
<object class="GtkGrid" id="info">
<style>
<class name="content"/>
</style>
</object>
</child>
</object>
</child>
</template>
</interface>

View File

@@ -1,334 +0,0 @@
#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

@@ -1,13 +0,0 @@
#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

@@ -1,9 +0,0 @@
#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

@@ -1,35 +0,0 @@
fontexplorer_sources = [
'fontcolors.c',
'fontcontrols.c',
'fontexplorerapp.c',
'fontexplorerwin.c',
'fontfeatures.c',
'fontvariations.c',
'glyphitem.c',
'glyphmodel.c',
'glyphsview.c',
'glyphview.c',
'infoview.c',
'language-names.c',
'main.c',
'plainview.c',
'rangeedit.c',
'samplechooser.c',
'sampleeditor.c',
'styleview.c',
'waterfallview.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

@@ -1,343 +0,0 @@
#include "plainview.h"
#include <gtk/gtk.h>
#include <hb-ot.h>
#include "glyphitem.h"
#include "glyphmodel.h"
#include "glyphview.h"
enum {
PROP_FONT_MAP = 1,
PROP_FONT_DESC,
PROP_SIZE,
PROP_LETTERSPACING,
PROP_LINE_HEIGHT,
PROP_FOREGROUND,
PROP_BACKGROUND,
PROP_VARIATIONS,
PROP_FEATURES,
PROP_PALETTE,
PROP_SAMPLE_TEXT,
NUM_PROPERTIES
};
static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
struct _PlainView
{
GtkWidget parent;
GtkLabel *content;
GtkScrolledWindow *swin;
Pango2FontMap *font_map;
Pango2FontDescription *font_desc;
float size;
char *variations;
char *features;
char *palette;
GQuark palette_quark;
int letterspacing;
float line_height;
GdkRGBA foreground;
GdkRGBA background;
GtkCssProvider *bg_provider;
char *sample_text;
};
struct _PlainViewClass
{
GtkWidgetClass parent_class;
};
G_DEFINE_TYPE(PlainView, plain_view, GTK_TYPE_WIDGET);
static void
plain_view_init (PlainView *self)
{
self->font_map = g_object_ref (pango2_font_map_get_default ());
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->palette_quark = g_quark_from_string (self->palette);
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
plain_view_dispose (GObject *object)
{
gtk_widget_clear_template (GTK_WIDGET (object), PLAIN_VIEW_TYPE);
G_OBJECT_CLASS (plain_view_parent_class)->dispose (object);
}
static void
plain_view_finalize (GObject *object)
{
PlainView *self = PLAIN_VIEW (object);
g_clear_object (&self->font_map);
pango2_font_description_free (self->font_desc);
g_free (self->variations);
g_free (self->features);
g_free (self->palette);
G_OBJECT_CLASS (plain_view_parent_class)->finalize (object);
}
static void
update_view (PlainView *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_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 (".content { 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
plain_view_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
PlainView *self = PLAIN_VIEW (object);
switch (prop_id)
{
case PROP_FONT_MAP:
g_set_object (&self->font_map, g_value_get_object (value));
gtk_widget_set_font_map (GTK_WIDGET (self->content), self->font_map);
break;
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));
self->palette_quark = g_quark_from_string (self->palette);
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
plain_view_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
PlainView *self = PLAIN_VIEW (object);
switch (prop_id)
{
case PROP_FONT_MAP:
g_value_set_object (value, self->font_map);
break;
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;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
plain_view_class_init (PlainViewClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
object_class->dispose = plain_view_dispose;
object_class->finalize = plain_view_finalize;
object_class->get_property = plain_view_get_property;
object_class->set_property = plain_view_set_property;
properties[PROP_FONT_MAP] =
g_param_spec_object ("font-map", "", "",
PANGO2_TYPE_FONT_MAP,
G_PARAM_READWRITE);
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);
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/plainview.ui");
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), PlainView, swin);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), PlainView, content);
gtk_widget_class_set_css_name (GTK_WIDGET_CLASS (class), "plainview");
}

View File

@@ -1,14 +0,0 @@
#pragma once
#include <gtk/gtk.h>
#define PLAIN_VIEW_TYPE (plain_view_get_type ())
#define PLAIN_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PLAIN_VIEW_TYPE, PlainView))
typedef struct _PlainView PlainView;
typedef struct _PlainViewClass PlainViewClass;
GType plain_view_get_type (void);

View File

@@ -1,32 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="PlainView" parent="GtkWidget">
<property name="hexpand">1</property>
<property name="vexpand">1</property>
<child>
<object class="GtkScrolledWindow" id="swin">
<property name="hscrollbar-policy">never</property>
<property name="vscrollbar-policy">automatic</property>
<style>
<class name="view"/>
</style>
<child>
<object class="GtkLabel" id="content">
<property name="label">Content</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="content"/>
</style>
</object>
</child>
</object>
</child>
</template>
</interface>

View File

@@ -1,174 +0,0 @@
#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

@@ -1,15 +0,0 @@
#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

@@ -1,24 +0,0 @@
<?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

@@ -1,163 +0,0 @@
#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

@@ -1,15 +0,0 @@
#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

@@ -1,46 +0,0 @@
<?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

@@ -1,162 +0,0 @@
#include "sampleeditor.h"
#include <gtk/gtk.h>
enum {
PROP_SAMPLE_TEXT = 1,
PROP_EDITING,
NUM_PROPERTIES
};
static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
struct _SampleEditor
{
GtkWidget parent;
GtkTextView *edit;
char *sample_text;
gboolean editing;
};
struct _SampleEditorClass
{
GtkWidgetClass parent_class;
};
G_DEFINE_TYPE(SampleEditor, sample_editor, GTK_TYPE_WIDGET);
static void
sample_editor_init (SampleEditor *self)
{
self->sample_text = g_strdup ("Some sample text is better than other sample text");
self->editing = FALSE;
gtk_widget_set_layout_manager (GTK_WIDGET (self),
gtk_box_layout_new (GTK_ORIENTATION_VERTICAL));
gtk_widget_init_template (GTK_WIDGET (self));
}
static void
sample_editor_dispose (GObject *object)
{
gtk_widget_clear_template (GTK_WIDGET (object), SAMPLE_EDITOR_TYPE);
G_OBJECT_CLASS (sample_editor_parent_class)->dispose (object);
}
static void
sample_editor_finalize (GObject *object)
{
SampleEditor *self = SAMPLE_EDITOR (object);
g_free (self->sample_text);
G_OBJECT_CLASS (sample_editor_parent_class)->finalize (object);
}
static void
update_editing (SampleEditor *self,
gboolean editing)
{
GtkTextBuffer *buffer;
if (self->editing == editing)
return;
self->editing = editing;
buffer = gtk_text_view_get_buffer (self->edit);
if (self->editing)
{
gtk_text_buffer_set_text (buffer, self->sample_text, -1);
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);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SAMPLE_TEXT]);
}
}
static void
sample_editor_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
SampleEditor *self = SAMPLE_EDITOR (object);
switch (prop_id)
{
case PROP_SAMPLE_TEXT:
g_free (self->sample_text);
self->sample_text = g_strdup (g_value_get_string (value));
break;
case PROP_EDITING:
update_editing (self, g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
sample_editor_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
SampleEditor *self = SAMPLE_EDITOR (object);
switch (prop_id)
{
case PROP_SAMPLE_TEXT:
g_value_set_string (value, self->sample_text);
break;
case PROP_EDITING:
g_value_set_boolean (value, self->editing);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
sample_editor_class_init (SampleEditorClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
object_class->dispose = sample_editor_dispose;
object_class->finalize = sample_editor_finalize;
object_class->get_property = sample_editor_get_property;
object_class->set_property = sample_editor_set_property;
properties[PROP_SAMPLE_TEXT] =
g_param_spec_string ("sample-text", "", "",
"",
G_PARAM_READWRITE);
properties[PROP_EDITING] =
g_param_spec_boolean ("editing", "", "",
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/sampleeditor.ui");
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), SampleEditor, edit);
gtk_widget_class_set_css_name (GTK_WIDGET_CLASS (class), "sampleeditor");
}

View File

@@ -1,14 +0,0 @@
#pragma once
#include <gtk/gtk.h>
#define SAMPLE_EDITOR_TYPE (sample_editor_get_type ())
#define SAMPLE_EDITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SAMPLE_EDITOR_TYPE, SampleEditor))
typedef struct _SampleEditor SampleEditor;
typedef struct _SampleEditorClass SampleEditorClass;
GType sample_editor_get_type (void);

View File

@@ -1,25 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="SampleEditor" parent="GtkWidget">
<style>
<class name="view"/>
</style>
<child>
<object class="GtkScrolledWindow">
<property name="hscrollbar-policy">never</property>
<property name="vscrollbar-policy">automatic</property>
<property name="hexpand">1</property>
<property name="vexpand">1</property>
<child>
<object class="GtkTextView" id="edit">
<property name="wrap-mode">word-char</property>
<property name="left-margin">20</property>
<property name="right-margin">20</property>
<property name="top-margin">20</property>
<property name="bottom-margin">20</property>
</object>
</child>
</object>
</child>
</template>
</interface>

View File

@@ -1,506 +0,0 @@
#include "styleview.h"
#include <gtk/gtk.h>
#include <hb-ot.h>
#include "glyphitem.h"
#include "glyphmodel.h"
#include "glyphview.h"
enum {
PROP_FONT_MAP = 1,
PROP_FONT_DESC,
PROP_SIZE,
PROP_LETTERSPACING,
PROP_LINE_HEIGHT,
PROP_FOREGROUND,
PROP_BACKGROUND,
PROP_VARIATIONS,
PROP_FEATURES,
PROP_PALETTE,
PROP_SAMPLE_TEXT,
PROP_HAS_STYLES,
NUM_PROPERTIES
};
static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
struct _StyleView
{
GtkWidget parent;
GtkLabel *content;
GtkScrolledWindow *swin;
Pango2FontMap *font_map;
Pango2FontDescription *font_desc;
float size;
char *variations;
char *features;
char *palette;
GQuark palette_quark;
int letterspacing;
float line_height;
GdkRGBA foreground;
GdkRGBA background;
GtkCssProvider *bg_provider;
char *sample_text;
gboolean has_styles;
};
struct _StyleViewClass
{
GtkWidgetClass parent_class;
};
G_DEFINE_TYPE(StyleView, style_view, GTK_TYPE_WIDGET);
static void
style_view_init (StyleView *self)
{
self->font_map = g_object_ref (pango2_font_map_get_default ());
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->palette_quark = g_quark_from_string (self->palette);
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");
self->has_styles = FALSE;
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
style_view_dispose (GObject *object)
{
gtk_widget_clear_template (GTK_WIDGET (object), STYLE_VIEW_TYPE);
G_OBJECT_CLASS (style_view_parent_class)->dispose (object);
}
static void
style_view_finalize (GObject *object)
{
StyleView *self = STYLE_VIEW (object);
g_clear_object (&self->font_map);
pango2_font_description_free (self->font_desc);
g_free (self->variations);
g_free (self->features);
g_free (self->palette);
G_OBJECT_CLASS (style_view_parent_class)->finalize (object);
}
static Pango2Font *
get_font (StyleView *self)
{
Pango2Context *context;
Pango2FontDescription *desc;
Pango2Font *font;
context = pango2_context_new_with_font_map (self->font_map);
desc = pango2_font_description_copy_static (self->font_desc);
pango2_font_description_set_variations (desc, self->variations);
pango2_font_description_set_size (desc, self->size * PANGO2_SCALE);
font = pango2_context_load_font (context, desc);
pango2_font_description_free (desc);
g_object_unref (context);
return font;
}
static void
update_has_styles (StyleView *self)
{
Pango2Font *font = get_font (self);
hb_face_t *hb_face = hb_font_get_face (pango2_font_get_hb_font (font));
gboolean has_styles;
has_styles = hb_ot_var_get_named_instance_count (hb_face) > 0;
g_object_unref (font);
if (self->has_styles == has_styles)
return;
self->has_styles = has_styles;
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_HAS_STYLES]);
}
static int
measure_names (Pango2Context *context,
hb_face_t *hb_face)
{
Pango2Layout *layout;
Pango2FontDescription *desc;
GString *str;
int width, height;
layout = pango2_layout_new (context);
desc = pango2_font_description_from_string ("Cantarell Regular 12");
pango2_layout_set_font_description (layout, desc);
pango2_font_description_free (desc);
str = g_string_new ("");
for (int i = 0; i < hb_ot_var_get_named_instance_count (hb_face); i++)
{
hb_ot_name_id_t name_id;
char name[20];
unsigned int name_len = 20;
name_id = hb_ot_var_named_instance_get_subfamily_name_id (hb_face, i);
hb_ot_name_get_utf8 (hb_face, name_id, HB_LANGUAGE_INVALID, &name_len, name);
g_string_append_printf (str, " %s\n", name);
}
pango2_layout_set_text (layout, str->str, -1);
pango2_lines_get_size (pango2_layout_get_lines (layout), &width, &height);
g_string_free (str, TRUE);
g_object_unref (layout);
return width;
}
static void
update_view (StyleView *self)
{
Pango2FontDescription *desc;
Pango2AttrList *attrs;
char *fg, *bg, *css;
GString *str;
int start, end, text_len;
Pango2Font *font = get_font (self);
hb_face_t *hb_face = hb_font_get_face (pango2_font_get_hb_font (font));
unsigned int n_axes;
float *coords = NULL;
hb_ot_var_axis_info_t *axes;
Pango2FontDescription *label_desc;
Pango2TabArray *tabs;
int width;
desc = pango2_font_description_copy_static (self->font_desc);
pango2_font_description_set_variations (desc, self->variations);
pango2_font_description_set_size (desc, self->size * PANGO2_SCALE);
attrs = pango2_attr_list_new ();
pango2_attr_list_insert (attrs, pango2_attr_font_desc_new (desc));
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));
str = g_string_new ("");
start = 0;
text_len = strlen (self->sample_text);
n_axes = hb_ot_var_get_axis_count (hb_face);
axes = g_newa (hb_ot_var_axis_info_t, n_axes);
hb_ot_var_get_axis_infos (hb_face, 0, &n_axes, axes);
coords = g_newa (float, n_axes);
label_desc = pango2_font_description_from_string ("Cantarell Regular 12");
width = measure_names (gtk_widget_get_pango_context (GTK_WIDGET (self->content)), hb_face);
tabs = pango2_tab_array_new (1, PANGO2_TAB_POSITIONS_DEFAULT);
pango2_tab_array_set_tab (tabs, 0, PANGO2_TAB_LEFT, width);
gtk_label_set_tabs (self->content, tabs);
pango2_tab_array_free (tabs);
for (int i = 0; i < hb_ot_var_get_named_instance_count (hb_face); i++)
{
unsigned int n_coords = n_axes;
Pango2Attribute *attr;
GString *variations;
hb_ot_name_id_t name_id;
char name[20];
unsigned int name_len = 20;
name_id = hb_ot_var_named_instance_get_subfamily_name_id (hb_face, i);
hb_ot_name_get_utf8 (hb_face, name_id, HB_LANGUAGE_INVALID, &name_len, name);
g_string_append_printf (str, "%s\t", name);
end = str->len;
attr = pango2_attr_font_desc_new (label_desc);
pango2_attribute_set_range (attr, start, end);
pango2_attr_list_insert (attrs, attr);
start = end;
hb_ot_var_named_instance_get_design_coords (hb_face, i, &n_coords, coords);
variations = g_string_new ("");
for (int j = 0; j < n_axes; j++)
{
char buf[5] = { 0, };
if (variations->len > 0)
g_string_append_c (variations, ',');
hb_tag_to_string (axes[j].tag, buf);
g_string_append_printf (variations, "%s=%f", buf, coords[j]);
}
g_string_append (str, self->sample_text);
g_string_append (str, ""); /* Unicode line separator */
end = start + text_len + strlen ("");
pango2_font_description_set_variations (desc, variations->str);
g_string_free (variations, TRUE);
attr = pango2_attr_font_desc_new (desc);
pango2_attribute_set_range (attr, start, end);
pango2_attr_list_insert (attrs, attr);
start = end;
}
pango2_font_description_free (label_desc);
gtk_label_set_text (self->content, str->str);
gtk_label_set_attributes (self->content, attrs);
g_string_free (str, TRUE);
pango2_attr_list_unref (attrs);
pango2_font_description_free (desc);
fg = gdk_rgba_to_string (&self->foreground);
bg = gdk_rgba_to_string (&self->background);
css = g_strdup_printf (".content { 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);
g_object_unref (font);
}
static void
style_view_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
StyleView *self = STYLE_VIEW (object);
switch (prop_id)
{
case PROP_FONT_MAP:
g_set_object (&self->font_map, g_value_get_object (value));
gtk_widget_set_font_map (GTK_WIDGET (self->content), self->font_map);
update_has_styles (self);
break;
case PROP_FONT_DESC:
pango2_font_description_free (self->font_desc);
self->font_desc = pango2_font_description_copy (g_value_get_boxed (value));
update_has_styles (self);
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));
self->palette_quark = g_quark_from_string (self->palette);
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
style_view_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
StyleView *self = STYLE_VIEW (object);
switch (prop_id)
{
case PROP_FONT_MAP:
g_value_set_object (value, self->font_map);
break;
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_HAS_STYLES:
g_value_set_boolean (value, self->has_styles);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
style_view_class_init (StyleViewClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
object_class->dispose = style_view_dispose;
object_class->finalize = style_view_finalize;
object_class->get_property = style_view_get_property;
object_class->set_property = style_view_set_property;
properties[PROP_FONT_MAP] =
g_param_spec_object ("font-map", "", "",
PANGO2_TYPE_FONT_MAP,
G_PARAM_READWRITE);
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_HAS_STYLES] =
g_param_spec_boolean ("has-styles", "", "",
FALSE,
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/styleview.ui");
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), StyleView, swin);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), StyleView, content);
gtk_widget_class_set_css_name (GTK_WIDGET_CLASS (class), "styleview");
}

View File

@@ -1,14 +0,0 @@
#pragma once
#include <gtk/gtk.h>
#define STYLE_VIEW_TYPE (style_view_get_type ())
#define STYLE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), STYLE_VIEW_TYPE, StyleView))
typedef struct _StyleView StyleView;
typedef struct _StyleViewClass StyleViewClass;
GType style_view_get_type (void);

View File

@@ -1,31 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="StyleView" parent="GtkWidget">
<property name="hexpand">1</property>
<property name="vexpand">1</property>
<style>
<class name="view"/>
</style>
<child>
<object class="GtkScrolledWindow" id="swin">
<property name="hscrollbar-policy">automatic</property>
<property name="vscrollbar-policy">automatic</property>
<child>
<object class="GtkLabel" id="content">
<property name="label">Content</property>
<property name="wrap">0</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="content"/>
</style>
</object>
</child>
</object>
</child>
</template>
</interface>

View File

@@ -1,401 +0,0 @@
#include "waterfallview.h"
#include <gtk/gtk.h>
#include <hb-ot.h>
#include "glyphitem.h"
#include "glyphmodel.h"
#include "glyphview.h"
enum {
PROP_FONT_MAP = 1,
PROP_FONT_DESC,
PROP_SIZE,
PROP_LETTERSPACING,
PROP_LINE_HEIGHT,
PROP_FOREGROUND,
PROP_BACKGROUND,
PROP_VARIATIONS,
PROP_FEATURES,
PROP_PALETTE,
PROP_SAMPLE_TEXT,
NUM_PROPERTIES
};
static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
struct _WaterfallView
{
GtkWidget parent;
GtkLabel *content;
GtkScrolledWindow *swin;
Pango2FontMap *font_map;
Pango2FontDescription *font_desc;
float size;
char *variations;
char *features;
char *palette;
GQuark palette_quark;
int letterspacing;
float line_height;
GdkRGBA foreground;
GdkRGBA background;
GtkCssProvider *bg_provider;
char *sample_text;
};
struct _WaterfallViewClass
{
GtkWidgetClass parent_class;
};
G_DEFINE_TYPE(WaterfallView, waterfall_view, GTK_TYPE_WIDGET);
static void
waterfall_view_init (WaterfallView *self)
{
self->font_map = g_object_ref (pango2_font_map_get_default ());
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->palette_quark = g_quark_from_string (self->palette);
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
waterfall_view_dispose (GObject *object)
{
gtk_widget_clear_template (GTK_WIDGET (object), WATERFALL_VIEW_TYPE);
G_OBJECT_CLASS (waterfall_view_parent_class)->dispose (object);
}
static void
waterfall_view_finalize (GObject *object)
{
WaterfallView *self = WATERFALL_VIEW (object);
g_clear_object (&self->font_map);
pango2_font_description_free (self->font_desc);
g_free (self->variations);
g_free (self->features);
g_free (self->palette);
G_OBJECT_CLASS (waterfall_view_parent_class)->finalize (object);
}
static void
update_view (WaterfallView *self)
{
Pango2FontDescription *desc;
Pango2AttrList *attrs;
char *fg, *bg, *css;
GString *str;
int sizes[] = { 7, 8, 9, 10, 12, 14, 16, 20, 24, 30, 40, 50, 60, 70, 90, 120 };
int start, end, text_len;
Pango2TabArray *tabs;
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_line_height_new (self->line_height));
pango2_attr_list_insert (attrs, pango2_attr_letter_spacing_new (self->letterspacing));
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);
tabs = pango2_tab_array_new (2, PANGO2_TAB_POSITIONS_SPACES);
pango2_tab_array_set_tab (tabs, 0, PANGO2_TAB_RIGHT, 5);
pango2_tab_array_set_tab (tabs, 1, PANGO2_TAB_LEFT, 8);
gtk_label_set_tabs (self->content, tabs);
pango2_tab_array_free (tabs);
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_printf (str, "\t%d\t", sizes[i]);
end = str->len;
attr = pango2_attr_family_new ("Cantarell");
pango2_attribute_set_range (attr, start, end);
pango2_attr_list_insert (attrs, attr);
attr = pango2_attr_weight_new (PANGO2_WEIGHT_NORMAL);
pango2_attribute_set_range (attr, start, end);
pango2_attr_list_insert (attrs, attr);
attr = pango2_attr_style_new (PANGO2_STYLE_NORMAL);
pango2_attribute_set_range (attr, start, end);
pango2_attr_list_insert (attrs, attr);
attr = pango2_attr_size_new (12 * PANGO2_SCALE);
pango2_attribute_set_range (attr, start, end);
pango2_attr_list_insert (attrs, attr);
attr = pango2_attr_font_features_new ("tnum=1");
pango2_attribute_set_range (attr, start, end);
pango2_attr_list_insert (attrs, attr);
attr = pango2_attr_letter_spacing_new (0);
pango2_attribute_set_range (attr, start, end);
pango2_attr_list_insert (attrs, attr);
start = end;
g_string_append (str, self->sample_text);
g_string_append (str, ""); /* Unicode line separator */
end = start + text_len + strlen ("");
attr = pango2_attr_size_new (sizes[i] * PANGO2_SCALE);
pango2_attribute_set_range (attr, start, end);
pango2_attr_list_insert (attrs, attr);
start = end;
}
gtk_label_set_text (self->content, str->str);
gtk_label_set_attributes (self->content, attrs);
g_string_free (str, TRUE);
pango2_attr_list_unref (attrs);
fg = gdk_rgba_to_string (&self->foreground);
bg = gdk_rgba_to_string (&self->background);
css = g_strdup_printf (".content { 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
waterfall_view_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
WaterfallView *self = WATERFALL_VIEW (object);
switch (prop_id)
{
case PROP_FONT_MAP:
g_set_object (&self->font_map, g_value_get_object (value));
gtk_widget_set_font_map (GTK_WIDGET (self->content), self->font_map);
break;
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));
self->palette_quark = g_quark_from_string (self->palette);
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
waterfall_view_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
WaterfallView *self = WATERFALL_VIEW (object);
switch (prop_id)
{
case PROP_FONT_MAP:
g_value_set_object (value, self->font_map);
break;
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;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
waterfall_view_class_init (WaterfallViewClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
object_class->dispose = waterfall_view_dispose;
object_class->finalize = waterfall_view_finalize;
object_class->get_property = waterfall_view_get_property;
object_class->set_property = waterfall_view_set_property;
properties[PROP_FONT_MAP] =
g_param_spec_object ("font-map", "", "",
PANGO2_TYPE_FONT_MAP,
G_PARAM_READWRITE);
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);
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/waterfallview.ui");
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), WaterfallView, swin);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), WaterfallView, content);
gtk_widget_class_set_css_name (GTK_WIDGET_CLASS (class), "waterfallview");
}

View File

@@ -1,14 +0,0 @@
#pragma once
#include <gtk/gtk.h>
#define WATERFALL_VIEW_TYPE (waterfall_view_get_type ())
#define WATERFALL_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), WATERFALL_VIEW_TYPE, WaterfallView))
typedef struct _WaterfallView WaterfallView;
typedef struct _WaterfallViewClass WaterfallViewClass;
GType waterfall_view_get_type (void);

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