diff --git a/doc/testing.html b/doc/testing.html
index 6285fab1682..c1c0f15fed9 100644
--- a/doc/testing.html
+++ b/doc/testing.html
@@ -411,6 +411,13 @@ instrumentation
special target jcov-test instead of test, e.g.
make jcov-test TEST=jdk_lang. This will make sure the JCov
image is built, and that JCov reporting is enabled.
+To include JCov coverage for just a subset of all modules, you can
+use the --with-jcov-modules arguments to
+configure, e.g.
+--with-jcov-modules=jdk.compiler,java.desktop.
+For more fine-grained control, you can pass arbitrary filters to JCov
+using --with-jcov-filters, and you can specify a specific
+JDK to instrument using --with-jcov-input-jdk.
The JCov report is stored in
build/$BUILD/test-results/jcov-output/report.
Please note that running with JCov reporting can be very memory
diff --git a/doc/testing.md b/doc/testing.md
index 351690c5e60..f6a25457b5e 100644
--- a/doc/testing.md
+++ b/doc/testing.md
@@ -345,6 +345,14 @@ The simplest way to run tests with JCov coverage report is to use the special
target `jcov-test` instead of `test`, e.g. `make jcov-test TEST=jdk_lang`. This
will make sure the JCov image is built, and that JCov reporting is enabled.
+To include JCov coverage for just a subset of all modules, you can use the
+`--with-jcov-modules` arguments to `configure`, e.g.
+`--with-jcov-modules=jdk.compiler,java.desktop`.
+
+For more fine-grained control, you can pass arbitrary filters to JCov using
+`--with-jcov-filters`, and you can specify a specific JDK to instrument
+using `--with-jcov-input-jdk`.
+
The JCov report is stored in `build/$BUILD/test-results/jcov-output/report`.
Please note that running with JCov reporting can be very memory intensive.
diff --git a/make/Coverage.gmk b/make/Coverage.gmk
index 2fd4e4ec6d4..a375c343185 100644
--- a/make/Coverage.gmk
+++ b/make/Coverage.gmk
@@ -34,21 +34,28 @@ else
JCOV_INPUT_IMAGE_DIR := $(JDK_IMAGE_DIR)
endif
+JCOV_SUPPORT_DIR := $(SUPPORT_OUTPUTDIR)/jcov
+
#moving instrumented jdk image in and out of jcov_temp because of CODETOOLS-7902299
-JCOV_TEMP := $(SUPPORT_OUTPUTDIR)/jcov_temp
+JCOV_TEMP := $(JCOV_SUPPORT_DIR)/temp
+
+ifneq ($(JCOV_MODULES), )
+ JCOV_MODULES_FILTER := $(foreach m, $(JCOV_MODULES), -include_module $m)
+endif
$(JCOV_IMAGE_DIR)/release: $(JCOV_INPUT_IMAGE_DIR)/release
$(call LogWarn, Creating instrumented jdk image with JCov)
$(call MakeDir, $(JCOV_TEMP) $(IMAGES_OUTPUTDIR))
$(RM) -r $(JCOV_IMAGE_DIR) $(JCOV_TEMP)/*
$(CP) -r $(JCOV_INPUT_IMAGE_DIR) $(JCOV_TEMP)/$(JCOV_IMAGE_SUBDIR)
- $(JAVA) -Xmx3g -jar $(JCOV_HOME)/lib/jcov.jar JREInstr \
+ $(call ExecuteWithLog, $(JCOV_SUPPORT_DIR)/run-jcov, \
+ $(JAVA) -Xmx3g -jar $(JCOV_HOME)/lib/jcov.jar JREInstr \
-t $(JCOV_TEMP)/$(JCOV_IMAGE_SUBDIR)/template.xml \
-rt $(JCOV_HOME)/lib/jcov_network_saver.jar \
-exclude 'java.lang.Object' \
-exclude jdk.test.Main -exclude '**\$Proxy*' \
- $(JCOV_FILTERS) \
- $(JCOV_TEMP)/$(JCOV_IMAGE_SUBDIR)
+ $(JCOV_MODULES_FILTER) $(JCOV_FILTERS) \
+ $(JCOV_TEMP)/$(JCOV_IMAGE_SUBDIR))
$(MV) $(JCOV_TEMP)/$(JCOV_IMAGE_SUBDIR) $(JCOV_IMAGE_DIR)
$(RMDIR) $(JCOV_TEMP)
diff --git a/make/RunTests.gmk b/make/RunTests.gmk
index 69dc47a0c61..3c0280353a9 100644
--- a/make/RunTests.gmk
+++ b/make/RunTests.gmk
@@ -115,6 +115,7 @@ JTREG_COV_OPTIONS :=
ifeq ($(TEST_OPTS_JCOV), true)
JCOV_OUTPUT_DIR := $(TEST_RESULTS_DIR)/jcov-output
+ JCOV_SUPPORT_DIR := $(TEST_SUPPORT_DIR)/jcov-support
JCOV_GRABBER_LOG := $(JCOV_OUTPUT_DIR)/grabber.log
JCOV_RESULT_FILE := $(JCOV_OUTPUT_DIR)/result.xml
JCOV_REPORT := $(JCOV_OUTPUT_DIR)/report
@@ -1343,12 +1344,14 @@ TARGETS += run-all-tests pre-run-test post-run-test run-test-report run-test
ifeq ($(TEST_OPTS_JCOV), true)
+ JCOV_VM_OPTS := -Xmx4g -Djdk.xml.totalEntitySizeLimit=0 -Djdk.xml.maxGeneralEntitySizeLimit=0
+
jcov-do-start-grabber:
$(call MakeDir, $(JCOV_OUTPUT_DIR))
if $(JAVA) -jar $(JCOV_HOME)/lib/jcov.jar GrabberManager -status 1>/dev/null 2>&1 ; then \
$(JAVA) -jar $(JCOV_HOME)/lib/jcov.jar GrabberManager -stop -stoptimeout 3600 ; \
fi
- $(JAVA) -Xmx4g -jar $(JCOV_HOME)/lib/jcov.jar Grabber -v -t \
+ $(JAVA) $(JCOV_VM_OPTS) -jar $(JCOV_HOME)/lib/jcov.jar Grabber -v -t \
$(JCOV_IMAGE_DIR)/template.xml -o $(JCOV_RESULT_FILE) \
1>$(JCOV_GRABBER_LOG) 2>&1 &
@@ -1361,6 +1364,10 @@ ifeq ($(TEST_OPTS_JCOV), true)
$(JAVA) -jar $(JCOV_HOME)/lib/jcov.jar GrabberManager -stop -stoptimeout 3600
JCOV_REPORT_TITLE := JDK code coverage report
+ ifneq ($(JCOV_MODULES), )
+ JCOV_MODULES_FILTER := $(foreach m, $(JCOV_MODULES), -include_module $m)
+ JCOV_REPORT_TITLE += Included modules: $(JCOV_MODULES)
+ endif
ifneq ($(JCOV_FILTERS), )
JCOV_REPORT_TITLE += Code filters: $(JCOV_FILTERS)
endif
@@ -1368,11 +1375,12 @@ ifeq ($(TEST_OPTS_JCOV), true)
jcov-gen-report: jcov-stop-grabber
$(call LogWarn, Generating JCov report ...)
- $(JAVA) -Xmx4g -jar $(JCOV_HOME)/lib/jcov.jar RepGen -sourcepath \
+ $(call ExecuteWithLog, $(JCOV_SUPPORT_DIR)/run-jcov-repgen, \
+ $(JAVA) $(JCOV_VM_OPTS) -jar $(JCOV_HOME)/lib/jcov.jar RepGen -sourcepath \
`$(ECHO) $(TOPDIR)/src/*/share/classes/ | $(TR) ' ' ':'` -fmt html \
- $(JCOV_FILTERS) \
+ $(JCOV_MODULES_FILTER) $(JCOV_FILTERS) \
-mainReportTitle "$(JCOV_REPORT_TITLE)" \
- -o $(JCOV_REPORT) $(JCOV_RESULT_FILE)
+ -o $(JCOV_REPORT) $(JCOV_RESULT_FILE))
TARGETS += jcov-do-start-grabber jcov-start-grabber jcov-stop-grabber \
jcov-gen-report
@@ -1392,7 +1400,7 @@ ifeq ($(TEST_OPTS_JCOV), true)
jcov-gen-diffcoverage: jcov-stop-grabber
$(call LogWarn, Generating diff coverage with changeset $(TEST_OPTS_JCOV_DIFF_CHANGESET) ... )
$(DIFF_COMMAND)
- $(JAVA) -Xmx4g -jar $(JCOV_HOME)/lib/jcov.jar \
+ $(JAVA) $(JCOV_VM_OPTS) -jar $(JCOV_HOME)/lib/jcov.jar \
DiffCoverage -replaceDiff "src/.*/classes/:" -all \
$(JCOV_RESULT_FILE) $(JCOV_SOURCE_DIFF) > \
$(JCOV_DIFF_COVERAGE_REPORT)
diff --git a/make/RunTestsPrebuilt.gmk b/make/RunTestsPrebuilt.gmk
index ba9731789b0..f5fe1d33830 100644
--- a/make/RunTestsPrebuilt.gmk
+++ b/make/RunTestsPrebuilt.gmk
@@ -217,9 +217,9 @@ else ifeq ($(OPENJDK_TARGET_OS), macosx)
else ifeq ($(OPENJDK_TARGET_OS), windows)
NUM_CORES := $(NUMBER_OF_PROCESSORS)
MEMORY_SIZE := $(shell \
- $(EXPR) `wmic computersystem get totalphysicalmemory -value \
- | $(GREP) = | $(SED) 's/\\r//g' \
- | $(CUT) -d "=" -f 2-` / 1024 / 1024 \
+ $(EXPR) `powershell -Command \
+ "(Get-CimInstance Win32_ComputerSystem).TotalPhysicalMemory" \
+ | $(SED) 's/\\r//g' ` / 1024 / 1024 \
)
endif
ifeq ($(NUM_CORES), )
diff --git a/make/autoconf/boot-jdk.m4 b/make/autoconf/boot-jdk.m4
index d39e6e75a94..feb16c7d179 100644
--- a/make/autoconf/boot-jdk.m4
+++ b/make/autoconf/boot-jdk.m4
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -180,11 +180,13 @@ AC_DEFUN([BOOTJDK_CHECK_JAVA_HOME],
# Test: Is there a java or javac in the PATH, which is a symlink to the JDK?
AC_DEFUN([BOOTJDK_CHECK_JAVA_IN_PATH_IS_SYMLINK],
[
- UTIL_LOOKUP_PROGS(JAVAC_CHECK, javac, , NOFIXPATH)
- UTIL_LOOKUP_PROGS(JAVA_CHECK, java, , NOFIXPATH)
- BINARY="$JAVAC_CHECK"
- if test "x$JAVAC_CHECK" = x; then
- BINARY="$JAVA_CHECK"
+ UTIL_LOOKUP_PROGS(JAVAC_CHECK, javac)
+ UTIL_GET_EXECUTABLE(JAVAC_CHECK) # Will setup JAVAC_CHECK_EXECUTABLE
+ UTIL_LOOKUP_PROGS(JAVA_CHECK, java)
+ UTIL_GET_EXECUTABLE(JAVA_CHECK) # Will setup JAVA_CHECK_EXECUTABLE
+ BINARY="$JAVAC_CHECK_EXECUTABLE"
+ if test "x$JAVAC_CHECK_EXECUTABLE" = x; then
+ BINARY="$JAVA_CHECK_EXECUTABLE"
fi
if test "x$BINARY" != x; then
# So there is a java(c) binary, it might be part of a JDK.
diff --git a/make/autoconf/build-performance.m4 b/make/autoconf/build-performance.m4
index 4414ea0d93c..10e86e75199 100644
--- a/make/autoconf/build-performance.m4
+++ b/make/autoconf/build-performance.m4
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -75,7 +75,8 @@ AC_DEFUN([BPERF_CHECK_MEMORY_SIZE],
FOUND_MEM=yes
elif test "x$OPENJDK_BUILD_OS" = xwindows; then
# Windows, but without cygwin
- MEMORY_SIZE=`wmic computersystem get totalphysicalmemory -value | grep = | cut -d "=" -f 2-`
+ MEMORY_SIZE=`powershell -Command \
+ "(Get-CimInstance Win32_ComputerSystem).TotalPhysicalMemory" | $SED 's/\\r//g' `
MEMORY_SIZE=`expr $MEMORY_SIZE / 1024 / 1024`
FOUND_MEM=yes
fi
diff --git a/make/autoconf/jdk-options.m4 b/make/autoconf/jdk-options.m4
index f8a512f503d..289ed935fdf 100644
--- a/make/autoconf/jdk-options.m4
+++ b/make/autoconf/jdk-options.m4
@@ -405,10 +405,19 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_CODE_COVERAGE],
JCOV_FILTERS="$with_jcov_filters"
fi
fi
+
+ UTIL_ARG_WITH(NAME: jcov-modules, TYPE: string,
+ DEFAULT: [], RESULT: JCOV_MODULES_COMMMA_SEPARATED,
+ DESC: [which modules to include in jcov (comma-separated)],
+ OPTIONAL: true)
+
+ # Replace "," with " ".
+ JCOV_MODULES=${JCOV_MODULES_COMMMA_SEPARATED//,/ }
AC_SUBST(JCOV_ENABLED)
AC_SUBST(JCOV_HOME)
AC_SUBST(JCOV_INPUT_JDK)
AC_SUBST(JCOV_FILTERS)
+ AC_SUBST(JCOV_MODULES)
])
################################################################################
diff --git a/make/autoconf/spec.gmk.template b/make/autoconf/spec.gmk.template
index ebaa487b40a..e720916d88a 100644
--- a/make/autoconf/spec.gmk.template
+++ b/make/autoconf/spec.gmk.template
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -454,6 +454,7 @@ JCOV_ENABLED := @JCOV_ENABLED@
JCOV_HOME := @JCOV_HOME@
JCOV_INPUT_JDK := @JCOV_INPUT_JDK@
JCOV_FILTERS := @JCOV_FILTERS@
+JCOV_MODULES := @JCOV_MODULES@
# AddressSanitizer
ASAN_ENABLED := @ASAN_ENABLED@
diff --git a/make/autoconf/util_paths.m4 b/make/autoconf/util_paths.m4
index 9e3e5472c9e..c3cc3955deb 100644
--- a/make/autoconf/util_paths.m4
+++ b/make/autoconf/util_paths.m4
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -186,7 +186,6 @@ AC_DEFUN([UTIL_CHECK_WINENV_EXEC_TYPE],
# it need to be in the PATH.
# $1: The name of the variable to fix
# $2: Where to look for the command (replaces $PATH)
-# $3: set to NOFIXPATH to skip prefixing FIXPATH, even if needed on platform
AC_DEFUN([UTIL_FIXUP_EXECUTABLE],
[
input="[$]$1"
@@ -282,10 +281,6 @@ AC_DEFUN([UTIL_FIXUP_EXECUTABLE],
fi
fi
- if test "x$3" = xNOFIXPATH; then
- fixpath_prefix=""
- fi
-
# Now join together the path and the arguments once again
new_complete="$fixpath_prefix$new_path$arguments"
$1="$new_complete"
@@ -379,7 +374,6 @@ AC_DEFUN([UTIL_SETUP_TOOL],
# $1: variable to set
# $2: executable name (or list of names) to look for
# $3: [path]
-# $4: set to NOFIXPATH to skip prefixing FIXPATH, even if needed on platform
AC_DEFUN([UTIL_LOOKUP_PROGS],
[
UTIL_SETUP_TOOL($1, [
@@ -421,10 +415,8 @@ AC_DEFUN([UTIL_LOOKUP_PROGS],
# If we have FIXPATH enabled, strip all instances of it and prepend
# a single one, to avoid double fixpath prefixing.
- if test "x$4" != xNOFIXPATH; then
- [ if [[ $FIXPATH != "" && $result =~ ^"$FIXPATH " ]]; then ]
- result="\$FIXPATH ${result#"$FIXPATH "}"
- fi
+ [ if [[ $FIXPATH != "" && $result =~ ^"$FIXPATH " ]]; then ]
+ result="\$FIXPATH ${result#"$FIXPATH "}"
fi
AC_MSG_RESULT([$result])
break 2;
@@ -515,6 +507,24 @@ AC_DEFUN([UTIL_ADD_FIXPATH],
fi
])
+################################################################################
+# Return a path to the executable binary from a command line, stripping away
+# any FIXPATH prefix or arguments. The resulting value can be checked for
+# existence using "test -e". The result is returned in a variable named
+# "$1_EXECUTABLE".
+#
+# $1: variable describing the command to get the binary for
+AC_DEFUN([UTIL_GET_EXECUTABLE],
+[
+ # Strip the FIXPATH prefix, if any
+ fixpath_stripped="[$]$1"
+ [ if [[ $FIXPATH != "" && $fixpath_stripped =~ ^"$FIXPATH " ]]; then ]
+ fixpath_stripped="${fixpath_stripped#"$FIXPATH "}"
+ fi
+ # Remove any arguments following the binary
+ $1_EXECUTABLE="${fixpath_stripped%% *}"
+])
+
################################################################################
AC_DEFUN([UTIL_REMOVE_SYMBOLIC_LINKS],
[
diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js
index f0cb6f451a3..172ed74f4cd 100644
--- a/make/conf/jib-profiles.js
+++ b/make/conf/jib-profiles.js
@@ -241,10 +241,10 @@ var getJibProfilesCommon = function (input, data) {
// List of the main profile names used for iteration
common.main_profile_names = [
- "linux-x64", "linux-x86", "macosx-x64", "macosx-aarch64",
+ "macosx-x64", "macosx-aarch64",
"windows-x64", "windows-aarch64",
- "linux-aarch64", "linux-arm32", "linux-ppc64le", "linux-s390x",
- "linux-riscv64"
+ "linux-x64", "linux-aarch64",
+ "linux-arm32", "linux-ppc64le", "linux-s390x", "linux-riscv64"
];
// These are the base settings for all the main build profiles.
@@ -283,9 +283,6 @@ var getJibProfilesCommon = function (input, data) {
labels: "open"
};
- common.configure_args_64bit = ["--with-target-bits=64"];
- common.configure_args_32bit = ["--with-target-bits=32"];
-
/**
* Define common artifacts template for all main profiles
* @param o - Object containing data for artifacts
@@ -412,58 +409,34 @@ var getJibProfilesProfiles = function (input, common, data) {
// Main SE profiles
var profiles = {
-
- "linux-x64": {
- target_os: "linux",
- target_cpu: "x64",
- dependencies: ["devkit", "gtest", "build_devkit", "graphviz", "pandoc", "tidy"],
- configure_args: concat(
- (input.build_cpu == "x64" ? common.configure_args_64bit
- : "--openjdk-target=x86_64-linux-gnu"),
- "--with-zlib=system", "--disable-dtrace",
- (isWsl(input) ? [ "--host=x86_64-unknown-linux-gnu",
- "--build=x86_64-unknown-linux-gnu" ] : [])),
- },
-
- "linux-x86": {
- target_os: "linux",
- target_cpu: "x86",
- build_cpu: "x64",
- dependencies: ["devkit", "gtest", "libffi"],
- configure_args: concat(common.configure_args_32bit, [
- "--with-jvm-variants=minimal,server",
- "--with-zlib=system",
- "--with-libffi=" + input.get("libffi", "home_path"),
- "--enable-libffi-bundling",
- "--enable-fallback-linker"
- ])
- },
-
"macosx-x64": {
target_os: "macosx",
target_cpu: "x64",
dependencies: ["devkit", "gtest", "graphviz", "pandoc", "tidy"],
- configure_args: concat(common.configure_args_64bit, "--with-zlib=system",
+ configure_args: [
+ "--with-zlib=system",
"--with-macosx-version-max=11.00.00",
"--enable-compatible-cds-alignment",
// Use system SetFile instead of the one in the devkit as the
// devkit one may not work on Catalina.
- "SETFILE=/usr/bin/SetFile"),
+ "SETFILE=/usr/bin/SetFile"
+ ],
},
"macosx-aarch64": {
target_os: "macosx",
target_cpu: "aarch64",
dependencies: ["devkit", "gtest", "graphviz", "pandoc", "tidy"],
- configure_args: concat(common.configure_args_64bit,
- "--with-macosx-version-max=11.00.00"),
+ configure_args: [
+ "--with-macosx-version-max=11.00.00"
+ ],
},
"windows-x64": {
target_os: "windows",
target_cpu: "x64",
dependencies: ["devkit", "gtest", "pandoc"],
- configure_args: concat(common.configure_args_64bit),
+ configure_args: [],
},
"windows-aarch64": {
@@ -475,7 +448,19 @@ var getJibProfilesProfiles = function (input, common, data) {
],
},
- "linux-aarch64": {
+ "linux-x64": {
+ target_os: "linux",
+ target_cpu: "x64",
+ dependencies: ["devkit", "gtest", "build_devkit", "graphviz", "pandoc", "tidy"],
+ configure_args: concat(
+ "--with-zlib=system",
+ "--disable-dtrace",
+ (cross_compiling ? [ "--openjdk-target=x86_64-linux-gnu" ] : []),
+ (isWsl(input) ? [ "--host=x86_64-unknown-linux-gnu",
+ "--build=x86_64-unknown-linux-gnu" ] : [])),
+ },
+
+ "linux-aarch64": {
target_os: "linux",
target_cpu: "aarch64",
dependencies: ["devkit", "gtest", "build_devkit", "graphviz", "pandoc", "tidy"],
@@ -492,8 +477,10 @@ var getJibProfilesProfiles = function (input, common, data) {
build_cpu: "x64",
dependencies: ["devkit", "gtest", "build_devkit"],
configure_args: [
- "--openjdk-target=arm-linux-gnueabihf", "--with-freetype=bundled",
- "--with-abi-profile=arm-vfp-hflt", "--disable-warnings-as-errors"
+ "--openjdk-target=arm-linux-gnueabihf",
+ "--with-freetype=bundled",
+ "--with-abi-profile=arm-vfp-hflt",
+ "--disable-warnings-as-errors"
],
},
@@ -503,7 +490,8 @@ var getJibProfilesProfiles = function (input, common, data) {
build_cpu: "x64",
dependencies: ["devkit", "gtest", "build_devkit"],
configure_args: [
- "--openjdk-target=ppc64le-linux-gnu", "--with-freetype=bundled",
+ "--openjdk-target=ppc64le-linux-gnu",
+ "--with-freetype=bundled",
"--disable-warnings-as-errors"
],
},
@@ -514,7 +502,8 @@ var getJibProfilesProfiles = function (input, common, data) {
build_cpu: "x64",
dependencies: ["devkit", "gtest", "build_devkit"],
configure_args: [
- "--openjdk-target=s390x-linux-gnu", "--with-freetype=bundled",
+ "--openjdk-target=s390x-linux-gnu",
+ "--with-freetype=bundled",
"--disable-warnings-as-errors"
],
},
@@ -525,7 +514,8 @@ var getJibProfilesProfiles = function (input, common, data) {
build_cpu: "x64",
dependencies: ["devkit", "gtest", "build_devkit"],
configure_args: [
- "--openjdk-target=riscv64-linux-gnu", "--with-freetype=bundled",
+ "--openjdk-target=riscv64-linux-gnu",
+ "--with-freetype=bundled",
"--disable-warnings-as-errors"
],
},
@@ -586,24 +576,24 @@ var getJibProfilesProfiles = function (input, common, data) {
target_os: "linux",
target_cpu: "x64",
dependencies: ["devkit", "gtest", "libffi"],
- configure_args: concat(common.configure_args_64bit, [
+ configure_args: [
"--with-zlib=system",
"--with-jvm-variants=zero",
"--with-libffi=" + input.get("libffi", "home_path"),
"--enable-libffi-bundling",
- ])
+ ]
},
"linux-aarch64-zero": {
target_os: "linux",
target_cpu: "aarch64",
dependencies: ["devkit", "gtest", "libffi"],
- configure_args: concat(common.configure_args_64bit, [
+ configure_args: [
"--with-zlib=system",
"--with-jvm-variants=zero",
"--with-libffi=" + input.get("libffi", "home_path"),
"--enable-libffi-bundling"
- ])
+ ]
},
"linux-x86-zero": {
@@ -611,12 +601,13 @@ var getJibProfilesProfiles = function (input, common, data) {
target_cpu: "x86",
build_cpu: "x64",
dependencies: ["devkit", "gtest", "libffi"],
- configure_args: concat(common.configure_args_32bit, [
+ configure_args: [
+ "--with-target-bits=32",
"--with-zlib=system",
"--with-jvm-variants=zero",
"--with-libffi=" + input.get("libffi", "home_path"),
"--enable-libffi-bundling"
- ])
+ ]
}
}
profiles = concatObjects(profiles, zeroProfiles);
@@ -635,8 +626,10 @@ var getJibProfilesProfiles = function (input, common, data) {
target_os: "linux",
target_cpu: "x64",
dependencies: ["devkit", "gtest"],
- configure_args: concat(common.configure_args_64bit,
- "--with-zlib=system", "--disable-precompiled-headers"),
+ configure_args: [
+ "--with-zlib=system",
+ "--disable-precompiled-headers"
+ ],
},
};
profiles = concatObjects(profiles, noPchProfiles);
@@ -693,9 +686,6 @@ var getJibProfilesProfiles = function (input, common, data) {
"linux-x64": {
platform: "linux-x64",
},
- "linux-x86": {
- platform: "linux-x86",
- },
"macosx-x64": {
platform: "macos-x64",
jdk_subdir: "jdk-" + data.version + ".jdk/Contents/Home",
diff --git a/make/test/BuildMicrobenchmark.gmk b/make/test/BuildMicrobenchmark.gmk
index 92f40472c3c..347ca44d25f 100644
--- a/make/test/BuildMicrobenchmark.gmk
+++ b/make/test/BuildMicrobenchmark.gmk
@@ -119,7 +119,6 @@ $(JMH_UNPACKED_JARS_DONE): $(JMH_RUNTIME_JARS)
$(foreach jar, $(JMH_RUNTIME_JARS), \
$$($(UNZIP) -oq $(jar) -d $(JMH_UNPACKED_DIR)))
$(RM) -r $(JMH_UNPACKED_DIR)/META-INF
- $(RM) $(JMH_UNPACKED_DIR)/*.xml
$(TOUCH) $@
# Copy dependency files for inclusion in the benchmark JARs
diff --git a/src/hotspot/cpu/aarch64/jvmciCodeInstaller_aarch64.cpp b/src/hotspot/cpu/aarch64/jvmciCodeInstaller_aarch64.cpp
index 3015206dadc..071dd2c4179 100644
--- a/src/hotspot/cpu/aarch64/jvmciCodeInstaller_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/jvmciCodeInstaller_aarch64.cpp
@@ -180,6 +180,7 @@ bool CodeInstaller::pd_relocate(address pc, jint mark) {
case POLL_RETURN_FAR:
_instructions->relocate(pc, relocInfo::poll_return_type);
return true;
+#if INCLUDE_ZGC
case Z_BARRIER_RELOCATION_FORMAT_LOAD_GOOD_BEFORE_TB_X:
_instructions->relocate(pc, barrier_Relocation::spec(), ZBarrierRelocationFormatLoadGoodBeforeTbX);
return true;
@@ -192,6 +193,7 @@ bool CodeInstaller::pd_relocate(address pc, jint mark) {
case Z_BARRIER_RELOCATION_FORMAT_STORE_BAD_BEFORE_MOV:
_instructions->relocate(pc, barrier_Relocation::spec(), ZBarrierRelocationFormatStoreBadBeforeMov);
return true;
+#endif
}
return false;
diff --git a/src/hotspot/cpu/riscv/assembler_riscv.hpp b/src/hotspot/cpu/riscv/assembler_riscv.hpp
index 4773043e1ba..63d5d4f3e61 100644
--- a/src/hotspot/cpu/riscv/assembler_riscv.hpp
+++ b/src/hotspot/cpu/riscv/assembler_riscv.hpp
@@ -1904,8 +1904,14 @@ enum VectorMask {
INSN(vand_vv, 0b1010111, 0b000, 0b001001);
// Vector Single-Width Integer Add and Subtract
- INSN(vsub_vv, 0b1010111, 0b000, 0b000010);
INSN(vadd_vv, 0b1010111, 0b000, 0b000000);
+ INSN(vsub_vv, 0b1010111, 0b000, 0b000010);
+
+ // Vector Saturating Integer Add and Subtract
+ INSN(vsadd_vv, 0b1010111, 0b000, 0b100001);
+ INSN(vsaddu_vv, 0b1010111, 0b000, 0b100000);
+ INSN(vssub_vv, 0b1010111, 0b000, 0b100011);
+ INSN(vssubu_vv, 0b1010111, 0b000, 0b100010);
// Vector Register Gather Instructions
INSN(vrgather_vv, 0b1010111, 0b000, 0b001100);
diff --git a/src/hotspot/cpu/riscv/riscv_v.ad b/src/hotspot/cpu/riscv/riscv_v.ad
index 58c78874797..b6b8395dbb7 100644
--- a/src/hotspot/cpu/riscv/riscv_v.ad
+++ b/src/hotspot/cpu/riscv/riscv_v.ad
@@ -251,7 +251,6 @@ instruct vmaskcmp_fp(vRegMask dst, vReg src1, vReg src2, immI cond) %{
predicate(Matcher::vector_element_basic_type(n) == T_FLOAT ||
Matcher::vector_element_basic_type(n) == T_DOUBLE);
match(Set dst (VectorMaskCmp (Binary src1 src2) cond));
- effect(TEMP_DEF dst);
format %{ "vmaskcmp_fp $dst, $src1, $src2, $cond" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this);
@@ -651,6 +650,144 @@ instruct vsubL_vx_masked(vReg dst_src, iRegL src2, vRegMask_V0 v0) %{
ins_pipe(pipe_slow);
%}
+// -------- vector saturating integer operations
+
+// vector saturating signed integer addition
+
+instruct vsadd(vReg dst, vReg src1, vReg src2) %{
+ predicate(n->is_SaturatingVector() && !n->as_SaturatingVector()->is_unsigned());
+ match(Set dst (SaturatingAddV src1 src2));
+ ins_cost(VEC_COST);
+ format %{ "vsadd $dst, $src1, $src2" %}
+ ins_encode %{
+ BasicType bt = Matcher::vector_element_basic_type(this);
+ assert(is_integral_type(bt), "unsupported type");
+ __ vsetvli_helper(bt, Matcher::vector_length(this));
+ __ vsadd_vv(as_VectorRegister($dst$$reg),
+ as_VectorRegister($src1$$reg), as_VectorRegister($src2$$reg));
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+// vector saturating unsigned integer addition
+
+instruct vsaddu(vReg dst, vReg src1, vReg src2) %{
+ predicate(n->is_SaturatingVector() && n->as_SaturatingVector()->is_unsigned());
+ match(Set dst (SaturatingAddV src1 src2));
+ ins_cost(VEC_COST);
+ format %{ "vsaddu $dst, $src1, $src2" %}
+ ins_encode %{
+ BasicType bt = Matcher::vector_element_basic_type(this);
+ assert(is_integral_type(bt), "unsupported type");
+ __ vsetvli_helper(bt, Matcher::vector_length(this));
+ __ vsaddu_vv(as_VectorRegister($dst$$reg),
+ as_VectorRegister($src1$$reg), as_VectorRegister($src2$$reg));
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+// vector saturating signed integer addition (predicated)
+
+instruct vsadd_masked(vReg dst_src, vReg src1, vRegMask_V0 v0) %{
+ predicate(n->is_SaturatingVector() && !n->as_SaturatingVector()->is_unsigned());
+ match(Set dst_src (SaturatingAddV (Binary dst_src src1) v0));
+ ins_cost(VEC_COST);
+ format %{ "vsadd_masked $dst_src, $dst_src, $src1, $v0" %}
+ ins_encode %{
+ BasicType bt = Matcher::vector_element_basic_type(this);
+ assert(is_integral_type(bt), "unsupported type");
+ __ vsetvli_helper(bt, Matcher::vector_length(this));
+ __ vsadd_vv(as_VectorRegister($dst_src$$reg), as_VectorRegister($dst_src$$reg),
+ as_VectorRegister($src1$$reg), Assembler::v0_t);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+// vector saturating unsigned integer addition (predicated)
+
+instruct vsaddu_masked(vReg dst_src, vReg src1, vRegMask_V0 v0) %{
+ predicate(n->is_SaturatingVector() && n->as_SaturatingVector()->is_unsigned());
+ match(Set dst_src (SaturatingAddV (Binary dst_src src1) v0));
+ ins_cost(VEC_COST);
+ format %{ "vsaddu_masked $dst_src, $dst_src, $src1, $v0" %}
+ ins_encode %{
+ BasicType bt = Matcher::vector_element_basic_type(this);
+ assert(is_integral_type(bt), "unsupported type");
+ __ vsetvli_helper(bt, Matcher::vector_length(this));
+ __ vsaddu_vv(as_VectorRegister($dst_src$$reg), as_VectorRegister($dst_src$$reg),
+ as_VectorRegister($src1$$reg), Assembler::v0_t);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+// vector saturating signed integer subtraction
+
+instruct vssub(vReg dst, vReg src1, vReg src2) %{
+ predicate(n->is_SaturatingVector() && !n->as_SaturatingVector()->is_unsigned());
+ match(Set dst (SaturatingSubV src1 src2));
+ ins_cost(VEC_COST);
+ format %{ "vssub $dst, $src1, $src2" %}
+ ins_encode %{
+ BasicType bt = Matcher::vector_element_basic_type(this);
+ assert(is_integral_type(bt), "unsupported type");
+ __ vsetvli_helper(bt, Matcher::vector_length(this));
+ __ vssub_vv(as_VectorRegister($dst$$reg),
+ as_VectorRegister($src1$$reg), as_VectorRegister($src2$$reg));
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+// vector saturating unsigned integer subtraction
+
+instruct vssubu(vReg dst, vReg src1, vReg src2) %{
+ predicate(n->is_SaturatingVector() && n->as_SaturatingVector()->is_unsigned());
+ match(Set dst (SaturatingSubV src1 src2));
+ ins_cost(VEC_COST);
+ format %{ "vssubu $dst, $src1, $src2" %}
+ ins_encode %{
+ BasicType bt = Matcher::vector_element_basic_type(this);
+ assert(is_integral_type(bt), "unsupported type");
+ __ vsetvli_helper(bt, Matcher::vector_length(this));
+ __ vssubu_vv(as_VectorRegister($dst$$reg),
+ as_VectorRegister($src1$$reg), as_VectorRegister($src2$$reg));
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+// vector saturating signed integer subtraction (predicated)
+
+instruct vssub_masked(vReg dst_src, vReg src1, vRegMask_V0 v0) %{
+ predicate(n->is_SaturatingVector() && !n->as_SaturatingVector()->is_unsigned());
+ match(Set dst_src (SaturatingSubV (Binary dst_src src1) v0));
+ ins_cost(VEC_COST);
+ format %{ "vssub_masked $dst_src, $dst_src, $src1, $v0" %}
+ ins_encode %{
+ BasicType bt = Matcher::vector_element_basic_type(this);
+ assert(is_integral_type(bt), "unsupported type");
+ __ vsetvli_helper(bt, Matcher::vector_length(this));
+ __ vssub_vv(as_VectorRegister($dst_src$$reg), as_VectorRegister($dst_src$$reg),
+ as_VectorRegister($src1$$reg), Assembler::v0_t);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+// vector saturating unsigned integer subtraction (predicated)
+
+instruct vssubu_masked(vReg dst_src, vReg src1, vRegMask_V0 v0) %{
+ predicate(n->is_SaturatingVector() && n->as_SaturatingVector()->is_unsigned());
+ match(Set dst_src (SaturatingSubV (Binary dst_src src1) v0));
+ ins_cost(VEC_COST);
+ format %{ "vssubu_masked $dst_src, $dst_src, $src1, $v0" %}
+ ins_encode %{
+ BasicType bt = Matcher::vector_element_basic_type(this);
+ assert(is_integral_type(bt), "unsupported type");
+ __ vsetvli_helper(bt, Matcher::vector_length(this));
+ __ vssubu_vv(as_VectorRegister($dst_src$$reg), as_VectorRegister($dst_src$$reg),
+ as_VectorRegister($src1$$reg), Assembler::v0_t);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
// vector and
instruct vand(vReg dst, vReg src1, vReg src2) %{
diff --git a/src/hotspot/cpu/s390/frame_s390.inline.hpp b/src/hotspot/cpu/s390/frame_s390.inline.hpp
index b033b3f939b..ede7039ce0a 100644
--- a/src/hotspot/cpu/s390/frame_s390.inline.hpp
+++ b/src/hotspot/cpu/s390/frame_s390.inline.hpp
@@ -203,11 +203,14 @@ inline intptr_t* frame::interpreter_frame_expression_stack() const {
// Also begin is one past last monitor.
inline intptr_t* frame::interpreter_frame_top_frame_sp() {
- return (intptr_t*)ijava_state()->top_frame_sp;
+ intptr_t n = *addr_at(_z_ijava_idx(top_frame_sp));
+ return &fp()[n]; // return relativized locals
}
inline void frame::interpreter_frame_set_top_frame_sp(intptr_t* top_frame_sp) {
- ijava_state()->top_frame_sp = (intptr_t) top_frame_sp;
+ assert(is_interpreted_frame(), "interpreted frame expected");
+ // set relativized top_frame_sp
+ ijava_state()->top_frame_sp = (intptr_t) (top_frame_sp - fp());
}
inline void frame::interpreter_frame_set_sender_sp(intptr_t* sender_sp) {
diff --git a/src/hotspot/cpu/s390/interp_masm_s390.cpp b/src/hotspot/cpu/s390/interp_masm_s390.cpp
index a7bea358f4e..9717d260279 100644
--- a/src/hotspot/cpu/s390/interp_masm_s390.cpp
+++ b/src/hotspot/cpu/s390/interp_masm_s390.cpp
@@ -576,7 +576,10 @@ void InterpreterMacroAssembler::prepare_to_jump_from_interpreted(Register method
// Satisfy interpreter calling convention (see generate_normal_entry()).
z_lgr(Z_R10, Z_SP); // Set sender sp (aka initial caller sp, aka unextended sp).
// Record top_frame_sp, because the callee might modify it, if it's compiled.
- z_stg(Z_SP, _z_ijava_state_neg(top_frame_sp), Z_fp);
+ assert_different_registers(Z_R1, method);
+ z_sgrk(Z_R1, Z_SP, Z_fp);
+ z_srag(Z_R1, Z_R1, Interpreter::logStackElementSize);
+ z_stg(Z_R1, _z_ijava_state_neg(top_frame_sp), Z_fp);
save_bcp();
save_esp();
z_lgr(Z_method, method); // Set Z_method (kills Z_fp!).
diff --git a/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp b/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp
index 4edf8046833..04fe574088e 100644
--- a/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp
+++ b/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp
@@ -637,6 +637,8 @@ address TemplateInterpreterGenerator::generate_return_entry_for (TosState state,
Register sp_before_i2c_extension = Z_bcp;
__ z_lg(Z_fp, _z_abi(callers_sp), Z_SP); // Restore frame pointer.
__ z_lg(sp_before_i2c_extension, Address(Z_fp, _z_ijava_state_neg(top_frame_sp)));
+ __ z_slag(sp_before_i2c_extension, sp_before_i2c_extension, Interpreter::logStackElementSize);
+ __ z_agr(sp_before_i2c_extension, Z_fp);
__ resize_frame_absolute(sp_before_i2c_extension, Z_locals/*tmp*/, true/*load_fp*/);
// TODO(ZASM): necessary??
diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp
index 19e25cde2ec..177be6e59f7 100644
--- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp
+++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp
@@ -5731,7 +5731,7 @@ void C2_MacroAssembler::vector_compress_expand_avx2(int opcode, XMMRegister dst,
// in a permute table row contains either a valid permute index or a -1 (default)
// value, this can potentially be used as a blending mask after
// compressing/expanding the source vector lanes.
- vblendvps(dst, dst, xtmp, permv, vec_enc, false, permv);
+ vblendvps(dst, dst, xtmp, permv, vec_enc, true, permv);
}
void C2_MacroAssembler::vector_compress_expand(int opcode, XMMRegister dst, XMMRegister src, KRegister mask,
diff --git a/src/hotspot/share/cds/aotClassLocation.cpp b/src/hotspot/share/cds/aotClassLocation.cpp
index 8471d04b572..9df28d61bbc 100644
--- a/src/hotspot/share/cds/aotClassLocation.cpp
+++ b/src/hotspot/share/cds/aotClassLocation.cpp
@@ -1030,6 +1030,7 @@ bool AOTClassLocationConfig::validate(bool has_aot_linked_classes, bool* has_ext
}
} else {
log_warning(cds)("%s%s", mismatch_msg, hint_msg);
+ MetaspaceShared::report_loading_error(nullptr);
}
}
return success;
diff --git a/src/hotspot/share/cds/archiveBuilder.cpp b/src/hotspot/share/cds/archiveBuilder.cpp
index 3de4cdec187..549b7b3ba6a 100644
--- a/src/hotspot/share/cds/archiveBuilder.cpp
+++ b/src/hotspot/share/cds/archiveBuilder.cpp
@@ -313,7 +313,7 @@ address ArchiveBuilder::reserve_buffer() {
ReservedSpace rs = MemoryReserver::reserve(buffer_size,
MetaspaceShared::core_region_alignment(),
os::vm_page_size(),
- mtClassShared);
+ mtNone);
if (!rs.is_reserved()) {
log_error(cds)("Failed to reserve %zu bytes of output buffer.", buffer_size);
MetaspaceShared::unrecoverable_writing_error();
diff --git a/src/hotspot/share/cds/cdsConfig.cpp b/src/hotspot/share/cds/cdsConfig.cpp
index 701b2584774..463bfe3a98d 100644
--- a/src/hotspot/share/cds/cdsConfig.cpp
+++ b/src/hotspot/share/cds/cdsConfig.cpp
@@ -647,6 +647,14 @@ bool CDSConfig::is_using_archive() {
return UseSharedSpaces;
}
+bool CDSConfig::is_using_only_default_archive() {
+ return is_using_archive() &&
+ input_static_archive_path() != nullptr &&
+ default_archive_path() != nullptr &&
+ strcmp(input_static_archive_path(), default_archive_path()) == 0 &&
+ input_dynamic_archive_path() == nullptr;
+}
+
bool CDSConfig::is_logging_lambda_form_invokers() {
return ClassListWriter::is_enabled() || is_dumping_dynamic_archive();
}
diff --git a/src/hotspot/share/cds/cdsConfig.hpp b/src/hotspot/share/cds/cdsConfig.hpp
index e82acebd175..0fb6cc1ec6a 100644
--- a/src/hotspot/share/cds/cdsConfig.hpp
+++ b/src/hotspot/share/cds/cdsConfig.hpp
@@ -103,6 +103,7 @@ public:
// input archive(s)
static bool is_using_archive() NOT_CDS_RETURN_(false);
+ static bool is_using_only_default_archive() NOT_CDS_RETURN_(false);
// static_archive
static bool is_dumping_static_archive() { return CDS_ONLY(_is_dumping_static_archive) NOT_CDS(false); }
diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp
index fbef3c9532d..ff537ef96d6 100644
--- a/src/hotspot/share/cds/filemap.cpp
+++ b/src/hotspot/share/cds/filemap.cpp
@@ -326,7 +326,7 @@ bool FileMapInfo::validate_class_location() {
if (header()->has_full_module_graph() && has_extra_module_paths) {
CDSConfig::stop_using_optimized_module_handling();
- log_info(cds)("optimized module handling: disabled because extra module path(s) are specified");
+ MetaspaceShared::report_loading_error("optimized module handling: disabled because extra module path(s) are specified");
}
if (CDSConfig::is_dumping_dynamic_archive()) {
@@ -1256,7 +1256,7 @@ char* FileMapInfo::map_bitmap_region() {
char* bitmap_base = map_memory(_fd, _full_path, r->file_offset(),
requested_addr, r->used_aligned(), read_only, allow_exec, mtClassShared);
if (bitmap_base == nullptr) {
- log_info(cds)("failed to map relocation bitmap");
+ MetaspaceShared::report_loading_error("failed to map relocation bitmap");
return nullptr;
}
@@ -1454,9 +1454,9 @@ void FileMapInfo::map_or_load_heap_region() {
success = ArchiveHeapLoader::load_heap_region(this);
} else {
if (!UseCompressedOops && !ArchiveHeapLoader::can_map()) {
- log_info(cds)("Cannot use CDS heap data. Selected GC not compatible -XX:-UseCompressedOops");
+ MetaspaceShared::report_loading_error("Cannot use CDS heap data. Selected GC not compatible -XX:-UseCompressedOops");
} else {
- log_info(cds)("Cannot use CDS heap data. UseEpsilonGC, UseG1GC, UseSerialGC, UseParallelGC, or UseShenandoahGC are required.");
+ MetaspaceShared::report_loading_error("Cannot use CDS heap data. UseEpsilonGC, UseG1GC, UseSerialGC, UseParallelGC, or UseShenandoahGC are required.");
}
}
}
@@ -1468,8 +1468,10 @@ void FileMapInfo::map_or_load_heap_region() {
// all AOT-linked classes are visible.
//
// We get here because the heap is too small. The app will fail anyway. So let's quit.
- MetaspaceShared::unrecoverable_loading_error("CDS archive has aot-linked classes but the archived "
- "heap objects cannot be loaded. Try increasing your heap size.");
+ log_error(cds)("%s has aot-linked classes but the archived "
+ "heap objects cannot be loaded. Try increasing your heap size.",
+ CDSConfig::type_of_archive_being_loaded());
+ MetaspaceShared::unrecoverable_loading_error();
}
CDSConfig::stop_using_full_module_graph("archive heap loading failed");
}
@@ -1635,7 +1637,7 @@ bool FileMapInfo::map_heap_region_impl() {
// allocate from java heap
HeapWord* start = G1CollectedHeap::heap()->alloc_archive_region(word_size, (HeapWord*)requested_start);
if (start == nullptr) {
- log_info(cds)("UseSharedSpaces: Unable to allocate java heap region for archive heap.");
+ MetaspaceShared::report_loading_error("UseSharedSpaces: Unable to allocate java heap region for archive heap.");
return false;
}
@@ -1670,7 +1672,7 @@ bool FileMapInfo::map_heap_region_impl() {
if (VerifySharedSpaces && !r->check_region_crc(base)) {
dealloc_heap_region();
- log_info(cds)("UseSharedSpaces: mapped heap region is corrupt");
+ MetaspaceShared::report_loading_error("UseSharedSpaces: mapped heap region is corrupt");
return false;
}
}
@@ -1694,7 +1696,7 @@ bool FileMapInfo::map_heap_region_impl() {
if (_heap_pointers_need_patching) {
char* bitmap_base = map_bitmap_region();
if (bitmap_base == nullptr) {
- log_info(cds)("CDS heap cannot be used because bitmap region cannot be mapped");
+ MetaspaceShared::report_loading_error("CDS heap cannot be used because bitmap region cannot be mapped");
dealloc_heap_region();
_heap_pointers_need_patching = false;
return false;
@@ -1807,16 +1809,16 @@ bool FileMapInfo::open_as_input() {
// are replaced at runtime by JVMTI ClassFileLoadHook. All of those classes are resolved
// during the JVMTI "early" stage, so we can still use CDS if
// JvmtiExport::has_early_class_hook_env() is false.
- log_info(cds)("CDS is disabled because early JVMTI ClassFileLoadHook is in use.");
+ MetaspaceShared::report_loading_error("CDS is disabled because early JVMTI ClassFileLoadHook is in use.");
return false;
}
if (!open_for_read() || !init_from_file(_fd) || !validate_header()) {
if (_is_static) {
- log_info(cds)("Loading static archive failed.");
+ MetaspaceShared::report_loading_error("Loading static archive failed.");
return false;
} else {
- log_info(cds)("Loading dynamic archive failed.");
+ MetaspaceShared::report_loading_error("Loading dynamic archive failed.");
if (AutoCreateSharedArchive) {
CDSConfig::enable_dumping_dynamic_archive(_full_path);
}
@@ -1831,29 +1833,34 @@ bool FileMapInfo::validate_aot_class_linking() {
// These checks need to be done after FileMapInfo::initialize(), which gets called before Universe::heap()
// is available.
if (header()->has_aot_linked_classes()) {
+ const char* archive_type = CDSConfig::type_of_archive_being_loaded();
CDSConfig::set_has_aot_linked_classes(true);
if (JvmtiExport::should_post_class_file_load_hook()) {
- log_error(cds)("CDS archive has aot-linked classes. It cannot be used when JVMTI ClassFileLoadHook is in use.");
+ log_error(cds)("%s has aot-linked classes. It cannot be used when JVMTI ClassFileLoadHook is in use.",
+ archive_type);
return false;
}
if (JvmtiExport::has_early_vmstart_env()) {
- log_error(cds)("CDS archive has aot-linked classes. It cannot be used when JVMTI early vm start is in use.");
+ log_error(cds)("%s has aot-linked classes. It cannot be used when JVMTI early vm start is in use.",
+ archive_type);
return false;
}
if (!CDSConfig::is_using_full_module_graph()) {
- log_error(cds)("CDS archive has aot-linked classes. It cannot be used when archived full module graph is not used.");
+ log_error(cds)("%s has aot-linked classes. It cannot be used when archived full module graph is not used.",
+ archive_type);
return false;
}
const char* prop = Arguments::get_property("java.security.manager");
if (prop != nullptr && strcmp(prop, "disallow") != 0) {
- log_error(cds)("CDS archive has aot-linked classes. It cannot be used with -Djava.security.manager=%s.", prop);
+ log_error(cds)("%s has aot-linked classes. It cannot be used with -Djava.security.manager=%s.",
+ archive_type, prop);
return false;
}
#if INCLUDE_JVMTI
if (Arguments::has_jdwp_agent()) {
- log_error(cds)("CDS archive has aot-linked classes. It cannot be used with JDWP agent");
+ log_error(cds)("%s has aot-linked classes. It cannot be used with JDWP agent", archive_type);
return false;
}
#endif
@@ -1913,8 +1920,8 @@ bool FileMapHeader::validate() {
const char* prop = Arguments::get_property("java.system.class.loader");
if (prop != nullptr) {
if (has_aot_linked_classes()) {
- log_error(cds)("CDS archive has aot-linked classes. It cannot be used when the "
- "java.system.class.loader property is specified.");
+ log_error(cds)("%s has aot-linked classes. It cannot be used when the "
+ "java.system.class.loader property is specified.", CDSConfig::type_of_archive_being_loaded());
return false;
}
log_warning(cds)("Archived non-system classes are disabled because the "
diff --git a/src/hotspot/share/cds/metaspaceShared.cpp b/src/hotspot/share/cds/metaspaceShared.cpp
index 5f7b496f8d2..654c2e7ecd7 100644
--- a/src/hotspot/share/cds/metaspaceShared.cpp
+++ b/src/hotspot/share/cds/metaspaceShared.cpp
@@ -937,7 +937,7 @@ void MetaspaceShared::preload_and_dump_impl(StaticArchiveBuilder& builder, TRAPS
if (CDSConfig::is_dumping_heap()) {
assert(CDSConfig::allow_only_single_java_thread(), "Required");
if (!HeapShared::is_archived_boot_layer_available(THREAD)) {
- log_info(cds)("archivedBootLayer not available, disabling full module graph");
+ report_loading_error("archivedBootLayer not available, disabling full module graph");
CDSConfig::stop_dumping_full_module_graph();
}
// Do this before link_shared_classes(), as the following line may load new classes.
@@ -1118,10 +1118,7 @@ bool MetaspaceShared::is_shared_static(void* p) {
// - When -XX:+RequireSharedSpaces is specified, AND the JVM cannot load the archive(s) due
// to version or classpath mismatch.
void MetaspaceShared::unrecoverable_loading_error(const char* message) {
- log_error(cds)("An error has occurred while processing the %s.", CDSConfig::type_of_archive_being_loaded());
- if (message != nullptr) {
- log_error(cds)("%s", message);
- }
+ report_loading_error(message);
if (CDSConfig::is_dumping_final_static_archive()) {
vm_exit_during_initialization("Must be a valid AOT configuration generated by the current JVM", AOTConfiguration);
@@ -1132,6 +1129,30 @@ void MetaspaceShared::unrecoverable_loading_error(const char* message) {
}
}
+void MetaspaceShared::report_loading_error(const char* format, ...) {
+ // If the user doesn't specify any CDS options, we will try to load the default CDS archive, which
+ // may fail due to incompatible VM options. Print at the info level to avoid excessive verbosity.
+ // However, if the user has specified a CDS archive (or AOT cache), they would be interested in
+ // knowing that the loading fails, so we print at the error level.
+ Log(cds) log;
+ LogStream ls_error(log.error());
+ LogStream ls_info(log.info());
+ LogStream& ls = (!CDSConfig::is_using_archive()) || CDSConfig::is_using_only_default_archive() ? ls_info : ls_error;
+
+ static bool printed_error = false;
+ if (!printed_error) { // No need for locks. Loading error checks happen only in main thread.
+ ls.print_cr("An error has occurred while processing the %s. Run with -Xlog:cds for details.", CDSConfig::type_of_archive_being_loaded());
+ printed_error = true;
+ }
+
+ if (format != nullptr) {
+ va_list ap;
+ va_start(ap, format);
+ ls.vprint_cr(format, ap);
+ va_end(ap);
+ }
+}
+
// This function is called when the JVM is unable to write the specified CDS archive due to an
// unrecoverable error.
void MetaspaceShared::unrecoverable_writing_error(const char* message) {
@@ -1193,11 +1214,14 @@ void MetaspaceShared::initialize_runtime_shared_and_meta_spaces() {
// The base archive cannot be mapped. We cannot dump the dynamic shared archive.
AutoCreateSharedArchive = false;
CDSConfig::disable_dumping_dynamic_archive();
- log_info(cds)("Unable to map shared spaces");
if (PrintSharedArchiveAndExit) {
MetaspaceShared::unrecoverable_loading_error("Unable to use shared archive.");
- } else if (RequireSharedSpaces) {
- MetaspaceShared::unrecoverable_loading_error("Unable to map shared spaces");
+ } else {
+ if (RequireSharedSpaces) {
+ MetaspaceShared::unrecoverable_loading_error("Unable to map shared spaces");
+ } else {
+ report_loading_error("Unable to map shared spaces");
+ }
}
}
@@ -1712,8 +1736,8 @@ MapArchiveResult MetaspaceShared::map_archive(FileMapInfo* mapinfo, char* mapped
mapinfo->set_is_mapped(false);
if (mapinfo->core_region_alignment() != (size_t)core_region_alignment()) {
- log_info(cds)("Unable to map CDS archive -- core_region_alignment() expected: %zu"
- " actual: %zu", mapinfo->core_region_alignment(), core_region_alignment());
+ report_loading_error("Unable to map CDS archive -- core_region_alignment() expected: %zu"
+ " actual: %zu", mapinfo->core_region_alignment(), core_region_alignment());
return MAP_ARCHIVE_OTHER_FAILURE;
}
diff --git a/src/hotspot/share/cds/metaspaceShared.hpp b/src/hotspot/share/cds/metaspaceShared.hpp
index 875801cc0e6..8fb92196acc 100644
--- a/src/hotspot/share/cds/metaspaceShared.hpp
+++ b/src/hotspot/share/cds/metaspaceShared.hpp
@@ -110,7 +110,8 @@ public:
static bool is_shared_dynamic(void* p) NOT_CDS_RETURN_(false);
static bool is_shared_static(void* p) NOT_CDS_RETURN_(false);
- static void unrecoverable_loading_error(const char* message = nullptr);
+ static void unrecoverable_loading_error(const char* message = nullptr) ATTRIBUTE_PRINTF(1, 0);
+ static void report_loading_error(const char* format, ...) ATTRIBUTE_PRINTF(1, 0);
static void unrecoverable_writing_error(const char* message = nullptr);
static void writing_error(const char* message = nullptr);
diff --git a/src/hotspot/share/classfile/modules.cpp b/src/hotspot/share/classfile/modules.cpp
index a506c4502a4..463bd765701 100644
--- a/src/hotspot/share/classfile/modules.cpp
+++ b/src/hotspot/share/classfile/modules.cpp
@@ -604,21 +604,21 @@ void Modules::ArchivedProperty::runtime_check() const {
bool disable = false;
if (runtime_value == nullptr) {
if (_archived_value != nullptr) {
- log_info(cds)("Mismatched values for property %s: %s specified during dump time but not during runtime", _prop, _archived_value);
+ MetaspaceShared::report_loading_error("Mismatched values for property %s: %s specified during dump time but not during runtime", _prop, _archived_value);
disable = true;
}
} else {
if (_archived_value == nullptr) {
- log_info(cds)("Mismatched values for property %s: %s specified during runtime but not during dump time", _prop, runtime_value);
+ MetaspaceShared::report_loading_error("Mismatched values for property %s: %s specified during runtime but not during dump time", _prop, runtime_value);
disable = true;
} else if (strcmp(runtime_value, _archived_value) != 0) {
- log_info(cds)("Mismatched values for property %s: runtime %s dump time %s", _prop, runtime_value, _archived_value);
+ MetaspaceShared::report_loading_error("Mismatched values for property %s: runtime %s dump time %s", _prop, runtime_value, _archived_value);
disable = true;
}
}
if (disable) {
- log_info(cds)("Disabling optimized module handling");
+ MetaspaceShared::report_loading_error("Disabling optimized module handling");
CDSConfig::stop_using_optimized_module_handling();
}
}
diff --git a/src/hotspot/share/code/aotCodeCache.cpp b/src/hotspot/share/code/aotCodeCache.cpp
index 68a8e9ed70a..12706ef3e99 100644
--- a/src/hotspot/share/code/aotCodeCache.cpp
+++ b/src/hotspot/share/code/aotCodeCache.cpp
@@ -48,6 +48,9 @@
#if INCLUDE_G1GC
#include "gc/g1/g1BarrierSetRuntime.hpp"
#endif
+#if INCLUDE_SHENANDOAHGC
+#include "gc/shenandoah/shenandoahRuntime.hpp"
+#endif
#if INCLUDE_ZGC
#include "gc/z/zBarrierSetRuntime.hpp"
#endif
@@ -976,9 +979,9 @@ ImmutableOopMapSet* AOTCodeReader::read_oop_map_set() {
// [_blobs_base, _blobs_base + _blobs_max -1],
// ...
// [_c_str_base, _c_str_base + _c_str_max -1],
-#define _extrs_max 10
+#define _extrs_max 13
#define _blobs_max 10
-#define _all_max 20
+#define _all_max 23
#define _extrs_base 0
#define _blobs_base (_extrs_base + _extrs_max)
@@ -1012,6 +1015,11 @@ void AOTCodeAddressTable::init_extrs() {
SET_ADDRESS(_extrs, G1BarrierSetRuntime::write_ref_field_post_entry);
SET_ADDRESS(_extrs, G1BarrierSetRuntime::write_ref_field_pre_entry);
#endif
+#if INCLUDE_SHENANDOAHGC
+ SET_ADDRESS(_extrs, ShenandoahRuntime::write_ref_field_pre);
+ SET_ADDRESS(_extrs, ShenandoahRuntime::load_reference_barrier_phantom);
+ SET_ADDRESS(_extrs, ShenandoahRuntime::load_reference_barrier_phantom_narrow);
+#endif
#if INCLUDE_ZGC
SET_ADDRESS(_extrs, ZBarrierSetRuntime::load_barrier_on_phantom_oop_field_preloaded_addr());
#if defined(AMD64)
diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp
index e3bd3131b45..ed6167dac22 100644
--- a/src/hotspot/share/code/nmethod.cpp
+++ b/src/hotspot/share/code/nmethod.cpp
@@ -28,6 +28,7 @@
#include "code/dependencies.hpp"
#include "code/nativeInst.hpp"
#include "code/nmethod.inline.hpp"
+#include "code/relocInfo.hpp"
#include "code/scopeDesc.hpp"
#include "compiler/abstractCompiler.hpp"
#include "compiler/compilationLog.hpp"
@@ -1323,8 +1324,9 @@ nmethod::nmethod(
_unwind_handler_offset = 0;
CHECKED_CAST(_oops_size, uint16_t, align_up(code_buffer->total_oop_size(), oopSize));
- int metadata_size = align_up(code_buffer->total_metadata_size(), wordSize);
- JVMCI_ONLY( _jvmci_data_size = 0; )
+ uint16_t metadata_size;
+ CHECKED_CAST(metadata_size, uint16_t, align_up(code_buffer->total_metadata_size(), wordSize));
+ JVMCI_ONLY( _metadata_size = metadata_size; )
assert(_mutable_data_size == _relocation_size + metadata_size,
"wrong mutable data size: %d != %d + %d",
_mutable_data_size, _relocation_size, metadata_size);
@@ -1497,9 +1499,10 @@ nmethod::nmethod(
}
CHECKED_CAST(_oops_size, uint16_t, align_up(code_buffer->total_oop_size(), oopSize));
- uint16_t metadata_size = (uint16_t)align_up(code_buffer->total_metadata_size(), wordSize);
- JVMCI_ONLY(CHECKED_CAST(_jvmci_data_size, uint16_t, align_up(compiler->is_jvmci() ? jvmci_data->size() : 0, oopSize)));
- int jvmci_data_size = 0 JVMCI_ONLY(+ _jvmci_data_size);
+ uint16_t metadata_size;
+ CHECKED_CAST(metadata_size, uint16_t, align_up(code_buffer->total_metadata_size(), wordSize));
+ JVMCI_ONLY( _metadata_size = metadata_size; )
+ int jvmci_data_size = 0 JVMCI_ONLY( + align_up(compiler->is_jvmci() ? jvmci_data->size() : 0, oopSize));
assert(_mutable_data_size == _relocation_size + metadata_size + jvmci_data_size,
"wrong mutable data size: %d != %d + %d + %d",
_mutable_data_size, _relocation_size, metadata_size, jvmci_data_size);
@@ -1646,6 +1649,10 @@ void nmethod::maybe_print_nmethod(const DirectiveSet* directive) {
}
void nmethod::print_nmethod(bool printmethod) {
+ // Enter a critical section to prevent a race with deopts that patch code and updates the relocation info.
+ // Unfortunately, we have to lock the NMethodState_lock before the tty lock due to the deadlock rules and
+ // cannot lock in a more finely grained manner.
+ ConditionalMutexLocker ml(NMethodState_lock, !NMethodState_lock->owned_by_self(), Mutex::_no_safepoint_check_flag);
ttyLocker ttyl; // keep the following output all in one block
if (xtty != nullptr) {
xtty->begin_head("print_nmethod");
@@ -2035,6 +2042,17 @@ bool nmethod::make_not_entrant(const char* reason) {
// cache call.
NativeJump::patch_verified_entry(entry_point(), verified_entry_point(),
SharedRuntime::get_handle_wrong_method_stub());
+
+ // Update the relocation info for the patched entry.
+ // First, get the old relocation info...
+ RelocIterator iter(this, verified_entry_point(), verified_entry_point() + 8);
+ if (iter.next() && iter.addr() == verified_entry_point()) {
+ Relocation* old_reloc = iter.reloc();
+ // ...then reset the iterator to update it.
+ RelocIterator iter(this, verified_entry_point(), verified_entry_point() + 8);
+ relocInfo::change_reloc_info_for_address(&iter, verified_entry_point(), old_reloc->type(),
+ relocInfo::relocType::runtime_call_type);
+ }
}
if (update_recompile_counts()) {
diff --git a/src/hotspot/share/code/nmethod.hpp b/src/hotspot/share/code/nmethod.hpp
index 1c536a5d7e1..2ce6e5cd361 100644
--- a/src/hotspot/share/code/nmethod.hpp
+++ b/src/hotspot/share/code/nmethod.hpp
@@ -237,7 +237,9 @@ class nmethod : public CodeBlob {
uint16_t _oops_size;
#if INCLUDE_JVMCI
- uint16_t _jvmci_data_size;
+ // _metadata_size is not specific to JVMCI. In the non-JVMCI case, it can be derived as:
+ // _metadata_size = mutable_data_size - relocation_size
+ uint16_t _metadata_size;
#endif
// Offset in immutable data section
@@ -537,8 +539,8 @@ public:
// mutable data
Metadata** metadata_begin () const { return (Metadata**) (mutable_data_begin() + _relocation_size); }
#if INCLUDE_JVMCI
- Metadata** metadata_end () const { return (Metadata**) (mutable_data_end() - _jvmci_data_size); }
- address jvmci_data_begin () const { return mutable_data_end() - _jvmci_data_size; }
+ Metadata** metadata_end () const { return (Metadata**) (mutable_data_begin() + _relocation_size + _metadata_size); }
+ address jvmci_data_begin () const { return mutable_data_begin() + _relocation_size + _metadata_size; }
address jvmci_data_end () const { return mutable_data_end(); }
#else
Metadata** metadata_end () const { return (Metadata**) mutable_data_end(); }
diff --git a/src/hotspot/share/code/nmethod.inline.hpp b/src/hotspot/share/code/nmethod.inline.hpp
index 49af1e0b95f..1e556b68250 100644
--- a/src/hotspot/share/code/nmethod.inline.hpp
+++ b/src/hotspot/share/code/nmethod.inline.hpp
@@ -33,21 +33,12 @@
inline bool nmethod::is_deopt_pc(address pc) { return is_deopt_entry(pc) || is_deopt_mh_entry(pc); }
-// When using JVMCI the address might be off by the size of a call instruction.
inline bool nmethod::is_deopt_entry(address pc) {
- return pc == deopt_handler_begin()
-#if INCLUDE_JVMCI
- || (is_compiled_by_jvmci() && pc == (deopt_handler_begin() + NativeCall::byte_size()))
-#endif
- ;
+ return pc == deopt_handler_begin();
}
inline bool nmethod::is_deopt_mh_entry(address pc) {
- return pc == deopt_mh_handler_begin()
-#if INCLUDE_JVMCI
- || (is_compiled_by_jvmci() && pc == (deopt_mh_handler_begin() + NativeCall::byte_size()))
-#endif
- ;
+ return pc == deopt_mh_handler_begin();
}
// class ExceptionCache methods
diff --git a/src/hotspot/share/compiler/compileTask.cpp b/src/hotspot/share/compiler/compileTask.cpp
index 87d4a11e528..fd066a9bc87 100644
--- a/src/hotspot/share/compiler/compileTask.cpp
+++ b/src/hotspot/share/compiler/compileTask.cpp
@@ -471,7 +471,7 @@ void CompileTask::print_inlining_inner_message(outputStream* st, InliningResult
}
void CompileTask::print_ul(const char* msg){
- LogTarget(Debug, jit, compilation) lt;
+ LogTarget(Info, jit, compilation) lt;
if (lt.is_enabled()) {
LogStream ls(lt);
print(&ls, msg, /* short form */ true, /* cr */ true);
@@ -479,7 +479,7 @@ void CompileTask::print_ul(const char* msg){
}
void CompileTask::print_ul(const nmethod* nm, const char* msg) {
- LogTarget(Debug, jit, compilation) lt;
+ LogTarget(Info, jit, compilation) lt;
if (lt.is_enabled()) {
LogStream ls(lt);
print_impl(&ls, nm->method(), nm->compile_id(),
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp
index 41faf3efa24..353da67ed88 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp
@@ -98,6 +98,9 @@
#include "utilities/events.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/powerOfTwo.hpp"
+#if INCLUDE_JVMCI
+#include "jvmci/jvmci.hpp"
+#endif
#if INCLUDE_JFR
#include "gc/shenandoah/shenandoahJfrSupport.hpp"
#endif
@@ -2233,6 +2236,9 @@ void ShenandoahHeap::stw_unload_classes(bool full_gc) {
ShenandoahGCWorkerPhase worker_phase(phase);
bool unloading_occurred = SystemDictionary::do_unloading(gc_timer());
+ // Clean JVMCI metadata handles.
+ JVMCI_ONLY(JVMCI::do_unloading(unloading_occurred));
+
uint num_workers = _workers->active_workers();
ShenandoahClassUnloadingTask unlink_task(phase, num_workers, unloading_occurred);
_workers->run_task(&unlink_task);
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRuntime.cpp b/src/hotspot/share/gc/shenandoah/shenandoahRuntime.cpp
index d2a5f71bca6..97ba5012efa 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahRuntime.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRuntime.cpp
@@ -48,6 +48,10 @@ JRT_LEAF(void, ShenandoahRuntime::write_ref_field_pre(oopDesc * orig, JavaThread
ShenandoahBarrierSet::satb_mark_queue_set().enqueue_known_active(queue, orig);
JRT_END
+void ShenandoahRuntime::write_barrier_pre(oopDesc* orig) {
+ write_ref_field_pre(orig, JavaThread::current());
+}
+
JRT_LEAF(oopDesc*, ShenandoahRuntime::load_reference_barrier_strong(oopDesc* src, oop* load_addr))
return ShenandoahBarrierSet::barrier_set()->load_reference_barrier_mutator(src, load_addr);
JRT_END
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRuntime.hpp b/src/hotspot/share/gc/shenandoah/shenandoahRuntime.hpp
index 4ad8fc997ea..0ed8959d95e 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahRuntime.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRuntime.hpp
@@ -37,6 +37,7 @@ public:
static void arraycopy_barrier_narrow_oop(narrowOop* src, narrowOop* dst, size_t length);
static void write_ref_field_pre(oopDesc* orig, JavaThread* thread);
+ static void write_barrier_pre(oopDesc* orig);
static oopDesc* load_reference_barrier_strong(oopDesc* src, oop* load_addr);
static oopDesc* load_reference_barrier_strong_narrow(oopDesc* src, narrowOop* load_addr);
diff --git a/src/hotspot/share/gc/z/zBarrierSet.cpp b/src/hotspot/share/gc/z/zBarrierSet.cpp
index a4893fc351a..43ea791a260 100644
--- a/src/hotspot/share/gc/z/zBarrierSet.cpp
+++ b/src/hotspot/share/gc/z/zBarrierSet.cpp
@@ -115,7 +115,9 @@ static void deoptimize_allocation(JavaThread* thread) {
assert(caller_frame.is_compiled_frame(), "must be compiled");
const nmethod* const nm = caller_frame.cb()->as_nmethod();
- if (nm->is_compiled_by_c2() && !caller_frame.is_deoptimized_frame()) {
+ if ((nm->is_compiled_by_c2() || nm->is_compiled_by_jvmci()) && !caller_frame.is_deoptimized_frame()) {
+ // The JIT might have elided barriers on this object so deoptimize the frame and let the
+ // intepreter deal with it.
Deoptimization::deoptimize_frame(thread, caller_frame.id());
}
}
diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.hpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.hpp
index b44b4bb9116..f9643c6394e 100644
--- a/src/hotspot/share/jvmci/jvmciCompilerToVM.hpp
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.hpp
@@ -111,6 +111,10 @@ class CompilerToVM {
#if INCLUDE_ZGC
static int sizeof_ZStoreBarrierEntry;
#endif
+#if INCLUDE_SHENANDOAHGC
+ static address shenandoah_in_cset_fast_test_addr;
+ static int shenandoah_region_size_bytes_shift;
+#endif
#ifdef X86
static int L1_line_size;
diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp
index a729e34a279..591f30e7b19 100644
--- a/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp
@@ -52,6 +52,10 @@
#include "runtime/sharedRuntime.hpp"
#include "runtime/stubRoutines.hpp"
#include "utilities/resourceHash.hpp"
+#if INCLUDE_SHENANDOAHGC
+#include "gc/shenandoah/shenandoahHeap.hpp"
+#include "gc/shenandoah/shenandoahHeapRegion.hpp"
+#endif
int CompilerToVM::Data::oopDesc_klass_offset_in_bytes;
int CompilerToVM::Data::arrayOopDesc_length_offset_in_bytes;
@@ -86,6 +90,11 @@ address CompilerToVM::Data::ZPointerVectorLoadBadMask_address;
address CompilerToVM::Data::ZPointerVectorStoreBadMask_address;
address CompilerToVM::Data::ZPointerVectorStoreGoodMask_address;
+#if INCLUDE_SHENANDOAHGC
+address CompilerToVM::Data::shenandoah_in_cset_fast_test_addr;
+int CompilerToVM::Data::shenandoah_region_size_bytes_shift;
+#endif
+
bool CompilerToVM::Data::continuations_enabled;
#ifdef AARCH64
@@ -227,12 +236,24 @@ void CompilerToVM::Data::initialize(JVMCI_TRAPS) {
assert(base != nullptr, "unexpected byte_map_base");
cardtable_start_address = base;
cardtable_shift = CardTable::card_shift();
+#if INCLUDE_SHENANDOAHGC
+ } else if (bs->is_a(BarrierSet::ShenandoahBarrierSet)) {
+ cardtable_start_address = nullptr;
+ cardtable_shift = CardTable::card_shift();
+#endif
} else {
// No card mark barriers
cardtable_start_address = nullptr;
cardtable_shift = 0;
}
+#if INCLUDE_SHENANDOAHGC
+ if (UseShenandoahGC) {
+ shenandoah_in_cset_fast_test_addr = ShenandoahHeap::in_cset_fast_test_addr();
+ shenandoah_region_size_bytes_shift = ShenandoahHeapRegion::region_size_bytes_shift_jint();
+ }
+#endif
+
#ifdef X86
L1_line_size = VM_Version::L1_line_size();
#endif
diff --git a/src/hotspot/share/jvmci/jvmci_globals.cpp b/src/hotspot/share/jvmci/jvmci_globals.cpp
index a41351218f8..d4d52afd069 100644
--- a/src/hotspot/share/jvmci/jvmci_globals.cpp
+++ b/src/hotspot/share/jvmci/jvmci_globals.cpp
@@ -229,7 +229,7 @@ bool JVMCIGlobals::enable_jvmci_product_mode(JVMFlagOrigin origin, bool use_graa
}
bool JVMCIGlobals::gc_supports_jvmci() {
- return UseSerialGC || UseParallelGC || UseG1GC || UseZGC || UseEpsilonGC;
+ return UseSerialGC || UseParallelGC || UseG1GC || UseZGC || UseShenandoahGC || UseEpsilonGC;
}
void JVMCIGlobals::check_jvmci_supported_gc() {
diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp
index 8ca13a3a6c3..dfc15368cf6 100644
--- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp
+++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp
@@ -53,6 +53,10 @@
#include "gc/z/zBarrierSetRuntime.hpp"
#include "gc/z/zThreadLocalData.hpp"
#endif
+#if INCLUDE_SHENANDOAHGC
+#include "gc/shenandoah/shenandoahRuntime.hpp"
+#include "gc/shenandoah/shenandoahThreadLocalData.hpp"
+#endif
#define VM_STRUCTS(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field) \
static_field(CompilerToVM::Data, oopDesc_klass_offset_in_bytes, int) \
@@ -129,6 +133,8 @@
static_field(CompilerToVM::Data, sizeof_arrayOopDesc, int) \
static_field(CompilerToVM::Data, sizeof_BasicLock, int) \
ZGC_ONLY(static_field(CompilerToVM::Data, sizeof_ZStoreBarrierEntry, int)) \
+ SHENANDOAHGC_ONLY(static_field(CompilerToVM::Data, shenandoah_in_cset_fast_test_addr, address)) \
+ SHENANDOAHGC_ONLY(static_field(CompilerToVM::Data, shenandoah_region_size_bytes_shift,int)) \
\
static_field(CompilerToVM::Data, dsin, address) \
static_field(CompilerToVM::Data, dcos, address) \
@@ -895,6 +901,13 @@
declare_function(JVMCIRuntime::load_and_clear_exception) \
G1GC_ONLY(declare_function(JVMCIRuntime::write_barrier_pre)) \
G1GC_ONLY(declare_function(JVMCIRuntime::write_barrier_post)) \
+ SHENANDOAHGC_ONLY(declare_function(ShenandoahRuntime::load_reference_barrier_strong)) \
+ SHENANDOAHGC_ONLY(declare_function(ShenandoahRuntime::load_reference_barrier_strong_narrow)) \
+ SHENANDOAHGC_ONLY(declare_function(ShenandoahRuntime::load_reference_barrier_weak)) \
+ SHENANDOAHGC_ONLY(declare_function(ShenandoahRuntime::load_reference_barrier_weak_narrow)) \
+ SHENANDOAHGC_ONLY(declare_function(ShenandoahRuntime::load_reference_barrier_phantom)) \
+ SHENANDOAHGC_ONLY(declare_function(ShenandoahRuntime::load_reference_barrier_phantom_narrow)) \
+ SHENANDOAHGC_ONLY(declare_function(ShenandoahRuntime::write_barrier_pre)) \
declare_function(JVMCIRuntime::validate_object) \
\
declare_function(JVMCIRuntime::test_deoptimize_call_int)
@@ -941,6 +954,15 @@
#endif // INCLUDE_ZGC
+#if INCLUDE_SHENANDOAHGC
+
+#define VM_INT_CONSTANTS_JVMCI_SHENANDOAH(declare_constant, declare_constant_with_value, declare_preprocessor_constant) \
+ declare_constant_with_value("ShenandoahThreadLocalData::gc_state_offset", in_bytes(ShenandoahThreadLocalData::gc_state_offset())) \
+ declare_constant_with_value("ShenandoahThreadLocalData::satb_mark_queue_index_offset", in_bytes(ShenandoahThreadLocalData::satb_mark_queue_index_offset())) \
+ declare_constant_with_value("ShenandoahThreadLocalData::satb_mark_queue_buffer_offset", in_bytes(ShenandoahThreadLocalData::satb_mark_queue_buffer_offset())) \
+ declare_constant_with_value("ShenandoahThreadLocalData::card_table_offset", in_bytes(ShenandoahThreadLocalData::card_table_offset())) \
+
+#endif
#ifdef LINUX
@@ -1063,6 +1085,11 @@ VMIntConstantEntry JVMCIVMStructs::localHotSpotVMIntConstants[] = {
GENERATE_VM_INT_CONSTANT_WITH_VALUE_ENTRY,
GENERATE_PREPROCESSOR_VM_INT_CONSTANT_ENTRY)
#endif
+#if INCLUDE_SHENANDOAHGC
+ VM_INT_CONSTANTS_JVMCI_SHENANDOAH(GENERATE_VM_INT_CONSTANT_ENTRY,
+ GENERATE_VM_INT_CONSTANT_WITH_VALUE_ENTRY,
+ GENERATE_PREPROCESSOR_VM_INT_CONSTANT_ENTRY)
+#endif
#ifdef VM_INT_CPU_FEATURE_CONSTANTS
VM_INT_CPU_FEATURE_CONSTANTS
#endif
diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp
index effc7e21354..10846a32626 100644
--- a/src/hotspot/share/opto/compile.cpp
+++ b/src/hotspot/share/opto/compile.cpp
@@ -5205,32 +5205,39 @@ IdealGraphPrinter* Compile::_debug_network_printer = nullptr;
// Called from debugger. Prints method to the default file with the default phase name.
// This works regardless of any Ideal Graph Visualizer flags set or not.
-void igv_print() {
- Compile::current()->igv_print_method_to_file();
+// Use in debugger (gdb/rr): p igv_print($sp, $fp, $pc).
+void igv_print(void* sp, void* fp, void* pc) {
+ frame fr(sp, fp, pc);
+ Compile::current()->igv_print_method_to_file(nullptr, false, &fr);
}
// Same as igv_print() above but with a specified phase name.
-void igv_print(const char* phase_name) {
- Compile::current()->igv_print_method_to_file(phase_name);
+void igv_print(const char* phase_name, void* sp, void* fp, void* pc) {
+ frame fr(sp, fp, pc);
+ Compile::current()->igv_print_method_to_file(phase_name, false, &fr);
}
// Called from debugger. Prints method with the default phase name to the default network or the one specified with
// the network flags for the Ideal Graph Visualizer, or to the default file depending on the 'network' argument.
// This works regardless of any Ideal Graph Visualizer flags set or not.
-void igv_print(bool network) {
+// Use in debugger (gdb/rr): p igv_print(true, $sp, $fp, $pc).
+void igv_print(bool network, void* sp, void* fp, void* pc) {
+ frame fr(sp, fp, pc);
if (network) {
- Compile::current()->igv_print_method_to_network();
+ Compile::current()->igv_print_method_to_network(nullptr, &fr);
} else {
- Compile::current()->igv_print_method_to_file();
+ Compile::current()->igv_print_method_to_file(nullptr, false, &fr);
}
}
-// Same as igv_print(bool network) above but with a specified phase name.
-void igv_print(bool network, const char* phase_name) {
+// Same as igv_print(bool network, ...) above but with a specified phase name.
+// Use in debugger (gdb/rr): p igv_print(true, "MyPhase", $sp, $fp, $pc).
+void igv_print(bool network, const char* phase_name, void* sp, void* fp, void* pc) {
+ frame fr(sp, fp, pc);
if (network) {
- Compile::current()->igv_print_method_to_network(phase_name);
+ Compile::current()->igv_print_method_to_network(phase_name, &fr);
} else {
- Compile::current()->igv_print_method_to_file(phase_name);
+ Compile::current()->igv_print_method_to_file(phase_name, false, &fr);
}
}
@@ -5242,16 +5249,20 @@ void igv_print_default() {
// Called from debugger, especially when replaying a trace in which the program state cannot be altered like with rr replay.
// A method is appended to an existing default file with the default phase name. This means that igv_append() must follow
// an earlier igv_print(*) call which sets up the file. This works regardless of any Ideal Graph Visualizer flags set or not.
-void igv_append() {
- Compile::current()->igv_print_method_to_file("Debug", true);
+// Use in debugger (gdb/rr): p igv_append($sp, $fp, $pc).
+void igv_append(void* sp, void* fp, void* pc) {
+ frame fr(sp, fp, pc);
+ Compile::current()->igv_print_method_to_file(nullptr, true, &fr);
}
-// Same as igv_append() above but with a specified phase name.
-void igv_append(const char* phase_name) {
- Compile::current()->igv_print_method_to_file(phase_name, true);
+// Same as igv_append(...) above but with a specified phase name.
+// Use in debugger (gdb/rr): p igv_append("MyPhase", $sp, $fp, $pc).
+void igv_append(const char* phase_name, void* sp, void* fp, void* pc) {
+ frame fr(sp, fp, pc);
+ Compile::current()->igv_print_method_to_file(phase_name, true, &fr);
}
-void Compile::igv_print_method_to_file(const char* phase_name, bool append) {
+void Compile::igv_print_method_to_file(const char* phase_name, bool append, const frame* fr) {
const char* file_name = "custom_debug.xml";
if (_debug_file_printer == nullptr) {
_debug_file_printer = new IdealGraphPrinter(C, file_name, append);
@@ -5259,23 +5270,23 @@ void Compile::igv_print_method_to_file(const char* phase_name, bool append) {
_debug_file_printer->update_compiled_method(C->method());
}
tty->print_cr("Method %s to %s", append ? "appended" : "printed", file_name);
- _debug_file_printer->print_graph(phase_name);
+ _debug_file_printer->print_graph(phase_name, fr);
}
-void Compile::igv_print_method_to_network(const char* phase_name) {
+void Compile::igv_print_method_to_network(const char* phase_name, const frame* fr) {
ResourceMark rm;
GrowableArray empty_list;
- igv_print_graph_to_network(phase_name, empty_list);
+ igv_print_graph_to_network(phase_name, empty_list, fr);
}
-void Compile::igv_print_graph_to_network(const char* name, GrowableArray& visible_nodes) {
+void Compile::igv_print_graph_to_network(const char* name, GrowableArray& visible_nodes, const frame* fr) {
if (_debug_network_printer == nullptr) {
_debug_network_printer = new IdealGraphPrinter(C);
} else {
_debug_network_printer->update_compiled_method(C->method());
}
tty->print_cr("Method printed over network stream to IGV");
- _debug_network_printer->print(name, C->root(), visible_nodes);
+ _debug_network_printer->print(name, C->root(), visible_nodes, fr);
}
#endif
diff --git a/src/hotspot/share/opto/compile.hpp b/src/hotspot/share/opto/compile.hpp
index 33b9187e262..6d43948964e 100644
--- a/src/hotspot/share/opto/compile.hpp
+++ b/src/hotspot/share/opto/compile.hpp
@@ -673,13 +673,13 @@ public:
void init_igv();
void dump_igv(const char* graph_name, int level = 3) {
if (should_print_igv(level)) {
- _igv_printer->print_graph(graph_name);
+ _igv_printer->print_graph(graph_name, nullptr);
}
}
- void igv_print_method_to_file(const char* phase_name = "Debug", bool append = false);
- void igv_print_method_to_network(const char* phase_name = "Debug");
- void igv_print_graph_to_network(const char* name, GrowableArray& visible_nodes);
+ void igv_print_method_to_file(const char* phase_name = nullptr, bool append = false, const frame* fr = nullptr);
+ void igv_print_method_to_network(const char* phase_name = nullptr, const frame* fr = nullptr);
+ void igv_print_graph_to_network(const char* name, GrowableArray& visible_nodes, const frame* fr);
static IdealGraphPrinter* debug_file_printer() { return _debug_file_printer; }
static IdealGraphPrinter* debug_network_printer() { return _debug_network_printer; }
#endif
diff --git a/src/hotspot/share/opto/idealGraphPrinter.cpp b/src/hotspot/share/opto/idealGraphPrinter.cpp
index 9f17e350059..9a337739be5 100644
--- a/src/hotspot/share/opto/idealGraphPrinter.cpp
+++ b/src/hotspot/share/opto/idealGraphPrinter.cpp
@@ -27,8 +27,10 @@
#include "opto/idealGraphPrinter.hpp"
#include "opto/machnode.hpp"
#include "opto/parse.hpp"
+#include "runtime/arguments.hpp"
#include "runtime/threadCritical.hpp"
#include "runtime/threadSMR.hpp"
+#include "utilities/decoder.hpp"
#include "utilities/stringUtils.hpp"
#ifndef PRODUCT
@@ -49,6 +51,13 @@ const char *IdealGraphPrinter::REMOVE_EDGE_ELEMENT = "removeEdge";
const char *IdealGraphPrinter::REMOVE_NODE_ELEMENT = "removeNode";
const char *IdealGraphPrinter::COMPILATION_ID_PROPERTY = "compilationId";
const char *IdealGraphPrinter::COMPILATION_OSR_PROPERTY = "osr";
+const char *IdealGraphPrinter::COMPILATION_ARGUMENTS_PROPERTY = "arguments";
+const char *IdealGraphPrinter::COMPILATION_MACHINE_PROPERTY = "machine";
+const char *IdealGraphPrinter::COMPILATION_CPU_FEATURES_PROPERTY = "cpuFeatures";
+const char *IdealGraphPrinter::COMPILATION_VM_VERSION_PROPERTY = "vm";
+const char *IdealGraphPrinter::COMPILATION_DATE_TIME_PROPERTY = "dateTime";
+const char *IdealGraphPrinter::COMPILATION_PROCESS_ID_PROPERTY = "processId";
+const char *IdealGraphPrinter::COMPILATION_THREAD_ID_PROPERTY = "threadId";
const char *IdealGraphPrinter::METHOD_NAME_PROPERTY = "name";
const char *IdealGraphPrinter::METHOD_IS_PUBLIC_PROPERTY = "public";
const char *IdealGraphPrinter::METHOD_IS_STATIC_PROPERTY = "static";
@@ -336,6 +345,42 @@ void IdealGraphPrinter::begin_method() {
print_prop(COMPILATION_ID_PROPERTY, C->compile_id());
+ stringStream args;
+ Arguments::print_jvm_args_on(&args);
+ print_prop(COMPILATION_ARGUMENTS_PROPERTY, args.freeze());
+
+ stringStream machine;
+ buffer[0] = 0;
+ os::print_summary_info(&machine, buffer, sizeof(buffer) - 1);
+ print_prop(COMPILATION_MACHINE_PROPERTY, machine.freeze());
+
+ print_prop(COMPILATION_CPU_FEATURES_PROPERTY, VM_Version::features_string());
+
+ stringStream version;
+ buffer[0] = 0;
+ JDK_Version::current().to_string(buffer, sizeof(buffer) - 1);
+ const char* runtime_name = JDK_Version::runtime_name() != nullptr ?
+ JDK_Version::runtime_name() : "";
+ const char* runtime_version = JDK_Version::runtime_version() != nullptr ?
+ JDK_Version::runtime_version() : "";
+ const char* vendor_version = JDK_Version::runtime_vendor_version() != nullptr ?
+ JDK_Version::runtime_vendor_version() : "";
+ const char* jdk_debug_level = VM_Version::printable_jdk_debug_level() != nullptr ?
+ VM_Version::printable_jdk_debug_level() : "";
+
+ version.print_cr("%s%s%s (%s) (%sbuild %s)", runtime_name,
+ (*vendor_version != '\0') ? " " : "", vendor_version,
+ buffer, jdk_debug_level, runtime_version);
+ print_prop(COMPILATION_VM_VERSION_PROPERTY, version.freeze());
+
+ stringStream time;
+ buffer[0] = 0;
+ os::print_date_and_time(&time, buffer, sizeof(buffer) - 1);
+ print_prop(COMPILATION_DATE_TIME_PROPERTY, time.freeze());
+
+ print_prop(COMPILATION_PROCESS_ID_PROPERTY, os::current_process_id());
+ print_prop(COMPILATION_THREAD_ID_PROPERTY, os::current_thread_id());
+
tail(PROPERTIES_ELEMENT);
_should_send_method = true;
@@ -862,24 +907,91 @@ void IdealGraphPrinter::walk_nodes(Node* start, bool edges) {
}
}
-void IdealGraphPrinter::print_graph(const char* name) {
+// Whether the stack walk should skip the given frame when producing a C2 stack
+// trace. We consider IGV- and debugger-specific frames uninteresting.
+static bool should_skip_frame(const char* name) {
+ return strstr(name, "IdealGraphPrinter") != nullptr ||
+ strstr(name, "Compile::print_method") != nullptr ||
+ strstr(name, "Compile::igv_print_graph") != nullptr ||
+ strstr(name, "PrintBFS") != nullptr ||
+ strstr(name, "Node::dump_bfs") != nullptr;
+}
+
+// Whether the stack walk should be considered done when visiting a certain
+// frame. The purpose of walking the stack is producing a C2 trace, so we
+// consider all frames below (and including) C2Compiler::compile_method(..)
+// uninteresting.
+static bool should_end_stack_walk(const char* name) {
+ return strstr(name, "C2Compiler::compile_method") != nullptr;
+}
+
+void IdealGraphPrinter::print_stack(const frame* initial_frame, outputStream* graph_name) {
+ char buf[O_BUFLEN];
+ frame fr = initial_frame == nullptr ? os::current_frame() : *initial_frame;
+ int frame = 0;
+ for (int count = 0; count < StackPrintLimit && fr.pc() != nullptr; count++) {
+ int offset;
+ buf[0] = '\0';
+ bool found = os::dll_address_to_function_name(fr.pc(), buf, sizeof(buf), &offset);
+ if (!found || should_end_stack_walk(buf)) {
+ break;
+ }
+ if (!should_skip_frame(buf)) {
+ stringStream frame_loc;
+ frame_loc.print("%s", buf);
+ buf[0] = '\0';
+ int line_no;
+ if (Decoder::get_source_info(fr.pc(), buf, sizeof(buf), &line_no, count != 1)) {
+ frame_loc.print(" (%s:%d)", buf, line_no);
+ if (graph_name != nullptr) {
+ // Extract a debug graph name and return.
+ graph_name->print("%s:%d", buf, line_no);
+ return;
+ }
+ }
+ if (graph_name == nullptr) {
+ // Print frame as IGV property and continue to the next frame.
+ stringStream frame_number_str;
+ frame_number_str.print("frame %d:", frame);
+ print_prop(frame_number_str.freeze(), frame_loc.freeze());
+ frame++;
+ }
+ }
+ fr = frame::next_frame(fr, Thread::current_or_null());
+ }
+}
+
+void IdealGraphPrinter::print_graph(const char* name, const frame* fr) {
ResourceMark rm;
GrowableArray empty_list;
- print(name, (Node*) C->root(), empty_list);
+ print(name, (Node*) C->root(), empty_list, fr);
}
// Print current ideal graph
-void IdealGraphPrinter::print(const char* name, Node* node, GrowableArray& visible_nodes) {
+void IdealGraphPrinter::print(const char* name, Node* node, GrowableArray& visible_nodes, const frame* fr) {
if (!_current_method || !_should_send_method || node == nullptr) return;
+ if (name == nullptr) {
+ stringStream graph_name;
+ print_stack(fr, &graph_name);
+ name = graph_name.freeze();
+ if (strlen(name) == 0) {
+ name = "Debug";
+ }
+ }
+
// Warning, unsafe cast?
_chaitin = (PhaseChaitin *)C->regalloc();
begin_head(GRAPH_ELEMENT);
- print_attr(GRAPH_NAME_PROPERTY, (const char *)name);
+ print_attr(GRAPH_NAME_PROPERTY, name);
end_head();
+ head(PROPERTIES_ELEMENT);
+ print_stack(fr, nullptr);
+ tail(PROPERTIES_ELEMENT);
+
head(NODES_ELEMENT);
if (C->cfg() != nullptr) {
// Compute the maximum estimated frequency in the current graph.
@@ -1047,7 +1159,6 @@ void IdealGraphPrinter::print(const char* name, Node* node, GrowableArray {
static const char *ALL_PROPERTY;
static const char *COMPILATION_ID_PROPERTY;
static const char *COMPILATION_OSR_PROPERTY;
+ static const char *COMPILATION_ARGUMENTS_PROPERTY;
+ static const char *COMPILATION_MACHINE_PROPERTY;
+ static const char *COMPILATION_CPU_FEATURES_PROPERTY;
+ static const char *COMPILATION_VM_VERSION_PROPERTY;
+ static const char *COMPILATION_DATE_TIME_PROPERTY;
+ static const char *COMPILATION_PROCESS_ID_PROPERTY;
+ static const char *COMPILATION_THREAD_ID_PROPERTY;
static const char *METHOD_NAME_PROPERTY;
static const char *BLOCK_NAME_PROPERTY;
static const char *BLOCK_DOMINATOR_PROPERTY;
@@ -110,6 +117,10 @@ class IdealGraphPrinter : public CHeapObj {
double _max_freq;
bool _append;
+ // Walk the native stack and print relevant C2 frames as IGV properties (if
+ // graph_name == nullptr) or the graph name based on the highest C2 frame (if
+ // graph_name != nullptr).
+ void print_stack(const frame* initial_frame, outputStream* graph_name);
void print_method(ciMethod* method, int bci, InlineTree* tree);
void print_inline_tree(InlineTree* tree);
void visit_node(Node* n, bool edges);
@@ -149,8 +160,8 @@ class IdealGraphPrinter : public CHeapObj {
void print_inlining();
void begin_method();
void end_method();
- void print_graph(const char* name);
- void print(const char* name, Node* root, GrowableArray& hidden_nodes);
+ void print_graph(const char* name, const frame* fr = nullptr);
+ void print(const char* name, Node* root, GrowableArray& hidden_nodes, const frame* fr = nullptr);
void set_compile(Compile* compile) {C = compile; }
void update_compiled_method(ciMethod* current_method);
};
diff --git a/src/hotspot/share/opto/node.cpp b/src/hotspot/share/opto/node.cpp
index a635abebec1..3875c6ce325 100644
--- a/src/hotspot/share/opto/node.cpp
+++ b/src/hotspot/share/opto/node.cpp
@@ -1774,8 +1774,8 @@ Node* Node::find(const int idx, bool only_ctrl) {
class PrintBFS {
public:
- PrintBFS(const Node* start, const int max_distance, const Node* target, const char* options, outputStream* st)
- : _start(start), _max_distance(max_distance), _target(target), _options(options), _output(st),
+ PrintBFS(const Node* start, const int max_distance, const Node* target, const char* options, outputStream* st, const frame* fr)
+ : _start(start), _max_distance(max_distance), _target(target), _options(options), _output(st), _frame(fr),
_dcc(this), _info_uid(cmpkey, hashkey) {}
void run();
@@ -1796,6 +1796,7 @@ private:
const Node* _target;
const char* _options;
outputStream* _output;
+ const frame* _frame;
// options
bool _traverse_inputs = false;
@@ -2057,7 +2058,7 @@ void PrintBFS::print() {
if (_print_igv) {
Compile* C = Compile::current();
C->init_igv();
- C->igv_print_graph_to_network("PrintBFS", _print_list);
+ C->igv_print_graph_to_network(nullptr, _print_list, _frame);
}
} else {
_output->print_cr("No nodes to print.");
@@ -2102,6 +2103,8 @@ void PrintBFS::print_options_help(bool print_examples) {
_output->print_cr(" B: print scheduling blocks (if available)");
_output->print_cr(" $: dump only, no header, no other columns");
_output->print_cr(" !: show nodes on IGV (sent over network stream)");
+ _output->print_cr(" (use preferably with dump_bfs(int, Node*, char*, void*, void*, void*)");
+ _output->print_cr(" to produce a C2 stack trace along with the graph dump, see examples below)");
_output->print_cr("");
_output->print_cr("recursively follow edges to nodes with permitted visit types,");
_output->print_cr("on the boundary additionally display nodes allowed in boundary types");
@@ -2151,6 +2154,9 @@ void PrintBFS::print_options_help(bool print_examples) {
_output->print_cr(" find all paths (A) between two nodes of length at most 8");
_output->print_cr(" find_node(741)->dump_bfs(7, find_node(741), \"c+A\")");
_output->print_cr(" find all control loops for this node");
+ _output->print_cr(" find_node(741)->dump_bfs(7, find_node(741), \"c+A!\", $sp, $fp, $pc)");
+ _output->print_cr(" same as above, but printing the resulting subgraph");
+ _output->print_cr(" along with a C2 stack trace on IGV");
}
}
@@ -2409,8 +2415,8 @@ void Node::dump_bfs(const int max_distance, Node* target, const char* options) c
}
// Used to dump to stream.
-void Node::dump_bfs(const int max_distance, Node* target, const char* options, outputStream* st) const {
- PrintBFS bfs(this, max_distance, target, options, st);
+void Node::dump_bfs(const int max_distance, Node* target, const char* options, outputStream* st, const frame* fr) const {
+ PrintBFS bfs(this, max_distance, target, options, st, fr);
bfs.run();
}
@@ -2419,6 +2425,13 @@ void Node::dump_bfs(const int max_distance) const {
dump_bfs(max_distance, nullptr, nullptr);
}
+// Call this from debugger, with stack handling register arguments for IGV dumps.
+// Example: p find_node(741)->dump_bfs(7, find_node(741), "c+A!", $sp, $fp, $pc).
+void Node::dump_bfs(const int max_distance, Node* target, const char* options, void* sp, void* fp, void* pc) const {
+ frame fr(sp, fp, pc);
+ dump_bfs(max_distance, target, options, tty, &fr);
+}
+
// -----------------------------dump_idx---------------------------------------
void Node::dump_idx(bool align, outputStream* st, DumpConfig* dc) const {
if (dc != nullptr) {
diff --git a/src/hotspot/share/opto/node.hpp b/src/hotspot/share/opto/node.hpp
index e1a4ee22661..843baf48cf8 100644
--- a/src/hotspot/share/opto/node.hpp
+++ b/src/hotspot/share/opto/node.hpp
@@ -1298,9 +1298,10 @@ public:
public:
Node* find(int idx, bool only_ctrl = false); // Search the graph for the given idx.
Node* find_ctrl(int idx); // Search control ancestors for the given idx.
- void dump_bfs(const int max_distance, Node* target, const char* options, outputStream* st) const;
+ void dump_bfs(const int max_distance, Node* target, const char* options, outputStream* st, const frame* fr = nullptr) const;
void dump_bfs(const int max_distance, Node* target, const char* options) const; // directly to tty
void dump_bfs(const int max_distance) const; // dump_bfs(max_distance, nullptr, nullptr)
+ void dump_bfs(const int max_distance, Node* target, const char* options, void* sp, void* fp, void* pc) const;
class DumpConfig {
public:
// overridden to implement coloring of node idx
diff --git a/src/hotspot/share/prims/jvmtiEnv.cpp b/src/hotspot/share/prims/jvmtiEnv.cpp
index b2af12b08a6..6a1f451bb74 100644
--- a/src/hotspot/share/prims/jvmtiEnv.cpp
+++ b/src/hotspot/share/prims/jvmtiEnv.cpp
@@ -988,6 +988,10 @@ JvmtiEnv::SuspendThreadList(jint request_count, const jthread* request_list, jvm
self_tobj = Handle(current, thread_oop);
continue; // self suspend after all other suspends
}
+ if (java_lang_VirtualThread::is_instance(thread_oop)) {
+ oop carrier_thread = java_lang_VirtualThread::carrier_thread(thread_oop);
+ java_thread = carrier_thread == nullptr ? nullptr : java_lang_Thread::thread(carrier_thread);
+ }
results[i] = suspend_thread(thread_oop, java_thread, /* single_suspend */ true);
}
}
@@ -1114,6 +1118,10 @@ JvmtiEnv::ResumeThreadList(jint request_count, const jthread* request_list, jvmt
continue;
}
}
+ if (java_lang_VirtualThread::is_instance(thread_oop)) {
+ oop carrier_thread = java_lang_VirtualThread::carrier_thread(thread_oop);
+ java_thread = carrier_thread == nullptr ? nullptr : java_lang_Thread::thread(carrier_thread);
+ }
results[i] = resume_thread(thread_oop, java_thread, /* single_resume */ true);
}
// per-thread resume results returned via results parameter
diff --git a/src/hotspot/share/prims/jvmtiEnvBase.cpp b/src/hotspot/share/prims/jvmtiEnvBase.cpp
index 9e0929e69cf..3b6602f2420 100644
--- a/src/hotspot/share/prims/jvmtiEnvBase.cpp
+++ b/src/hotspot/share/prims/jvmtiEnvBase.cpp
@@ -1398,8 +1398,7 @@ JvmtiEnvBase::is_vthread_suspended(oop vt_oop, JavaThread* jt) {
bool suspended = false;
if (java_lang_VirtualThread::is_instance(vt_oop)) {
suspended = JvmtiVTSuspender::is_vthread_suspended(vt_oop);
- }
- if (vt_oop->is_a(vmClasses::BoundVirtualThread_klass())) {
+ } else if (vt_oop->is_a(vmClasses::BoundVirtualThread_klass())) {
suspended = jt->is_suspended();
}
return suspended;
@@ -1757,57 +1756,46 @@ JvmtiEnvBase::suspend_thread(oop thread_oop, JavaThread* java_thread, bool singl
Handle thread_h(current, thread_oop);
bool is_virtual = java_lang_VirtualThread::is_instance(thread_h());
- if (is_virtual) {
- if (single_suspend) {
- if (JvmtiVTSuspender::is_vthread_suspended(thread_h())) {
- return JVMTI_ERROR_THREAD_SUSPENDED;
- }
- JvmtiVTSuspender::register_vthread_suspend(thread_h());
- // Check if virtual thread is mounted and there is a java_thread.
- // A non-null java_thread is always passed in the !single_suspend case.
- oop carrier_thread = java_lang_VirtualThread::carrier_thread(thread_h());
- java_thread = carrier_thread == nullptr ? nullptr : java_lang_Thread::thread(carrier_thread);
+ // Unmounted vthread case.
+
+ if (is_virtual && java_thread == nullptr) {
+ assert(single_suspend, "sanity check");
+ if (JvmtiVTSuspender::is_vthread_suspended(thread_h())) {
+ return JVMTI_ERROR_THREAD_SUSPENDED;
}
- // The java_thread can be still blocked in VTMS transition after a previous JVMTI resume call.
- // There is no need to suspend the java_thread in this case. After vthread unblocking,
- // it will check for ext_suspend request and suspend itself if necessary.
- if (java_thread == nullptr || java_thread->is_suspended()) {
- // We are done if the virtual thread is unmounted or
- // the java_thread is externally suspended.
- return JVMTI_ERROR_NONE;
- }
- // The virtual thread is mounted: suspend the java_thread.
+ JvmtiVTSuspender::register_vthread_suspend(thread_h());
+ return JVMTI_ERROR_NONE;
}
+
+ // Platform thread or mounted vthread cases.
+
+ assert(java_thread != nullptr, "sanity check");
+ assert(!java_thread->is_in_VTMS_transition(), "sanity check");
+
// Don't allow hidden thread suspend request.
if (java_thread->is_hidden_from_external_view()) {
return JVMTI_ERROR_NONE;
}
- bool is_thread_carrying = is_thread_carrying_vthread(java_thread, thread_h());
-
- // A case of non-virtual thread.
- if (!is_virtual) {
- // Thread.suspend() is used in some tests. It sets jt->is_suspended() only.
- if (java_thread->is_carrier_thread_suspended() ||
- (!is_thread_carrying && java_thread->is_suspended())) {
- return JVMTI_ERROR_THREAD_SUSPENDED;
- }
- java_thread->set_carrier_thread_suspended();
- }
- assert(!java_thread->is_in_VTMS_transition(), "sanity check");
-
- assert(!single_suspend || (!is_virtual && java_thread->is_carrier_thread_suspended()) ||
- (is_virtual && JvmtiVTSuspender::is_vthread_suspended(thread_h())),
- "sanity check");
// An attempt to handshake-suspend a thread carrying a virtual thread will result in
// suspension of mounted virtual thread. So, we just mark it as suspended
// and it will be actually suspended at virtual thread unmount transition.
- if (!is_thread_carrying) {
+ bool is_thread_carrying = is_thread_carrying_vthread(java_thread, thread_h());
+ if (is_thread_carrying) {
+ return java_thread->set_carrier_thread_suspended() ? JVMTI_ERROR_NONE : JVMTI_ERROR_THREAD_SUSPENDED;
+ } else {
+ // Platform thread (not carrying vthread) or mounted vthread cases.
assert(thread_h() != nullptr, "sanity check");
assert(single_suspend || thread_h()->is_a(vmClasses::BaseVirtualThread_klass()),
"SuspendAllVirtualThreads should never suspend non-virtual threads");
- // Case of mounted virtual or attached carrier thread.
- if (!java_thread->java_suspend()) {
+
+ // Ideally we would just need to check java_thread->is_suspended(), but we have to
+ // consider the case of trying to suspend a thread that was previously suspended while
+ // carrying a vthread but has already unmounted it.
+ if (java_thread->is_suspended() || (!is_virtual && java_thread->is_carrier_thread_suspended())) {
+ return JVMTI_ERROR_THREAD_SUSPENDED;
+ }
+ if (!java_thread->java_suspend(is_virtual && single_suspend)) {
// Thread is already suspended or in process of exiting.
if (java_thread->is_exiting()) {
// The thread was in the process of exiting.
@@ -1815,8 +1803,8 @@ JvmtiEnvBase::suspend_thread(oop thread_oop, JavaThread* java_thread, bool singl
}
return JVMTI_ERROR_THREAD_SUSPENDED;
}
+ return JVMTI_ERROR_NONE;
}
- return JVMTI_ERROR_NONE;
}
// java_thread - protected by ThreadsListHandle
@@ -1827,54 +1815,51 @@ JvmtiEnvBase::resume_thread(oop thread_oop, JavaThread* java_thread, bool single
Handle thread_h(current, thread_oop);
bool is_virtual = java_lang_VirtualThread::is_instance(thread_h());
- if (is_virtual) {
- if (single_resume) {
- if (!JvmtiVTSuspender::is_vthread_suspended(thread_h())) {
- return JVMTI_ERROR_THREAD_NOT_SUSPENDED;
- }
- JvmtiVTSuspender::register_vthread_resume(thread_h());
- // Check if virtual thread is mounted and there is a java_thread.
- // A non-null java_thread is always passed in the !single_resume case.
- oop carrier_thread = java_lang_VirtualThread::carrier_thread(thread_h());
- java_thread = carrier_thread == nullptr ? nullptr : java_lang_Thread::thread(carrier_thread);
+ // Unmounted vthread case.
+
+ if (is_virtual && java_thread == nullptr) {
+ assert(single_resume, "sanity check");
+ if (!JvmtiVTSuspender::is_vthread_suspended(thread_h())) {
+ return JVMTI_ERROR_THREAD_NOT_SUSPENDED;
}
- // The java_thread can be still blocked in VTMS transition after a previous JVMTI suspend call.
- // There is no need to resume the java_thread in this case. After vthread unblocking,
- // it will check for is_vthread_suspended request and remain resumed if necessary.
- if (java_thread == nullptr || !java_thread->is_suspended()) {
- // We are done if the virtual thread is unmounted or
- // the java_thread is not externally suspended.
- return JVMTI_ERROR_NONE;
- }
- // The virtual thread is mounted and java_thread is supended: resume the java_thread.
+ JvmtiVTSuspender::register_vthread_resume(thread_h());
+ return JVMTI_ERROR_NONE;
}
+
+ // Platform thread or mounted vthread cases.
+
+ assert(java_thread != nullptr, "sanity check");
+ assert(!java_thread->is_in_VTMS_transition(), "sanity check");
+
// Don't allow hidden thread resume request.
if (java_thread->is_hidden_from_external_view()) {
return JVMTI_ERROR_NONE;
}
+
bool is_thread_carrying = is_thread_carrying_vthread(java_thread, thread_h());
+ if (is_thread_carrying) {
+ return java_thread->clear_carrier_thread_suspended() ? JVMTI_ERROR_NONE : JVMTI_ERROR_THREAD_NOT_SUSPENDED;
+ } else {
+ // Platform thread (not carrying vthread) or mounted vthread cases.
- // A case of a non-virtual thread.
- if (!is_virtual) {
- if (!java_thread->is_carrier_thread_suspended() &&
- (is_thread_carrying || !java_thread->is_suspended())) {
- return JVMTI_ERROR_THREAD_NOT_SUSPENDED;
- }
- java_thread->clear_carrier_thread_suspended();
- }
- assert(!java_thread->is_in_VTMS_transition(), "sanity check");
-
- if (!is_thread_carrying) {
assert(thread_h() != nullptr, "sanity check");
assert(single_resume || thread_h()->is_a(vmClasses::BaseVirtualThread_klass()),
"ResumeAllVirtualThreads should never resume non-virtual threads");
- if (java_thread->is_suspended()) {
- if (!java_thread->java_resume()) {
- return JVMTI_ERROR_THREAD_NOT_SUSPENDED;
- }
+
+ // Ideally we would not have to check this but we have to consider the case
+ // of trying to resume a thread that was previously suspended while carrying
+ // a vthread but has already unmounted it.
+ if (!is_virtual && java_thread->is_carrier_thread_suspended()) {
+ bool res = java_thread->clear_carrier_thread_suspended();
+ assert(res, "resume operations running concurrently?");
+ return JVMTI_ERROR_NONE;
}
+
+ if (!java_thread->java_resume(is_virtual && single_resume)) {
+ return JVMTI_ERROR_THREAD_NOT_SUSPENDED;
+ }
+ return JVMTI_ERROR_NONE;
}
- return JVMTI_ERROR_NONE;
}
ResourceTracker::ResourceTracker(JvmtiEnv* env) {
diff --git a/src/hotspot/share/prims/jvmtiImpl.cpp b/src/hotspot/share/prims/jvmtiImpl.cpp
index 9caea2de520..0059636099e 100644
--- a/src/hotspot/share/prims/jvmtiImpl.cpp
+++ b/src/hotspot/share/prims/jvmtiImpl.cpp
@@ -658,7 +658,7 @@ vframe *VM_GetOrSetLocal::get_vframe() {
javaVFrame *VM_GetOrSetLocal::get_java_vframe() {
vframe* vf = get_vframe();
- if (!(_self || _thread->is_carrier_thread_suspended())) {
+ if (!_self && !_thread->is_suspended() && !_thread->is_carrier_thread_suspended()) {
_result = JVMTI_ERROR_THREAD_NOT_SUSPENDED;
return nullptr;
}
diff --git a/src/hotspot/share/prims/jvmtiThreadState.cpp b/src/hotspot/share/prims/jvmtiThreadState.cpp
index b4119825bd3..40d7800de79 100644
--- a/src/hotspot/share/prims/jvmtiThreadState.cpp
+++ b/src/hotspot/share/prims/jvmtiThreadState.cpp
@@ -254,7 +254,10 @@ JvmtiVTMSTransitionDisabler::print_info() {
// disable VTMS transitions for one virtual thread
// disable VTMS transitions for all threads if thread is nullptr or a platform thread
JvmtiVTMSTransitionDisabler::JvmtiVTMSTransitionDisabler(jthread thread)
- : _is_SR(false), _thread(thread)
+ : _is_SR(false),
+ _is_virtual(false),
+ _is_self(false),
+ _thread(thread)
{
if (!Continuations::enabled()) {
return; // JvmtiVTMSTransitionDisabler is no-op without virtual threads
@@ -262,21 +265,26 @@ JvmtiVTMSTransitionDisabler::JvmtiVTMSTransitionDisabler(jthread thread)
if (Thread::current_or_null() == nullptr) {
return; // Detached thread, can be a call from Agent_OnLoad.
}
+ JavaThread* current = JavaThread::current();
+ oop thread_oop = JNIHandles::resolve_external_guard(thread);
+ _is_virtual = java_lang_VirtualThread::is_instance(thread_oop);
+
+ if (thread == nullptr ||
+ (!_is_virtual && thread_oop == current->threadObj()) ||
+ (_is_virtual && thread_oop == current->vthread())) {
+ _is_self = true;
+ return; // no need for current thread to disable and enable transitions for itself
+ }
if (!sync_protocol_enabled_permanently()) {
JvmtiVTMSTransitionDisabler::inc_sync_protocol_enabled_count();
}
- oop thread_oop = JNIHandles::resolve_external_guard(thread);
// Target can be virtual or platform thread.
// If target is a platform thread then we have to disable VTMS transitions for all threads.
// It is by several reasons:
// - carrier threads can mount virtual threads which may cause incorrect behavior
// - there is no mechanism to disable transitions for a specific carrier thread yet
- if (!java_lang_VirtualThread::is_instance(thread_oop)) {
- _thread = nullptr; // target is a platform thread, switch to disabling VTMS transitions for all threads
- }
-
- if (_thread != nullptr) {
+ if (_is_virtual) {
VTMS_transition_disable_for_one(); // disable VTMS transitions for one virtual thread
} else {
VTMS_transition_disable_for_all(); // disable VTMS transitions for all virtual threads
@@ -285,7 +293,10 @@ JvmtiVTMSTransitionDisabler::JvmtiVTMSTransitionDisabler(jthread thread)
// disable VTMS transitions for all virtual threads
JvmtiVTMSTransitionDisabler::JvmtiVTMSTransitionDisabler(bool is_SR)
- : _is_SR(is_SR), _thread(nullptr)
+ : _is_SR(is_SR),
+ _is_virtual(false),
+ _is_self(false),
+ _thread(nullptr)
{
if (!Continuations::enabled()) {
return; // JvmtiVTMSTransitionDisabler is no-op without virtual threads
@@ -309,7 +320,10 @@ JvmtiVTMSTransitionDisabler::~JvmtiVTMSTransitionDisabler() {
if (Thread::current_or_null() == nullptr) {
return; // Detached thread, can be a call from Agent_OnLoad.
}
- if (_thread != nullptr) {
+ if (_is_self) {
+ return; // no need for current thread to disable and enable transitions for itself
+ }
+ if (_is_virtual) {
VTMS_transition_enable_for_one(); // enable VTMS transitions for one virtual thread
} else {
VTMS_transition_enable_for_all(); // enable VTMS transitions for all virtual threads
@@ -684,7 +698,7 @@ JvmtiVTSuspender::_not_suspended_list = new VirtualThreadList();
void
JvmtiVTSuspender::register_all_vthreads_suspend() {
- MonitorLocker ml(JvmtiVTMSTransition_lock);
+ MutexLocker ml(JvmtiVThreadSuspend_lock, Mutex::_no_safepoint_check_flag);
_SR_mode = SR_all;
_suspended_list->invalidate();
@@ -693,7 +707,7 @@ JvmtiVTSuspender::register_all_vthreads_suspend() {
void
JvmtiVTSuspender::register_all_vthreads_resume() {
- MonitorLocker ml(JvmtiVTMSTransition_lock);
+ MutexLocker ml(JvmtiVThreadSuspend_lock, Mutex::_no_safepoint_check_flag);
_SR_mode = SR_none;
_suspended_list->invalidate();
@@ -703,7 +717,7 @@ JvmtiVTSuspender::register_all_vthreads_resume() {
void
JvmtiVTSuspender::register_vthread_suspend(oop vt) {
int64_t id = java_lang_Thread::thread_id(vt);
- MonitorLocker ml(JvmtiVTMSTransition_lock);
+ MutexLocker ml(JvmtiVThreadSuspend_lock, Mutex::_no_safepoint_check_flag);
if (_SR_mode == SR_all) {
assert(_not_suspended_list->contains(id),
@@ -720,7 +734,7 @@ JvmtiVTSuspender::register_vthread_suspend(oop vt) {
void
JvmtiVTSuspender::register_vthread_resume(oop vt) {
int64_t id = java_lang_Thread::thread_id(vt);
- MonitorLocker ml(JvmtiVTMSTransition_lock);
+ MutexLocker ml(JvmtiVThreadSuspend_lock, Mutex::_no_safepoint_check_flag);
if (_SR_mode == SR_all) {
assert(!_not_suspended_list->contains(id),
diff --git a/src/hotspot/share/prims/jvmtiThreadState.hpp b/src/hotspot/share/prims/jvmtiThreadState.hpp
index c9362d5b8cb..53144607a3c 100644
--- a/src/hotspot/share/prims/jvmtiThreadState.hpp
+++ b/src/hotspot/share/prims/jvmtiThreadState.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -86,6 +86,8 @@ class JvmtiVTMSTransitionDisabler {
static volatile bool _sync_protocol_enabled_permanently; // seen a suspender: JvmtiVTMSTransitionDisabler protocol is enabled permanently
bool _is_SR; // is suspender or resumer
+ bool _is_virtual; // target thread is virtual
+ bool _is_self; // JvmtiVTMSTransitionDisabler is a no-op for current platform, carrier or virtual thread
jthread _thread; // virtual thread to disable transitions for, no-op if it is a platform thread
DEBUG_ONLY(static void print_info();)
diff --git a/src/hotspot/share/runtime/handshake.cpp b/src/hotspot/share/runtime/handshake.cpp
index 26d3be7c36a..6bed5e9d546 100644
--- a/src/hotspot/share/runtime/handshake.cpp
+++ b/src/hotspot/share/runtime/handshake.cpp
@@ -28,6 +28,7 @@
#include "logging/log.hpp"
#include "logging/logStream.hpp"
#include "memory/resourceArea.hpp"
+#include "prims/jvmtiThreadState.hpp"
#include "runtime/atomic.hpp"
#include "runtime/globals.hpp"
#include "runtime/handshake.hpp"
@@ -729,7 +730,7 @@ class ThreadSelfSuspensionHandshake : public AsyncHandshakeClosure {
virtual bool is_suspend() { return true; }
};
-bool HandshakeState::suspend_with_handshake() {
+bool HandshakeState::suspend_with_handshake(bool register_vthread_SR) {
assert(_handshakee->threadObj() != nullptr, "cannot suspend with a null threadObj");
if (_handshakee->is_exiting()) {
log_trace(thread, suspend)("JavaThread:" INTPTR_FORMAT " exiting", p2i(_handshakee));
@@ -744,7 +745,7 @@ bool HandshakeState::suspend_with_handshake() {
// Target is going to wake up and leave suspension.
// Let's just stop the thread from doing that.
log_trace(thread, suspend)("JavaThread:" INTPTR_FORMAT " re-suspended", p2i(_handshakee));
- set_suspended(true);
+ set_suspended(true, register_vthread_SR);
return true;
}
}
@@ -752,7 +753,7 @@ bool HandshakeState::suspend_with_handshake() {
assert(!is_suspended(), "cannot be suspended without a suspend request");
// Thread is safe, so it must execute the request, thus we can count it as suspended
// from this point.
- set_suspended(true);
+ set_suspended(true, register_vthread_SR);
set_async_suspend_handshake(true);
log_trace(thread, suspend)("JavaThread:" INTPTR_FORMAT " suspended, arming ThreadSuspension", p2i(_handshakee));
ThreadSelfSuspensionHandshake* ts = new ThreadSelfSuspensionHandshake();
@@ -762,17 +763,19 @@ bool HandshakeState::suspend_with_handshake() {
// This is the closure that synchronously honors the suspend request.
class SuspendThreadHandshake : public HandshakeClosure {
+ bool _register_vthread_SR;
bool _did_suspend;
public:
- SuspendThreadHandshake() : HandshakeClosure("SuspendThread"), _did_suspend(false) {}
+ SuspendThreadHandshake(bool register_vthread_SR) : HandshakeClosure("SuspendThread"),
+ _register_vthread_SR(register_vthread_SR), _did_suspend(false) {}
void do_thread(Thread* thr) {
JavaThread* target = JavaThread::cast(thr);
- _did_suspend = target->handshake_state()->suspend_with_handshake();
+ _did_suspend = target->handshake_state()->suspend_with_handshake(_register_vthread_SR);
}
bool did_suspend() { return _did_suspend; }
};
-bool HandshakeState::suspend() {
+bool HandshakeState::suspend(bool register_vthread_SR) {
JVMTI_ONLY(assert(!_handshakee->is_in_VTMS_transition(), "no suspend allowed in VTMS transition");)
JavaThread* self = JavaThread::current();
if (_handshakee == self) {
@@ -780,31 +783,42 @@ bool HandshakeState::suspend() {
// and just suspend directly
ThreadBlockInVM tbivm(self);
MutexLocker ml(&_lock, Mutex::_no_safepoint_check_flag);
- set_suspended(true);
+ set_suspended(true, register_vthread_SR);
do_self_suspend();
return true;
} else {
- SuspendThreadHandshake st;
+ SuspendThreadHandshake st(register_vthread_SR);
Handshake::execute(&st, _handshakee);
return st.did_suspend();
}
}
-bool HandshakeState::resume() {
- if (!is_suspended()) {
- return false;
- }
+bool HandshakeState::resume(bool register_vthread_SR) {
MutexLocker ml(&_lock, Mutex::_no_safepoint_check_flag);
if (!is_suspended()) {
assert(!_handshakee->is_suspended(), "cannot be suspended without a suspend request");
return false;
}
// Resume the thread.
- set_suspended(false);
+ set_suspended(false, register_vthread_SR);
_lock.notify();
return true;
}
+void HandshakeState::set_suspended(bool is_suspend, bool register_vthread_SR) {
+#if INCLUDE_JVMTI
+ if (register_vthread_SR) {
+ assert(_handshakee->is_vthread_mounted(), "sanity check");
+ if (is_suspend) {
+ JvmtiVTSuspender::register_vthread_suspend(_handshakee->vthread());
+ } else {
+ JvmtiVTSuspender::register_vthread_resume(_handshakee->vthread());
+ }
+ }
+#endif
+ Atomic::store(&_suspended, is_suspend);
+}
+
void HandshakeState::handle_unsafe_access_error() {
if (is_suspended()) {
// A suspend handshake was added to the queue after the
diff --git a/src/hotspot/share/runtime/handshake.hpp b/src/hotspot/share/runtime/handshake.hpp
index f754b744de9..9e963003053 100644
--- a/src/hotspot/share/runtime/handshake.hpp
+++ b/src/hotspot/share/runtime/handshake.hpp
@@ -173,18 +173,18 @@ class HandshakeState {
bool _async_suspend_handshake;
// Called from the suspend handshake.
- bool suspend_with_handshake();
+ bool suspend_with_handshake(bool register_vthread_SR);
// Called from the async handshake (the trap)
// to stop a thread from continuing execution when suspended.
void do_self_suspend();
bool is_suspended() { return Atomic::load(&_suspended); }
- void set_suspended(bool to) { return Atomic::store(&_suspended, to); }
+ void set_suspended(bool to, bool register_vthread_SR);
bool has_async_suspend_handshake() { return _async_suspend_handshake; }
void set_async_suspend_handshake(bool to) { _async_suspend_handshake = to; }
- bool suspend();
- bool resume();
+ bool suspend(bool register_vthread_SR);
+ bool resume(bool register_vthread_SR);
};
#endif // SHARE_RUNTIME_HANDSHAKE_HPP
diff --git a/src/hotspot/share/runtime/javaThread.cpp b/src/hotspot/share/runtime/javaThread.cpp
index 8a6da52d762..9f5dd07c4dc 100644
--- a/src/hotspot/share/runtime/javaThread.cpp
+++ b/src/hotspot/share/runtime/javaThread.cpp
@@ -1193,7 +1193,7 @@ void JavaThread::set_is_VTMS_transition_disabler(bool val) {
// - Target thread will not execute any new bytecode.
// - Target thread will not enter any new monitors.
//
-bool JavaThread::java_suspend() {
+bool JavaThread::java_suspend(bool register_vthread_SR) {
#if INCLUDE_JVMTI
// Suspending a JavaThread in VTMS transition or disabling VTMS transitions can cause deadlocks.
assert(!is_in_VTMS_transition(), "no suspend allowed in VTMS transition");
@@ -1202,13 +1202,13 @@ bool JavaThread::java_suspend() {
guarantee(Thread::is_JavaThread_protected(/* target */ this),
"target JavaThread is not protected in calling context.");
- return this->handshake_state()->suspend();
+ return this->handshake_state()->suspend(register_vthread_SR);
}
-bool JavaThread::java_resume() {
+bool JavaThread::java_resume(bool register_vthread_SR) {
guarantee(Thread::is_JavaThread_protected_by_TLH(/* target */ this),
"missing ThreadsListHandle in calling context.");
- return this->handshake_state()->resume();
+ return this->handshake_state()->resume(register_vthread_SR);
}
// Wait for another thread to perform object reallocation and relocking on behalf of
diff --git a/src/hotspot/share/runtime/javaThread.hpp b/src/hotspot/share/runtime/javaThread.hpp
index 01da26a97e8..8c62319f8dc 100644
--- a/src/hotspot/share/runtime/javaThread.hpp
+++ b/src/hotspot/share/runtime/javaThread.hpp
@@ -698,8 +698,8 @@ private:
// Suspend/resume support for JavaThread
// higher-level suspension/resume logic called by the public APIs
- bool java_suspend();
- bool java_resume();
+ bool java_suspend(bool register_vthread_SR);
+ bool java_resume(bool register_vthread_SR);
bool is_suspended() { return _handshake.is_suspended(); }
// Check for async exception in addition to safepoint.
@@ -710,11 +710,11 @@ private:
void wait_for_object_deoptimization();
#if INCLUDE_JVMTI
- inline void set_carrier_thread_suspended();
- inline void clear_carrier_thread_suspended();
+ inline bool set_carrier_thread_suspended();
+ inline bool clear_carrier_thread_suspended();
bool is_carrier_thread_suspended() const {
- return _carrier_thread_suspended;
+ return Atomic::load(&_carrier_thread_suspended);
}
bool is_in_VTMS_transition() const { return _is_in_VTMS_transition; }
diff --git a/src/hotspot/share/runtime/javaThread.inline.hpp b/src/hotspot/share/runtime/javaThread.inline.hpp
index f434fc161bb..de492fda50b 100644
--- a/src/hotspot/share/runtime/javaThread.inline.hpp
+++ b/src/hotspot/share/runtime/javaThread.inline.hpp
@@ -71,11 +71,11 @@ inline void JavaThread::clear_obj_deopt_flag() {
}
#if INCLUDE_JVMTI
-inline void JavaThread::set_carrier_thread_suspended() {
- _carrier_thread_suspended = true;
+inline bool JavaThread::set_carrier_thread_suspended() {
+ return Atomic::cmpxchg(&_carrier_thread_suspended, false, true) == false;
}
-inline void JavaThread::clear_carrier_thread_suspended() {
- _carrier_thread_suspended = false;
+inline bool JavaThread::clear_carrier_thread_suspended() {
+ return Atomic::cmpxchg(&_carrier_thread_suspended, true, false) == true;
}
#endif
diff --git a/src/hotspot/share/runtime/mutexLocker.cpp b/src/hotspot/share/runtime/mutexLocker.cpp
index 8cb239636d2..74df0fa9188 100644
--- a/src/hotspot/share/runtime/mutexLocker.cpp
+++ b/src/hotspot/share/runtime/mutexLocker.cpp
@@ -50,6 +50,7 @@ Monitor* JNICritical_lock = nullptr;
Mutex* JvmtiThreadState_lock = nullptr;
Monitor* EscapeBarrier_lock = nullptr;
Monitor* JvmtiVTMSTransition_lock = nullptr;
+Mutex* JvmtiVThreadSuspend_lock = nullptr;
Monitor* Heap_lock = nullptr;
#if INCLUDE_PARALLELGC
Mutex* PSOldGenExpand_lock = nullptr;
@@ -260,6 +261,7 @@ void mutex_init() {
MUTEX_DEFN(DirectivesStack_lock , PaddedMutex , nosafepoint);
MUTEX_DEFN(JvmtiVTMSTransition_lock , PaddedMonitor, safepoint); // used for Virtual Thread Mount State transition management
+ MUTEX_DEFN(JvmtiVThreadSuspend_lock , PaddedMutex, nosafepoint-1);
MUTEX_DEFN(EscapeBarrier_lock , PaddedMonitor, nosafepoint); // Used to synchronize object reallocation/relocking triggered by JVMTI
MUTEX_DEFN(Management_lock , PaddedMutex , safepoint); // used for JVM management
diff --git a/src/hotspot/share/runtime/mutexLocker.hpp b/src/hotspot/share/runtime/mutexLocker.hpp
index c307f70ba80..b21a738c8ff 100644
--- a/src/hotspot/share/runtime/mutexLocker.hpp
+++ b/src/hotspot/share/runtime/mutexLocker.hpp
@@ -48,6 +48,7 @@ extern Monitor* JNICritical_lock; // a lock used while synchroniz
extern Mutex* JvmtiThreadState_lock; // a lock on modification of JVMTI thread data
extern Monitor* EscapeBarrier_lock; // a lock to sync reallocating and relocking objects because of JVMTI access
extern Monitor* JvmtiVTMSTransition_lock; // a lock for Virtual Thread Mount State transition (VTMS transition) management
+extern Mutex* JvmtiVThreadSuspend_lock; // a lock for virtual threads suspension
extern Monitor* Heap_lock; // a lock on the heap
#if INCLUDE_PARALLELGC
extern Mutex* PSOldGenExpand_lock; // a lock on expanding the heap
diff --git a/src/hotspot/share/sanitizers/ub.hpp b/src/hotspot/share/sanitizers/ub.hpp
index 66cd014c35c..d5901f6821c 100644
--- a/src/hotspot/share/sanitizers/ub.hpp
+++ b/src/hotspot/share/sanitizers/ub.hpp
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2024 SAP SE. All rights reserved.
+ * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2024, 2025 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -33,7 +33,10 @@
// Useful if the function or method is known to do something special or even 'dangerous', for
// example causing desired signals/crashes.
#ifdef UNDEFINED_BEHAVIOR_SANITIZER
-#if defined(__clang__) || defined(__GNUC__)
+#if defined(__clang__)
+#define ATTRIBUTE_NO_UBSAN __attribute__((no_sanitize("undefined","float-divide-by-zero")))
+#endif
+#if defined(__GNUC__) && !defined(__clang__)
#define ATTRIBUTE_NO_UBSAN __attribute__((no_sanitize("undefined")))
#endif
#endif
diff --git a/src/java.base/share/classes/java/lang/ProcessHandle.java b/src/java.base/share/classes/java/lang/ProcessHandle.java
index 51d13457b3f..750c93c9c57 100644
--- a/src/java.base/share/classes/java/lang/ProcessHandle.java
+++ b/src/java.base/share/classes/java/lang/ProcessHandle.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -89,7 +89,6 @@ import java.util.stream.Stream;
* @see Process
* @since 9
*/
-@jdk.internal.ValueBased
public interface ProcessHandle extends Comparable {
/**
@@ -114,7 +113,7 @@ public interface ProcessHandle extends Comparable {
* @throws UnsupportedOperationException if the implementation
* does not support this operation
*/
- public static Optional of(long pid) {
+ static Optional of(long pid) {
return ProcessHandleImpl.get(pid);
}
@@ -126,7 +125,7 @@ public interface ProcessHandle extends Comparable {
* @throws UnsupportedOperationException if the implementation
* does not support this operation
*/
- public static ProcessHandle current() {
+ static ProcessHandle current() {
return ProcessHandleImpl.current();
}
@@ -204,21 +203,21 @@ public interface ProcessHandle extends Comparable {
* and actions if the value is available.
* @since 9
*/
- public interface Info {
+ interface Info {
/**
* Returns the executable pathname of the process.
*
* @return an {@code Optional} of the executable pathname
* of the process
*/
- public Optional command();
+ Optional command();
/**
* Returns the command line of the process.
*
* If {@link #command command()} and {@link #arguments arguments()} return
* non-empty optionals, this is simply a convenience method which concatenates
- * the values of the two functions separated by spaces. Otherwise it will return a
+ * the values of the two functions separated by spaces. Otherwise, it will return a
* best-effort, platform dependent representation of the command line.
*
* @apiNote Note that the returned executable pathname and the
@@ -233,7 +232,7 @@ public interface ProcessHandle extends Comparable {
* @return an {@code Optional} of the command line
* of the process
*/
- public Optional commandLine();
+ Optional commandLine();
/**
* Returns an array of Strings of the arguments of the process.
@@ -244,28 +243,28 @@ public interface ProcessHandle extends Comparable {
*
* @return an {@code Optional} of the arguments of the process
*/
- public Optional arguments();
+ Optional arguments();
/**
* Returns the start time of the process.
*
* @return an {@code Optional} of the start time of the process
*/
- public Optional startInstant();
+ Optional startInstant();
/**
* Returns the total cputime accumulated of the process.
*
* @return an {@code Optional} for the accumulated total cputime
*/
- public Optional totalCpuDuration();
+ Optional totalCpuDuration();
/**
* Return the user of the process.
*
* @return an {@code Optional} for the user of the process
*/
- public Optional user();
+ Optional user();
}
/**
@@ -285,13 +284,11 @@ public interface ProcessHandle extends Comparable {
* {@link java.util.concurrent.CompletableFuture#isDone done} or to
* {@link java.util.concurrent.Future#get() wait} for it to terminate.
* {@link java.util.concurrent.Future#cancel(boolean) Cancelling}
- * the CompleteableFuture does not affect the Process.
+ * the {@linkplain CompletableFuture CompletableFuture} does not affect the Process.
* @apiNote
* The process may be observed to have terminated with {@link #isAlive}
- * before the ComputableFuture is completed and dependent actions are invoked.
- *
+ * before the {@code CompletableFuture} is completed and dependent actions are invoked.
* @return a new {@code CompletableFuture} for the ProcessHandle
- *
* @throws IllegalStateException if the process is the current process
*/
CompletableFuture onExit();
diff --git a/src/java.base/share/classes/java/lang/StringConcatHelper.java b/src/java.base/share/classes/java/lang/StringConcatHelper.java
index 3b057ecb028..f82e392a1fb 100644
--- a/src/java.base/share/classes/java/lang/StringConcatHelper.java
+++ b/src/java.base/share/classes/java/lang/StringConcatHelper.java
@@ -432,7 +432,7 @@ final class StringConcatHelper {
@ForceInline
static String doConcat(String s1, String s2) {
byte coder = (byte) (s1.coder() | s2.coder());
- int newLength = (s1.length() + s2.length()) << coder;
+ int newLength = checkOverflow(s1.length() + s2.length()) << coder;
byte[] buf = newArray(newLength);
s1.getBytes(buf, 0, coder);
s2.getBytes(buf, s1.length(), coder);
diff --git a/src/java.base/share/classes/java/lang/classfile/CodeBuilder.java b/src/java.base/share/classes/java/lang/classfile/CodeBuilder.java
index 9eafaa2df9c..6b1751476f7 100644
--- a/src/java.base/share/classes/java/lang/classfile/CodeBuilder.java
+++ b/src/java.base/share/classes/java/lang/classfile/CodeBuilder.java
@@ -2483,7 +2483,7 @@ public sealed interface CodeBuilder
var cpArgs = ref.bootstrapArgs();
List bsArguments = new ArrayList<>(cpArgs.length);
for (var constantValue : cpArgs) {
- bsArguments.add(BytecodeHelpers.constantEntry(constantPool(), constantValue));
+ bsArguments.add(constantPool().loadableConstantEntry(requireNonNull(constantValue)));
}
BootstrapMethodEntry bm = constantPool().bsmEntry(bsMethod, bsArguments);
NameAndTypeEntry nameAndType = constantPool().nameAndTypeEntry(ref.invocationName(), ref.invocationType());
@@ -2941,7 +2941,7 @@ public sealed interface CodeBuilder
* @see ConstantInstruction.LoadConstantInstruction
*/
default CodeBuilder ldc(ConstantDesc value) {
- return ldc(BytecodeHelpers.constantEntry(constantPool(), value));
+ return ldc(constantPool().loadableConstantEntry(requireNonNull(value)));
}
/**
diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolBuilder.java b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolBuilder.java
index b7145eeb59c..6b75126a90f 100644
--- a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolBuilder.java
+++ b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolBuilder.java
@@ -36,6 +36,7 @@ import java.lang.invoke.MethodHandleInfo;
import java.util.List;
import java.util.function.Consumer;
+import jdk.internal.classfile.impl.AbstractPoolEntry;
import jdk.internal.classfile.impl.AbstractPoolEntry.ClassEntryImpl;
import jdk.internal.classfile.impl.ClassReaderImpl;
import jdk.internal.classfile.impl.SplitConstantPool;
@@ -385,11 +386,13 @@ public sealed interface ConstantPoolBuilder
default MethodHandleEntry methodHandleEntry(DirectMethodHandleDesc descriptor) {
var owner = classEntry(descriptor.owner());
var nat = nameAndTypeEntry(utf8Entry(descriptor.methodName()), utf8Entry(descriptor.lookupDescriptor()));
- return methodHandleEntry(descriptor.refKind(), switch (descriptor.kind()) {
+ var ret = methodHandleEntry(descriptor.refKind(), switch (descriptor.kind()) {
case GETTER, SETTER, STATIC_GETTER, STATIC_SETTER -> fieldRefEntry(owner, nat);
case INTERFACE_STATIC, INTERFACE_VIRTUAL, INTERFACE_SPECIAL -> interfaceMethodRefEntry(owner, nat);
case STATIC, VIRTUAL, SPECIAL, CONSTRUCTOR -> methodRefEntry(owner, nat);
});
+ ((AbstractPoolEntry.MethodHandleEntryImpl) ret).sym = descriptor;
+ return ret;
}
/**
@@ -414,7 +417,9 @@ public sealed interface ConstantPoolBuilder
* @see InvokeDynamicEntry#asSymbol() InvokeDynamicEntry::asSymbol
*/
default InvokeDynamicEntry invokeDynamicEntry(DynamicCallSiteDesc dcsd) {
- return invokeDynamicEntry(bsmEntry((DirectMethodHandleDesc)dcsd.bootstrapMethod(), List.of(dcsd.bootstrapArgs())), nameAndTypeEntry(dcsd.invocationName(), dcsd.invocationType()));
+ var ret = invokeDynamicEntry(bsmEntry((DirectMethodHandleDesc)dcsd.bootstrapMethod(), List.of(dcsd.bootstrapArgs())), nameAndTypeEntry(dcsd.invocationName(), dcsd.invocationType()));
+ ((AbstractPoolEntry.InvokeDynamicEntryImpl) ret).sym = dcsd;
+ return ret;
}
/**
@@ -440,7 +445,9 @@ public sealed interface ConstantPoolBuilder
* @see ConstantDynamicEntry#asSymbol() ConstantDynamicEntry::asSymbol
*/
default ConstantDynamicEntry constantDynamicEntry(DynamicConstantDesc> dcd) {
- return constantDynamicEntry(bsmEntry(dcd.bootstrapMethod(), List.of(dcd.bootstrapArgs())), nameAndTypeEntry(dcd.constantName(), dcd.constantType()));
+ var ret = constantDynamicEntry(bsmEntry(dcd.bootstrapMethod(), List.of(dcd.bootstrapArgs())), nameAndTypeEntry(dcd.constantName(), dcd.constantType()));
+ ((AbstractPoolEntry.ConstantDynamicEntryImpl) ret).sym = dcd;
+ return ret;
}
/**
diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
index 3251de9bc4b..007834ed5f4 100644
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
@@ -501,7 +501,7 @@ public final class MethodHandles {
*
*
* | {@link java.lang.invoke.MethodHandles.Lookup#findGetter lookup.findGetter(C.class,"f",FT.class)} |
- * {@code FT f;} | {@code (T) this.f;} |
+ * {@code FT f;} | {@code (FT) this.f;} |
*
*
* | {@link java.lang.invoke.MethodHandles.Lookup#findStaticGetter lookup.findStaticGetter(C.class,"f",FT.class)} |
diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractPoolEntry.java b/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractPoolEntry.java
index bf558ddef16..962a2057585 100644
--- a/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractPoolEntry.java
+++ b/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractPoolEntry.java
@@ -295,9 +295,13 @@ public abstract sealed class AbstractPoolEntry {
@Override
public Utf8EntryImpl clone(ConstantPoolBuilder cp) {
- return (state == State.STRING && rawBytes == null)
+ var ret = (state == State.STRING && rawBytes == null)
? (Utf8EntryImpl) cp.utf8Entry(stringValue)
: ((SplitConstantPool) cp).maybeCloneUtf8Entry(this);
+ var mySym = this.typeSym;
+ if (ret.typeSym == null && mySym != null)
+ ret.typeSym = mySym;
+ return ret;
}
@Override
@@ -939,6 +943,8 @@ public abstract sealed class AbstractPoolEntry {
extends AbstractDynamicConstantPoolEntry
implements InvokeDynamicEntry {
+ public @Stable DynamicCallSiteDesc sym;
+
InvokeDynamicEntryImpl(ConstantPool cpm, int index, int hash, BootstrapMethodEntryImpl bootstrapMethod,
NameAndTypeEntryImpl nameAndType) {
super(cpm, index, hash, bootstrapMethod, nameAndType);
@@ -957,13 +963,27 @@ public abstract sealed class AbstractPoolEntry {
@Override
public InvokeDynamicEntry clone(ConstantPoolBuilder cp) {
- return cp.invokeDynamicEntry(bootstrap(), nameAndType());
+ var ret = (InvokeDynamicEntryImpl) cp.invokeDynamicEntry(bootstrap(), nameAndType());
+ var mySym = this.sym;
+ if (ret.sym == null && mySym != null)
+ ret.sym = mySym;
+ return ret;
+ }
+
+ @Override
+ public DynamicCallSiteDesc asSymbol() {
+ var cache = this.sym;
+ if (cache != null)
+ return cache;
+ return this.sym = InvokeDynamicEntry.super.asSymbol();
}
}
public static final class ConstantDynamicEntryImpl extends AbstractDynamicConstantPoolEntry
implements ConstantDynamicEntry {
+ public @Stable DynamicConstantDesc> sym;
+
ConstantDynamicEntryImpl(ConstantPool cpm, int index, int hash, BootstrapMethodEntryImpl bootstrapMethod,
NameAndTypeEntryImpl nameAndType) {
super(cpm, index, hash, bootstrapMethod, nameAndType);
@@ -982,7 +1002,19 @@ public abstract sealed class AbstractPoolEntry {
@Override
public ConstantDynamicEntry clone(ConstantPoolBuilder cp) {
- return cp.constantDynamicEntry(bootstrap(), nameAndType());
+ var ret = (ConstantDynamicEntryImpl) cp.constantDynamicEntry(bootstrap(), nameAndType());
+ var mySym = this.sym;
+ if (ret.sym == null && mySym != null)
+ ret.sym = mySym;
+ return ret;
+ }
+
+ @Override
+ public DynamicConstantDesc> asSymbol() {
+ var cache = this.sym;
+ if (cache != null)
+ return cache;
+ return this.sym = ConstantDynamicEntry.super.asSymbol();
}
}
@@ -991,6 +1023,7 @@ public abstract sealed class AbstractPoolEntry {
private final int refKind;
private final AbstractPoolEntry.AbstractMemberRefEntry reference;
+ public @Stable DirectMethodHandleDesc sym;
MethodHandleEntryImpl(ConstantPool cpm, int index, int hash, int refKind, AbstractPoolEntry.AbstractMemberRefEntry
reference) {
@@ -1023,7 +1056,14 @@ public abstract sealed class AbstractPoolEntry {
@Override
public DirectMethodHandleDesc asSymbol() {
- return MethodHandleDesc.of(
+ var cache = this.sym;
+ if (cache != null)
+ return cache;
+ return computeSymbol();
+ }
+
+ private DirectMethodHandleDesc computeSymbol() {
+ return this.sym = MethodHandleDesc.of(
DirectMethodHandleDesc.Kind.valueOf(kind(), reference() instanceof InterfaceMethodRefEntry),
((MemberRefEntry) reference()).owner().asSymbol(),
((MemberRefEntry) reference()).nameAndType().name().stringValue(),
@@ -1037,7 +1077,11 @@ public abstract sealed class AbstractPoolEntry {
@Override
public MethodHandleEntry clone(ConstantPoolBuilder cp) {
- return cp.methodHandleEntry(refKind, reference);
+ var ret = (MethodHandleEntryImpl) cp.methodHandleEntry(refKind, reference);
+ var mySym = this.sym;
+ if (ret.sym == null && mySym != null)
+ ret.sym = mySym;
+ return ret;
}
@Override
diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/BytecodeHelpers.java b/src/java.base/share/classes/jdk/internal/classfile/impl/BytecodeHelpers.java
index 25daf4e4648..a51728eb3e9 100644
--- a/src/java.base/share/classes/jdk/internal/classfile/impl/BytecodeHelpers.java
+++ b/src/java.base/share/classes/jdk/internal/classfile/impl/BytecodeHelpers.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, Alibaba Group Holding Limited. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -29,12 +29,10 @@ import java.lang.classfile.BootstrapMethodEntry;
import java.lang.classfile.Opcode;
import java.lang.classfile.TypeKind;
import java.lang.classfile.constantpool.*;
-import java.lang.constant.ClassDesc;
import java.lang.constant.ConstantDesc;
import java.lang.constant.ConstantDescs;
import java.lang.constant.DirectMethodHandleDesc;
import java.lang.constant.DynamicConstantDesc;
-import java.lang.constant.MethodTypeDesc;
import java.lang.invoke.MethodHandleInfo;
import java.util.ArrayList;
import java.util.List;
@@ -515,38 +513,6 @@ public class BytecodeHelpers {
: Opcode.LDC;
}
- public static LoadableConstantEntry constantEntry(ConstantPoolBuilder constantPool,
- ConstantDesc constantValue) {
- // this method is invoked during JVM bootstrap - cannot use pattern switch
- if (constantValue instanceof Integer value) {
- return constantPool.intEntry(value);
- }
- if (constantValue instanceof String value) {
- return constantPool.stringEntry(value);
- }
- if (constantValue instanceof ClassDesc value && !value.isPrimitive()) {
- return constantPool.classEntry(value);
- }
- if (constantValue instanceof Long value) {
- return constantPool.longEntry(value);
- }
- if (constantValue instanceof Float value) {
- return constantPool.floatEntry(value);
- }
- if (constantValue instanceof Double value) {
- return constantPool.doubleEntry(value);
- }
- if (constantValue instanceof MethodTypeDesc value) {
- return constantPool.methodTypeEntry(value);
- }
- if (constantValue instanceof DirectMethodHandleDesc value) {
- return handleDescToHandleInfo(constantPool, value);
- } if (constantValue instanceof DynamicConstantDesc> value) {
- return handleConstantDescToHandleInfo(constantPool, value);
- }
- throw new UnsupportedOperationException("not yet: " + requireNonNull(constantValue));
- }
-
public static ConstantDesc intrinsicConstantValue(Opcode opcode) {
return switch (opcode) {
case ACONST_NULL -> ConstantDescs.NULL;
diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/SplitConstantPool.java b/src/java.base/share/classes/jdk/internal/classfile/impl/SplitConstantPool.java
index 2ea6fa943a7..5a5f2908ae6 100644
--- a/src/java.base/share/classes/jdk/internal/classfile/impl/SplitConstantPool.java
+++ b/src/java.base/share/classes/jdk/internal/classfile/impl/SplitConstantPool.java
@@ -30,6 +30,7 @@ import java.lang.classfile.ClassReader;
import java.lang.classfile.attribute.BootstrapMethodsAttribute;
import java.lang.classfile.constantpool.*;
import java.lang.constant.ClassDesc;
+import java.lang.constant.DynamicCallSiteDesc;
import java.lang.constant.MethodTypeDesc;
import java.util.Arrays;
import java.util.List;
@@ -521,6 +522,10 @@ public final class SplitConstantPool implements ConstantPoolBuilder {
AbstractPoolEntry.ClassEntryImpl cloneClassEntry(AbstractPoolEntry.ClassEntryImpl e) {
var ce = tryFindClassEntry(e.hashCode(), e.ref1);
if (ce != null) {
+ var mySym = e.sym;
+ if (ce.sym == null && mySym != null) {
+ ce.sym = mySym;
+ }
return ce;
}
diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/StackMapGenerator.java b/src/java.base/share/classes/jdk/internal/classfile/impl/StackMapGenerator.java
index 7e16aea5a52..eb17e99a94d 100644
--- a/src/java.base/share/classes/jdk/internal/classfile/impl/StackMapGenerator.java
+++ b/src/java.base/share/classes/jdk/internal/classfile/impl/StackMapGenerator.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, Alibaba Group Holding Limited. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -716,7 +716,7 @@ public final class StackMapGenerator {
case TAG_METHOD_TYPE ->
currentFrame.pushStack(Type.METHOD_TYPE);
case TAG_DYNAMIC ->
- currentFrame.pushStack(cp.entryByIndex(index, ConstantDynamicEntry.class).asSymbol().constantType());
+ currentFrame.pushStack(cp.entryByIndex(index, ConstantDynamicEntry.class).typeSymbol());
default ->
throw generatorError("CP entry #%d %s is not loadable constant".formatted(index, cp.entryByIndex(index).tag()));
}
diff --git a/src/java.base/share/classes/sun/launcher/resources/launcher.properties b/src/java.base/share/classes/sun/launcher/resources/launcher.properties
index e8dc89161fd..5ed1ca2bfbc 100644
--- a/src/java.base/share/classes/sun/launcher/resources/launcher.properties
+++ b/src/java.base/share/classes/sun/launcher/resources/launcher.properties
@@ -154,7 +154,7 @@ java.launcher.X.usage=\n\
\ -Xmixed mixed mode execution (default)\n\
\ -Xmn sets the initial and maximum size (in bytes) of the heap\n\
\ for the young generation (nursery)\n\
-\ -Xms set initial Java heap size\n\
+\ -Xms set minimum and initial Java heap size\n\
\ -Xmx set maximum Java heap size\n\
\ -Xnoclassgc disable class garbage collection\n\
\ -Xrs reduce use of OS signals by Java/VM (see documentation)\n\
diff --git a/src/java.base/share/classes/sun/security/util/Debug.java b/src/java.base/share/classes/sun/security/util/Debug.java
index 74d33c036ef..f6c0c523165 100644
--- a/src/java.base/share/classes/sun/security/util/Debug.java
+++ b/src/java.base/share/classes/sun/security/util/Debug.java
@@ -31,8 +31,6 @@ import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.HexFormat;
-import java.util.regex.Pattern;
-import java.util.regex.Matcher;
import java.util.Locale;
/**
@@ -65,7 +63,7 @@ public class Debug {
}
if (args != null) {
- args = marshal(args);
+ args = args.toLowerCase(Locale.ENGLISH);
if (args.equals("help")) {
Help();
} else if (args.contains("all")) {
@@ -349,69 +347,6 @@ public class Debug {
return sb.toString();
}
- /**
- * change a string into lower case except permission classes and URLs.
- */
- private static String marshal(String args) {
- if (args != null) {
- StringBuilder target = new StringBuilder();
- StringBuilder source = new StringBuilder(args);
-
- // obtain the "permission=" options
- // the syntax of classname: IDENTIFIER.IDENTIFIER
- // the regular express to match a class name:
- // "[a-zA-Z_$][a-zA-Z0-9_$]*([.][a-zA-Z_$][a-zA-Z0-9_$]*)*"
- String keyReg = "[Pp][Ee][Rr][Mm][Ii][Ss][Ss][Ii][Oo][Nn]=";
- String keyStr = "permission=";
- String reg = keyReg +
- "[a-zA-Z_$][a-zA-Z0-9_$]*([.][a-zA-Z_$][a-zA-Z0-9_$]*)*";
- Pattern pattern = Pattern.compile(reg);
- Matcher matcher = pattern.matcher(source);
- StringBuilder left = new StringBuilder();
- while (matcher.find()) {
- String matched = matcher.group();
- target.append(matched.replaceFirst(keyReg, keyStr));
- target.append(" ");
-
- // delete the matched sequence
- matcher.appendReplacement(left, "");
- }
- matcher.appendTail(left);
- source = left;
-
- // obtain the "codebase=" options
- // the syntax of URL is too flexible, and here assumes that the
- // URL contains no space, comma(','), and semicolon(';'). That
- // also means those characters also could be used as separator
- // after codebase option.
- // However, the assumption is incorrect in some special situation
- // when the URL contains comma or semicolon
- keyReg = "[Cc][Oo][Dd][Ee][Bb][Aa][Ss][Ee]=";
- keyStr = "codebase=";
- reg = keyReg + "[^, ;]*";
- pattern = Pattern.compile(reg);
- matcher = pattern.matcher(source);
- left = new StringBuilder();
- while (matcher.find()) {
- String matched = matcher.group();
- target.append(matched.replaceFirst(keyReg, keyStr));
- target.append(" ");
-
- // delete the matched sequence
- matcher.appendReplacement(left, "");
- }
- matcher.appendTail(left);
- source = left;
-
- // convert the rest to lower-case characters
- target.append(source.toString().toLowerCase(Locale.ENGLISH));
-
- return target.toString();
- }
-
- return null;
- }
-
public static String toString(byte[] b) {
if (b == null) {
return "(null)";
diff --git a/src/java.base/share/classes/sun/util/resources/CurrencyNames.properties b/src/java.base/share/classes/sun/util/resources/CurrencyNames.properties
index 7e6acccf6e5..d2d9ff1035b 100644
--- a/src/java.base/share/classes/sun/util/resources/CurrencyNames.properties
+++ b/src/java.base/share/classes/sun/util/resources/CurrencyNames.properties
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -261,6 +261,7 @@ VES=VES
VND=VND
VUV=VUV
WST=WST
+XAD=XAD
XAF=XAF
XAG=XAG
XAU=XAU
@@ -488,6 +489,7 @@ ves=Venezuelan Bolívar Soberano
vnd=Vietnamese Dong
vuv=Vanuatu Vatu
wst=Samoan Tala
+xad=Arab Accounting Dinar
xaf=CFA Franc BEAC
xag=Silver
xau=Gold
diff --git a/src/java.base/share/data/currency/CurrencyData.properties b/src/java.base/share/data/currency/CurrencyData.properties
index 5a28abccd00..ff2d1f87ed3 100644
--- a/src/java.base/share/data/currency/CurrencyData.properties
+++ b/src/java.base/share/data/currency/CurrencyData.properties
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -32,7 +32,7 @@ formatVersion=3
# Version of the currency code information in this class.
# It is a serial number that accompanies with each amendment.
-dataVersion=177
+dataVersion=179
# List of all valid ISO 4217 currency codes.
# To ensure compatibility, do not remove codes.
@@ -54,7 +54,7 @@ all=ADP020-AED784-AFA004-AFN971-ALL008-AMD051-ANG532-AOA973-ARS032-ATS040-AUD036
SBD090-SCR690-SDD736-SDG938-SEK752-SGD702-SHP654-SIT705-SKK703-SLE925-SLL694-SOS706-\
SRD968-SRG740-SSP728-STD678-STN930-SVC222-SYP760-SZL748-THB764-TJS972-TMM795-TMT934-TND788-TOP776-\
TPE626-TRL792-TRY949-TTD780-TWD901-TZS834-UAH980-UGX800-USD840-USN997-USS998-UYI940-\
- UYU858-UZS860-VEB862-VED926-VEF937-VES928-VND704-VUV548-WST882-XAF950-XAG961-XAU959-XBA955-\
+ UYU858-UZS860-VEB862-VED926-VEF937-VES928-VND704-VUV548-WST882-XAD396-XAF950-XAG961-XAU959-XBA955-\
XBB956-XBC957-XBD958-XCD951-XCG532-XDR960-XFO000-XFU000-XOF952-XPD964-XPF953-\
XPT962-XSU994-XTS963-XUA965-XXX999-YER886-YUM891-ZAR710-ZMK894-ZMW967-ZWD716-ZWG924-\
ZWL932-ZWN942-ZWR935
diff --git a/src/java.base/share/native/libjava/ub.h b/src/java.base/share/native/libjava/ub.h
index d6e0cac3bea..3019e672694 100644
--- a/src/java.base/share/native/libjava/ub.h
+++ b/src/java.base/share/native/libjava/ub.h
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2024 SAP SE. All rights reserved.
+ * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2024, 2025 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -32,7 +32,10 @@
* following function or method.
*/
#ifdef UNDEFINED_BEHAVIOR_SANITIZER
-#if defined(__clang__) || defined(__GNUC__)
+#if defined(__clang__)
+#define ATTRIBUTE_NO_UBSAN __attribute__((no_sanitize("undefined","float-divide-by-zero")))
+#endif
+#if defined(__GNUC__) && !defined(__clang__)
#define ATTRIBUTE_NO_UBSAN __attribute__((no_sanitize("undefined")))
#endif
#endif
diff --git a/src/java.compiler/share/classes/javax/lang/model/SourceVersion.java b/src/java.compiler/share/classes/javax/lang/model/SourceVersion.java
index 9260ce532f1..6bc1dab1f8a 100644
--- a/src/java.compiler/share/classes/javax/lang/model/SourceVersion.java
+++ b/src/java.compiler/share/classes/javax/lang/model/SourceVersion.java
@@ -81,6 +81,8 @@ public enum SourceVersion {
* switch in second preview, module Import Declarations in second
* preview, simple source files and instance main in fourth
* preview, flexible constructor bodies in third preview)
+ * 25: module import declarations, compact source files and
+ * instance main methods,
*/
/**
@@ -449,11 +451,18 @@ public enum SourceVersion {
* The version introduced by the Java Platform, Standard Edition
* 25.
*
+ * Additions in this release include module import declarations
+ * and compact source files and instance main methods.
+ *
* @since 25
*
* @see
* The Java Language Specification, Java SE 25 Edition
+ * @see
+ * JEP 511: Module Import Declarations
+ * @see
+ * JEP 512: Compact Source Files and Instance Main Methods
*/
RELEASE_25,
; // Reduce code churn when appending new constants
diff --git a/src/java.compiler/share/classes/javax/lang/model/util/Elements.java b/src/java.compiler/share/classes/javax/lang/model/util/Elements.java
index 7f0b493572e..5d97674c53d 100644
--- a/src/java.compiler/share/classes/javax/lang/model/util/Elements.java
+++ b/src/java.compiler/share/classes/javax/lang/model/util/Elements.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -778,6 +778,12 @@ public interface Elements {
* elements.getTypeElement("I"));
* }
*
+ * @apiNote This method examines the method's name, signature, subclass relationship, and accessibility
+ * in determining whether one method overrides another, as specified in JLS {@jls 8.4.8.1}.
+ * In addition, an implementation may have stricter checks including method modifiers, return types and
+ * exception types as described in JLS {@jls 8.4.8.1} and {@jls 8.4.8.3}.
+ * Note that such additional compile-time checks are not guaranteed and may vary between implementations.
+ *
* @param overrider the first method, possible overrider
* @param overridden the second method, possibly being overridden
* @param type the class or interface of which the first method is a member
diff --git a/src/java.desktop/macosx/native/libjsound/PLATFORM_API_MacOSX_Ports.cpp b/src/java.desktop/macosx/native/libjsound/PLATFORM_API_MacOSX_Ports.cpp
index bf4f2e143a0..ae0ffa5f2ca 100644
--- a/src/java.desktop/macosx/native/libjsound/PLATFORM_API_MacOSX_Ports.cpp
+++ b/src/java.desktop/macosx/native/libjsound/PLATFORM_API_MacOSX_Ports.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -124,9 +124,12 @@ OSStatus ChangeListenerProc(AudioObjectID inObjectID, UInt32 inNumberAddresses,
kAudioHardwarePropertyDevices, &size);
if (err == noErr) {
int count = size/sizeof(AudioDeviceID);
- AudioDeviceID devices[count];
+ AudioDeviceID *devices = (AudioDeviceID *) malloc(size);
+ if (!devices) {
+ break;
+ }
err = GetAudioObjectProperty(kAudioObjectSystemObject, kAudioObjectPropertyScopeGlobal,
- kAudioHardwarePropertyDevices, count*sizeof(AudioDeviceID), devices, 1);
+ kAudioHardwarePropertyDevices, size, devices, 1);
if (err == noErr) {
bool found = false;
for (int j = 0; j < count; j++) {
@@ -139,6 +142,7 @@ OSStatus ChangeListenerProc(AudioObjectID inObjectID, UInt32 inNumberAddresses,
invalid = true;
}
}
+ free(devices);
}
break;
case kAudioObjectPropertyOwnedObjects:
@@ -148,9 +152,12 @@ OSStatus ChangeListenerProc(AudioObjectID inObjectID, UInt32 inNumberAddresses,
kAudioObjectPropertyOwnedObjects, &size);
if (err == noErr) {
int count = size / sizeof(AudioObjectID);
- AudioObjectID controlIDs[count];
+ AudioObjectID *controlIDs = (AudioObjectID *) malloc(size);
+ if (!controlIDs) {
+ break;
+ }
err = GetAudioObjectProperty(mixer->deviceID, kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyOwnedObjects, count * sizeof(AudioObjectID), &controlIDs, 1);
+ kAudioObjectPropertyOwnedObjects, size, controlIDs, 1);
if (err == noErr) {
for (PortControl *ctrl = mixer->portControls; ctrl != NULL; ctrl = ctrl->next) {
for (int i = 0; i < ctrl->controlCount; i++) {
@@ -168,6 +175,7 @@ OSStatus ChangeListenerProc(AudioObjectID inObjectID, UInt32 inNumberAddresses,
}
}
}
+ free(controlIDs);
}
}
}
@@ -229,6 +237,9 @@ INT32 PORT_GetPortMixerDescription(INT32 mixerIndex, PortMixerDescription* mixer
void* PORT_Open(INT32 mixerIndex) {
TRACE1("\n>>PORT_Open (mixerIndex=%d)\n", (int)mixerIndex);
PortMixer *mixer = (PortMixer *)calloc(1, sizeof(PortMixer));
+ if (!mixer) {
+ return nullptr;
+ }
mixer->deviceID = deviceCache.GetDeviceID(mixerIndex);
if (mixer->deviceID != 0) {
@@ -480,16 +491,20 @@ void PORT_GetControls(void* id, INT32 portIndex, PortControlCreator* creator) {
mixer->deviceControlCount = size / sizeof(AudioObjectID);
TRACE1(" PORT_GetControls: detected %d owned objects\n", mixer->deviceControlCount);
- AudioObjectID controlIDs[mixer->deviceControlCount];
+ AudioObjectID *controlIDs = (AudioObjectID *) malloc(size);
+ if (!controlIDs) {
+ return;
+ }
err = GetAudioObjectProperty(mixer->deviceID, kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyOwnedObjects, sizeof(controlIDs), controlIDs, 1);
+ kAudioObjectPropertyOwnedObjects, size, controlIDs, 1);
if (err) {
OS_ERROR1(err, "PORT_GetControls (portIndex = %d) get OwnedObject values", portIndex);
} else {
mixer->deviceControls = (AudioControl *)calloc(mixer->deviceControlCount, sizeof(AudioControl));
if (mixer->deviceControls == NULL) {
+ free(controlIDs);
return;
}
@@ -513,6 +528,7 @@ void PORT_GetControls(void* id, INT32 portIndex, PortControlCreator* creator) {
control->controlID, FourCC2Str(control->classID), FourCC2Str(control->scope), control->channel);
}
}
+ free(controlIDs);
}
}
@@ -524,10 +540,14 @@ void PORT_GetControls(void* id, INT32 portIndex, PortControlCreator* creator) {
int totalChannels = GetChannelCount(mixer->deviceID, port->scope == kAudioDevicePropertyScopeOutput ? 1 : 0);
// collect volume and mute controls
- AudioControl* volumeControls[totalChannels+1]; // 0 - for master channel
- memset(&volumeControls, 0, sizeof(AudioControl *) * (totalChannels+1));
- AudioControl* muteControls[totalChannels+1]; // 0 - for master channel
- memset(&muteControls, 0, sizeof(AudioControl *) * (totalChannels+1));
+ size_t totalAndMaster = totalChannels + 1; // 0 - for master channel
+ AudioControl **volumeControls = (AudioControl **) calloc(totalAndMaster, sizeof(AudioControl *));
+ AudioControl **muteControls = (AudioControl **) calloc(totalAndMaster, sizeof(AudioControl *));
+ if (!volumeControls || !muteControls) {
+ free(muteControls);
+ free(volumeControls);
+ return;
+ }
for (int i=0; ideviceControlCount; i++) {
AudioControl *control = &mixer->deviceControls[i];
@@ -626,6 +646,8 @@ void PORT_GetControls(void* id, INT32 portIndex, PortControlCreator* creator) {
CFIndex length = CFStringGetLength(cfname) + 1;
channelName = (char *)malloc(length);
if (channelName == NULL) {
+ free(muteControls);
+ free(volumeControls);
return;
}
CFStringGetCString(cfname, channelName, length, kCFStringEncodingUTF8);
@@ -633,6 +655,8 @@ void PORT_GetControls(void* id, INT32 portIndex, PortControlCreator* creator) {
} else {
channelName = (char *)malloc(16);
if (channelName == NULL) {
+ free(muteControls);
+ free(volumeControls);
return;
}
snprintf(channelName, 16, "Ch %d", ch);
@@ -657,7 +681,8 @@ void PORT_GetControls(void* id, INT32 portIndex, PortControlCreator* creator) {
}
AddChangeListeners(mixer);
-
+ free(muteControls);
+ free(volumeControls);
TRACE1("<controlCount];
+ Float32 *subVolumes = (Float32 *) malloc(control->controlCount * sizeof(Float32));
+ if (!subVolumes) {
+ return DEFAULT_VOLUME_VALUE;
+ }
Float32 maxVolume;
switch (control->type) {
case PortControl::Volume:
if (!TestPortControlValidity(control)) {
- return DEFAULT_VOLUME_VALUE;
+ result = DEFAULT_VOLUME_VALUE;
+ break;
}
if (!GetPortControlVolumes(control, subVolumes, &maxVolume)) {
- return DEFAULT_VOLUME_VALUE;
+ result = DEFAULT_VOLUME_VALUE;
+ break;
}
result = maxVolume;
break;
case PortControl::Balance:
if (!TestPortControlValidity(control)) {
- return DEFAULT_BALANCE_VALUE;
+ result = DEFAULT_BALANCE_VALUE;
+ break;
}
// balance control always has 2 volume controls
if (!GetPortControlVolumes(control, subVolumes, &maxVolume)) {
- return DEFAULT_VOLUME_VALUE;
+ result = DEFAULT_VOLUME_VALUE;
+ break;
}
// calculate balance value
if (subVolumes[0] > subVolumes[1]) {
@@ -806,9 +838,10 @@ float PORT_GetFloatValue(void* controlIDV) {
break;
default:
ERROR1("GetFloatValue requested for non-Float control (control-type == %d)\n", control->type);
- return 0;
+ result = 0;
+ break;
}
-
+ free(subVolumes);
TRACE1("<controlCount];
+ Float32 *subVolumes = (Float32 *) malloc(sizeof(Float32) * control->controlCount);
+ if (!subVolumes) {
+ return;
+ }
Float32 maxVolume;
switch (control->type) {
case PortControl::Volume:
if (!GetPortControlVolumes(control, subVolumes, &maxVolume)) {
- return;
+ break;
}
// update the values
if (maxVolume > 0.001) {
@@ -845,7 +881,7 @@ void PORT_SetFloatValue(void* controlIDV, float value) {
case PortControl::Balance:
// balance control always has 2 volume controls
if (!GetPortControlVolumes(control, subVolumes, &maxVolume)) {
- return;
+ break;
}
// calculate new values
if (value < 0.0f) {
@@ -861,8 +897,9 @@ void PORT_SetFloatValue(void* controlIDV, float value) {
break;
default:
ERROR1("PORT_SetFloatValue requested for non-Float control (control-type == %d)\n", control->type);
- return;
+ break;
}
+ free(subVolumes);
}
#endif // USE_PORTS
diff --git a/src/java.desktop/share/classes/sun/print/PSPrinterJob.java b/src/java.desktop/share/classes/sun/print/PSPrinterJob.java
index 7404c6c3948..03fdb532b71 100644
--- a/src/java.desktop/share/classes/sun/print/PSPrinterJob.java
+++ b/src/java.desktop/share/classes/sun/print/PSPrinterJob.java
@@ -127,24 +127,6 @@ public class PSPrinterJob extends RasterPrinterJob {
*/
private static final int MAX_PSSTR = (1024 * 64 - 1);
- private static final int RED_MASK = 0x00ff0000;
- private static final int GREEN_MASK = 0x0000ff00;
- private static final int BLUE_MASK = 0x000000ff;
-
- private static final int RED_SHIFT = 16;
- private static final int GREEN_SHIFT = 8;
- private static final int BLUE_SHIFT = 0;
-
- private static final int LOWNIBBLE_MASK = 0x0000000f;
- private static final int HINIBBLE_MASK = 0x000000f0;
- private static final int HINIBBLE_SHIFT = 4;
- private static final byte[] hexDigits = {
- (byte)'0', (byte)'1', (byte)'2', (byte)'3',
- (byte)'4', (byte)'5', (byte)'6', (byte)'7',
- (byte)'8', (byte)'9', (byte)'A', (byte)'B',
- (byte)'C', (byte)'D', (byte)'E', (byte)'F'
- };
-
private static final int PS_XRES = 300;
private static final int PS_YRES = 300;
@@ -267,14 +249,6 @@ public class PSPrinterJob extends RasterPrinterJob {
private double xres = PS_XRES;
private double yres = PS_YRES;
- /* non-null if printing EPS for Java Plugin */
- private EPSPrinter epsPrinter = null;
-
- /**
- * The metrics for the font currently set.
- */
- FontMetrics mCurMetrics;
-
/**
* The output stream to which the generated PostScript
* is written.
@@ -513,46 +487,43 @@ public class PSPrinterJob extends RasterPrinterJob {
OutputStream output = null;
- if (epsPrinter == null) {
- if (getPrintService() instanceof PSStreamPrintService) {
- StreamPrintService sps = (StreamPrintService)getPrintService();
- mDestType = RasterPrinterJob.STREAM;
- if (sps.isDisposed()) {
- throw new PrinterException("service is disposed");
- }
- output = sps.getOutputStream();
- if (output == null) {
- throw new PrinterException("Null output stream");
+ if (getPrintService() instanceof PSStreamPrintService) {
+ StreamPrintService sps = (StreamPrintService)getPrintService();
+ mDestType = RasterPrinterJob.STREAM;
+ if (sps.isDisposed()) {
+ throw new PrinterException("service is disposed");
+ }
+ output = sps.getOutputStream();
+ if (output == null) {
+ throw new PrinterException("Null output stream");
+ }
+ } else {
+ /* REMIND: This needs to be more maintainable */
+ mNoJobSheet = super.noJobSheet;
+ if (super.destinationAttr != null) {
+ mDestType = RasterPrinterJob.FILE;
+ mDestination = super.destinationAttr;
+ }
+ if (mDestType == RasterPrinterJob.FILE) {
+ try {
+ spoolFile = new File(mDestination);
+ output = new FileOutputStream(spoolFile);
+ } catch (IOException ex) {
+ abortDoc();
+ throw new PrinterIOException(ex);
}
} else {
- /* REMIND: This needs to be more maintainable */
- mNoJobSheet = super.noJobSheet;
- if (super.destinationAttr != null) {
- mDestType = RasterPrinterJob.FILE;
- mDestination = super.destinationAttr;
- }
- if (mDestType == RasterPrinterJob.FILE) {
- try {
- spoolFile = new File(mDestination);
- output = new FileOutputStream(spoolFile);
- } catch (IOException ex) {
- abortDoc();
- throw new PrinterIOException(ex);
- }
- } else {
- PrinterOpener po = new PrinterOpener();
- po.run();
- if (po.pex != null) {
- throw po.pex;
- }
- output = po.result;
+ PrinterOpener po = new PrinterOpener();
+ po.run();
+ if (po.pex != null) {
+ throw po.pex;
}
+ output = po.result;
}
-
- mPSStream = new PrintStream(new BufferedOutputStream(output));
- mPSStream.println(ADOBE_PS_STR);
}
+ mPSStream = new PrintStream(new BufferedOutputStream(output));
+ mPSStream.println(ADOBE_PS_STR);
mPSStream.println("%%BeginProlog");
mPSStream.println(READIMAGEPROC);
mPSStream.println("/BD {bind def} bind def");
@@ -619,45 +590,43 @@ public class PSPrinterJob extends RasterPrinterJob {
mPSStream.println("%%EndProlog");
mPSStream.println("%%BeginSetup");
- if (epsPrinter == null) {
- // Set Page Size using first page's format.
- PageFormat pageFormat = getPageable().getPageFormat(0);
- double paperHeight = pageFormat.getPaper().getHeight();
- double paperWidth = pageFormat.getPaper().getWidth();
+ // Set Page Size using first page's format.
+ PageFormat pageFormat = getPageable().getPageFormat(0);
+ double paperHeight = pageFormat.getPaper().getHeight();
+ double paperWidth = pageFormat.getPaper().getWidth();
- /* PostScript printers can always generate uncollated copies.
- */
- mPSStream.print("<< /PageSize [" +
- paperWidth + " "+ paperHeight+"]");
+ /* PostScript printers can always generate uncollated copies.
+ */
+ mPSStream.print("<< /PageSize [" +
+ paperWidth + " "+ paperHeight+"]");
- final PrintService pservice = getPrintService();
- Boolean isPS = Boolean.TRUE;
- try {
- Class> psClass = Class.forName("sun.print.IPPPrintService");
- if (psClass.isInstance(pservice)) {
- Method isPSMethod = psClass.getMethod("isPostscript",
- (Class[])null);
- isPS = (Boolean)isPSMethod.invoke(pservice, (Object[])null);
- }
- } catch (Throwable t) {
+ final PrintService pservice = getPrintService();
+ Boolean isPS = Boolean.TRUE;
+ try {
+ Class> psClass = Class.forName("sun.print.IPPPrintService");
+ if (psClass.isInstance(pservice)) {
+ Method isPSMethod = psClass.getMethod("isPostscript",
+ (Class[])null);
+ isPS = (Boolean)isPSMethod.invoke(pservice, (Object[])null);
}
- if (isPS) {
- mPSStream.print(" /DeferredMediaSelection true");
- }
-
- mPSStream.print(" /ImagingBBox null /ManualFeed false");
- mPSStream.print(isCollated() ? " /Collate true":"");
- mPSStream.print(" /NumCopies " +getCopiesInt());
-
- if (sidesAttr != Sides.ONE_SIDED) {
- if (sidesAttr == Sides.TWO_SIDED_LONG_EDGE) {
- mPSStream.print(" /Duplex true ");
- } else if (sidesAttr == Sides.TWO_SIDED_SHORT_EDGE) {
- mPSStream.print(" /Duplex true /Tumble true ");
- }
- }
- mPSStream.println(" >> setpagedevice ");
+ } catch (Throwable t) {
}
+ if (isPS) {
+ mPSStream.print(" /DeferredMediaSelection true");
+ }
+
+ mPSStream.print(" /ImagingBBox null /ManualFeed false");
+ mPSStream.print(isCollated() ? " /Collate true":"");
+ mPSStream.print(" /NumCopies " +getCopiesInt());
+
+ if (sidesAttr != Sides.ONE_SIDED) {
+ if (sidesAttr == Sides.TWO_SIDED_LONG_EDGE) {
+ mPSStream.print(" /Duplex true ");
+ } else if (sidesAttr == Sides.TWO_SIDED_SHORT_EDGE) {
+ mPSStream.print(" /Duplex true /Tumble true ");
+ }
+ }
+ mPSStream.println(" >> setpagedevice ");
mPSStream.println("%%EndSetup");
}
@@ -1175,36 +1144,6 @@ public class PSPrinterJob extends RasterPrinterJob {
return psFont;
}
-
- private static String escapeParens(String str) {
- if (str.indexOf('(') == -1 && str.indexOf(')') == -1 ) {
- return str;
- } else {
- int count = 0;
- int pos = 0;
- while ((pos = str.indexOf('(', pos)) != -1) {
- count++;
- pos++;
- }
- pos = 0;
- while ((pos = str.indexOf(')', pos)) != -1) {
- count++;
- pos++;
- }
- char []inArr = str.toCharArray();
- char []outArr = new char[inArr.length+count];
- pos = 0;
- for (int i=0;i 0) {
- return Printable.NO_SUCH_PAGE;
- } else {
- // "aware" client code can detect that its been passed a
- // PrinterGraphics and could theoretically print
- // differently. I think this is more likely useful than
- // a problem.
- applet.printAll(g);
- return Printable.PAGE_EXISTS;
- }
- }
-
- }
-
- /*
- * This class can take an application-client supplied printable object
- * and send the result to a stream.
- * The application does not need to send any postscript to this stream
- * unless it needs to specify a translation etc.
- * It assumes that its importing application obeys all the conventions
- * for importation of EPS. See Appendix H - Encapsulated Postscript File
- * Format - of the Adobe Postscript Language Reference Manual, 2nd edition.
- * This class could be used as the basis for exposing the ability to
- * generate EPSF from 2D graphics as a StreamPrintService.
- * In that case a MediaPrintableArea attribute could be used to
- * communicate the bounding box.
- */
- public static class EPSPrinter implements Pageable {
-
- private PageFormat pf;
- private PSPrinterJob job;
- private int llx, lly, urx, ury;
- private Printable printable;
- private PrintStream stream;
- private String epsTitle;
-
- public EPSPrinter(Printable printable, String title,
- PrintStream stream,
- int x, int y, int wid, int hgt) {
-
- this.printable = printable;
- this.epsTitle = title;
- this.stream = stream;
- llx = x;
- lly = y;
- urx = llx+wid;
- ury = lly+hgt;
- // construct a PageFormat with zero margins representing the
- // exact bounds of the applet. ie construct a theoretical
- // paper which happens to exactly match applet panel size.
- Paper p = new Paper();
- p.setSize((double)wid, (double)hgt);
- p.setImageableArea(0.0,0.0, (double)wid, (double)hgt);
- pf = new PageFormat();
- pf.setPaper(p);
- }
-
- public void print() throws PrinterException {
- stream.println("%!PS-Adobe-3.0 EPSF-3.0");
- stream.println("%%BoundingBox: " +
- llx + " " + lly + " " + urx + " " + ury);
- stream.println("%%Title: " + epsTitle);
- stream.println("%%Creator: Java Printing");
- stream.println("%%CreationDate: " + new java.util.Date());
- stream.println("%%EndComments");
- stream.println("/pluginSave save def");
- stream.println("mark"); // for restoring stack state on return
-
- job = new PSPrinterJob();
- job.epsPrinter = this; // modifies the behaviour of PSPrinterJob
- job.mPSStream = stream;
- job.mDestType = RasterPrinterJob.STREAM; // prevents closure
-
- job.startDoc();
- try {
- job.printPage(this, 0);
- } catch (Throwable t) {
- if (t instanceof PrinterException) {
- throw (PrinterException)t;
- } else {
- throw new PrinterException(t.toString());
- }
- } finally {
- stream.println("cleartomark"); // restore stack state
- stream.println("pluginSave restore");
- job.endDoc();
- }
- stream.flush();
- }
-
- public int getNumberOfPages() {
- return 1;
- }
-
- public PageFormat getPageFormat(int pgIndex) {
- if (pgIndex > 0) {
- throw new IndexOutOfBoundsException("pgIndex");
- } else {
- return pf;
- }
- }
-
- public Printable getPrintable(int pgIndex) {
- if (pgIndex > 0) {
- throw new IndexOutOfBoundsException("pgIndex");
- } else {
- return printable;
- }
- }
-
- }
}
diff --git a/src/java.desktop/share/legal/harfbuzz.md b/src/java.desktop/share/legal/harfbuzz.md
index 2d0a28ed310..e0c40705ed6 100644
--- a/src/java.desktop/share/legal/harfbuzz.md
+++ b/src/java.desktop/share/legal/harfbuzz.md
@@ -1,4 +1,4 @@
-## Harfbuzz v10.4.0
+## Harfbuzz 11.2.0
### Harfbuzz License
diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Color/CBDT/CBDT.hh b/src/java.desktop/share/native/libharfbuzz/OT/Color/CBDT/CBDT.hh
index 43a611a0058..b8f6fa4054b 100644
--- a/src/java.desktop/share/native/libharfbuzz/OT/Color/CBDT/CBDT.hh
+++ b/src/java.desktop/share/native/libharfbuzz/OT/Color/CBDT/CBDT.hh
@@ -949,25 +949,25 @@ struct CBDT
hb_glyph_extents_t extents;
hb_glyph_extents_t pixel_extents;
- hb_blob_t *blob = reference_png (font, glyph);
-
- if (unlikely (blob == hb_blob_get_empty ()))
- return false;
-
- if (unlikely (!hb_font_get_glyph_extents (font, glyph, &extents)))
+ if (unlikely (!font->get_glyph_extents (glyph, &extents, false)))
return false;
if (unlikely (!get_extents (font, glyph, &pixel_extents, false)))
return false;
+ hb_blob_t *blob = reference_png (font, glyph);
+ if (unlikely (hb_blob_is_immutable (blob)))
+ return false;
+
bool ret = funcs->image (data,
blob,
pixel_extents.width, -pixel_extents.height,
HB_PAINT_IMAGE_FORMAT_PNG,
- font->slant_xy,
+ 0.f,
&extents);
hb_blob_destroy (blob);
+
return ret;
}
diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Color/COLR/COLR.hh b/src/java.desktop/share/native/libharfbuzz/OT/Color/COLR/COLR.hh
index 4d6272d05cb..73e6b4c305b 100644
--- a/src/java.desktop/share/native/libharfbuzz/OT/Color/COLR/COLR.hh
+++ b/src/java.desktop/share/native/libharfbuzz/OT/Color/COLR/COLR.hh
@@ -33,6 +33,7 @@
#include "../../../hb-open-type.hh"
#include "../../../hb-ot-var-common.hh"
#include "../../../hb-paint.hh"
+#include "../../../hb-paint-bounded.hh"
#include "../../../hb-paint-extents.hh"
#include "../CPAL/CPAL.hh"
@@ -47,6 +48,12 @@ namespace OT {
struct hb_paint_context_t;
}
+struct hb_colr_scratch_t
+{
+ hb_paint_bounded_context_t paint_bounded;
+ hb_paint_extents_context_t paint_extents;
+};
+
namespace OT {
struct COLR;
@@ -90,12 +97,27 @@ public:
font (font_),
palette (
#ifndef HB_NO_COLOR
- font->face->table.CPAL->get_palette_colors (palette_)
+ // https://github.com/harfbuzz/harfbuzz/issues/5116
+ font->face->table.CPAL->get_palette_colors (palette_ < font->face->table.CPAL->get_palette_count () ? palette_ : 0)
#endif
),
foreground (foreground_),
instancer (instancer_)
- { }
+ {
+ if (font->is_synthetic ())
+ {
+ font = hb_font_create_sub_font (font);
+ hb_font_set_synthetic_bold (font, 0, 0, true);
+ hb_font_set_synthetic_slant (font, 0);
+ }
+ else
+ hb_font_reference (font);
+ }
+
+ ~hb_paint_context_t ()
+ {
+ hb_font_destroy (font);
+ }
hb_color_t get_color (unsigned int color_index, float alpha, hb_bool_t *is_foreground)
{
@@ -932,9 +954,9 @@ struct PaintGlyph
void paint_glyph (hb_paint_context_t *c) const
{
TRACE_PAINT (this);
- c->funcs->push_inverse_root_transform (c->data, c->font);
+ c->funcs->push_inverse_font_transform (c->data, c->font);
c->funcs->push_clip_glyph (c->data, gid, c->font);
- c->funcs->push_root_transform (c->data, c->font);
+ c->funcs->push_font_transform (c->data, c->font);
c->recurse (this+paint);
c->funcs->pop_transform (c->data);
c->funcs->pop_clip (c->data);
@@ -1511,10 +1533,12 @@ struct PaintComposite
void paint_glyph (hb_paint_context_t *c) const
{
TRACE_PAINT (this);
+ c->funcs->push_group (c->data);
c->recurse (this+backdrop);
c->funcs->push_group (c->data);
c->recurse (this+src);
c->funcs->pop_group (c->data, (hb_paint_composite_mode_t) (int) mode);
+ c->funcs->pop_group (c->data, HB_PAINT_COMPOSITE_MODE_SRC_OVER);
}
HBUINT8 format; /* format = 32 */
@@ -1612,7 +1636,7 @@ struct ClipBox
void closurev1 (hb_colrv1_closure_context_t* c) const
{
switch (u.format) {
- case 2: u.format2.closurev1 (c);
+ case 2: u.format2.closurev1 (c); return;
default:return;
}
}
@@ -2079,6 +2103,8 @@ struct COLR
{
static constexpr hb_tag_t tableTag = HB_OT_TAG_COLR;
+ bool has_data () const { return has_v0_data () || version; }
+
bool has_v0_data () const { return numBaseGlyphs; }
bool has_v1_data () const
{
@@ -2112,7 +2138,53 @@ struct COLR
{
accelerator_t (hb_face_t *face)
{ colr = hb_sanitize_context_t ().reference_table (face); }
- ~accelerator_t () { this->colr.destroy (); }
+
+ ~accelerator_t ()
+ {
+ auto *scratch = cached_scratch.get_relaxed ();
+ if (scratch)
+ {
+ scratch->~hb_colr_scratch_t ();
+ hb_free (scratch);
+ }
+
+ colr.destroy ();
+ }
+
+
+ bool has_data () const { return colr->has_data (); }
+
+#ifndef HB_NO_PAINT
+ bool
+ get_extents (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_glyph_extents_t *extents) const
+ {
+ if (unlikely (!has_data ())) return false;
+
+ hb_colr_scratch_t *scratch = acquire_scratch ();
+ if (unlikely (!scratch)) return true;
+ bool ret = colr->get_extents (font, glyph, extents, *scratch);
+ release_scratch (scratch);
+ return ret;
+ }
+
+ bool paint_glyph (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_paint_funcs_t *funcs, void *data,
+ unsigned int palette_index,
+ hb_color_t foreground,
+ bool clip = true) const
+ {
+ if (unlikely (!has_data ())) return false;
+
+ hb_colr_scratch_t *scratch = acquire_scratch ();
+ if (unlikely (!scratch)) return true;
+ bool ret = colr->paint_glyph (font, glyph, funcs, data, palette_index, foreground, clip, *scratch);
+ release_scratch (scratch);
+ return ret;
+ }
+#endif
bool is_valid () { return colr.get_blob ()->length; }
@@ -2148,7 +2220,33 @@ struct COLR
{ return colr->get_delta_set_index_map_ptr (); }
private:
+
+ hb_colr_scratch_t *acquire_scratch () const
+ {
+ hb_colr_scratch_t *scratch = cached_scratch.get_acquire ();
+
+ if (!scratch || unlikely (!cached_scratch.cmpexch (scratch, nullptr)))
+ {
+ scratch = (hb_colr_scratch_t *) hb_calloc (1, sizeof (hb_colr_scratch_t));
+ if (unlikely (!scratch))
+ return nullptr;
+ }
+
+ return scratch;
+ }
+ void release_scratch (hb_colr_scratch_t *scratch) const
+ {
+ if (!cached_scratch.cmpexch (nullptr, scratch))
+ {
+ scratch->~hb_colr_scratch_t ();
+ hb_free (scratch);
+ }
+ }
+
+ public:
hb_blob_ptr_t colr;
+ private:
+ mutable hb_atomic_t cached_scratch;
};
void closure_glyphs (hb_codepoint_t glyph,
@@ -2520,7 +2618,10 @@ struct COLR
#ifndef HB_NO_PAINT
bool
- get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
+ get_extents (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_glyph_extents_t *extents,
+ hb_colr_scratch_t &scratch) const
{
ItemVarStoreInstancer instancer (get_var_store_ptr (),
@@ -2534,10 +2635,10 @@ struct COLR
}
auto *extents_funcs = hb_paint_extents_get_funcs ();
- hb_paint_extents_context_t extents_data;
- bool ret = paint_glyph (font, glyph, extents_funcs, &extents_data, 0, HB_COLOR(0,0,0,0));
+ scratch.paint_extents.clear ();
+ bool ret = paint_glyph (font, glyph, extents_funcs, &scratch.paint_extents, 0, HB_COLOR(0,0,0,0), true, scratch);
- hb_extents_t e = extents_data.get_extents ();
+ auto e = scratch.paint_extents.get_extents ();
if (e.is_void ())
{
extents->x_bearing = 0;
@@ -2583,7 +2684,12 @@ struct COLR
#ifndef HB_NO_PAINT
bool
- paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data, unsigned int palette_index, hb_color_t foreground, bool clip = true) const
+ paint_glyph (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_paint_funcs_t *funcs, void *data,
+ unsigned int palette_index, hb_color_t foreground,
+ bool clip,
+ hb_colr_scratch_t &scratch) const
{
ItemVarStoreInstancer instancer (get_var_store_ptr (),
get_delta_set_index_map_ptr (),
@@ -2617,26 +2723,26 @@ struct COLR
}
else
{
- auto *extents_funcs = hb_paint_extents_get_funcs ();
- hb_paint_extents_context_t extents_data;
+ clip = false;
+ is_bounded = false;
+ }
+
+ if (!is_bounded)
+ {
+ auto *bounded_funcs = hb_paint_bounded_get_funcs ();
+ scratch.paint_bounded.clear ();
paint_glyph (font, glyph,
- extents_funcs, &extents_data,
+ bounded_funcs, &scratch.paint_bounded,
palette_index, foreground,
- false);
+ false,
+ scratch);
- hb_extents_t extents = extents_data.get_extents ();
- is_bounded = extents_data.is_bounded ();
-
- c.funcs->push_clip_rectangle (c.data,
- extents.xmin,
- extents.ymin,
- extents.xmax,
- extents.ymax);
+ is_bounded = scratch.paint_bounded.is_bounded ();
}
}
- c.funcs->push_root_transform (c.data, font);
+ c.funcs->push_font_transform (c.data, font);
if (is_bounded)
c.recurse (*paint);
@@ -2714,9 +2820,7 @@ void PaintColrLayers::paint_glyph (hb_paint_context_t *c) const
return;
const Paint &paint = paint_offset_lists.get_paint (i);
- c->funcs->push_group (c->data);
c->recurse (paint);
- c->funcs->pop_group (c->data, HB_PAINT_COMPOSITE_MODE_SRC_OVER);
}
}
@@ -2728,7 +2832,7 @@ void PaintColrGlyph::paint_glyph (hb_paint_context_t *c) const
if (unlikely (!node.visit (gid)))
return;
- c->funcs->push_inverse_root_transform (c->data, c->font);
+ c->funcs->push_inverse_font_transform (c->data, c->font);
if (c->funcs->color_glyph (c->data, gid, c->font))
{
c->funcs->pop_transform (c->data);
diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Color/sbix/sbix.hh b/src/java.desktop/share/native/libharfbuzz/OT/Color/sbix/sbix.hh
index e95d8c13a44..b77486a4340 100644
--- a/src/java.desktop/share/native/libharfbuzz/OT/Color/sbix/sbix.hh
+++ b/src/java.desktop/share/native/libharfbuzz/OT/Color/sbix/sbix.hh
@@ -237,27 +237,28 @@ struct sbix
int x_offset = 0, y_offset = 0;
unsigned int strike_ppem = 0;
- hb_blob_t *blob = reference_png (font, glyph, &x_offset, &y_offset, &strike_ppem);
hb_glyph_extents_t extents;
hb_glyph_extents_t pixel_extents;
- if (blob == hb_blob_get_empty ())
- return false;
-
- if (!hb_font_get_glyph_extents (font, glyph, &extents))
+ if (!font->get_glyph_extents (glyph, &extents, false))
return false;
if (unlikely (!get_extents (font, glyph, &pixel_extents, false)))
return false;
+ hb_blob_t *blob = reference_png (font, glyph, &x_offset, &y_offset, &strike_ppem);
+ if (hb_blob_is_immutable (blob))
+ return false;
+
bool ret = funcs->image (data,
blob,
pixel_extents.width, -pixel_extents.height,
HB_PAINT_IMAGE_FORMAT_PNG,
- font->slant_xy,
+ 0.f,
&extents);
hb_blob_destroy (blob);
+
return ret;
}
diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Color/svg/svg.hh b/src/java.desktop/share/native/libharfbuzz/OT/Color/svg/svg.hh
index 9f676f9689e..9249abf7075 100644
--- a/src/java.desktop/share/native/libharfbuzz/OT/Color/svg/svg.hh
+++ b/src/java.desktop/share/native/libharfbuzz/OT/Color/svg/svg.hh
@@ -104,15 +104,16 @@ struct SVG
if (blob == hb_blob_get_empty ())
return false;
- funcs->image (data,
- blob,
- 0, 0,
- HB_PAINT_IMAGE_FORMAT_SVG,
- font->slant_xy,
- nullptr);
+ bool ret = funcs->image (data,
+ blob,
+ 0, 0,
+ HB_PAINT_IMAGE_FORMAT_SVG,
+ 0.f,
+ nullptr);
hb_blob_destroy (blob);
- return true;
+
+ return ret;
}
private:
diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat1.hh b/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat1.hh
index 4a925763bd7..97ea51089ec 100644
--- a/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat1.hh
+++ b/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat1.hh
@@ -77,7 +77,7 @@ struct CoverageFormat1_3
bool intersects (const hb_set_t *glyphs) const
{
- if (glyphArray.len > glyphs->get_population () * hb_bit_storage ((unsigned) glyphArray.len) / 2)
+ if (glyphArray.len > glyphs->get_population () * hb_bit_storage ((unsigned) glyphArray.len))
{
for (auto g : *glyphs)
if (get_coverage (g) != NOT_COVERED)
diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat2.hh b/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat2.hh
index 247b7274b14..0c9bd09cbf7 100644
--- a/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat2.hh
+++ b/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat2.hh
@@ -120,7 +120,7 @@ struct CoverageFormat2_4
bool intersects (const hb_set_t *glyphs) const
{
- if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len) / 2)
+ if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len))
{
for (auto g : *glyphs)
if (get_coverage (g) != NOT_COVERED)
diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GDEF/GDEF.hh b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GDEF/GDEF.hh
index 542480d2dd0..ceba37b0619 100644
--- a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GDEF/GDEF.hh
+++ b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GDEF/GDEF.hh
@@ -205,20 +205,19 @@ struct CaretValueFormat3
unsigned varidx = (this+deviceTable).get_variation_index ();
hb_pair_t *new_varidx_delta;
- if (!c->plan->layout_variation_idx_delta_map.has (varidx, &new_varidx_delta))
- return_trace (false);
+ if (c->plan->layout_variation_idx_delta_map.has (varidx, &new_varidx_delta)) {
+ uint32_t new_varidx = hb_first (*new_varidx_delta);
+ int delta = hb_second (*new_varidx_delta);
+ if (delta != 0)
+ {
+ if (!c->serializer->check_assign (out->coordinate, coordinate + delta, HB_SERIALIZE_ERROR_INT_OVERFLOW))
+ return_trace (false);
+ }
- uint32_t new_varidx = hb_first (*new_varidx_delta);
- int delta = hb_second (*new_varidx_delta);
- if (delta != 0)
- {
- if (!c->serializer->check_assign (out->coordinate, coordinate + delta, HB_SERIALIZE_ERROR_INT_OVERFLOW))
- return_trace (false);
+ if (new_varidx == HB_OT_LAYOUT_NO_VARIATIONS_INDEX)
+ return_trace (c->serializer->check_assign (out->caretValueFormat, 1, HB_SERIALIZE_ERROR_INT_OVERFLOW));
}
- if (new_varidx == HB_OT_LAYOUT_NO_VARIATIONS_INDEX)
- return_trace (c->serializer->check_assign (out->caretValueFormat, 1, HB_SERIALIZE_ERROR_INT_OVERFLOW));
-
if (!c->serializer->embed (deviceTable))
return_trace (false);
@@ -1015,7 +1014,8 @@ struct GDEF
hb_blob_ptr_t table;
#ifndef HB_NO_GDEF_CACHE
hb_vector_t mark_glyph_set_digests;
- mutable hb_cache_t<21, 3, 8> glyph_props_cache;
+ mutable hb_cache_t<21, 3> glyph_props_cache;
+ static_assert (sizeof (glyph_props_cache) == 512, "");
#endif
};
diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/GPOS.hh b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/GPOS.hh
index f4af98b25fd..ce3f74d8c3b 100644
--- a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/GPOS.hh
+++ b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/GPOS.hh
@@ -152,8 +152,11 @@ GPOS::position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer)
for (unsigned i = 0; i < len; i++)
propagate_attachment_offsets (pos, len, i, direction);
- if (unlikely (font->slant))
+ if (unlikely (font->slant_xy) &&
+ HB_DIRECTION_IS_HORIZONTAL (direction))
{
+ /* Slanting shaping results is only supported for horizontal text,
+ * as it gets weird otherwise. */
for (unsigned i = 0; i < len; i++)
if (unlikely (pos[i].y_offset))
pos[i].x_offset += roundf (font->slant_xy * pos[i].y_offset);
diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairPosFormat1.hh b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairPosFormat1.hh
index 597ff4c088a..2748882f527 100644
--- a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairPosFormat1.hh
+++ b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairPosFormat1.hh
@@ -54,7 +54,7 @@ struct PairPosFormat1_3
{
auto &cov = this+coverage;
- if (pairSet.len > glyphs->get_population () * hb_bit_storage ((unsigned) pairSet.len) / 4)
+ if (pairSet.len > glyphs->get_population () * hb_bit_storage ((unsigned) pairSet.len))
{
for (hb_codepoint_t g : glyphs->iter())
{
diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Var/VARC/VARC.hh b/src/java.desktop/share/native/libharfbuzz/OT/Var/VARC/VARC.hh
index dbbbec9eee0..2ea1b6bca32 100644
--- a/src/java.desktop/share/native/libharfbuzz/OT/Var/VARC/VARC.hh
+++ b/src/java.desktop/share/native/libharfbuzz/OT/Var/VARC/VARC.hh
@@ -21,6 +21,24 @@ namespace OT {
#ifndef HB_NO_VAR_COMPOSITES
+struct hb_varc_scratch_t
+{
+ hb_vector_t axisIndices;
+ hb_vector_t axisValues;
+ hb_glyf_scratch_t glyf_scratch;
+};
+
+struct hb_varc_context_t
+{
+ hb_font_t *font;
+ hb_draw_session_t *draw_session;
+ hb_extents_t *extents;
+ mutable hb_decycler_t decycler;
+ mutable signed edges_left;
+ mutable signed depth_left;
+ hb_varc_scratch_t &scratch;
+};
+
struct VarComponent
{
enum class flags_t : uint32_t
@@ -44,41 +62,32 @@ struct VarComponent
};
HB_INTERNAL hb_ubytes_t
- get_path_at (hb_font_t *font,
+ get_path_at (const hb_varc_context_t &c,
hb_codepoint_t parent_gid,
- hb_draw_session_t &draw_session,
hb_array_t coords,
hb_transform_t transform,
hb_ubytes_t record,
- hb_decycler_t *decycler,
- signed *edges_left,
- signed depth_left,
- hb_glyf_scratch_t &scratch,
VarRegionList::cache_t *cache = nullptr) const;
};
struct VarCompositeGlyph
{
static void
- get_path_at (hb_font_t *font,
- hb_codepoint_t glyph,
- hb_draw_session_t &draw_session,
+ get_path_at (const hb_varc_context_t &c,
+ hb_codepoint_t gid,
hb_array_t coords,
hb_transform_t transform,
hb_ubytes_t record,
- hb_decycler_t *decycler,
- signed *edges_left,
- signed depth_left,
- hb_glyf_scratch_t &scratch,
- VarRegionList::cache_t *cache = nullptr)
+ VarRegionList::cache_t *cache)
{
while (record)
{
const VarComponent &comp = * (const VarComponent *) (record.arrayZ);
- record = comp.get_path_at (font, glyph,
- draw_session, coords, transform,
+ record = comp.get_path_at (c,
+ gid,
+ coords, transform,
record,
- decycler, edges_left, depth_left, scratch, cache);
+ cache);
}
}
};
@@ -92,36 +101,47 @@ struct VARC
static constexpr hb_tag_t tableTag = HB_TAG ('V', 'A', 'R', 'C');
HB_INTERNAL bool
- get_path_at (hb_font_t *font,
- hb_codepoint_t glyph,
- hb_draw_session_t &draw_session,
+ get_path_at (const hb_varc_context_t &c,
+ hb_codepoint_t gid,
hb_array_t coords,
- hb_transform_t transform,
- hb_codepoint_t parent_glyph,
- hb_decycler_t *decycler,
- signed *edges_left,
- signed depth_left,
- hb_glyf_scratch_t &scratch) const;
+ hb_transform_t transform = HB_TRANSFORM_IDENTITY,
+ hb_codepoint_t parent_gid = HB_CODEPOINT_INVALID,
+ VarRegionList::cache_t *parent_cache = nullptr) const;
bool
get_path (hb_font_t *font,
hb_codepoint_t gid,
hb_draw_session_t &draw_session,
- hb_glyf_scratch_t &scratch) const
+ hb_varc_scratch_t &scratch) const
{
- hb_decycler_t decycler;
- signed edges = HB_MAX_GRAPH_EDGE_COUNT;
+ hb_varc_context_t c {font,
+ &draw_session,
+ nullptr,
+ hb_decycler_t {},
+ HB_MAX_GRAPH_EDGE_COUNT,
+ HB_MAX_NESTING_LEVEL,
+ scratch};
- return get_path_at (font,
- gid,
- draw_session,
- hb_array (font->coords, font->num_coords),
- HB_TRANSFORM_IDENTITY,
- HB_CODEPOINT_INVALID,
- &decycler,
- &edges,
- HB_MAX_NESTING_LEVEL,
- scratch);
+ return get_path_at (c, gid,
+ hb_array (font->coords, font->num_coords));
+ }
+
+ bool
+ get_extents (hb_font_t *font,
+ hb_codepoint_t gid,
+ hb_extents_t *extents,
+ hb_varc_scratch_t &scratch) const
+ {
+ hb_varc_context_t c {font,
+ nullptr,
+ extents,
+ hb_decycler_t {},
+ HB_MAX_GRAPH_EDGE_COUNT,
+ HB_MAX_NESTING_LEVEL,
+ scratch};
+
+ return get_path_at (c, gid,
+ hb_array (font->coords, font->num_coords));
}
bool sanitize (hb_sanitize_context_t *c) const
@@ -150,7 +170,7 @@ struct VARC
auto *scratch = cached_scratch.get_relaxed ();
if (scratch)
{
- scratch->~hb_glyf_scratch_t ();
+ scratch->~hb_varc_scratch_t ();
hb_free (scratch);
}
@@ -162,34 +182,60 @@ struct VARC
{
if (!table->has_data ()) return false;
- hb_glyf_scratch_t *scratch;
-
- // Borrow the cached strach buffer.
- {
- scratch = cached_scratch.get_acquire ();
- if (!scratch || unlikely (!cached_scratch.cmpexch (scratch, nullptr)))
- {
- scratch = (hb_glyf_scratch_t *) hb_calloc (1, sizeof (hb_glyf_scratch_t));
- if (unlikely (!scratch))
- return true;
- }
- }
-
+ auto *scratch = acquire_scratch ();
+ if (unlikely (!scratch)) return true;
bool ret = table->get_path (font, gid, draw_session, *scratch);
+ release_scratch (scratch);
+ return ret;
+ }
- // Put it back.
- if (!cached_scratch.cmpexch (nullptr, scratch))
- {
- scratch->~hb_glyf_scratch_t ();
- hb_free (scratch);
- }
+ bool
+ get_extents (hb_font_t *font,
+ hb_codepoint_t gid,
+ hb_glyph_extents_t *extents) const
+ {
+ if (!table->has_data ()) return false;
+
+ hb_extents_t f_extents;
+
+ auto *scratch = acquire_scratch ();
+ if (unlikely (!scratch)) return true;
+ bool ret = table->get_extents (font, gid, &f_extents, *scratch);
+ release_scratch (scratch);
+
+ if (ret)
+ *extents = f_extents.to_glyph_extents (font->x_scale < 0, font->y_scale < 0);
return ret;
}
+ private:
+
+ hb_varc_scratch_t *acquire_scratch () const
+ {
+ hb_varc_scratch_t *scratch = cached_scratch.get_acquire ();
+
+ if (!scratch || unlikely (!cached_scratch.cmpexch (scratch, nullptr)))
+ {
+ scratch = (hb_varc_scratch_t *) hb_calloc (1, sizeof (hb_varc_scratch_t));
+ if (unlikely (!scratch))
+ return nullptr;
+ }
+
+ return scratch;
+ }
+ void release_scratch (hb_varc_scratch_t *scratch) const
+ {
+ if (!cached_scratch.cmpexch (nullptr, scratch))
+ {
+ scratch->~hb_varc_scratch_t ();
+ hb_free (scratch);
+ }
+ }
+
private:
hb_blob_ptr_t table;
- hb_atomic_ptr_t cached_scratch;
+ mutable hb_atomic_t cached_scratch;
};
bool has_data () const { return version.major != 0; }
diff --git a/src/java.desktop/share/native/libharfbuzz/OT/glyf/glyf.hh b/src/java.desktop/share/native/libharfbuzz/OT/glyf/glyf.hh
index 681c3b9a007..d9e5fedfa92 100644
--- a/src/java.desktop/share/native/libharfbuzz/OT/glyf/glyf.hh
+++ b/src/java.desktop/share/native/libharfbuzz/OT/glyf/glyf.hh
@@ -429,16 +429,27 @@ struct glyf_accelerator_t
}
public:
- bool get_extents (hb_font_t *font, hb_codepoint_t gid, hb_glyph_extents_t *extents) const
+
+ bool get_extents (hb_font_t *font,
+ hb_codepoint_t gid,
+ hb_glyph_extents_t *extents) const
+ { return get_extents_at (font, gid, extents, hb_array (font->coords, font->num_coords)); }
+
+ bool get_extents_at (hb_font_t *font,
+ hb_codepoint_t gid,
+ hb_glyph_extents_t *extents,
+ hb_array_t coords) const
{
if (unlikely (gid >= num_glyphs)) return false;
#ifndef HB_NO_VAR
- if (font->num_coords)
+ if (coords)
{
hb_glyf_scratch_t scratch;
- return get_points (font, gid, points_aggregator_t (font, extents, nullptr, true),
- hb_array (font->coords, font->num_coords),
+ return get_points (font,
+ gid,
+ points_aggregator_t (font, extents, nullptr, true),
+ coords,
scratch);
}
#endif
@@ -532,7 +543,7 @@ struct glyf_accelerator_t
unsigned int num_glyphs;
hb_blob_ptr_t loca_table;
hb_blob_ptr_t glyf_table;
- hb_atomic_ptr_t cached_scratch;
+ mutable hb_atomic_t cached_scratch;
};
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-common.hh b/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-common.hh
index 673c7fbe945..d5a44bf473c 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-common.hh
+++ b/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-common.hh
@@ -29,6 +29,8 @@
#include "hb-aat-layout.hh"
#include "hb-aat-map.hh"
+#include "hb-ot-layout-common.hh"
+#include "hb-ot-layout-gdef-table.hh"
#include "hb-open-type.hh"
#include "hb-cache.hh"
#include "hb-bit-set.hh"
@@ -48,6 +50,61 @@ struct ankr;
using hb_aat_class_cache_t = hb_cache_t<15, 8, 7>;
static_assert (sizeof (hb_aat_class_cache_t) == 256, "");
+struct hb_aat_scratch_t
+{
+ hb_aat_scratch_t () = default;
+ hb_aat_scratch_t (const hb_aat_scratch_t &) = delete;
+
+ hb_aat_scratch_t (hb_aat_scratch_t &&o)
+ {
+ buffer_glyph_set.set_relaxed (o.buffer_glyph_set.get_relaxed ());
+ o.buffer_glyph_set.set_relaxed (nullptr);
+ }
+ hb_aat_scratch_t & operator = (hb_aat_scratch_t &&o)
+ {
+ buffer_glyph_set.set_relaxed (o.buffer_glyph_set.get_relaxed ());
+ o.buffer_glyph_set.set_relaxed (nullptr);
+ return *this;
+ }
+ ~hb_aat_scratch_t ()
+ {
+ auto *s = buffer_glyph_set.get_relaxed ();
+ if (unlikely (!s))
+ return;
+ s->fini ();
+ hb_free (s);
+ }
+
+ hb_bit_set_t *create_buffer_glyph_set () const
+ {
+ hb_bit_set_t *s = buffer_glyph_set.get_acquire ();
+ if (s && buffer_glyph_set.cmpexch (s, nullptr))
+ return s;
+
+ s = (hb_bit_set_t *) hb_calloc (1, sizeof (hb_bit_set_t));
+ if (unlikely (!s))
+ return nullptr;
+ s->init ();
+
+ return s;
+ }
+ void destroy_buffer_glyph_set (hb_bit_set_t *s) const
+ {
+ if (unlikely (!s))
+ return;
+ if (buffer_glyph_set.cmpexch (nullptr, s))
+ return;
+ s->fini ();
+ hb_free (s);
+ }
+
+ mutable hb_atomic_t buffer_glyph_set;
+};
+
+enum { DELETED_GLYPH = 0xFFFF };
+
+#define HB_BUFFER_SCRATCH_FLAG_AAT_HAS_DELETED HB_BUFFER_SCRATCH_FLAG_SHAPER0
+
struct hb_aat_apply_context_t :
hb_dispatch_context_t
{
@@ -64,10 +121,11 @@ struct hb_aat_apply_context_t :
hb_buffer_t *buffer;
hb_sanitize_context_t sanitizer;
const ankr *ankr_table;
- const OT::GDEF *gdef_table;
+ const OT::GDEF &gdef;
+ bool has_glyph_classes;
const hb_sorted_vector_t *range_flags = nullptr;
bool using_buffer_glyph_set = false;
- hb_bit_set_t buffer_glyph_set;
+ hb_bit_set_t *buffer_glyph_set = nullptr;
const hb_bit_set_t *left_set = nullptr;
const hb_bit_set_t *right_set = nullptr;
const hb_bit_set_t *machine_glyph_set = nullptr;
@@ -90,15 +148,15 @@ struct hb_aat_apply_context_t :
void setup_buffer_glyph_set ()
{
- using_buffer_glyph_set = buffer->len >= 4;
+ using_buffer_glyph_set = buffer->len >= 4 && buffer_glyph_set;
- if (using_buffer_glyph_set)
- buffer->collect_codepoints (buffer_glyph_set);
+ if (likely (using_buffer_glyph_set))
+ buffer->collect_codepoints (*buffer_glyph_set);
}
bool buffer_intersects_machine () const
{
- if (using_buffer_glyph_set)
- return buffer_glyph_set.intersects (*machine_glyph_set);
+ if (likely (using_buffer_glyph_set))
+ return buffer_glyph_set->intersects (*machine_glyph_set);
// Faster for shorter buffers.
for (unsigned i = 0; i < buffer->len; i++)
@@ -106,6 +164,69 @@ struct hb_aat_apply_context_t :
return true;
return false;
}
+
+ template
+ HB_NODISCARD bool output_glyphs (unsigned int count,
+ const T *glyphs)
+ {
+ if (likely (using_buffer_glyph_set))
+ buffer_glyph_set->add_array (glyphs, count);
+ for (unsigned int i = 0; i < count; i++)
+ {
+ if (glyphs[i] == DELETED_GLYPH)
+ {
+ buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_AAT_HAS_DELETED;
+ _hb_glyph_info_set_aat_deleted (&buffer->cur());
+ }
+ else
+ {
+#ifndef HB_NO_OT_LAYOUT
+ if (has_glyph_classes)
+ _hb_glyph_info_set_glyph_props (&buffer->cur(),
+ gdef.get_glyph_props (glyphs[i]));
+#endif
+ }
+ if (unlikely (!buffer->output_glyph (glyphs[i]))) return false;
+ }
+ return true;
+ }
+
+ HB_NODISCARD bool replace_glyph (hb_codepoint_t glyph)
+ {
+ if (glyph == DELETED_GLYPH)
+ {
+ buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_AAT_HAS_DELETED;
+ _hb_glyph_info_set_aat_deleted (&buffer->cur());
+ }
+
+ if (likely (using_buffer_glyph_set))
+ buffer_glyph_set->add (glyph);
+#ifndef HB_NO_OT_LAYOUT
+ if (has_glyph_classes)
+ _hb_glyph_info_set_glyph_props (&buffer->cur(),
+ gdef.get_glyph_props (glyph));
+#endif
+ return buffer->replace_glyph (glyph);
+ }
+
+ HB_NODISCARD bool delete_glyph ()
+ {
+ buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_AAT_HAS_DELETED;
+ _hb_glyph_info_set_aat_deleted (&buffer->cur());
+ return buffer->replace_glyph (DELETED_GLYPH);
+ }
+
+ void replace_glyph_inplace (unsigned i, hb_codepoint_t glyph)
+ {
+ buffer->info[i].codepoint = glyph;
+ if (likely (using_buffer_glyph_set))
+ buffer_glyph_set->add (glyph);
+#ifndef HB_NO_OT_LAYOUT
+ if (has_glyph_classes)
+ _hb_glyph_info_set_glyph_props (&buffer->info[i],
+ gdef.get_glyph_props (glyph));
+#endif
+ }
};
@@ -113,8 +234,6 @@ struct hb_aat_apply_context_t :
* Lookup Table
*/
-enum { DELETED_GLYPH = 0xFFFF };
-
template struct Lookup;
template
@@ -179,6 +298,7 @@ struct LookupSegmentSingle
template
void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const
{
+ if (first == DELETED_GLYPH) return;
if (!filter (value)) return;
glyphs.add_range (first, last);
}
@@ -268,6 +388,7 @@ struct LookupSegmentArray
template
void collect_glyphs_filtered (set_t &glyphs, const void *base, const filter_t &filter) const
{
+ if (first == DELETED_GLYPH) return;
const auto &values = base+valuesZ;
for (hb_codepoint_t i = first; i <= last; i++)
if (filter (values[i - first]))
@@ -368,6 +489,7 @@ struct LookupSingle
template
void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const
{
+ if (glyph == DELETED_GLYPH) return;
if (!filter (value)) return;
glyphs.add (glyph);
}
@@ -746,6 +868,10 @@ struct StateTable
}
// And glyphs in those classes.
+
+ if (filter (CLASS_DELETED_GLYPH))
+ glyphs.add (DELETED_GLYPH);
+
(this+classTable).collect_glyphs_filtered (glyphs, num_glyphs, filter);
}
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-kerx-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-kerx-table.hh
index a091b05660c..ca4f2243346 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-kerx-table.hh
+++ b/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-kerx-table.hh
@@ -185,6 +185,9 @@ struct Format1Entry
DEFINE_SIZE_STATIC (2);
};
+ static bool initiateAction (const Entry &entry)
+ { return entry.flags & Push; }
+
static bool performAction (const Entry &entry)
{ return entry.data.kernActionIndex != 0xFFFF; }
@@ -325,8 +328,9 @@ struct KerxSubTableFormat1
}
else if (buffer->info[idx].mask & kern_mask)
{
- o.x_advance += c->font->em_scale_x (v);
- o.x_offset += c->font->em_scale_x (v);
+ auto scaled = c->font->em_scale_x (v);
+ o.x_advance += scaled;
+ o.x_offset += scaled;
}
}
else
@@ -394,10 +398,8 @@ struct KerxSubTableFormat1
template
void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
{
- set_t set;
- machine.collect_glyphs (set, num_glyphs);
- left_set.union_ (set);
- right_set.union_ (set);
+ machine.collect_initial_glyphs (left_set, num_glyphs, *this);
+ //machine.collect_glyphs (right_set, num_glyphs); // right_set is unused for machine kerning
}
protected:
@@ -671,10 +673,8 @@ struct KerxSubTableFormat4
template
void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
{
- set_t set;
- machine.collect_glyphs (set, num_glyphs);
- left_set.union_ (set);
- right_set.union_ (set);
+ machine.collect_initial_glyphs (left_set, num_glyphs, *this);
+ //machine.collect_glyphs (right_set, num_glyphs); // right_set is unused for machine kerning
}
protected:
@@ -921,7 +921,18 @@ struct KerxSubTable
* The 'kerx' Table
*/
-using kern_accelerator_data_t = hb_vector_t>;
+struct kern_subtable_accelerator_data_t
+{
+ hb_bit_set_t left_set;
+ hb_bit_set_t right_set;
+ mutable hb_aat_class_cache_t class_cache;
+};
+
+struct kern_accelerator_data_t
+{
+ hb_vector_t subtable_accels;
+ hb_aat_scratch_t scratch;
+};
template
struct KerxTable
@@ -985,6 +996,8 @@ struct KerxTable
{
c->buffer->unsafe_to_concat ();
+ c->setup_buffer_glyph_set ();
+
typedef typename T::SubTable SubTable;
bool ret = false;
@@ -996,12 +1009,25 @@ struct KerxTable
{
bool reverse;
+ auto &subtable_accel = accel_data.subtable_accels[i];
+
if (!T::Types::extended && (st->u.header.coverage & st->u.header.Variation))
goto skip;
if (HB_DIRECTION_IS_HORIZONTAL (c->buffer->props.direction) != st->u.header.is_horizontal ())
goto skip;
+ c->left_set = &subtable_accel.left_set;
+ c->right_set = &subtable_accel.right_set;
+ c->machine_glyph_set = &subtable_accel.left_set;
+ c->machine_class_cache = &subtable_accel.class_cache;
+
+ if (!c->buffer_intersects_machine ())
+ {
+ (void) c->buffer->message (c->font, "skipped subtable %u because no glyph matches", c->lookup_index);
+ goto skip;
+ }
+
reverse = bool (st->u.header.coverage & st->u.header.Backwards) !=
HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction);
@@ -1028,9 +1054,6 @@ struct KerxTable
if (reverse)
c->buffer->reverse ();
- c->left_set = &accel_data[i].first;
- c->right_set = &accel_data[i].second;
-
{
/* See comment in sanitize() for conditional here. */
hb_sanitize_with_object_t with (&c->sanitizer, i < count - 1 ? st : (const SubTable *) nullptr);
@@ -1106,9 +1129,13 @@ struct KerxTable
unsigned int count = thiz()->tableCount;
for (unsigned int i = 0; i < count; i++)
{
- hb_bit_set_t left_set, right_set;
- st->collect_glyphs (left_set, right_set, num_glyphs);
- accel_data.push (hb_pair (left_set, right_set));
+ auto &subtable_accel = *accel_data.subtable_accels.push ();
+ if (unlikely (accel_data.subtable_accels.in_error ()))
+ return accel_data;
+
+ st->collect_glyphs (subtable_accel.left_set, subtable_accel.right_set, num_glyphs);
+ subtable_accel.class_cache.clear ();
+
st = &StructAfter (*st);
}
@@ -1137,6 +1164,7 @@ struct KerxTable
hb_blob_ptr_t table;
kern_accelerator_data_t accel_data;
+ hb_aat_scratch_t scratch;
};
};
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-morx-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-morx-table.hh
index cabdc0eb555..92b07eec6e5 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-morx-table.hh
+++ b/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-morx-table.hh
@@ -30,8 +30,6 @@
#include "hb-open-type.hh"
#include "hb-aat-layout-common.hh"
#include "hb-ot-layout.hh"
-#include "hb-ot-layout-common.hh"
-#include "hb-ot-layout-gdef-table.hh"
#include "hb-aat-map.hh"
/*
@@ -178,12 +176,6 @@ struct RearrangementSubtable
StateTableDriver driver (machine, c->face);
- if (!c->buffer_intersects_machine ())
- {
- (void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches");
- return_trace (false);
- }
-
driver.drive (&dc, c);
return_trace (dc.ret);
@@ -242,9 +234,7 @@ struct ContextualSubtable
ret (false),
c (c_),
table (table_),
- gdef (*c->gdef_table),
mark_set (false),
- has_glyph_classes (gdef.has_glyph_classes ()),
mark (0),
subs (table+table->substitutionTables) {}
@@ -281,12 +271,7 @@ struct ContextualSubtable
if (replacement)
{
buffer->unsafe_to_break (mark, hb_min (buffer->idx + 1, buffer->len));
- hb_codepoint_t glyph = *replacement;
- buffer->info[mark].codepoint = glyph;
- c->buffer_glyph_set.add (glyph);
- if (has_glyph_classes)
- _hb_glyph_info_set_glyph_props (&buffer->info[mark],
- gdef.get_glyph_props (*replacement));
+ c->replace_glyph_inplace (mark, *replacement);
ret = true;
}
@@ -312,12 +297,7 @@ struct ContextualSubtable
}
if (replacement)
{
- hb_codepoint_t glyph = *replacement;
- buffer->info[idx].codepoint = glyph;
- c->buffer_glyph_set.add (glyph);
- if (has_glyph_classes)
- _hb_glyph_info_set_glyph_props (&buffer->info[idx],
- gdef.get_glyph_props (*replacement));
+ c->replace_glyph_inplace (idx, *replacement);
ret = true;
}
@@ -333,9 +313,7 @@ struct ContextualSubtable
hb_aat_apply_context_t *c;
const ContextualSubtable *table;
private:
- const OT::GDEF &gdef;
bool mark_set;
- bool has_glyph_classes;
unsigned int mark;
const UnsizedListOfOffset16To, HBUINT, void, false> &subs;
};
@@ -348,12 +326,6 @@ struct ContextualSubtable
StateTableDriver driver (machine, c->face);
- if (!c->buffer_intersects_machine ())
- {
- (void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches");
- return_trace (false);
- }
-
driver.drive (&dc, c);
return_trace (dc.ret);
@@ -581,7 +553,7 @@ struct LigatureSubtable
hb_codepoint_t lig = ligatureData;
DEBUG_MSG (APPLY, nullptr, "Produced ligature %u", lig);
- if (unlikely (!buffer->replace_glyph (lig))) return;
+ if (unlikely (!c->replace_glyph (lig))) return;
unsigned int lig_end = match_positions[(match_length - 1u) % ARRAY_LENGTH (match_positions)] + 1u;
/* Now go and delete all subsequent components. */
@@ -589,8 +561,7 @@ struct LigatureSubtable
{
DEBUG_MSG (APPLY, nullptr, "Skipping ligature component");
if (unlikely (!buffer->move_to (match_positions[--match_length % ARRAY_LENGTH (match_positions)]))) return;
- _hb_glyph_info_set_default_ignorable (&buffer->cur());
- if (unlikely (!buffer->replace_glyph (DELETED_GLYPH))) return;
+ if (!c->delete_glyph ()) return;
}
if (unlikely (!buffer->move_to (lig_end))) return;
@@ -624,12 +595,6 @@ struct LigatureSubtable
StateTableDriver driver (machine, c->face);
- if (!c->buffer_intersects_machine ())
- {
- (void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches");
- return_trace (false);
- }
-
driver.drive (&dc, c);
return_trace (dc.ret);
@@ -665,15 +630,6 @@ struct NoncontextualSubtable
{
TRACE_APPLY (this);
- if (!c->buffer_intersects_machine ())
- {
- (void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches");
- return_trace (false);
- }
-
- const OT::GDEF &gdef (*c->gdef_table);
- bool has_glyph_classes = gdef.has_glyph_classes ();
-
bool ret = false;
unsigned int num_glyphs = c->face->get_num_glyphs ();
@@ -703,12 +659,7 @@ struct NoncontextualSubtable
const HBGlyphID16 *replacement = substitute.get_value (info[i].codepoint, num_glyphs);
if (replacement)
{
- hb_codepoint_t glyph = *replacement;
- info[i].codepoint = glyph;
- c->buffer_glyph_set.add (glyph);
- if (has_glyph_classes)
- _hb_glyph_info_set_glyph_props (&info[i],
- gdef.get_glyph_props (*replacement));
+ c->replace_glyph_inplace (i, *replacement);
ret = true;
}
}
@@ -850,9 +801,7 @@ struct InsertionSubtable
if (buffer->idx < buffer->len && !before)
if (unlikely (!buffer->copy_glyph ())) return;
/* TODO We ignore KashidaLike setting. */
- if (unlikely (!buffer->replace_glyphs (0, count, glyphs))) return;
- for (unsigned int i = 0; i < count; i++)
- c->buffer_glyph_set.add (glyphs[i]);
+ if (unlikely (!c->output_glyphs (count, glyphs))) return;
ret = true;
if (buffer->idx < buffer->len && !before)
buffer->skip_glyph ();
@@ -881,7 +830,8 @@ struct InsertionSubtable
if (buffer->idx < buffer->len && !before)
if (unlikely (!buffer->copy_glyph ())) return;
/* TODO We ignore KashidaLike setting. */
- if (unlikely (!buffer->replace_glyphs (0, count, glyphs))) return;
+ if (unlikely (!c->output_glyphs (count, glyphs))) return;
+ ret = true;
if (buffer->idx < buffer->len && !before)
buffer->skip_glyph ();
@@ -921,12 +871,6 @@ struct InsertionSubtable
StateTableDriver driver (machine, c->face);
- if (!c->buffer_intersects_machine ())
- {
- (void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches");
- return_trace (false);
- }
-
driver.drive (&dc, c);
return_trace (dc.ret);
@@ -1224,6 +1168,7 @@ struct Chain
if (hb_none (hb_iter (c->range_flags) |
hb_map ([subtable_flags] (const hb_aat_map_t::range_flags_t _) -> bool { return subtable_flags & (_.flags); })))
goto skip;
+
c->subtable_flags = subtable_flags;
c->machine_glyph_set = accel ? &accel->subtables[i].glyph_set : &Null(hb_bit_set_t);
c->machine_class_cache = accel ? &accel->subtables[i].class_cache : nullptr;
@@ -1233,6 +1178,12 @@ struct Chain
bool (coverage & ChainSubtable::Vertical))
goto skip;
+ if (!c->buffer_intersects_machine ())
+ {
+ (void) c->buffer->message (c->font, "skipped chainsubtable %u because no glyph matches", c->lookup_index);
+ goto skip;
+ }
+
/* Buffer contents is always in logical direction. Determine if
* we need to reverse before applying this subtable. We reverse
* back after if we did reverse indeed.
@@ -1376,7 +1327,7 @@ struct mortmorx
this->chain_count = table->get_chain_count ();
- this->accels = (hb_atomic_ptr_t *) hb_calloc (this->chain_count, sizeof (*accels));
+ this->accels = (hb_atomic_t *) hb_calloc (this->chain_count, sizeof (*accels));
if (unlikely (!this->accels))
{
this->chain_count = 0;
@@ -1423,7 +1374,8 @@ struct mortmorx
hb_blob_ptr_t table;
unsigned int chain_count;
- hb_atomic_ptr_t *accels;
+ hb_atomic_t *accels;
+ hb_aat_scratch_t scratch;
};
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-trak-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-trak-table.hh
index 0db4035fd8c..4ee73ecee69 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-trak-table.hh
+++ b/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-trak-table.hh
@@ -31,6 +31,7 @@
#include "hb-aat-layout-common.hh"
#include "hb-ot-layout.hh"
#include "hb-open-type.hh"
+#include "hb-ot-stat-table.hh"
/*
* trak -- Tracking
@@ -115,7 +116,7 @@ struct TrackTableEntry
protected:
F16DOT16 track; /* Track value for this record. */
- NameID trackNameID; /* The 'name' table index for this track.
+ OT::NameID trackNameID; /* The 'name' table index for this track.
* (a short word or phrase like "loose"
* or "very tight") */
NNOffset16To>
@@ -142,9 +143,9 @@ struct TrackData
unsigned j = count - 1;
// Find the two entries that track is between.
- while (i + 1 < count && trackTable[i + 1].get_track_value () < track)
+ while (i + 1 < count && trackTable[i + 1].get_track_value () <= track)
i++;
- while (j > 0 && trackTable[j - 1].get_track_value () > track)
+ while (j > 0 && trackTable[j - 1].get_track_value () >= track)
j--;
// Exact match.
@@ -200,6 +201,46 @@ struct trak
float ptem = font->ptem > 0.f ? font->ptem : HB_CORETEXT_DEFAULT_FONT_SIZE;
return font->em_scalef_y ((this+vertData).get_tracking (this, ptem, track));
}
+ hb_position_t get_tracking (hb_font_t *font, hb_direction_t dir, float track = 0.f) const
+ {
+#ifndef HB_NO_STYLE
+ if (!font->face->table.STAT->has_data ())
+ return 0;
+ return HB_DIRECTION_IS_HORIZONTAL (dir) ?
+ get_h_tracking (font, track) :
+ get_v_tracking (font, track);
+#else
+ return 0;
+#endif
+ }
+
+ bool apply (hb_aat_apply_context_t *c, float track = 0.f) const
+ {
+ TRACE_APPLY (this);
+
+ float ptem = c->font->ptem;
+ if (unlikely (ptem <= 0.f))
+ {
+ /* https://developer.apple.com/documentation/coretext/1508745-ctfontcreatewithgraphicsfont */
+ ptem = HB_CORETEXT_DEFAULT_FONT_SIZE;
+ }
+
+ hb_buffer_t *buffer = c->buffer;
+ if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
+ {
+ hb_position_t advance_to_add = get_h_tracking (c->font, track);
+ foreach_grapheme (buffer, start, end)
+ buffer->pos[start].x_advance += advance_to_add;
+ }
+ else
+ {
+ hb_position_t advance_to_add = get_v_tracking (c->font, track);
+ foreach_grapheme (buffer, start, end)
+ buffer->pos[start].y_advance += advance_to_add;
+ }
+
+ return_trace (true);
+ }
bool sanitize (hb_sanitize_context_t *c) const
{
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.cc b/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.cc
index 2cc94257aa7..b349c3026b6 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.cc
+++ b/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.cc
@@ -34,7 +34,7 @@
#include "hb-aat-layout-just-table.hh" // Just so we compile it; unused otherwise.
#include "hb-aat-layout-kerx-table.hh"
#include "hb-aat-layout-morx-table.hh"
-#include "hb-aat-layout-trak-table.hh" // Just so we compile it; unused otherwise.
+#include "hb-aat-layout-trak-table.hh"
#include "hb-aat-ltag-table.hh"
#include "hb-ot-layout-gsub-table.hh"
@@ -58,13 +58,14 @@ AAT::hb_aat_apply_context_t::hb_aat_apply_context_t (const hb_ot_shape_plan_t *p
buffer (buffer_),
sanitizer (),
ankr_table (&Null (AAT::ankr)),
- gdef_table (
+ gdef (
#ifndef HB_NO_OT_LAYOUT
- face->table.GDEF->table
+ *face->table.GDEF->table
#else
- &Null (GDEF)
+ Null (GDEF)
#endif
),
+ has_glyph_classes (gdef.has_glyph_classes ()),
lookup_index (0)
{
sanitizer.init (blob);
@@ -203,7 +204,7 @@ hb_aat_layout_find_feature_mapping (hb_tag_t tag)
#endif
-#ifndef HB_NO_AAT
+#ifndef HB_NO_AAT_SHAPE
/*
* mort/morx/kerx/trak
@@ -287,11 +288,14 @@ hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan,
const hb_feature_t *features,
unsigned num_features)
{
- hb_aat_map_builder_t builder (font->face, plan->props);
- for (unsigned i = 0; i < num_features; i++)
- builder.add_feature (features[i]);
hb_aat_map_t map;
- builder.compile (map);
+ if (num_features)
+ {
+ hb_aat_map_builder_t builder (font->face, plan->props);
+ for (unsigned i = 0; i < num_features; i++)
+ builder.add_feature (features[i]);
+ builder.compile (map);
+ }
{
auto &accel = *font->face->table.morx;
@@ -300,7 +304,10 @@ hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan,
{
AAT::hb_aat_apply_context_t c (plan, font, buffer, accel.get_blob ());
if (!buffer->message (font, "start table morx")) return;
- morx.apply (&c, map, accel);
+ c.buffer_glyph_set = accel.scratch.create_buffer_glyph_set ();
+ morx.apply (&c, num_features ? map : plan->aat_map, accel);
+ accel.scratch.destroy_buffer_glyph_set (c.buffer_glyph_set);
+ c.buffer_glyph_set = nullptr;
(void) buffer->message (font, "end table morx");
return;
}
@@ -313,34 +320,24 @@ hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan,
{
AAT::hb_aat_apply_context_t c (plan, font, buffer, accel.get_blob ());
if (!buffer->message (font, "start table mort")) return;
- mort.apply (&c, map, accel);
+ mort.apply (&c, num_features ? map : plan->aat_map, accel);
(void) buffer->message (font, "end table mort");
return;
}
}
}
-void
-hb_aat_layout_zero_width_deleted_glyphs (hb_buffer_t *buffer)
-{
- unsigned int count = buffer->len;
- hb_glyph_info_t *info = buffer->info;
- hb_glyph_position_t *pos = buffer->pos;
- for (unsigned int i = 0; i < count; i++)
- if (unlikely (info[i].codepoint == AAT::DELETED_GLYPH))
- pos[i].x_advance = pos[i].y_advance = pos[i].x_offset = pos[i].y_offset = 0;
-}
-
static bool
is_deleted_glyph (const hb_glyph_info_t *info)
{
- return info->codepoint == AAT::DELETED_GLYPH;
+ return _hb_glyph_info_is_aat_deleted (info);
}
void
hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer)
{
- buffer->delete_glyphs_inplace (is_deleted_glyph);
+ if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_AAT_HAS_DELETED)
+ buffer->delete_glyphs_inplace (is_deleted_glyph);
}
/**
@@ -371,8 +368,11 @@ hb_aat_layout_position (const hb_ot_shape_plan_t *plan,
AAT::hb_aat_apply_context_t c (plan, font, buffer, accel.get_blob ());
if (!buffer->message (font, "start table kerx")) return;
+ c.buffer_glyph_set = accel.scratch.create_buffer_glyph_set ();
c.set_ankr_table (font->face->table.ankr.get ());
accel.apply (&c);
+ accel.scratch.destroy_buffer_glyph_set (c.buffer_glyph_set);
+ c.buffer_glyph_set = nullptr;
(void) buffer->message (font, "end table kerx");
}
@@ -394,6 +394,17 @@ hb_aat_layout_has_tracking (hb_face_t *face)
return face->table.trak->has_data ();
}
+void
+hb_aat_layout_track (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer)
+{
+ const AAT::trak& trak = *font->face->table.trak;
+
+ AAT::hb_aat_apply_context_t c (plan, font, buffer);
+ trak.apply (&c);
+}
+
/**
* hb_aat_layout_get_feature_types:
* @face: #hb_face_t to work upon
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.hh b/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.hh
index ee33223651a..ffa54408ebf 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.hh
+++ b/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.hh
@@ -60,9 +60,6 @@ hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan,
const hb_feature_t *features,
unsigned num_features);
-HB_INTERNAL void
-hb_aat_layout_zero_width_deleted_glyphs (hb_buffer_t *buffer);
-
HB_INTERNAL void
hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer);
@@ -71,5 +68,10 @@ hb_aat_layout_position (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
+HB_INTERNAL void
+hb_aat_layout_track (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer);
+
#endif /* HB_AAT_LAYOUT_HH */
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-aat-map.cc b/src/java.desktop/share/native/libharfbuzz/hb-aat-map.cc
index e0e9d14d9b8..306a95b7c4b 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-aat-map.cc
+++ b/src/java.desktop/share/native/libharfbuzz/hb-aat-map.cc
@@ -85,6 +85,11 @@ void
hb_aat_map_builder_t::compile (hb_aat_map_t &m)
{
/* Compute active features per range, and compile each. */
+ if (!features.length)
+ {
+ hb_aat_layout_compile_map (this, &m);
+ return;
+ }
/* Sort features by start/end events. */
hb_vector_t feature_events;
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-atomic.hh b/src/java.desktop/share/native/libharfbuzz/hb-atomic.hh
index d2de5f693f0..80bd90e87dc 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-atomic.hh
+++ b/src/java.desktop/share/native/libharfbuzz/hb-atomic.hh
@@ -80,15 +80,14 @@ _hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N)
#include
-#define _hb_memory_barrier() std::atomic_thread_fence(std::memory_order_ack_rel)
#define _hb_memory_r_barrier() std::atomic_thread_fence(std::memory_order_acquire)
#define _hb_memory_w_barrier() std::atomic_thread_fence(std::memory_order_release)
-#define hb_atomic_int_impl_add(AI, V) (reinterpret_cast::type> *> (AI)->fetch_add ((V), std::memory_order_acq_rel))
-#define hb_atomic_int_impl_set_relaxed(AI, V) (reinterpret_cast::type> *> (AI)->store ((V), std::memory_order_relaxed))
-#define hb_atomic_int_impl_set(AI, V) (reinterpret_cast::type> *> (AI)->store ((V), std::memory_order_release))
-#define hb_atomic_int_impl_get_relaxed(AI) (reinterpret_cast::type> const *> (AI)->load (std::memory_order_relaxed))
-#define hb_atomic_int_impl_get(AI) (reinterpret_cast::type> const *> (AI)->load (std::memory_order_acquire))
+#define hb_atomic_int_impl_add(AI, V) (reinterpret_cast::type> *> (AI)->fetch_add ((V), std::memory_order_acq_rel))
+#define hb_atomic_int_impl_set_relaxed(AI, V) (reinterpret_cast::type> *> (AI)->store ((V), std::memory_order_relaxed))
+#define hb_atomic_int_impl_set(AI, V) (reinterpret_cast::type> *> (AI)->store ((V), std::memory_order_release))
+#define hb_atomic_int_impl_get_relaxed(AI) (reinterpret_cast::type> const *> (AI)->load (std::memory_order_relaxed))
+#define hb_atomic_int_impl_get(AI) (reinterpret_cast::type> const *> (AI)->load (std::memory_order_acquire))
#define hb_atomic_ptr_impl_set_relaxed(P, V) (reinterpret_cast *> (P)->store ((V), std::memory_order_relaxed))
#define hb_atomic_ptr_impl_get_relaxed(P) (reinterpret_cast const *> (P)->load (std::memory_order_relaxed))
@@ -149,68 +148,53 @@ static inline void _hb_compiler_memory_r_barrier () {}
#define hb_atomic_ptr_impl_get_relaxed(P) (*(P))
#endif
#ifndef hb_atomic_int_impl_set
-inline void hb_atomic_int_impl_set (int *AI, int v) { _hb_memory_w_barrier (); *AI = v; }
-inline void hb_atomic_int_impl_set (short *AI, short v) { _hb_memory_w_barrier (); *AI = v; }
+template
+inline void hb_atomic_int_impl_set (T *AI, T v) { _hb_memory_w_barrier (); *AI = v; }
#endif
#ifndef hb_atomic_int_impl_get
-inline int hb_atomic_int_impl_get (const int *AI) { int v = *AI; _hb_memory_r_barrier (); return v; }
-inline short hb_atomic_int_impl_get (const short *AI) { short v = *AI; _hb_memory_r_barrier (); return v; }
+template
+inline T hb_atomic_int_impl_get (const T *AI) { T v = *AI; _hb_memory_r_barrier (); return v; }
#endif
#ifndef hb_atomic_ptr_impl_get
inline void *hb_atomic_ptr_impl_get (void ** const P) { void *v = *P; _hb_memory_r_barrier (); return v; }
#endif
-struct hb_atomic_short_t
+template
+struct hb_atomic_t
{
- hb_atomic_short_t () = default;
- constexpr hb_atomic_short_t (short v) : v (v) {}
+ hb_atomic_t () = default;
+ constexpr hb_atomic_t (T v) : v (v) {}
- hb_atomic_short_t& operator = (short v_) { set_relaxed (v_); return *this; }
- operator short () const { return get_relaxed (); }
+ hb_atomic_t& operator = (T v_) { set_relaxed (v_); return *this; }
+ operator T () const { return get_relaxed (); }
- void set_relaxed (short v_) { hb_atomic_int_impl_set_relaxed (&v, v_); }
- void set_release (short v_) { hb_atomic_int_impl_set (&v, v_); }
- short get_relaxed () const { return hb_atomic_int_impl_get_relaxed (&v); }
- short get_acquire () const { return hb_atomic_int_impl_get (&v); }
- short inc () { return hb_atomic_int_impl_add (&v, 1); }
- short dec () { return hb_atomic_int_impl_add (&v, -1); }
+ void set_relaxed (T v_) { hb_atomic_int_impl_set_relaxed (&v, v_); }
+ void set_release (T v_) { hb_atomic_int_impl_set (&v, v_); }
+ T get_relaxed () const { return hb_atomic_int_impl_get_relaxed (&v); }
+ T get_acquire () const { return hb_atomic_int_impl_get (&v); }
+ T inc () { return hb_atomic_int_impl_add (&v, 1); }
+ T dec () { return hb_atomic_int_impl_add (&v, -1); }
- short v = 0;
+ int operator ++ (int) { return inc (); }
+ int operator -- (int) { return dec (); }
+ long operator |= (long v_) { set_relaxed (get_relaxed () | v_); return *this; }
+
+ T v = 0;
};
-struct hb_atomic_int_t
+template
+struct hb_atomic_t
{
- hb_atomic_int_t () = default;
- constexpr hb_atomic_int_t (int v) : v (v) {}
-
- hb_atomic_int_t& operator = (int v_) { set_relaxed (v_); return *this; }
- operator int () const { return get_relaxed (); }
-
- void set_relaxed (int v_) { hb_atomic_int_impl_set_relaxed (&v, v_); }
- void set_release (int v_) { hb_atomic_int_impl_set (&v, v_); }
- int get_relaxed () const { return hb_atomic_int_impl_get_relaxed (&v); }
- int get_acquire () const { return hb_atomic_int_impl_get (&v); }
- int inc () { return hb_atomic_int_impl_add (&v, 1); }
- int dec () { return hb_atomic_int_impl_add (&v, -1); }
-
- int v = 0;
-};
-
-template
-struct hb_atomic_ptr_t
-{
- typedef hb_remove_pointer T;
-
- hb_atomic_ptr_t () = default;
- constexpr hb_atomic_ptr_t (T* v) : v (v) {}
- hb_atomic_ptr_t (const hb_atomic_ptr_t &other) = delete;
+ hb_atomic_t () = default;
+ constexpr hb_atomic_t (T* v) : v (v) {}
+ hb_atomic_t (const hb_atomic_t &other) = delete;
void init (T* v_ = nullptr) { set_relaxed (v_); }
void set_relaxed (T* v_) { hb_atomic_ptr_impl_set_relaxed (&v, v_); }
T *get_relaxed () const { return (T *) hb_atomic_ptr_impl_get_relaxed (&v); }
T *get_acquire () const { return (T *) hb_atomic_ptr_impl_get ((void **) &v); }
- bool cmpexch (const T *old, T *new_) const { return hb_atomic_ptr_impl_cmpexch ((void **) &v, (void *) old, (void *) new_); }
+ bool cmpexch (const T *old, T *new_) { return hb_atomic_ptr_impl_cmpexch ((void **) &v, (void *) old, (void *) new_); }
operator bool () const { return get_acquire () != nullptr; }
T * operator -> () const { return get_acquire (); }
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-bit-set.hh b/src/java.desktop/share/native/libharfbuzz/hb-bit-set.hh
index c42e617f67a..799c3607599 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-bit-set.hh
+++ b/src/java.desktop/share/native/libharfbuzz/hb-bit-set.hh
@@ -77,7 +77,7 @@ struct hb_bit_set_t
bool successful = true; /* Allocations successful */
mutable unsigned int population = 0;
- mutable hb_atomic_int_t last_page_lookup = 0;
+ mutable hb_atomic_t last_page_lookup = 0;
hb_sorted_vector_t page_map;
hb_vector_t pages;
@@ -88,7 +88,7 @@ struct hb_bit_set_t
{
if (unlikely (!successful)) return false;
- if (pages.length < count && count <= 2)
+ if (pages.length < count && (unsigned) pages.allocated < count && count <= 2)
exact_size = true; // Most sets are small and local
if (unlikely (!pages.resize (count, clear, exact_size) ||
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-bit-vector.hh b/src/java.desktop/share/native/libharfbuzz/hb-bit-vector.hh
new file mode 100644
index 00000000000..2a0ec3a0710
--- /dev/null
+++ b/src/java.desktop/share/native/libharfbuzz/hb-bit-vector.hh
@@ -0,0 +1,195 @@
+/*
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_BIT_VECTOR_HH
+#define HB_BIT_VECTOR_HH
+
+#include "hb.hh"
+
+#include "hb-atomic.hh"
+
+struct hb_min_max_t
+{
+ void add (hb_codepoint_t v) { min_v = hb_min (min_v, v); max_v = hb_max (max_v, v); }
+ void add_range (hb_codepoint_t a, hb_codepoint_t b)
+ {
+ min_v = hb_min (min_v, a);
+ max_v = hb_max (max_v, b);
+ }
+
+ template
+ void union_ (const set_t &set)
+ {
+ hb_codepoint_t set_min = set.get_min ();
+ if (unlikely (set_min == HB_CODEPOINT_INVALID))
+ return;
+ hb_codepoint_t set_max = set.get_max ();
+ min_v = hb_min (min_v, set_min);
+ max_v = hb_max (max_v, set_max);
+ }
+
+ hb_codepoint_t get_min () const { return min_v; }
+ hb_codepoint_t get_max () const { return max_v; }
+
+ private:
+ hb_codepoint_t min_v = HB_CODEPOINT_INVALID;
+ hb_codepoint_t max_v = 0;
+};
+
+template
+struct hb_bit_vector_t
+{
+ using int_t = uint64_t;
+ using elt_t = typename std::conditional, int_t>::type;
+
+ hb_bit_vector_t () = delete;
+ hb_bit_vector_t (const hb_bit_vector_t &other) = delete;
+ hb_bit_vector_t &operator= (const hb_bit_vector_t &other) = delete;
+
+ // Move
+ hb_bit_vector_t (hb_bit_vector_t &&other)
+ : min_v (other.min_v), max_v (other.max_v), count (other.count), elts (other.elts)
+ {
+ other.min_v = other.max_v = other.count = 0;
+ other.elts = nullptr;
+ }
+ hb_bit_vector_t &operator= (hb_bit_vector_t &&other)
+ {
+ hb_swap (min_v, other.min_v);
+ hb_swap (max_v, other.max_v);
+ hb_swap (count, other.count);
+ hb_swap (elts, other.elts);
+ return *this;
+ }
+
+ hb_bit_vector_t (unsigned min_v, unsigned max_v)
+ : min_v (min_v), max_v (max_v)
+ {
+ if (unlikely (min_v >= max_v))
+ {
+ min_v = max_v = count = 0;
+ return;
+ }
+
+ unsigned num = (max_v - min_v + sizeof (int_t) * 8) / (sizeof (int_t) * 8);
+ elts = (elt_t *) hb_calloc (num, sizeof (int_t));
+ if (unlikely (!elts))
+ {
+ min_v = max_v = count = 0;
+ return;
+ }
+
+ count = max_v - min_v + 1;
+ }
+ ~hb_bit_vector_t ()
+ {
+ hb_free (elts);
+ }
+
+ void add (hb_codepoint_t g) { elt (g) |= mask (g); }
+ void del (hb_codepoint_t g) { elt (g) &= ~mask (g); }
+ void set (hb_codepoint_t g, bool value) { if (value) add (g); else del (g); }
+ bool get (hb_codepoint_t g) const { return elt (g) & mask (g); }
+ bool has (hb_codepoint_t g) const { return get (g); }
+ bool may_have (hb_codepoint_t g) const { return get (g); }
+
+ bool operator [] (hb_codepoint_t g) const { return get (g); }
+ bool operator () (hb_codepoint_t g) const { return get (g); }
+
+ void add_range (hb_codepoint_t a, hb_codepoint_t b)
+ {
+ if (unlikely (!count || a > b || a < min_v || b > max_v))
+ return;
+
+ elt_t *la = &elt (a);
+ elt_t *lb = &elt (b);
+ if (la == lb)
+ *la |= (mask (b) << 1) - mask(a);
+ else
+ {
+ *la |= ~(mask (a) - 1llu);
+ la++;
+
+ hb_memset (la, 0xff, (char *) lb - (char *) la);
+
+ *lb |= ((mask (b) << 1) - 1llu);
+ }
+ }
+ void del_range (hb_codepoint_t a, hb_codepoint_t b)
+ {
+ if (unlikely (!count || a > b || a < min_v || b > max_v))
+ return;
+
+ elt_t *la = &elt (a);
+ elt_t *lb = &elt (b);
+ if (la == lb)
+ *la &= ~((mask (b) << 1llu) - mask(a));
+ else
+ {
+ *la &= mask (a) - 1;
+ la++;
+
+ hb_memset (la, 0, (char *) lb - (char *) la);
+
+ *lb &= ~((mask (b) << 1) - 1llu);
+ }
+ }
+ void set_range (hb_codepoint_t a, hb_codepoint_t b, bool v)
+ { if (v) add_range (a, b); else del_range (a, b); }
+
+ template
+ void union_ (const set_t &set)
+ {
+ for (hb_codepoint_t g : set)
+ add (g);
+ }
+
+ static const unsigned int ELT_BITS = sizeof (elt_t) * 8;
+ static constexpr unsigned ELT_MASK = ELT_BITS - 1;
+
+ static constexpr elt_t zero = 0;
+
+ elt_t &elt (hb_codepoint_t g)
+ {
+ g -= min_v;
+ if (unlikely (g >= count))
+ return Crap(elt_t);
+ return elts[g / ELT_BITS];
+ }
+ const elt_t& elt (hb_codepoint_t g) const
+ {
+ g -= min_v;
+ if (unlikely (g >= count))
+ return Null(elt_t);
+ return elts[g / ELT_BITS];
+ }
+
+ static constexpr int_t mask (hb_codepoint_t g) { return elt_t (1) << (g & ELT_MASK); }
+
+ hb_codepoint_t min_v = 0, max_v = 0, count = 0;
+ elt_t *elts = nullptr;
+};
+
+
+#endif /* HB_BIT_VECTOR_HH */
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-json.hh b/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-json.hh
index 69cc1640230..255497b652d 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-json.hh
+++ b/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-json.hh
@@ -32,96 +32,83 @@
#include "hb.hh"
-#line 36 "hb-buffer-deserialize-json.hh"
+#line 33 "hb-buffer-deserialize-json.hh"
static const unsigned char _deserialize_json_trans_keys[] = {
- 0u, 0u, 9u, 123u, 9u, 123u, 9u, 34u, 97u, 117u, 120u, 121u, 34u, 34u, 9u, 58u,
- 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u,
- 48u, 57u, 9u, 125u, 9u, 125u, 108u, 108u, 34u, 34u, 9u, 58u, 9u, 57u, 9u, 125u,
- 9u, 125u, 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u,
- 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 108u, 108u, 34u, 34u,
- 9u, 58u, 9u, 57u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 34u, 92u,
- 9u, 125u, 34u, 92u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 9u, 125u,
- 9u, 93u, 9u, 123u, 0u, 0u, 0
+ 0u, 0u, 9u, 34u, 97u, 121u, 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u,
+ 9u, 125u, 9u, 125u, 9u, 93u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u,
+ 9u, 125u, 9u, 125u, 108u, 108u, 34u, 34u, 9u, 58u, 9u, 57u, 9u, 125u, 9u, 125u,
+ 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 34u, 34u,
+ 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 108u, 108u, 34u, 34u, 9u, 58u,
+ 9u, 57u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 34u, 92u, 9u, 125u,
+ 34u, 92u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u,
+ 34u, 34u, 9u, 58u, 9u, 57u, 9u, 125u, 98u, 98u, 9u, 123u, 9u, 123u, 9u, 123u,
+ 0
};
static const char _deserialize_json_key_spans[] = {
- 0, 115, 115, 26, 21, 2, 1, 50,
- 49, 10, 117, 117, 117, 1, 50, 49,
- 10, 117, 117, 1, 1, 50, 49, 117,
- 117, 2, 1, 50, 49, 10, 117, 117,
- 1, 50, 49, 10, 117, 117, 1, 1,
- 50, 49, 117, 117, 1, 50, 49, 59,
- 117, 59, 117, 117, 1, 50, 49, 117,
- 85, 115, 0
+ 0, 26, 25, 2, 1, 50, 49, 10,
+ 117, 117, 85, 117, 1, 50, 49, 10,
+ 117, 117, 1, 1, 50, 49, 117, 117,
+ 2, 1, 50, 49, 10, 117, 117, 1,
+ 50, 49, 10, 117, 117, 1, 1, 50,
+ 49, 117, 117, 1, 50, 49, 59, 117,
+ 59, 117, 117, 1, 50, 49, 10, 117,
+ 1, 50, 49, 117, 1, 115, 115, 115
};
static const short _deserialize_json_index_offsets[] = {
- 0, 0, 116, 232, 259, 281, 284, 286,
- 337, 387, 398, 516, 634, 752, 754, 805,
- 855, 866, 984, 1102, 1104, 1106, 1157, 1207,
- 1325, 1443, 1446, 1448, 1499, 1549, 1560, 1678,
- 1796, 1798, 1849, 1899, 1910, 2028, 2146, 2148,
- 2150, 2201, 2251, 2369, 2487, 2489, 2540, 2590,
- 2650, 2768, 2828, 2946, 3064, 3066, 3117, 3167,
- 3285, 3371, 3487
+ 0, 0, 27, 53, 56, 58, 109, 159,
+ 170, 288, 406, 492, 610, 612, 663, 713,
+ 724, 842, 960, 962, 964, 1015, 1065, 1183,
+ 1301, 1304, 1306, 1357, 1407, 1418, 1536, 1654,
+ 1656, 1707, 1757, 1768, 1886, 2004, 2006, 2008,
+ 2059, 2109, 2227, 2345, 2347, 2398, 2448, 2508,
+ 2626, 2686, 2804, 2922, 2924, 2975, 3025, 3036,
+ 3154, 3156, 3207, 3257, 3375, 3377, 3493, 3609
};
static const char _deserialize_json_indicies[] = {
0, 0, 0, 0, 0, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 0, 1, 1, 1, 1, 1, 1, 1,
+ 0, 1, 2, 1, 3, 1, 4, 5,
+ 1, 6, 7, 8, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 9, 1, 8, 10, 10, 1, 11, 12,
+ 1, 13, 1, 13, 13, 13, 13, 13,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 13, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 14, 1, 14, 14,
+ 14, 14, 14, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 14, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 15, 1, 1, 16, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 1,
+ 18, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 1, 20, 20, 20, 20, 20,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 2, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 3, 1, 2, 2, 2,
- 2, 2, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 2, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 3,
- 1, 4, 4, 4, 4, 4, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 4, 1, 5, 1, 6, 1, 7, 8,
- 1, 9, 10, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 11, 1, 12, 13, 1, 14, 1, 14,
- 14, 14, 14, 14, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 14, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 15, 1, 15, 15, 15, 15, 15, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 15, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 16, 1,
- 1, 17, 18, 18, 18, 18, 18, 18,
- 18, 18, 18, 1, 19, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 1, 21,
- 21, 21, 21, 21, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 20, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 21, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 22, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 22,
+ 1, 23, 23, 23, 23, 23, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 23, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 0, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -131,12 +118,52 @@ static const char _deserialize_json_indicies[] = {
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 23, 1, 24, 24, 24,
- 24, 24, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 24, 1, 24,
+ 24, 24, 24, 24, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 24, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 24, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 4, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 25, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 25, 1, 20, 20, 20,
+ 20, 20, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 20, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 21, 1, 1, 1, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 22, 1, 26, 1, 26, 26, 26,
+ 26, 26, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 26, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 27, 1,
+ 27, 27, 27, 27, 27, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 27,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 28, 1, 1, 29,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 1, 31, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 1, 33, 33, 33,
+ 33, 33, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 33, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 34, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -146,42 +173,13 @@ static const char _deserialize_json_indicies[] = {
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 25, 1, 21, 21, 21, 21, 21,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 21, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 22, 1,
- 1, 1, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 23,
- 1, 26, 1, 26, 26, 26, 26, 26,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 26, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 27, 1, 27, 27,
- 27, 27, 27, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 27, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 28, 1, 1, 29, 30, 30,
- 30, 30, 30, 30, 30, 30, 30, 1,
- 31, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 1, 33, 33, 33, 33, 33,
+ 1, 35, 1, 33, 33, 33, 33, 33,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 33, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 34, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -190,13 +188,24 @@ static const char _deserialize_json_indicies[] = {
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 35,
- 1, 33, 33, 33, 33, 33, 1, 1,
+ 1, 36, 1, 37, 1, 37, 37, 37,
+ 37, 37, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 37, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 33, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 34, 1, 1, 1,
- 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 38, 1,
+ 38, 38, 38, 38, 38, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 38,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 39,
+ 40, 40, 40, 40, 40, 40, 40, 40,
+ 40, 1, 41, 41, 41, 41, 41, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 41, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 42, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -204,25 +213,43 @@ static const char _deserialize_json_indicies[] = {
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 35, 1, 36,
- 1, 37, 1, 37, 37, 37, 37, 37,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 37, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 38, 1, 38, 38,
- 38, 38, 38, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 38, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 39, 40, 40,
- 40, 40, 40, 40, 40, 40, 40, 1,
+ 1, 1, 1, 1, 1, 1, 43, 1,
41, 41, 41, 41, 41, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 41,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 42, 1, 1, 1, 1,
+ 1, 1, 1, 42, 1, 1, 1, 44,
+ 44, 44, 44, 44, 44, 44, 44, 44,
+ 44, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 43, 1, 45, 46,
+ 1, 47, 1, 47, 47, 47, 47, 47,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 47, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 48, 1, 48, 48,
+ 48, 48, 48, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 48, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 49, 1, 1, 50, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 1,
+ 52, 53, 53, 53, 53, 53, 53, 53,
+ 53, 53, 1, 54, 54, 54, 54, 54,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 54, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 55, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -232,57 +259,41 @@ static const char _deserialize_json_indicies[] = {
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 43, 1, 41, 41,
- 41, 41, 41, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 41, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 42, 1, 1, 1, 44, 44, 44,
- 44, 44, 44, 44, 44, 44, 44, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 43, 1, 45, 46, 1, 47,
- 1, 47, 47, 47, 47, 47, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 47, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 48, 1, 48, 48, 48, 48,
- 48, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 48, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 49, 1, 1, 50, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 1, 52, 53,
- 53, 53, 53, 53, 53, 53, 53, 53,
+ 1, 1, 1, 1, 1, 1, 1, 56,
1, 54, 54, 54, 54, 54, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
54, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 55, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 56, 1, 54,
- 54, 54, 54, 54, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 54, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 55, 1, 1, 1, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53,
+ 53, 53, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 56, 1, 57,
+ 1, 57, 57, 57, 57, 57, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 57, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 58, 1, 58, 58, 58, 58,
+ 58, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 58, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 59, 1, 1, 60, 61, 61, 61, 61,
+ 61, 61, 61, 61, 61, 1, 62, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63,
+ 1, 64, 64, 64, 64, 64, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 64, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 65, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -291,26 +302,41 @@ static const char _deserialize_json_indicies[] = {
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 56, 1, 57, 1, 57,
- 57, 57, 57, 57, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 57, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 58, 1, 58, 58, 58, 58, 58, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 58, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 59, 1,
- 1, 60, 61, 61, 61, 61, 61, 61,
- 61, 61, 61, 1, 62, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 1, 64,
+ 1, 1, 1, 1, 1, 66, 1, 64,
64, 64, 64, 64, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 64, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 65, 1, 1, 1, 1, 1,
+ 1, 1, 65, 1, 1, 1, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 66, 1, 67, 1, 68,
+ 1, 68, 68, 68, 68, 68, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 68, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 69, 1, 69, 69, 69, 69,
+ 69, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 69, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 70, 71, 71, 71, 71,
+ 71, 71, 71, 71, 71, 1, 72, 72,
+ 72, 72, 72, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 72, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 73, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -320,39 +346,13 @@ static const char _deserialize_json_indicies[] = {
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 66, 1, 64, 64, 64,
- 64, 64, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 64, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 65, 1, 1, 1, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 66, 1, 67, 1, 68, 1, 68,
- 68, 68, 68, 68, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 68, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 69, 1, 69, 69, 69, 69, 69, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 69, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 70, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 1, 72, 72, 72, 72,
+ 1, 1, 74, 1, 72, 72, 72, 72,
72, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 72, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 73,
+ 1, 1, 1, 75, 75, 75, 75, 75,
+ 75, 75, 75, 75, 75, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -361,48 +361,32 @@ static const char _deserialize_json_indicies[] = {
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 74, 1, 76, 1, 76, 76, 76, 76,
+ 76, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 76, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 74, 1, 72, 72, 72, 72, 72, 1,
+ 1, 1, 1, 1, 1, 77, 1, 77,
+ 77, 77, 77, 77, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 72, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 73, 1, 1,
- 1, 75, 75, 75, 75, 75, 75, 75,
- 75, 75, 75, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 74, 1,
- 76, 1, 76, 76, 76, 76, 76, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 76, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 77, 1, 77, 77, 77,
- 77, 77, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 77, 1, 78, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 79, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 1, 82,
+ 1, 1, 1, 1, 1, 1, 77, 1,
+ 78, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 79, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80,
+ 1, 82, 81, 81, 81, 81, 81, 81,
81, 81, 81, 81, 81, 81, 81, 81,
81, 81, 81, 81, 81, 81, 81, 81,
81, 81, 81, 81, 81, 81, 81, 81,
81, 81, 81, 81, 81, 81, 81, 81,
81, 81, 81, 81, 81, 81, 81, 81,
81, 81, 81, 81, 81, 81, 81, 81,
- 81, 81, 81, 81, 81, 81, 81, 81,
- 81, 83, 81, 84, 84, 84, 84, 84,
+ 81, 81, 81, 83, 81, 84, 84, 84,
+ 84, 84, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 84, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 84, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 85, 1,
+ 85, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -412,20 +396,35 @@ static const char _deserialize_json_indicies[] = {
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 86,
- 1, 81, 1, 1, 1, 1, 1, 1,
+ 1, 86, 1, 81, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 81, 1, 87, 87, 87,
+ 1, 1, 1, 1, 1, 81, 1, 87,
+ 87, 87, 87, 87, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 87, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 88, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 89, 1, 87, 87, 87,
87, 87, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 87, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 88, 1, 1, 1, 1, 1, 1, 1,
+ 88, 1, 1, 1, 90, 90, 90, 90,
+ 90, 90, 90, 90, 90, 90, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -434,42 +433,27 @@ static const char _deserialize_json_indicies[] = {
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 89, 1, 91, 1, 91, 91, 91,
+ 91, 91, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 89, 1, 87, 87, 87, 87, 87,
+ 1, 1, 1, 1, 91, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 87, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 88, 1,
- 1, 1, 90, 90, 90, 90, 90, 90,
- 90, 90, 90, 90, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 92, 1,
+ 92, 92, 92, 92, 92, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 92,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 89,
- 1, 91, 1, 91, 91, 91, 91, 91,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 91, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 92, 1, 92, 92,
- 92, 92, 92, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 92, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 93, 94, 94,
- 94, 94, 94, 94, 94, 94, 94, 1,
- 87, 87, 87, 87, 87, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 87,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 88, 1, 1, 1, 95,
+ 1, 1, 1, 1, 93, 1, 1, 94,
95, 95, 95, 95, 95, 95, 95, 95,
- 95, 1, 1, 1, 1, 1, 1, 1,
+ 95, 1, 23, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 1, 23, 23, 23,
+ 23, 23, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 23, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 1, 1, 1, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -477,21 +461,53 @@ static const char _deserialize_json_indicies[] = {
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 89, 1, 96, 96,
- 96, 96, 96, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 96, 1, 1,
+ 1, 24, 1, 97, 1, 97, 97, 97,
+ 97, 97, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 97, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 97, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 98, 1,
+ 98, 98, 98, 98, 98, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 98,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 99,
+ 100, 100, 100, 100, 100, 100, 100, 100,
+ 100, 1, 87, 87, 87, 87, 87, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 87, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 88, 1, 1,
+ 1, 101, 101, 101, 101, 101, 101, 101,
+ 101, 101, 101, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 98, 1, 2, 2, 2, 2,
- 2, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 2, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 89, 1,
+ 8, 1, 102, 102, 102, 102, 102, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 102, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 103, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 104, 1, 103, 103,
+ 103, 103, 103, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 103, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -502,50 +518,66 @@ static const char _deserialize_json_indicies[] = {
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 3, 1,
- 1, 0
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 104, 1, 25, 25, 25, 25, 25, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 25, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 104, 1, 0
};
static const char _deserialize_json_trans_targs[] = {
- 1, 0, 2, 3, 3, 4, 5, 19,
- 25, 38, 44, 52, 6, 13, 7, 8,
- 9, 10, 12, 10, 12, 11, 3, 56,
- 11, 56, 14, 15, 16, 17, 18, 17,
- 18, 11, 3, 56, 20, 21, 22, 23,
- 24, 11, 3, 56, 24, 26, 32, 27,
- 28, 29, 30, 31, 30, 31, 11, 3,
- 56, 33, 34, 35, 36, 37, 36, 37,
- 11, 3, 56, 39, 40, 41, 42, 43,
- 11, 3, 56, 43, 45, 46, 47, 50,
- 51, 47, 48, 49, 11, 3, 56, 11,
- 3, 56, 51, 53, 54, 50, 55, 55,
- 56, 57, 58
+ 1, 0, 2, 3, 18, 24, 37, 43,
+ 51, 56, 60, 4, 12, 5, 6, 7,
+ 8, 11, 8, 11, 9, 1, 10, 9,
+ 10, 63, 13, 14, 15, 16, 17, 16,
+ 17, 9, 1, 10, 19, 20, 21, 22,
+ 23, 9, 1, 10, 23, 25, 31, 26,
+ 27, 28, 29, 30, 29, 30, 9, 1,
+ 10, 32, 33, 34, 35, 36, 35, 36,
+ 9, 1, 10, 38, 39, 40, 41, 42,
+ 9, 1, 10, 42, 44, 45, 46, 49,
+ 50, 46, 47, 48, 9, 1, 10, 9,
+ 1, 10, 50, 52, 53, 54, 9, 55,
+ 55, 57, 58, 49, 59, 59, 61, 62,
+ 1
};
static const char _deserialize_json_trans_actions[] = {
- 0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
- 2, 2, 2, 0, 0, 3, 3, 4,
- 0, 5, 0, 0, 2, 2, 2, 0,
- 0, 6, 6, 7, 0, 0, 0, 2,
- 2, 8, 8, 9, 0, 0, 0, 0,
- 0, 2, 2, 2, 0, 0, 10, 10,
- 11, 0, 0, 2, 2, 2, 0, 0,
- 12, 12, 13, 0, 0, 0, 2, 2,
- 14, 14, 15, 0, 0, 0, 2, 16,
- 16, 0, 17, 0, 18, 18, 19, 20,
- 20, 21, 17, 0, 0, 22, 22, 23,
- 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 1,
+ 1, 1, 0, 0, 2, 2, 2, 0,
+ 0, 3, 0, 0, 1, 1, 1, 0,
+ 0, 4, 4, 4, 0, 0, 0, 1,
+ 1, 5, 5, 5, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0, 6, 6,
+ 6, 0, 0, 1, 1, 1, 0, 0,
+ 7, 7, 7, 0, 0, 0, 1, 1,
+ 8, 8, 8, 0, 0, 0, 1, 9,
+ 9, 0, 10, 0, 11, 11, 11, 12,
+ 12, 12, 10, 0, 0, 1, 1, 1,
+ 0, 0, 0, 13, 13, 14, 0, 0,
+ 15
};
-static const int deserialize_json_start = 1;
-static const int deserialize_json_first_final = 56;
+static const int deserialize_json_start = 61;
+static const int deserialize_json_first_final = 61;
static const int deserialize_json_error = 0;
-static const int deserialize_json_en_main = 1;
+static const int deserialize_json_en_main = 61;
-#line 111 "hb-buffer-deserialize-json.rl"
+#line 115 "hb-buffer-deserialize-json.rl"
static hb_bool_t
@@ -565,12 +597,12 @@ _hb_buffer_deserialize_json (hb_buffer_t *buffer,
hb_glyph_info_t info = {0};
hb_glyph_position_t pos = {0};
-#line 569 "hb-buffer-deserialize-json.hh"
+#line 594 "hb-buffer-deserialize-json.hh"
{
cs = deserialize_json_start;
}
-#line 574 "hb-buffer-deserialize-json.hh"
+#line 597 "hb-buffer-deserialize-json.hh"
{
int _slen;
int _trans;
@@ -595,14 +627,14 @@ _resume:
goto _again;
switch ( _deserialize_json_trans_actions[_trans] ) {
- case 1:
+ case 15:
#line 38 "hb-buffer-deserialize-json.rl"
{
hb_memset (&info, 0, sizeof (info));
hb_memset (&pos , 0, sizeof (pos ));
}
break;
- case 5:
+ case 3:
#line 43 "hb-buffer-deserialize-json.rl"
{
buffer->add_info (info);
@@ -612,75 +644,21 @@ _resume:
*end_ptr = p;
}
break;
- case 2:
+ case 1:
#line 51 "hb-buffer-deserialize-json.rl"
{
tok = p;
}
- break;
- case 17:
-#line 55 "hb-buffer-deserialize-json.rl"
- { if (unlikely (!buffer->ensure_glyphs ())) return false; }
- break;
- case 23:
-#line 56 "hb-buffer-deserialize-json.rl"
- { if (unlikely (!buffer->ensure_unicode ())) return false; }
- break;
- case 18:
-#line 58 "hb-buffer-deserialize-json.rl"
- {
- /* TODO Unescape \" and \\ if found. */
- if (!hb_font_glyph_from_string (font,
- tok+1, p - tok - 2, /* Skip "" */
- &info.codepoint))
- return false;
-}
- break;
- case 20:
-#line 66 "hb-buffer-deserialize-json.rl"
- { if (!parse_uint (tok, p, &info.codepoint)) return false; }
- break;
- case 8:
-#line 67 "hb-buffer-deserialize-json.rl"
- { if (!parse_uint (tok, p, &info.cluster )) return false; }
break;
case 10:
-#line 68 "hb-buffer-deserialize-json.rl"
- { if (!parse_int (tok, p, &pos.x_offset )) return false; }
- break;
- case 12:
-#line 69 "hb-buffer-deserialize-json.rl"
- { if (!parse_int (tok, p, &pos.y_offset )) return false; }
- break;
- case 3:
-#line 70 "hb-buffer-deserialize-json.rl"
- { if (!parse_int (tok, p, &pos.x_advance)) return false; }
- break;
- case 6:
-#line 71 "hb-buffer-deserialize-json.rl"
- { if (!parse_int (tok, p, &pos.y_advance)) return false; }
- break;
- case 14:
-#line 72 "hb-buffer-deserialize-json.rl"
- { if (!parse_uint (tok, p, &info.mask )) return false; }
- break;
- case 16:
-#line 51 "hb-buffer-deserialize-json.rl"
- {
- tok = p;
-}
#line 55 "hb-buffer-deserialize-json.rl"
{ if (unlikely (!buffer->ensure_glyphs ())) return false; }
break;
- case 22:
-#line 51 "hb-buffer-deserialize-json.rl"
- {
- tok = p;
-}
+ case 14:
#line 56 "hb-buffer-deserialize-json.rl"
{ if (unlikely (!buffer->ensure_unicode ())) return false; }
break;
- case 19:
+ case 11:
#line 58 "hb-buffer-deserialize-json.rl"
{
/* TODO Unescape \" and \\ if found. */
@@ -688,101 +666,53 @@ _resume:
tok+1, p - tok - 2, /* Skip "" */
&info.codepoint))
return false;
-}
-#line 43 "hb-buffer-deserialize-json.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
}
break;
- case 21:
+ case 12:
#line 66 "hb-buffer-deserialize-json.rl"
{ if (!parse_uint (tok, p, &info.codepoint)) return false; }
-#line 43 "hb-buffer-deserialize-json.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
break;
- case 9:
+ case 5:
#line 67 "hb-buffer-deserialize-json.rl"
{ if (!parse_uint (tok, p, &info.cluster )) return false; }
-#line 43 "hb-buffer-deserialize-json.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
break;
- case 11:
+ case 6:
#line 68 "hb-buffer-deserialize-json.rl"
{ if (!parse_int (tok, p, &pos.x_offset )) return false; }
-#line 43 "hb-buffer-deserialize-json.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 13:
-#line 69 "hb-buffer-deserialize-json.rl"
- { if (!parse_int (tok, p, &pos.y_offset )) return false; }
-#line 43 "hb-buffer-deserialize-json.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 4:
-#line 70 "hb-buffer-deserialize-json.rl"
- { if (!parse_int (tok, p, &pos.x_advance)) return false; }
-#line 43 "hb-buffer-deserialize-json.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
break;
case 7:
+#line 69 "hb-buffer-deserialize-json.rl"
+ { if (!parse_int (tok, p, &pos.y_offset )) return false; }
+ break;
+ case 2:
+#line 70 "hb-buffer-deserialize-json.rl"
+ { if (!parse_int (tok, p, &pos.x_advance)) return false; }
+ break;
+ case 4:
#line 71 "hb-buffer-deserialize-json.rl"
{ if (!parse_int (tok, p, &pos.y_advance)) return false; }
-#line 43 "hb-buffer-deserialize-json.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
break;
- case 15:
+ case 8:
#line 72 "hb-buffer-deserialize-json.rl"
{ if (!parse_uint (tok, p, &info.mask )) return false; }
-#line 43 "hb-buffer-deserialize-json.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
break;
-#line 786 "hb-buffer-deserialize-json.hh"
+ case 9:
+#line 51 "hb-buffer-deserialize-json.rl"
+ {
+ tok = p;
+}
+#line 55 "hb-buffer-deserialize-json.rl"
+ { if (unlikely (!buffer->ensure_glyphs ())) return false; }
+ break;
+ case 13:
+#line 51 "hb-buffer-deserialize-json.rl"
+ {
+ tok = p;
+}
+#line 56 "hb-buffer-deserialize-json.rl"
+ { if (unlikely (!buffer->ensure_unicode ())) return false; }
+ break;
+#line 689 "hb-buffer-deserialize-json.hh"
}
_again:
@@ -794,12 +724,12 @@ _again:
_out: {}
}
-#line 132 "hb-buffer-deserialize-json.rl"
+#line 136 "hb-buffer-deserialize-json.rl"
*end_ptr = p;
- return p == pe && *(p-1) != ']';
+ return p == pe;
}
#endif /* HB_BUFFER_DESERIALIZE_JSON_HH */
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-text-glyphs.hh b/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-text-glyphs.hh
index 8e526ce4e2a..78570486376 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-text-glyphs.hh
+++ b/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-text-glyphs.hh
@@ -32,287 +32,344 @@
#include "hb.hh"
-#line 36 "hb-buffer-deserialize-text-glyphs.hh"
+#line 33 "hb-buffer-deserialize-text-glyphs.hh"
static const unsigned char _deserialize_text_glyphs_trans_keys[] = {
- 0u, 0u, 48u, 57u, 45u, 57u, 48u, 57u, 45u, 57u, 48u, 57u, 48u, 57u, 45u, 57u,
- 48u, 57u, 44u, 44u, 45u, 57u, 48u, 57u, 44u, 57u, 43u, 124u, 9u, 124u, 9u, 124u,
- 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u,
- 9u, 124u, 9u, 124u, 9u, 124u, 0
+ 0u, 0u, 35u, 124u, 48u, 57u, 60u, 124u, 45u, 57u, 48u, 57u, 44u, 44u, 45u, 57u,
+ 48u, 57u, 44u, 44u, 45u, 57u, 48u, 57u, 44u, 44u, 45u, 57u, 48u, 57u, 62u, 62u,
+ 93u, 124u, 45u, 57u, 48u, 57u, 35u, 124u, 45u, 57u, 48u, 57u, 35u, 124u, 35u, 124u,
+ 35u, 124u, 35u, 124u, 35u, 124u, 35u, 124u, 48u, 57u, 35u, 124u, 45u, 57u, 48u, 57u,
+ 44u, 44u, 45u, 57u, 48u, 57u, 35u, 124u, 35u, 124u, 44u, 57u, 35u, 124u, 43u, 124u,
+ 35u, 124u, 48u, 62u, 44u, 57u, 44u, 57u, 44u, 57u, 48u, 124u, 35u, 124u, 35u, 124u,
+ 35u, 124u, 0
};
static const char _deserialize_text_glyphs_key_spans[] = {
- 0, 10, 13, 10, 13, 10, 10, 13,
- 10, 1, 13, 10, 14, 82, 116, 116,
- 116, 116, 116, 116, 116, 116, 116, 116,
- 116, 116, 116
+ 0, 90, 10, 65, 13, 10, 1, 13,
+ 10, 1, 13, 10, 1, 13, 10, 1,
+ 32, 13, 10, 90, 13, 10, 90, 90,
+ 90, 90, 90, 90, 10, 90, 13, 10,
+ 1, 13, 10, 90, 90, 14, 90, 82,
+ 90, 15, 14, 14, 14, 77, 90, 90,
+ 90
};
static const short _deserialize_text_glyphs_index_offsets[] = {
- 0, 0, 11, 25, 36, 50, 61, 72,
- 86, 97, 99, 113, 124, 139, 222, 339,
- 456, 573, 690, 807, 924, 1041, 1158, 1275,
- 1392, 1509, 1626
+ 0, 0, 91, 102, 168, 182, 193, 195,
+ 209, 220, 222, 236, 247, 249, 263, 274,
+ 276, 309, 323, 334, 425, 439, 450, 541,
+ 632, 723, 814, 905, 996, 1007, 1098, 1112,
+ 1123, 1125, 1139, 1150, 1241, 1332, 1347, 1438,
+ 1521, 1612, 1628, 1643, 1658, 1673, 1751, 1842,
+ 1933
};
static const char _deserialize_text_glyphs_indicies[] = {
- 0, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 1, 3, 1, 1, 4,
- 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 1, 6, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 1, 8, 1, 1,
- 9, 10, 10, 10, 10, 10, 10, 10,
- 10, 10, 1, 11, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 1, 13, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 1, 15, 1, 1, 16, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 1, 18,
+ 1, 0, 0, 0, 0, 0, 0,
+ 0, 2, 3, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 4, 5, 0, 0, 6, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 7, 8, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 8, 0, 9, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 3, 11,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 12, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 12,
+ 3, 13, 3, 3, 14, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 3, 14,
+ 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 3, 16, 3, 17, 3, 3, 18,
19, 19, 19, 19, 19, 19, 19, 19,
- 19, 1, 20, 1, 21, 1, 1, 22,
- 23, 23, 23, 23, 23, 23, 23, 23,
- 23, 1, 24, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 1, 20, 1, 1,
- 1, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 1, 26, 26, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 26, 1,
- 1, 26, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 26, 26, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 26, 1, 28,
- 28, 28, 28, 28, 27, 27, 27, 27,
- 27, 27, 27, 27, 27, 27, 27, 27,
- 27, 27, 27, 27, 27, 27, 28, 27,
- 27, 29, 27, 27, 27, 27, 27, 27,
- 27, 30, 1, 27, 27, 27, 27, 27,
- 27, 27, 27, 27, 27, 27, 27, 27,
- 27, 27, 27, 31, 27, 27, 32, 27,
- 27, 27, 27, 27, 27, 27, 27, 27,
- 27, 27, 27, 27, 27, 27, 27, 27,
- 27, 27, 27, 27, 27, 27, 27, 27,
- 27, 27, 33, 1, 27, 27, 27, 27,
- 27, 27, 27, 27, 27, 27, 27, 27,
- 27, 27, 27, 27, 27, 27, 27, 27,
- 27, 27, 27, 27, 27, 27, 27, 27,
- 27, 27, 28, 27, 34, 34, 34, 34,
- 34, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 34, 26, 26, 35, 26,
- 26, 26, 26, 26, 26, 26, 36, 1,
- 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26,
- 37, 26, 26, 38, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 39,
- 1, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 40,
- 26, 41, 41, 41, 41, 41, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 41, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 42, 1, 43, 43,
- 43, 43, 43, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 43, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 44, 1, 41, 41, 41, 41, 41,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 41, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 42, 1,
- 46, 46, 46, 46, 46, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 46,
- 1, 1, 47, 1, 1, 1, 1, 1,
- 1, 1, 1, 48, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 49, 1, 50, 50, 50,
- 50, 50, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 50, 1, 1, 51,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 52, 1, 50, 50, 50, 50, 50, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 50, 1, 1, 51, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 52, 1, 46,
- 46, 46, 46, 46, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 46, 1,
- 1, 47, 1, 1, 1, 1, 1, 1,
- 1, 1, 48, 1, 1, 1, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 49, 1, 53, 53, 53, 53,
- 53, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 53, 1, 1, 54, 1,
- 1, 1, 1, 1, 1, 1, 55, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 56, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 57,
- 1, 58, 58, 58, 58, 58, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 58, 1, 1, 59, 1, 1, 1, 1,
- 1, 1, 1, 60, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 61, 1, 58, 58,
- 58, 58, 58, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 58, 1, 1,
- 59, 1, 1, 1, 1, 1, 1, 1,
- 60, 1, 1, 1, 1, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 61, 1, 53, 53, 53, 53, 53,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 53, 1, 1, 54, 1, 1,
- 1, 1, 1, 1, 1, 55, 1, 1,
- 1, 1, 62, 62, 62, 62, 62, 62,
- 62, 62, 62, 62, 1, 1, 1, 1,
- 1, 1, 56, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 57, 1,
- 0
+ 19, 3, 18, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 3, 20, 3, 21,
+ 3, 3, 22, 23, 23, 23, 23, 23,
+ 23, 23, 23, 23, 3, 22, 23, 23,
+ 23, 23, 23, 23, 23, 23, 23, 3,
+ 24, 3, 25, 3, 3, 26, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 3,
+ 26, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 3, 28, 3, 29, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 29, 3, 30, 3,
+ 3, 31, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 3, 33, 34, 34, 34,
+ 34, 34, 34, 34, 34, 34, 3, 35,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 36, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 37, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 38, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 38, 3, 39, 3, 3, 40, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 3,
+ 42, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 3, 44, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 45, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 46, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 46, 3, 44, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 3, 3, 45,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 46, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 46,
+ 3, 35, 3, 3, 3, 3, 3, 3,
+ 3, 3, 36, 3, 3, 3, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34, 34,
+ 3, 3, 37, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 38, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 38, 3, 1, 0, 0, 0,
+ 0, 0, 0, 0, 2, 3, 47, 0,
+ 0, 48, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 0, 0, 4, 5, 0,
+ 0, 6, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 7, 8, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 8, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 2,
+ 3, 0, 0, 0, 48, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 0, 0,
+ 4, 5, 0, 0, 6, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 7, 8, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 8, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 2, 16, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 4, 5, 0, 0, 6,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 7, 8, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 8, 0, 50, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 3,
+ 52, 3, 3, 3, 3, 3, 3, 3,
+ 53, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 54, 3, 3, 3, 55, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 56, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 56, 3, 57, 3, 3, 58, 59,
+ 59, 59, 59, 59, 59, 59, 59, 59,
+ 3, 60, 61, 61, 61, 61, 61, 61,
+ 61, 61, 61, 3, 62, 3, 63, 3,
+ 3, 64, 65, 65, 65, 65, 65, 65,
+ 65, 65, 65, 3, 66, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 3, 68,
+ 3, 3, 3, 3, 3, 3, 3, 69,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 70, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 71, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 71, 3, 68, 3, 3, 3, 3, 3,
+ 3, 3, 69, 3, 3, 3, 3, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 3, 3, 70, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 71, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 71, 3, 62, 3, 3,
+ 3, 61, 61, 61, 61, 61, 61, 61,
+ 61, 61, 61, 3, 52, 3, 3, 3,
+ 3, 3, 3, 3, 53, 3, 3, 3,
+ 3, 72, 72, 72, 72, 72, 72, 72,
+ 72, 72, 72, 3, 3, 54, 3, 3,
+ 3, 55, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 56, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 56, 3, 0,
+ 0, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 0, 3, 3, 0, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 0, 0, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 0, 3, 1, 0, 0, 0, 0, 0,
+ 0, 0, 2, 16, 0, 0, 0, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 0, 0, 4, 5, 0, 0, 6,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 7, 8, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 8, 0, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 3,
+ 3, 3, 3, 28, 3, 24, 3, 3,
+ 3, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 3, 20, 3, 3, 3,
+ 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 3, 16, 3, 3, 3, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 3, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 3, 3, 11, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 12,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 12, 3,
+ 75, 74, 74, 74, 74, 74, 74, 74,
+ 76, 3, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 77, 78, 74, 74, 79, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 74,
+ 80, 81, 82, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 82, 74, 84, 83, 83, 83, 83,
+ 83, 83, 83, 85, 3, 83, 83, 83,
+ 83, 83, 83, 83, 83, 83, 83, 83,
+ 83, 83, 83, 83, 86, 87, 83, 83,
+ 88, 83, 83, 83, 83, 83, 83, 83,
+ 83, 83, 83, 83, 83, 83, 83, 83,
+ 83, 83, 83, 83, 83, 83, 83, 83,
+ 83, 83, 83, 83, 89, 90, 83, 83,
+ 83, 83, 83, 83, 83, 83, 83, 83,
+ 83, 83, 83, 83, 83, 83, 83, 83,
+ 83, 83, 83, 83, 83, 83, 83, 83,
+ 83, 83, 83, 83, 90, 83, 91, 74,
+ 74, 74, 74, 74, 74, 74, 92, 3,
+ 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 93,
+ 94, 74, 74, 95, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 81,
+ 96, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 96,
+ 74, 0
};
static const char _deserialize_text_glyphs_trans_targs[] = {
- 16, 0, 18, 3, 19, 22, 19, 22,
- 5, 20, 21, 20, 21, 23, 26, 8,
- 9, 12, 9, 12, 10, 11, 24, 25,
- 24, 25, 15, 15, 14, 1, 2, 6,
- 7, 13, 15, 1, 2, 6, 7, 13,
- 14, 17, 14, 17, 14, 18, 17, 1,
- 4, 14, 17, 1, 14, 17, 1, 2,
- 7, 14, 17, 1, 2, 14, 26
+ 1, 2, 17, 0, 25, 28, 30, 39,
+ 47, 3, 45, 4, 47, 5, 6, 44,
+ 7, 8, 9, 43, 10, 11, 12, 42,
+ 13, 14, 15, 41, 16, 47, 18, 19,
+ 24, 19, 24, 2, 20, 4, 47, 21,
+ 22, 23, 22, 23, 2, 4, 47, 26,
+ 27, 40, 29, 38, 2, 17, 4, 30,
+ 47, 31, 32, 37, 32, 37, 33, 34,
+ 35, 36, 35, 36, 2, 17, 4, 47,
+ 38, 45, 1, 2, 17, 25, 28, 30,
+ 48, 39, 47, 1, 2, 17, 25, 28,
+ 30, 39, 47, 2, 17, 25, 28, 30,
+ 47
};
static const char _deserialize_text_glyphs_trans_actions[] = {
- 1, 0, 1, 1, 1, 1, 0, 0,
- 1, 1, 1, 0, 0, 1, 1, 1,
- 1, 1, 0, 0, 2, 1, 1, 1,
- 0, 0, 0, 4, 3, 5, 5, 5,
- 5, 4, 6, 7, 7, 7, 7, 0,
- 6, 8, 8, 0, 0, 0, 9, 10,
- 10, 9, 11, 12, 11, 13, 14, 14,
- 14, 13, 15, 16, 16, 15, 0
+ 0, 1, 1, 0, 1, 1, 1, 0,
+ 1, 2, 2, 3, 3, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 2, 2,
+ 2, 0, 0, 4, 4, 4, 4, 2,
+ 2, 2, 0, 0, 5, 5, 5, 0,
+ 0, 0, 2, 2, 6, 6, 6, 6,
+ 6, 2, 2, 2, 0, 0, 7, 2,
+ 2, 2, 0, 0, 8, 8, 8, 8,
+ 0, 0, 9, 10, 10, 10, 10, 10,
+ 9, 9, 10, 12, 13, 13, 13, 13,
+ 13, 12, 13, 14, 14, 14, 14, 14,
+ 14
};
static const char _deserialize_text_glyphs_eof_actions[] = {
0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 3, 6,
- 8, 0, 8, 9, 11, 11, 9, 13,
- 15, 15, 13
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 11,
+ 0
};
-static const int deserialize_text_glyphs_start = 14;
-static const int deserialize_text_glyphs_first_final = 14;
+static const int deserialize_text_glyphs_start = 46;
+static const int deserialize_text_glyphs_first_final = 46;
static const int deserialize_text_glyphs_error = 0;
-static const int deserialize_text_glyphs_en_main = 14;
+static const int deserialize_text_glyphs_en_main = 46;
-#line 98 "hb-buffer-deserialize-text-glyphs.rl"
+#line 101 "hb-buffer-deserialize-text-glyphs.rl"
static hb_bool_t
@@ -322,39 +379,22 @@ _hb_buffer_deserialize_text_glyphs (hb_buffer_t *buffer,
const char **end_ptr,
hb_font_t *font)
{
- const char *p = buf, *pe = buf + buf_len, *eof = pe, *orig_pe = pe;
+ const char *p = buf, *pe = buf + buf_len, *eof = pe;
/* Ensure we have positions. */
(void) hb_buffer_get_glyph_positions (buffer, nullptr);
- while (p < pe && ISSPACE (*p))
- p++;
- if (p < pe && *p == (buffer->len ? '|' : '['))
- *end_ptr = ++p;
-
- const char *end = strchr ((char *) p, ']');
- if (end)
- pe = eof = end;
- else
- {
- end = strrchr ((char *) p, '|');
- if (end)
- pe = eof = end;
- else
- pe = eof = p;
- }
-
const char *tok = nullptr;
int cs;
hb_glyph_info_t info = {0};
hb_glyph_position_t pos = {0};
-#line 353 "hb-buffer-deserialize-text-glyphs.hh"
+#line 386 "hb-buffer-deserialize-text-glyphs.hh"
{
cs = deserialize_text_glyphs_start;
}
-#line 358 "hb-buffer-deserialize-text-glyphs.hh"
+#line 389 "hb-buffer-deserialize-text-glyphs.hh"
{
int _slen;
int _trans;
@@ -379,55 +419,68 @@ _resume:
goto _again;
switch ( _deserialize_text_glyphs_trans_actions[_trans] ) {
- case 1:
-#line 51 "hb-buffer-deserialize-text-glyphs.rl"
+ case 2:
+#line 50 "hb-buffer-deserialize-text-glyphs.rl"
{
tok = p;
}
break;
- case 7:
-#line 55 "hb-buffer-deserialize-text-glyphs.rl"
+ case 1:
+#line 54 "hb-buffer-deserialize-text-glyphs.rl"
{
/* TODO Unescape delimiters. */
if (!hb_font_glyph_from_string (font,
tok, p - tok,
&info.codepoint))
return false;
-}
- break;
- case 14:
-#line 63 "hb-buffer-deserialize-text-glyphs.rl"
- { if (!parse_uint (tok, p, &info.cluster )) return false; }
- break;
- case 2:
-#line 64 "hb-buffer-deserialize-text-glyphs.rl"
- { if (!parse_int (tok, p, &pos.x_offset )) return false; }
- break;
- case 16:
-#line 65 "hb-buffer-deserialize-text-glyphs.rl"
- { if (!parse_int (tok, p, &pos.y_offset )) return false; }
- break;
- case 10:
-#line 66 "hb-buffer-deserialize-text-glyphs.rl"
- { if (!parse_int (tok, p, &pos.x_advance)) return false; }
- break;
- case 12:
-#line 67 "hb-buffer-deserialize-text-glyphs.rl"
- { if (!parse_int (tok, p, &pos.y_advance)) return false; }
- break;
- case 4:
-#line 38 "hb-buffer-deserialize-text-glyphs.rl"
- {
- hb_memset (&info, 0, sizeof (info));
- hb_memset (&pos , 0, sizeof (pos ));
-}
-#line 51 "hb-buffer-deserialize-text-glyphs.rl"
- {
- tok = p;
}
break;
case 6:
-#line 55 "hb-buffer-deserialize-text-glyphs.rl"
+#line 62 "hb-buffer-deserialize-text-glyphs.rl"
+ { if (!parse_uint (tok, p, &info.cluster )) return false; }
+ break;
+ case 7:
+#line 63 "hb-buffer-deserialize-text-glyphs.rl"
+ { if (!parse_int (tok, p, &pos.x_offset )) return false; }
+ break;
+ case 8:
+#line 64 "hb-buffer-deserialize-text-glyphs.rl"
+ { if (!parse_int (tok, p, &pos.y_offset )) return false; }
+ break;
+ case 4:
+#line 65 "hb-buffer-deserialize-text-glyphs.rl"
+ { if (!parse_int (tok, p, &pos.x_advance)) return false; }
+ break;
+ case 5:
+#line 66 "hb-buffer-deserialize-text-glyphs.rl"
+ { if (!parse_int (tok, p, &pos.y_advance)) return false; }
+ break;
+ case 3:
+#line 67 "hb-buffer-deserialize-text-glyphs.rl"
+ { if (!parse_uint (tok, p, &info.mask )) return false; }
+ break;
+ case 9:
+#line 38 "hb-buffer-deserialize-text-glyphs.rl"
+ {
+ hb_memset (&info, 0, sizeof (info));
+ hb_memset (&pos , 0, sizeof (pos ));
+}
+#line 50 "hb-buffer-deserialize-text-glyphs.rl"
+ {
+ tok = p;
+}
+ break;
+ case 10:
+#line 38 "hb-buffer-deserialize-text-glyphs.rl"
+ {
+ hb_memset (&info, 0, sizeof (info));
+ hb_memset (&pos , 0, sizeof (pos ));
+}
+#line 50 "hb-buffer-deserialize-text-glyphs.rl"
+ {
+ tok = p;
+}
+#line 54 "hb-buffer-deserialize-text-glyphs.rl"
{
/* TODO Unescape delimiters. */
if (!hb_font_glyph_from_string (font,
@@ -435,86 +488,62 @@ _resume:
&info.codepoint))
return false;
}
+ break;
+ case 12:
#line 43 "hb-buffer-deserialize-text-glyphs.rl"
{
- buffer->add_info (info);
+ buffer->add_info_and_pos (info, pos);
if (unlikely (!buffer->successful))
return false;
- buffer->pos[buffer->len - 1] = pos;
*end_ptr = p;
+}
+#line 38 "hb-buffer-deserialize-text-glyphs.rl"
+ {
+ hb_memset (&info, 0, sizeof (info));
+ hb_memset (&pos , 0, sizeof (pos ));
+}
+#line 50 "hb-buffer-deserialize-text-glyphs.rl"
+ {
+ tok = p;
+}
+ break;
+ case 14:
+#line 54 "hb-buffer-deserialize-text-glyphs.rl"
+ {
+ /* TODO Unescape delimiters. */
+ if (!hb_font_glyph_from_string (font,
+ tok, p - tok,
+ &info.codepoint))
+ return false;
+}
+#line 38 "hb-buffer-deserialize-text-glyphs.rl"
+ {
+ hb_memset (&info, 0, sizeof (info));
+ hb_memset (&pos , 0, sizeof (pos ));
+}
+#line 50 "hb-buffer-deserialize-text-glyphs.rl"
+ {
+ tok = p;
}
break;
case 13:
-#line 63 "hb-buffer-deserialize-text-glyphs.rl"
- { if (!parse_uint (tok, p, &info.cluster )) return false; }
#line 43 "hb-buffer-deserialize-text-glyphs.rl"
{
- buffer->add_info (info);
+ buffer->add_info_and_pos (info, pos);
if (unlikely (!buffer->successful))
return false;
- buffer->pos[buffer->len - 1] = pos;
*end_ptr = p;
}
- break;
- case 15:
-#line 65 "hb-buffer-deserialize-text-glyphs.rl"
- { if (!parse_int (tok, p, &pos.y_offset )) return false; }
-#line 43 "hb-buffer-deserialize-text-glyphs.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 9:
-#line 66 "hb-buffer-deserialize-text-glyphs.rl"
- { if (!parse_int (tok, p, &pos.x_advance)) return false; }
-#line 43 "hb-buffer-deserialize-text-glyphs.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 11:
-#line 67 "hb-buffer-deserialize-text-glyphs.rl"
- { if (!parse_int (tok, p, &pos.y_advance)) return false; }
-#line 43 "hb-buffer-deserialize-text-glyphs.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 8:
-#line 68 "hb-buffer-deserialize-text-glyphs.rl"
- { if (!parse_uint (tok, p, &info.mask )) return false; }
-#line 43 "hb-buffer-deserialize-text-glyphs.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 5:
#line 38 "hb-buffer-deserialize-text-glyphs.rl"
{
hb_memset (&info, 0, sizeof (info));
hb_memset (&pos , 0, sizeof (pos ));
}
-#line 51 "hb-buffer-deserialize-text-glyphs.rl"
+#line 50 "hb-buffer-deserialize-text-glyphs.rl"
{
tok = p;
}
-#line 55 "hb-buffer-deserialize-text-glyphs.rl"
+#line 54 "hb-buffer-deserialize-text-glyphs.rl"
{
/* TODO Unescape delimiters. */
if (!hb_font_glyph_from_string (font,
@@ -523,34 +552,7 @@ _resume:
return false;
}
break;
- case 3:
-#line 38 "hb-buffer-deserialize-text-glyphs.rl"
- {
- hb_memset (&info, 0, sizeof (info));
- hb_memset (&pos , 0, sizeof (pos ));
-}
-#line 51 "hb-buffer-deserialize-text-glyphs.rl"
- {
- tok = p;
-}
-#line 55 "hb-buffer-deserialize-text-glyphs.rl"
- {
- /* TODO Unescape delimiters. */
- if (!hb_font_glyph_from_string (font,
- tok, p - tok,
- &info.codepoint))
- return false;
-}
-#line 43 "hb-buffer-deserialize-text-glyphs.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
-#line 554 "hb-buffer-deserialize-text-glyphs.hh"
+#line 523 "hb-buffer-deserialize-text-glyphs.hh"
}
_again:
@@ -562,128 +564,25 @@ _again:
if ( p == eof )
{
switch ( _deserialize_text_glyphs_eof_actions[cs] ) {
- case 6:
-#line 55 "hb-buffer-deserialize-text-glyphs.rl"
- {
- /* TODO Unescape delimiters. */
- if (!hb_font_glyph_from_string (font,
- tok, p - tok,
- &info.codepoint))
- return false;
-}
-#line 43 "hb-buffer-deserialize-text-glyphs.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 13:
-#line 63 "hb-buffer-deserialize-text-glyphs.rl"
- { if (!parse_uint (tok, p, &info.cluster )) return false; }
-#line 43 "hb-buffer-deserialize-text-glyphs.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 15:
-#line 65 "hb-buffer-deserialize-text-glyphs.rl"
- { if (!parse_int (tok, p, &pos.y_offset )) return false; }
-#line 43 "hb-buffer-deserialize-text-glyphs.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 9:
-#line 66 "hb-buffer-deserialize-text-glyphs.rl"
- { if (!parse_int (tok, p, &pos.x_advance)) return false; }
-#line 43 "hb-buffer-deserialize-text-glyphs.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
case 11:
-#line 67 "hb-buffer-deserialize-text-glyphs.rl"
- { if (!parse_int (tok, p, &pos.y_advance)) return false; }
#line 43 "hb-buffer-deserialize-text-glyphs.rl"
{
- buffer->add_info (info);
+ buffer->add_info_and_pos (info, pos);
if (unlikely (!buffer->successful))
return false;
- buffer->pos[buffer->len - 1] = pos;
*end_ptr = p;
}
break;
- case 8:
-#line 68 "hb-buffer-deserialize-text-glyphs.rl"
- { if (!parse_uint (tok, p, &info.mask )) return false; }
-#line 43 "hb-buffer-deserialize-text-glyphs.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 3:
-#line 38 "hb-buffer-deserialize-text-glyphs.rl"
- {
- hb_memset (&info, 0, sizeof (info));
- hb_memset (&pos , 0, sizeof (pos ));
-}
-#line 51 "hb-buffer-deserialize-text-glyphs.rl"
- {
- tok = p;
-}
-#line 55 "hb-buffer-deserialize-text-glyphs.rl"
- {
- /* TODO Unescape delimiters. */
- if (!hb_font_glyph_from_string (font,
- tok, p - tok,
- &info.codepoint))
- return false;
-}
-#line 43 "hb-buffer-deserialize-text-glyphs.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
-#line 671 "hb-buffer-deserialize-text-glyphs.hh"
+#line 542 "hb-buffer-deserialize-text-glyphs.hh"
}
}
_out: {}
}
-#line 136 "hb-buffer-deserialize-text-glyphs.rl"
+#line 122 "hb-buffer-deserialize-text-glyphs.rl"
- if (pe < orig_pe && *pe == ']')
- {
- pe++;
- if (p == pe)
- p++;
- }
-
*end_ptr = p;
return p == pe;
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-text-unicode.hh b/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-text-unicode.hh
index 6a1706ccb72..9e21beebd34 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-text-unicode.hh
+++ b/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-text-unicode.hh
@@ -34,135 +34,106 @@
#line 36 "hb-buffer-deserialize-text-unicode.hh"
static const unsigned char _deserialize_text_unicode_trans_keys[] = {
- 0u, 0u, 9u, 117u, 43u, 102u, 48u, 102u, 48u, 57u, 9u, 124u, 9u, 124u, 9u, 124u,
- 9u, 124u, 0
+ 0u, 0u, 43u, 102u, 48u, 102u, 48u, 124u, 48u, 57u, 62u, 124u, 48u, 124u, 60u, 117u,
+ 85u, 117u, 85u, 117u, 0
};
static const char _deserialize_text_unicode_key_spans[] = {
- 0, 109, 60, 55, 10, 116, 116, 116,
- 116
+ 0, 60, 55, 77, 10, 63, 77, 58,
+ 33, 33
};
static const short _deserialize_text_unicode_index_offsets[] = {
- 0, 0, 110, 171, 227, 238, 355, 472,
- 589
+ 0, 0, 61, 117, 195, 206, 270, 348,
+ 407, 441
};
static const char _deserialize_text_unicode_indicies[] = {
- 0, 0, 0, 0, 0, 1, 1,
+ 0, 1, 1, 1, 1, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 2,
+ 2, 2, 2, 2, 2, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 0, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 2,
+ 2, 2, 2, 2, 2, 1, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 2,
+ 2, 2, 2, 2, 2, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 2,
+ 2, 2, 2, 2, 2, 1, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 1, 1, 1, 4, 5, 1, 1, 3,
+ 3, 3, 3, 3, 3, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 3,
+ 3, 3, 3, 3, 3, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 5, 1, 6, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 1, 8,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 2, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 8, 1, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 1, 1, 1, 1, 8, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 2, 1, 3,
- 1, 1, 1, 1, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 1, 1,
- 1, 1, 1, 1, 1, 4, 4, 4,
- 4, 4, 4, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 4, 4, 4,
- 4, 4, 4, 1, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 1, 1,
- 1, 1, 1, 1, 1, 4, 4, 4,
- 4, 4, 4, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 4, 4, 4,
- 4, 4, 4, 1, 5, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 1, 7,
- 7, 7, 7, 7, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 7, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8,
- 1, 1, 1, 9, 1, 1, 1, 8,
- 8, 8, 8, 8, 8, 1, 1, 1,
+ 1, 1, 1, 8, 1, 10, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 8,
- 8, 8, 8, 8, 8, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 11, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 10, 1, 11, 11, 11, 11,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 11, 1,
11, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 11, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 11, 1, 12, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 0,
- 1, 12, 12, 12, 12, 12, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 12, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 13, 1, 12, 12,
- 12, 12, 12, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 12, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 13, 1, 0
+ 1, 1, 12, 1, 0
};
static const char _deserialize_text_unicode_trans_targs[] = {
- 1, 0, 2, 3, 5, 7, 8, 6,
- 5, 4, 1, 6, 6, 1, 8
+ 2, 0, 3, 3, 4, 9, 5, 6,
+ 9, 6, 8, 1, 1
};
static const char _deserialize_text_unicode_trans_actions[] = {
- 0, 0, 1, 0, 2, 2, 2, 3,
- 0, 4, 3, 0, 5, 5, 0
+ 0, 0, 1, 0, 2, 2, 1, 1,
+ 3, 0, 0, 4, 6
};
static const char _deserialize_text_unicode_eof_actions[] = {
- 0, 0, 0, 0, 0, 3, 0, 5,
- 5
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 5
};
-static const int deserialize_text_unicode_start = 1;
-static const int deserialize_text_unicode_first_final = 5;
+static const int deserialize_text_unicode_start = 7;
+static const int deserialize_text_unicode_first_final = 7;
static const int deserialize_text_unicode_error = 0;
-static const int deserialize_text_unicode_en_main = 1;
+static const int deserialize_text_unicode_en_main = 7;
-#line 79 "hb-buffer-deserialize-text-unicode.rl"
+#line 80 "hb-buffer-deserialize-text-unicode.rl"
static hb_bool_t
@@ -172,37 +143,19 @@ _hb_buffer_deserialize_text_unicode (hb_buffer_t *buffer,
const char **end_ptr,
hb_font_t *font)
{
- const char *p = buf, *pe = buf + buf_len, *eof = pe, *orig_pe = pe;
-
- while (p < pe && ISSPACE (*p))
- p++;
- if (p < pe && *p == (buffer->len ? '|' : '<'))
- *end_ptr = ++p;
-
- const char *end = strchr ((char *) p, '>');
- if (end)
- pe = eof = end;
- else
- {
- end = strrchr ((char *) p, '|');
- if (end)
- pe = eof = end;
- else
- pe = eof = p;
- }
-
+ const char *p = buf, *pe = buf + buf_len, *eof = pe;
const char *tok = nullptr;
int cs;
hb_glyph_info_t info = {0};
const hb_glyph_position_t pos = {0};
-#line 201 "hb-buffer-deserialize-text-unicode.hh"
+#line 154 "hb-buffer-deserialize-text-unicode.hh"
{
cs = deserialize_text_unicode_start;
}
-#line 206 "hb-buffer-deserialize-text-unicode.hh"
+#line 159 "hb-buffer-deserialize-text-unicode.hh"
{
int _slen;
int _trans;
@@ -227,38 +180,27 @@ _resume:
goto _again;
switch ( _deserialize_text_unicode_trans_actions[_trans] ) {
- case 1:
+ case 4:
#line 38 "hb-buffer-deserialize-text-unicode.rl"
{
hb_memset (&info, 0, sizeof (info));
}
break;
- case 2:
+ case 1:
#line 51 "hb-buffer-deserialize-text-unicode.rl"
{
tok = p;
}
break;
- case 4:
+ case 2:
#line 55 "hb-buffer-deserialize-text-unicode.rl"
{if (!parse_hex (tok, p, &info.codepoint )) return false; }
break;
case 3:
-#line 55 "hb-buffer-deserialize-text-unicode.rl"
- {if (!parse_hex (tok, p, &info.codepoint )) return false; }
-#line 42 "hb-buffer-deserialize-text-unicode.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- if (buffer->have_positions)
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 5:
#line 57 "hb-buffer-deserialize-text-unicode.rl"
{ if (!parse_uint (tok, p, &info.cluster )) return false; }
+ break;
+ case 6:
#line 42 "hb-buffer-deserialize-text-unicode.rl"
{
buffer->add_info (info);
@@ -267,9 +209,13 @@ _resume:
if (buffer->have_positions)
buffer->pos[buffer->len - 1] = pos;
*end_ptr = p;
+}
+#line 38 "hb-buffer-deserialize-text-unicode.rl"
+ {
+ hb_memset (&info, 0, sizeof (info));
}
break;
-#line 273 "hb-buffer-deserialize-text-unicode.hh"
+#line 219 "hb-buffer-deserialize-text-unicode.hh"
}
_again:
@@ -281,22 +227,7 @@ _again:
if ( p == eof )
{
switch ( _deserialize_text_unicode_eof_actions[cs] ) {
- case 3:
-#line 55 "hb-buffer-deserialize-text-unicode.rl"
- {if (!parse_hex (tok, p, &info.codepoint )) return false; }
-#line 42 "hb-buffer-deserialize-text-unicode.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- if (buffer->have_positions)
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
case 5:
-#line 57 "hb-buffer-deserialize-text-unicode.rl"
- { if (!parse_uint (tok, p, &info.cluster )) return false; }
#line 42 "hb-buffer-deserialize-text-unicode.rl"
{
buffer->add_info (info);
@@ -307,23 +238,16 @@ _again:
*end_ptr = p;
}
break;
-#line 311 "hb-buffer-deserialize-text-unicode.hh"
+#line 242 "hb-buffer-deserialize-text-unicode.hh"
}
}
_out: {}
}
-#line 115 "hb-buffer-deserialize-text-unicode.rl"
+#line 98 "hb-buffer-deserialize-text-unicode.rl"
- if (pe < orig_pe && *pe == '>')
- {
- pe++;
- if (p == pe)
- p++;
- }
-
*end_ptr = p;
return p == pe;
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-buffer-serialize.cc b/src/java.desktop/share/native/libharfbuzz/hb-buffer-serialize.cc
index bb2cddcb655..763172818c4 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-buffer-serialize.cc
+++ b/src/java.desktop/share/native/libharfbuzz/hb-buffer-serialize.cc
@@ -169,11 +169,13 @@ _hb_buffer_serialize_glyphs_json (hb_buffer_t *buffer,
if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS)
{
hb_glyph_extents_t extents;
- hb_font_get_glyph_extents(font, info[i].codepoint, &extents);
- p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"xb\":%d,\"yb\":%d",
- extents.x_bearing, extents.y_bearing));
- p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"w\":%d,\"h\":%d",
- extents.width, extents.height));
+ if (hb_font_get_glyph_extents(font, info[i].codepoint, &extents))
+ {
+ p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"xb\":%d,\"yb\":%d",
+ extents.x_bearing, extents.y_bearing));
+ p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"w\":%d,\"h\":%d",
+ extents.width, extents.height));
+ }
}
*p++ = '}';
@@ -318,8 +320,8 @@ _hb_buffer_serialize_glyphs_text (hb_buffer_t *buffer,
if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS)
{
hb_glyph_extents_t extents;
- hb_font_get_glyph_extents(font, info[i].codepoint, &extents);
- p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "<%d,%d,%d,%d>", extents.x_bearing, extents.y_bearing, extents.width, extents.height));
+ if (hb_font_get_glyph_extents(font, info[i].codepoint, &extents))
+ p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "<%d,%d,%d,%d>", extents.x_bearing, extents.y_bearing, extents.width, extents.height));
}
if (i == end-1) {
@@ -737,8 +739,7 @@ parse_hex (const char *pp, const char *end, uint32_t *pv)
* Deserializes glyphs @buffer from textual representation in the format
* produced by hb_buffer_serialize_glyphs().
*
- * Return value: `true` if parse was successful, `false` if an error
- * occurred.
+ * Return value: `true` if the full string was parsed, `false` otherwise.
*
* Since: 0.9.7
**/
@@ -810,8 +811,7 @@ hb_buffer_deserialize_glyphs (hb_buffer_t *buffer,
* Deserializes Unicode @buffer from textual representation in the format
* produced by hb_buffer_serialize_unicode().
*
- * Return value: `true` if parse was successful, `false` if an error
- * occurred.
+ * Return value: `true` if the full string was parsed, `false` otherwise.
*
* Since: 2.7.3
**/
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-buffer-verify.cc b/src/java.desktop/share/native/libharfbuzz/hb-buffer-verify.cc
index 3a4c9c9f317..56299d9b7e0 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-buffer-verify.cc
+++ b/src/java.desktop/share/native/libharfbuzz/hb-buffer-verify.cc
@@ -63,24 +63,25 @@ static bool
buffer_verify_monotone (hb_buffer_t *buffer,
hb_font_t *font)
{
- /* Check that clusters are monotone. */
- if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES ||
- buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
+ if (!HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE (buffer->cluster_level))
{
- bool is_forward = HB_DIRECTION_IS_FORWARD (hb_buffer_get_direction (buffer));
-
- unsigned int num_glyphs;
- hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, &num_glyphs);
-
- for (unsigned int i = 1; i < num_glyphs; i++)
- if (info[i-1].cluster != info[i].cluster &&
- (info[i-1].cluster < info[i].cluster) != is_forward)
- {
- buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "clusters are not monotone.");
- return false;
- }
+ /* Cannot perform this check without monotone clusters. */
+ return true;
}
+ bool is_forward = HB_DIRECTION_IS_FORWARD (hb_buffer_get_direction (buffer));
+
+ unsigned int num_glyphs;
+ hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, &num_glyphs);
+
+ for (unsigned int i = 1; i < num_glyphs; i++)
+ if (info[i-1].cluster != info[i].cluster &&
+ (info[i-1].cluster < info[i].cluster) != is_forward)
+ {
+ buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "clusters are not monotone.");
+ return false;
+ }
+
return true;
}
@@ -92,8 +93,7 @@ buffer_verify_unsafe_to_break (hb_buffer_t *buffer,
unsigned int num_features,
const char * const *shapers)
{
- if (buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES &&
- buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
+ if (!HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE (buffer->cluster_level))
{
/* Cannot perform this check without monotone clusters. */
return true;
@@ -207,8 +207,7 @@ buffer_verify_unsafe_to_concat (hb_buffer_t *buffer,
unsigned int num_features,
const char * const *shapers)
{
- if (buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES &&
- buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
+ if (!HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE (buffer->cluster_level))
{
/* Cannot perform this check without monotone clusters. */
return true;
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-buffer.cc b/src/java.desktop/share/native/libharfbuzz/hb-buffer.cc
index 72970c9c2f7..c0600fd839b 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-buffer.cc
+++ b/src/java.desktop/share/native/libharfbuzz/hb-buffer.cc
@@ -370,6 +370,18 @@ hb_buffer_t::add_info (const hb_glyph_info_t &glyph_info)
len++;
}
+void
+hb_buffer_t::add_info_and_pos (const hb_glyph_info_t &glyph_info,
+ const hb_glyph_position_t &glyph_pos)
+{
+ if (unlikely (!ensure (len + 1))) return;
+
+ info[len] = glyph_info;
+ assert (have_positions);
+ pos[len] = glyph_pos;
+
+ len++;
+}
void
@@ -518,7 +530,7 @@ void
hb_buffer_t::merge_clusters_impl (unsigned int start,
unsigned int end)
{
- if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS)
+ if (!HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE (cluster_level))
{
unsafe_to_break (start, end);
return;
@@ -551,7 +563,7 @@ void
hb_buffer_t::merge_out_clusters (unsigned int start,
unsigned int end)
{
- if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS)
+ if (!HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE (cluster_level))
return;
if (unlikely (end - start < 2))
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-buffer.h b/src/java.desktop/share/native/libharfbuzz/hb-buffer.h
index d2258634ff4..332001ef171 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-buffer.h
+++ b/src/java.desktop/share/native/libharfbuzz/hb-buffer.h
@@ -422,6 +422,7 @@ hb_buffer_get_flags (const hb_buffer_t *buffer);
* @HB_BUFFER_CLUSTER_LEVEL_CHARACTERS: Don't group cluster values.
* @HB_BUFFER_CLUSTER_LEVEL_DEFAULT: Default cluster level,
* equal to @HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES.
+ * @HB_BUFFER_CLUSTER_LEVEL_GRAPHEMES: Only group clusters, but don't enforce monotone order.
*
* Data type for holding HarfBuzz's clustering behavior options. The cluster level
* dictates one aspect of how HarfBuzz will treat non-base characters
@@ -429,11 +430,26 @@ hb_buffer_get_flags (const hb_buffer_t *buffer);
*
* In @HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES, non-base
* characters are merged into the cluster of the base character that precedes them.
+ * There is also cluster merging every time the clusters will otherwise become non-monotone.
*
* In @HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS, non-base characters are initially
* assigned their own cluster values, which are not merged into preceding base
* clusters. This allows HarfBuzz to perform additional operations like reorder
- * sequences of adjacent marks.
+ * sequences of adjacent marks. The output is still monotone, but the cluster
+ * values are more granular.
+ *
+ * In @HB_BUFFER_CLUSTER_LEVEL_CHARACTERS, non-base characters are assigned their
+ * own cluster values, which are not merged into preceding base clusters. Moreover,
+ * the cluster values are not merged into monotone order. This is the most granular
+ * cluster level, and it is useful for clients that need to know the exact cluster
+ * values of each character, but is harder to use for clients, since clusters
+ * might appear in any order.
+ *
+ * In @HB_BUFFER_CLUSTER_LEVEL_GRAPHEMES, non-base characters are merged into the
+ * cluster of the base character that precedes them. This is similar to the Unicode
+ * Grapheme Cluster algorithm, but it is not exactly the same. The output is
+ * not forced to be monotone. This is useful for clients that want to use HarfBuzz
+ * as a cheap implementation of the Unicode Grapheme Cluster algorithm.
*
* @HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES is the default, because it maintains
* backward compatibility with older versions of HarfBuzz. New client programs that
@@ -446,9 +462,52 @@ typedef enum {
HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES = 0,
HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS = 1,
HB_BUFFER_CLUSTER_LEVEL_CHARACTERS = 2,
+ HB_BUFFER_CLUSTER_LEVEL_GRAPHEMES = 3,
HB_BUFFER_CLUSTER_LEVEL_DEFAULT = HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES
} hb_buffer_cluster_level_t;
+/**
+ * HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE:
+ * @level: #hb_buffer_cluster_level_t to test
+ *
+ * Tests whether a cluster level groups cluster values into monotone order.
+ * Requires that the level be valid.
+ *
+ * Since: 11.0.0
+ */
+#define HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE(level) \
+ ((bool) ((1u << (unsigned) (level)) & \
+ ((1u << HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) | \
+ (1u << HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS))))
+
+/**
+ * HB_BUFFER_CLUSTER_LEVEL_IS_GRAPHEMES:
+ * @level: #hb_buffer_cluster_level_t to test
+ *
+ * Tests whether a cluster level groups cluster values by graphemes. Requires
+ * that the level be valid.
+ *
+ * Since: 11.0.0
+ */
+#define HB_BUFFER_CLUSTER_LEVEL_IS_GRAPHEMES(level) \
+ ((bool) ((1u << (unsigned) (level)) & \
+ ((1u << HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) | \
+ (1u << HB_BUFFER_CLUSTER_LEVEL_GRAPHEMES))))
+
+/**
+ * HB_BUFFER_CLUSTER_LEVEL_IS_CHARACTERS
+ * @level: #hb_buffer_cluster_level_t to test
+ *
+ * Tests whether a cluster level does not group cluster values by graphemes.
+ * Requires that the level be valid.
+ *
+ * Since: 11.0.0
+ */
+#define HB_BUFFER_CLUSTER_LEVEL_IS_CHARACTERS(level) \
+ ((bool) ((1u << (unsigned) (level)) & \
+ ((1u << HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARCATERS) | \
+ (1u << HB_BUFFER_CLUSTER_LEVEL_CHARACTERS))))
+
HB_EXTERN void
hb_buffer_set_cluster_level (hb_buffer_t *buffer,
hb_buffer_cluster_level_t cluster_level);
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-buffer.hh b/src/java.desktop/share/native/libharfbuzz/hb-buffer.hh
index c92e7df320e..81c0f4a72e3 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-buffer.hh
+++ b/src/java.desktop/share/native/libharfbuzz/hb-buffer.hh
@@ -229,6 +229,8 @@ struct hb_buffer_t
HB_INTERNAL void add (hb_codepoint_t codepoint,
unsigned int cluster);
HB_INTERNAL void add_info (const hb_glyph_info_t &glyph_info);
+ HB_INTERNAL void add_info_and_pos (const hb_glyph_info_t &glyph_info,
+ const hb_glyph_position_t &glyph_pos);
void reverse_range (unsigned start, unsigned end)
{
@@ -410,6 +412,9 @@ struct hb_buffer_t
{
end = hb_min (end, len);
+ if (unlikely (end - start > 255))
+ return;
+
if (interior && !from_out_buffer && end - start < 2)
return;
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-cache.hh b/src/java.desktop/share/native/libharfbuzz/hb-cache.hh
index 8c7e0c655e6..7d09ca89d7f 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-cache.hh
+++ b/src/java.desktop/share/native/libharfbuzz/hb-cache.hh
@@ -30,18 +30,31 @@
#include "hb.hh"
-/* Implements a lockfree cache for int->int functions.
+/* Implements a lockfree and thread-safe cache for int->int functions,
+ * using (optionally) _relaxed_ atomic integer operations.
*
- * The cache is a fixed-size array of 16-bit or 32-bit integers.
- * The key is split into two parts: the cache index and the rest.
+ * The cache is a fixed-size array of 16-bit or 32-bit integers,
+ * typically 256 elements.
*
- * The cache index is used to index into the array. The rest is used
- * to store the key and the value.
+ * The key is split into two parts: the cache index (high bits)
+ * and the rest (low bits).
+ *
+ * The cache index is used to index into the array. The array
+ * member is a 16-bit or 32-bit integer that is used *both*
+ * to store the low bits of the key, and the value.
*
* The value is stored in the least significant bits of the integer.
- * The key is stored in the most significant bits of the integer.
- * The key is shifted by cache_bits to the left to make room for the
- * value.
+ * The low bits of the key are stored in the most significant bits
+ * of the integer.
+ *
+ * A cache hit is detected by comparing the low bits of the key
+ * with the high bits of the integer at the array position indexed
+ * by the high bits of the key. If they match, the value is extracted
+ * from the least significant bits of the integer and returned.
+ * Otherwise, a cache miss is reported.
+ *
+ * Cache operations (storage and retrieval) involve just a few
+ * arithmetic operations and a single memory access.
*/
template ::type,
+ hb_atomic_t,
+ hb_atomic_t>::type,
typename std::conditional::type
+ unsigned short,
+ unsigned int>::type
>::type;
static_assert ((key_bits >= cache_bits), "");
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-cff2-interp-cs.hh b/src/java.desktop/share/native/libharfbuzz/hb-cff2-interp-cs.hh
index ab17d68318b..0eacdd92ab8 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-cff2-interp-cs.hh
+++ b/src/java.desktop/share/native/libharfbuzz/hb-cff2-interp-cs.hh
@@ -71,7 +71,8 @@ struct cff2_cs_interp_env_t : cs_interp_env_t
template
cff2_cs_interp_env_t (const hb_ubytes_t &str, ACC &acc, unsigned int fd,
const int *coords_=nullptr, unsigned int num_coords_=0)
- : SUPER (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs)
+ : SUPER (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs),
+ cached_scalars_vector (&acc.cached_scalars_vector)
{
coords = coords_;
num_coords = num_coords_;
@@ -80,9 +81,39 @@ struct cff2_cs_interp_env_t : cs_interp_env_t
set_ivs (acc.privateDicts[fd].ivs);
}
- void fini ()
+ ~cff2_cs_interp_env_t ()
{
- SUPER::fini ();
+ release_scalars_vector (scalars);
+ }
+
+ hb_vector_t *acquire_scalars_vector () const
+ {
+ hb_vector_t *scalars = cached_scalars_vector->get_acquire ();
+
+ if (!scalars || !cached_scalars_vector->cmpexch (scalars, nullptr))
+ {
+ scalars = (hb_vector_t *) hb_calloc (1, sizeof (hb_vector_t));
+ if (unlikely (!scalars))
+ return nullptr;
+ scalars->init ();
+ }
+
+ return scalars;
+ }
+
+ void release_scalars_vector (hb_vector_t *scalars) const
+ {
+ if (!scalars)
+ return;
+
+ scalars->clear ();
+
+ if (!cached_scalars_vector->cmpexch (nullptr, scalars))
+ {
+ scalars->fini ();
+ hb_free (scalars);
+ }
+ scalars = nullptr;
}
op_code_t fetch_op ()
@@ -111,14 +142,20 @@ struct cff2_cs_interp_env_t : cs_interp_env_t
{
if (!seen_blend)
{
- region_count = varStore->varStore.get_region_index_count (get_ivs ());
- if (do_blend)
+ scalars = acquire_scalars_vector ();
+ if (unlikely (!scalars))
+ SUPER::set_error ();
+ else
{
- if (unlikely (!scalars.resize_exact (region_count)))
- SUPER::set_error ();
- else
- varStore->varStore.get_region_scalars (get_ivs (), coords, num_coords,
- &scalars[0], region_count);
+ region_count = varStore->varStore.get_region_index_count (get_ivs ());
+ if (do_blend)
+ {
+ if (unlikely (!scalars->resize_exact (region_count)))
+ SUPER::set_error ();
+ else
+ varStore->varStore.get_region_scalars (get_ivs (), coords, num_coords,
+ &(*scalars)[0], region_count);
+ }
}
seen_blend = true;
}
@@ -149,11 +186,11 @@ struct cff2_cs_interp_env_t : cs_interp_env_t
double v = 0;
if (do_blend)
{
- if (likely (scalars.length == deltas.length))
+ if (likely (scalars && scalars->length == deltas.length))
{
- unsigned count = scalars.length;
+ unsigned count = scalars->length;
for (unsigned i = 0; i < count; i++)
- v += (double) scalars.arrayZ[i] * deltas.arrayZ[i].to_real ();
+ v += (double) scalars->arrayZ[i] * deltas.arrayZ[i].to_real ();
}
}
return v;
@@ -167,7 +204,8 @@ struct cff2_cs_interp_env_t : cs_interp_env_t
const CFF2ItemVariationStore *varStore;
unsigned int region_count;
unsigned int ivs;
- hb_vector_t scalars;
+ hb_vector_t *scalars = nullptr;
+ hb_atomic_t *> *cached_scalars_vector = nullptr;
bool do_blend;
bool seen_vsindex_ = false;
bool seen_blend = false;
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-common.cc b/src/java.desktop/share/native/libharfbuzz/hb-common.cc
index bce0d09d20a..5c8546a378c 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-common.cc
+++ b/src/java.desktop/share/native/libharfbuzz/hb-common.cc
@@ -42,7 +42,7 @@
/* hb_options_t */
-hb_atomic_int_t _hb_options;
+hb_atomic_t _hb_options;
void
_hb_options_init ()
@@ -273,7 +273,7 @@ struct hb_language_item_t {
/* Thread-safe lockfree language list */
-static hb_atomic_ptr_t langs;
+static hb_atomic_t langs;
static inline void
free_langs ()
@@ -403,7 +403,7 @@ hb_language_to_string (hb_language_t language)
hb_language_t
hb_language_get_default ()
{
- static hb_atomic_ptr_t default_language;
+ static hb_atomic_t default_language;
hb_language_t language = default_language;
if (unlikely (language == HB_LANGUAGE_INVALID))
@@ -968,6 +968,9 @@ hb_feature_from_string (const char *str, int len,
* understood by hb_feature_from_string(). The client in responsible for
* allocating big enough size for @buf, 128 bytes is more than enough.
*
+ * Note that the feature value will be omitted if it is '1', but the
+ * string won't include any whitespace.
+ *
* Since: 0.9.5
**/
void
@@ -1121,6 +1124,8 @@ get_C_locale ()
* understood by hb_variation_from_string(). The client in responsible for
* allocating big enough size for @buf, 128 bytes is more than enough.
*
+ * Note that the string won't include any whitespace.
+ *
* Since: 1.4.2
*/
void
@@ -1212,6 +1217,58 @@ uint8_t
return hb_color_get_blue (color);
}
+/**
+ * hb_malloc:
+ * @size: The size of the memory to allocate.
+ *
+ * Allocates @size bytes of memory, using the allocator set at
+ * compile-time. Typically just malloc().
+ *
+ * Return value: A pointer to the allocated memory.
+ *
+ * Since: 11.0.0
+ **/
+void* hb_malloc(size_t size) { return hb_malloc_impl (size); }
+
+/**
+ * hb_calloc:
+ * @nmemb: The number of elements to allocate.
+ * @size: The size of each element.
+ *
+ * Allocates @nmemb elements of @size bytes each, initialized to zero,
+ * using the allocator set at compile-time. Typically just calloc().
+ *
+ * Return value: A pointer to the allocated memory.
+ *
+ * Since: 11.0.0
+ **/
+void* hb_calloc(size_t nmemb, size_t size) { return hb_calloc_impl (nmemb, size); }
+
+/**
+ * hb_realloc:
+ * @ptr: The pointer to the memory to reallocate.
+ * @size: The new size of the memory.
+ *
+ * Reallocates the memory pointed to by @ptr to @size bytes, using the
+ * allocator set at compile-time. Typically just realloc().
+ *
+ * Return value: A pointer to the reallocated memory.
+ *
+ * Since: 11.0.0
+ **/
+void* hb_realloc(void *ptr, size_t size) { return hb_realloc_impl (ptr, size); }
+
+/**
+ * hb_free:
+ * @ptr: The pointer to the memory to free.
+ *
+ * Frees the memory pointed to by @ptr, using the allocator set at
+ * compile-time. Typically just free().
+ *
+ * Since: 11.0.0
+ **/
+void hb_free(void *ptr) { hb_free_impl (ptr); }
+
/* If there is no visibility control, then hb-static.cc will NOT
* define anything. Instead, we get it to define one set in here
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-common.h b/src/java.desktop/share/native/libharfbuzz/hb-common.h
index a8bae366f7e..5a0ef65392d 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-common.h
+++ b/src/java.desktop/share/native/libharfbuzz/hb-common.h
@@ -65,6 +65,7 @@ typedef unsigned __int64 uint64_t;
#else
# include
#endif
+#include
#if defined(__GNUC__) && ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
#define HB_DEPRECATED __attribute__((__deprecated__))
@@ -337,437 +338,7 @@ HB_EXTERN hb_bool_t
hb_language_matches (hb_language_t language,
hb_language_t specific);
-/**
- * hb_script_t:
- * @HB_SCRIPT_COMMON: `Zyyy`
- * @HB_SCRIPT_INHERITED: `Zinh`
- * @HB_SCRIPT_UNKNOWN: `Zzzz`
- * @HB_SCRIPT_ARABIC: `Arab`
- * @HB_SCRIPT_ARMENIAN: `Armn`
- * @HB_SCRIPT_BENGALI: `Beng`
- * @HB_SCRIPT_CYRILLIC: `Cyrl`
- * @HB_SCRIPT_DEVANAGARI: `Deva`
- * @HB_SCRIPT_GEORGIAN: `Geor`
- * @HB_SCRIPT_GREEK: `Grek`
- * @HB_SCRIPT_GUJARATI: `Gujr`
- * @HB_SCRIPT_GURMUKHI: `Guru`
- * @HB_SCRIPT_HANGUL: `Hang`
- * @HB_SCRIPT_HAN: `Hani`
- * @HB_SCRIPT_HEBREW: `Hebr`
- * @HB_SCRIPT_HIRAGANA: `Hira`
- * @HB_SCRIPT_KANNADA: `Knda`
- * @HB_SCRIPT_KATAKANA: `Kana`
- * @HB_SCRIPT_LAO: `Laoo`
- * @HB_SCRIPT_LATIN: `Latn`
- * @HB_SCRIPT_MALAYALAM: `Mlym`
- * @HB_SCRIPT_ORIYA: `Orya`
- * @HB_SCRIPT_TAMIL: `Taml`
- * @HB_SCRIPT_TELUGU: `Telu`
- * @HB_SCRIPT_THAI: `Thai`
- * @HB_SCRIPT_TIBETAN: `Tibt`
- * @HB_SCRIPT_BOPOMOFO: `Bopo`
- * @HB_SCRIPT_BRAILLE: `Brai`
- * @HB_SCRIPT_CANADIAN_SYLLABICS: `Cans`
- * @HB_SCRIPT_CHEROKEE: `Cher`
- * @HB_SCRIPT_ETHIOPIC: `Ethi`
- * @HB_SCRIPT_KHMER: `Khmr`
- * @HB_SCRIPT_MONGOLIAN: `Mong`
- * @HB_SCRIPT_MYANMAR: `Mymr`
- * @HB_SCRIPT_OGHAM: `Ogam`
- * @HB_SCRIPT_RUNIC: `Runr`
- * @HB_SCRIPT_SINHALA: `Sinh`
- * @HB_SCRIPT_SYRIAC: `Syrc`
- * @HB_SCRIPT_THAANA: `Thaa`
- * @HB_SCRIPT_YI: `Yiii`
- * @HB_SCRIPT_DESERET: `Dsrt`
- * @HB_SCRIPT_GOTHIC: `Goth`
- * @HB_SCRIPT_OLD_ITALIC: `Ital`
- * @HB_SCRIPT_BUHID: `Buhd`
- * @HB_SCRIPT_HANUNOO: `Hano`
- * @HB_SCRIPT_TAGALOG: `Tglg`
- * @HB_SCRIPT_TAGBANWA: `Tagb`
- * @HB_SCRIPT_CYPRIOT: `Cprt`
- * @HB_SCRIPT_LIMBU: `Limb`
- * @HB_SCRIPT_LINEAR_B: `Linb`
- * @HB_SCRIPT_OSMANYA: `Osma`
- * @HB_SCRIPT_SHAVIAN: `Shaw`
- * @HB_SCRIPT_TAI_LE: `Tale`
- * @HB_SCRIPT_UGARITIC: `Ugar`
- * @HB_SCRIPT_BUGINESE: `Bugi`
- * @HB_SCRIPT_COPTIC: `Copt`
- * @HB_SCRIPT_GLAGOLITIC: `Glag`
- * @HB_SCRIPT_KHAROSHTHI: `Khar`
- * @HB_SCRIPT_NEW_TAI_LUE: `Talu`
- * @HB_SCRIPT_OLD_PERSIAN: `Xpeo`
- * @HB_SCRIPT_SYLOTI_NAGRI: `Sylo`
- * @HB_SCRIPT_TIFINAGH: `Tfng`
- * @HB_SCRIPT_BALINESE: `Bali`
- * @HB_SCRIPT_CUNEIFORM: `Xsux`
- * @HB_SCRIPT_NKO: `Nkoo`
- * @HB_SCRIPT_PHAGS_PA: `Phag`
- * @HB_SCRIPT_PHOENICIAN: `Phnx`
- * @HB_SCRIPT_CARIAN: `Cari`
- * @HB_SCRIPT_CHAM: `Cham`
- * @HB_SCRIPT_KAYAH_LI: `Kali`
- * @HB_SCRIPT_LEPCHA: `Lepc`
- * @HB_SCRIPT_LYCIAN: `Lyci`
- * @HB_SCRIPT_LYDIAN: `Lydi`
- * @HB_SCRIPT_OL_CHIKI: `Olck`
- * @HB_SCRIPT_REJANG: `Rjng`
- * @HB_SCRIPT_SAURASHTRA: `Saur`
- * @HB_SCRIPT_SUNDANESE: `Sund`
- * @HB_SCRIPT_VAI: `Vaii`
- * @HB_SCRIPT_AVESTAN: `Avst`
- * @HB_SCRIPT_BAMUM: `Bamu`
- * @HB_SCRIPT_EGYPTIAN_HIEROGLYPHS: `Egyp`
- * @HB_SCRIPT_IMPERIAL_ARAMAIC: `Armi`
- * @HB_SCRIPT_INSCRIPTIONAL_PAHLAVI: `Phli`
- * @HB_SCRIPT_INSCRIPTIONAL_PARTHIAN: `Prti`
- * @HB_SCRIPT_JAVANESE: `Java`
- * @HB_SCRIPT_KAITHI: `Kthi`
- * @HB_SCRIPT_LISU: `Lisu`
- * @HB_SCRIPT_MEETEI_MAYEK: `Mtei`
- * @HB_SCRIPT_OLD_SOUTH_ARABIAN: `Sarb`
- * @HB_SCRIPT_OLD_TURKIC: `Orkh`
- * @HB_SCRIPT_SAMARITAN: `Samr`
- * @HB_SCRIPT_TAI_THAM: `Lana`
- * @HB_SCRIPT_TAI_VIET: `Tavt`
- * @HB_SCRIPT_BATAK: `Batk`
- * @HB_SCRIPT_BRAHMI: `Brah`
- * @HB_SCRIPT_MANDAIC: `Mand`
- * @HB_SCRIPT_CHAKMA: `Cakm`
- * @HB_SCRIPT_MEROITIC_CURSIVE: `Merc`
- * @HB_SCRIPT_MEROITIC_HIEROGLYPHS: `Mero`
- * @HB_SCRIPT_MIAO: `Plrd`
- * @HB_SCRIPT_SHARADA: `Shrd`
- * @HB_SCRIPT_SORA_SOMPENG: `Sora`
- * @HB_SCRIPT_TAKRI: `Takr`
- * @HB_SCRIPT_BASSA_VAH: `Bass`, Since: 0.9.30
- * @HB_SCRIPT_CAUCASIAN_ALBANIAN: `Aghb`, Since: 0.9.30
- * @HB_SCRIPT_DUPLOYAN: `Dupl`, Since: 0.9.30
- * @HB_SCRIPT_ELBASAN: `Elba`, Since: 0.9.30
- * @HB_SCRIPT_GRANTHA: `Gran`, Since: 0.9.30
- * @HB_SCRIPT_KHOJKI: `Khoj`, Since: 0.9.30
- * @HB_SCRIPT_KHUDAWADI: `Sind`, Since: 0.9.30
- * @HB_SCRIPT_LINEAR_A: `Lina`, Since: 0.9.30
- * @HB_SCRIPT_MAHAJANI: `Mahj`, Since: 0.9.30
- * @HB_SCRIPT_MANICHAEAN: `Mani`, Since: 0.9.30
- * @HB_SCRIPT_MENDE_KIKAKUI: `Mend`, Since: 0.9.30
- * @HB_SCRIPT_MODI: `Modi`, Since: 0.9.30
- * @HB_SCRIPT_MRO: `Mroo`, Since: 0.9.30
- * @HB_SCRIPT_NABATAEAN: `Nbat`, Since: 0.9.30
- * @HB_SCRIPT_OLD_NORTH_ARABIAN: `Narb`, Since: 0.9.30
- * @HB_SCRIPT_OLD_PERMIC: `Perm`, Since: 0.9.30
- * @HB_SCRIPT_PAHAWH_HMONG: `Hmng`, Since: 0.9.30
- * @HB_SCRIPT_PALMYRENE: `Palm`, Since: 0.9.30
- * @HB_SCRIPT_PAU_CIN_HAU: `Pauc`, Since: 0.9.30
- * @HB_SCRIPT_PSALTER_PAHLAVI: `Phlp`, Since: 0.9.30
- * @HB_SCRIPT_SIDDHAM: `Sidd`, Since: 0.9.30
- * @HB_SCRIPT_TIRHUTA: `Tirh`, Since: 0.9.30
- * @HB_SCRIPT_WARANG_CITI: `Wara`, Since: 0.9.30
- * @HB_SCRIPT_AHOM: `Ahom`, Since: 0.9.30
- * @HB_SCRIPT_ANATOLIAN_HIEROGLYPHS: `Hluw`, Since: 0.9.30
- * @HB_SCRIPT_HATRAN: `Hatr`, Since: 0.9.30
- * @HB_SCRIPT_MULTANI: `Mult`, Since: 0.9.30
- * @HB_SCRIPT_OLD_HUNGARIAN: `Hung`, Since: 0.9.30
- * @HB_SCRIPT_SIGNWRITING: `Sgnw`, Since: 0.9.30
- * @HB_SCRIPT_ADLAM: `Adlm`, Since: 1.3.0
- * @HB_SCRIPT_BHAIKSUKI: `Bhks`, Since: 1.3.0
- * @HB_SCRIPT_MARCHEN: `Marc`, Since: 1.3.0
- * @HB_SCRIPT_OSAGE: `Osge`, Since: 1.3.0
- * @HB_SCRIPT_TANGUT: `Tang`, Since: 1.3.0
- * @HB_SCRIPT_NEWA: `Newa`, Since: 1.3.0
- * @HB_SCRIPT_MASARAM_GONDI: `Gonm`, Since: 1.6.0
- * @HB_SCRIPT_NUSHU: `Nshu`, Since: 1.6.0
- * @HB_SCRIPT_SOYOMBO: `Soyo`, Since: 1.6.0
- * @HB_SCRIPT_ZANABAZAR_SQUARE: `Zanb`, Since: 1.6.0
- * @HB_SCRIPT_DOGRA: `Dogr`, Since: 1.8.0
- * @HB_SCRIPT_GUNJALA_GONDI: `Gong`, Since: 1.8.0
- * @HB_SCRIPT_HANIFI_ROHINGYA: `Rohg`, Since: 1.8.0
- * @HB_SCRIPT_MAKASAR: `Maka`, Since: 1.8.0
- * @HB_SCRIPT_MEDEFAIDRIN: `Medf`, Since: 1.8.0
- * @HB_SCRIPT_OLD_SOGDIAN: `Sogo`, Since: 1.8.0
- * @HB_SCRIPT_SOGDIAN: `Sogd`, Since: 1.8.0
- * @HB_SCRIPT_ELYMAIC: `Elym`, Since: 2.4.0
- * @HB_SCRIPT_NANDINAGARI: `Nand`, Since: 2.4.0
- * @HB_SCRIPT_NYIAKENG_PUACHUE_HMONG: `Hmnp`, Since: 2.4.0
- * @HB_SCRIPT_WANCHO: `Wcho`, Since: 2.4.0
- * @HB_SCRIPT_CHORASMIAN: `Chrs`, Since: 2.6.7
- * @HB_SCRIPT_DIVES_AKURU: `Diak`, Since: 2.6.7
- * @HB_SCRIPT_KHITAN_SMALL_SCRIPT: `Kits`, Since: 2.6.7
- * @HB_SCRIPT_YEZIDI: `Yezi`, Since: 2.6.7
- * @HB_SCRIPT_CYPRO_MINOAN: `Cpmn`, Since: 3.0.0
- * @HB_SCRIPT_OLD_UYGHUR: `Ougr`, Since: 3.0.0
- * @HB_SCRIPT_TANGSA: `Tnsa`, Since: 3.0.0
- * @HB_SCRIPT_TOTO: `Toto`, Since: 3.0.0
- * @HB_SCRIPT_VITHKUQI: `Vith`, Since: 3.0.0
- * @HB_SCRIPT_MATH: `Zmth`, Since: 3.4.0
- * @HB_SCRIPT_KAWI: `Kawi`, Since: 5.2.0
- * @HB_SCRIPT_NAG_MUNDARI: `Nagm`, Since: 5.2.0
- * @HB_SCRIPT_GARAY: `Gara`, Since: 10.0.0
- * @HB_SCRIPT_GURUNG_KHEMA: `Gukh`, Since: 10.0.0
- * @HB_SCRIPT_KIRAT_RAI: `Krai`, Since: 10.0.0
- * @HB_SCRIPT_OL_ONAL: `Onao`, Since: 10.0.0
- * @HB_SCRIPT_SUNUWAR: `Sunu`, Since: 10.0.0
- * @HB_SCRIPT_TODHRI: `Todr`, Since: 10.0.0
- * @HB_SCRIPT_TULU_TIGALARI: `Tutg`, Since: 10.0.0
- * @HB_SCRIPT_INVALID: No script set
- *
- * Data type for scripts. Each #hb_script_t's value is an #hb_tag_t corresponding
- * to the four-letter values defined by [ISO 15924](https://unicode.org/iso15924/).
- *
- * See also the Script (sc) property of the Unicode Character Database.
- *
- **/
-
-/* https://docs.google.com/spreadsheets/d/1Y90M0Ie3MUJ6UVCRDOypOtijlMDLNNyyLk36T6iMu0o */
-typedef enum
-{
- HB_SCRIPT_COMMON = HB_TAG ('Z','y','y','y'), /*1.1*/
- HB_SCRIPT_INHERITED = HB_TAG ('Z','i','n','h'), /*1.1*/
- HB_SCRIPT_UNKNOWN = HB_TAG ('Z','z','z','z'), /*5.0*/
-
- HB_SCRIPT_ARABIC = HB_TAG ('A','r','a','b'), /*1.1*/
- HB_SCRIPT_ARMENIAN = HB_TAG ('A','r','m','n'), /*1.1*/
- HB_SCRIPT_BENGALI = HB_TAG ('B','e','n','g'), /*1.1*/
- HB_SCRIPT_CYRILLIC = HB_TAG ('C','y','r','l'), /*1.1*/
- HB_SCRIPT_DEVANAGARI = HB_TAG ('D','e','v','a'), /*1.1*/
- HB_SCRIPT_GEORGIAN = HB_TAG ('G','e','o','r'), /*1.1*/
- HB_SCRIPT_GREEK = HB_TAG ('G','r','e','k'), /*1.1*/
- HB_SCRIPT_GUJARATI = HB_TAG ('G','u','j','r'), /*1.1*/
- HB_SCRIPT_GURMUKHI = HB_TAG ('G','u','r','u'), /*1.1*/
- HB_SCRIPT_HANGUL = HB_TAG ('H','a','n','g'), /*1.1*/
- HB_SCRIPT_HAN = HB_TAG ('H','a','n','i'), /*1.1*/
- HB_SCRIPT_HEBREW = HB_TAG ('H','e','b','r'), /*1.1*/
- HB_SCRIPT_HIRAGANA = HB_TAG ('H','i','r','a'), /*1.1*/
- HB_SCRIPT_KANNADA = HB_TAG ('K','n','d','a'), /*1.1*/
- HB_SCRIPT_KATAKANA = HB_TAG ('K','a','n','a'), /*1.1*/
- HB_SCRIPT_LAO = HB_TAG ('L','a','o','o'), /*1.1*/
- HB_SCRIPT_LATIN = HB_TAG ('L','a','t','n'), /*1.1*/
- HB_SCRIPT_MALAYALAM = HB_TAG ('M','l','y','m'), /*1.1*/
- HB_SCRIPT_ORIYA = HB_TAG ('O','r','y','a'), /*1.1*/
- HB_SCRIPT_TAMIL = HB_TAG ('T','a','m','l'), /*1.1*/
- HB_SCRIPT_TELUGU = HB_TAG ('T','e','l','u'), /*1.1*/
- HB_SCRIPT_THAI = HB_TAG ('T','h','a','i'), /*1.1*/
-
- HB_SCRIPT_TIBETAN = HB_TAG ('T','i','b','t'), /*2.0*/
-
- HB_SCRIPT_BOPOMOFO = HB_TAG ('B','o','p','o'), /*3.0*/
- HB_SCRIPT_BRAILLE = HB_TAG ('B','r','a','i'), /*3.0*/
- HB_SCRIPT_CANADIAN_SYLLABICS = HB_TAG ('C','a','n','s'), /*3.0*/
- HB_SCRIPT_CHEROKEE = HB_TAG ('C','h','e','r'), /*3.0*/
- HB_SCRIPT_ETHIOPIC = HB_TAG ('E','t','h','i'), /*3.0*/
- HB_SCRIPT_KHMER = HB_TAG ('K','h','m','r'), /*3.0*/
- HB_SCRIPT_MONGOLIAN = HB_TAG ('M','o','n','g'), /*3.0*/
- HB_SCRIPT_MYANMAR = HB_TAG ('M','y','m','r'), /*3.0*/
- HB_SCRIPT_OGHAM = HB_TAG ('O','g','a','m'), /*3.0*/
- HB_SCRIPT_RUNIC = HB_TAG ('R','u','n','r'), /*3.0*/
- HB_SCRIPT_SINHALA = HB_TAG ('S','i','n','h'), /*3.0*/
- HB_SCRIPT_SYRIAC = HB_TAG ('S','y','r','c'), /*3.0*/
- HB_SCRIPT_THAANA = HB_TAG ('T','h','a','a'), /*3.0*/
- HB_SCRIPT_YI = HB_TAG ('Y','i','i','i'), /*3.0*/
-
- HB_SCRIPT_DESERET = HB_TAG ('D','s','r','t'), /*3.1*/
- HB_SCRIPT_GOTHIC = HB_TAG ('G','o','t','h'), /*3.1*/
- HB_SCRIPT_OLD_ITALIC = HB_TAG ('I','t','a','l'), /*3.1*/
-
- HB_SCRIPT_BUHID = HB_TAG ('B','u','h','d'), /*3.2*/
- HB_SCRIPT_HANUNOO = HB_TAG ('H','a','n','o'), /*3.2*/
- HB_SCRIPT_TAGALOG = HB_TAG ('T','g','l','g'), /*3.2*/
- HB_SCRIPT_TAGBANWA = HB_TAG ('T','a','g','b'), /*3.2*/
-
- HB_SCRIPT_CYPRIOT = HB_TAG ('C','p','r','t'), /*4.0*/
- HB_SCRIPT_LIMBU = HB_TAG ('L','i','m','b'), /*4.0*/
- HB_SCRIPT_LINEAR_B = HB_TAG ('L','i','n','b'), /*4.0*/
- HB_SCRIPT_OSMANYA = HB_TAG ('O','s','m','a'), /*4.0*/
- HB_SCRIPT_SHAVIAN = HB_TAG ('S','h','a','w'), /*4.0*/
- HB_SCRIPT_TAI_LE = HB_TAG ('T','a','l','e'), /*4.0*/
- HB_SCRIPT_UGARITIC = HB_TAG ('U','g','a','r'), /*4.0*/
-
- HB_SCRIPT_BUGINESE = HB_TAG ('B','u','g','i'), /*4.1*/
- HB_SCRIPT_COPTIC = HB_TAG ('C','o','p','t'), /*4.1*/
- HB_SCRIPT_GLAGOLITIC = HB_TAG ('G','l','a','g'), /*4.1*/
- HB_SCRIPT_KHAROSHTHI = HB_TAG ('K','h','a','r'), /*4.1*/
- HB_SCRIPT_NEW_TAI_LUE = HB_TAG ('T','a','l','u'), /*4.1*/
- HB_SCRIPT_OLD_PERSIAN = HB_TAG ('X','p','e','o'), /*4.1*/
- HB_SCRIPT_SYLOTI_NAGRI = HB_TAG ('S','y','l','o'), /*4.1*/
- HB_SCRIPT_TIFINAGH = HB_TAG ('T','f','n','g'), /*4.1*/
-
- HB_SCRIPT_BALINESE = HB_TAG ('B','a','l','i'), /*5.0*/
- HB_SCRIPT_CUNEIFORM = HB_TAG ('X','s','u','x'), /*5.0*/
- HB_SCRIPT_NKO = HB_TAG ('N','k','o','o'), /*5.0*/
- HB_SCRIPT_PHAGS_PA = HB_TAG ('P','h','a','g'), /*5.0*/
- HB_SCRIPT_PHOENICIAN = HB_TAG ('P','h','n','x'), /*5.0*/
-
- HB_SCRIPT_CARIAN = HB_TAG ('C','a','r','i'), /*5.1*/
- HB_SCRIPT_CHAM = HB_TAG ('C','h','a','m'), /*5.1*/
- HB_SCRIPT_KAYAH_LI = HB_TAG ('K','a','l','i'), /*5.1*/
- HB_SCRIPT_LEPCHA = HB_TAG ('L','e','p','c'), /*5.1*/
- HB_SCRIPT_LYCIAN = HB_TAG ('L','y','c','i'), /*5.1*/
- HB_SCRIPT_LYDIAN = HB_TAG ('L','y','d','i'), /*5.1*/
- HB_SCRIPT_OL_CHIKI = HB_TAG ('O','l','c','k'), /*5.1*/
- HB_SCRIPT_REJANG = HB_TAG ('R','j','n','g'), /*5.1*/
- HB_SCRIPT_SAURASHTRA = HB_TAG ('S','a','u','r'), /*5.1*/
- HB_SCRIPT_SUNDANESE = HB_TAG ('S','u','n','d'), /*5.1*/
- HB_SCRIPT_VAI = HB_TAG ('V','a','i','i'), /*5.1*/
-
- HB_SCRIPT_AVESTAN = HB_TAG ('A','v','s','t'), /*5.2*/
- HB_SCRIPT_BAMUM = HB_TAG ('B','a','m','u'), /*5.2*/
- HB_SCRIPT_EGYPTIAN_HIEROGLYPHS = HB_TAG ('E','g','y','p'), /*5.2*/
- HB_SCRIPT_IMPERIAL_ARAMAIC = HB_TAG ('A','r','m','i'), /*5.2*/
- HB_SCRIPT_INSCRIPTIONAL_PAHLAVI = HB_TAG ('P','h','l','i'), /*5.2*/
- HB_SCRIPT_INSCRIPTIONAL_PARTHIAN = HB_TAG ('P','r','t','i'), /*5.2*/
- HB_SCRIPT_JAVANESE = HB_TAG ('J','a','v','a'), /*5.2*/
- HB_SCRIPT_KAITHI = HB_TAG ('K','t','h','i'), /*5.2*/
- HB_SCRIPT_LISU = HB_TAG ('L','i','s','u'), /*5.2*/
- HB_SCRIPT_MEETEI_MAYEK = HB_TAG ('M','t','e','i'), /*5.2*/
- HB_SCRIPT_OLD_SOUTH_ARABIAN = HB_TAG ('S','a','r','b'), /*5.2*/
- HB_SCRIPT_OLD_TURKIC = HB_TAG ('O','r','k','h'), /*5.2*/
- HB_SCRIPT_SAMARITAN = HB_TAG ('S','a','m','r'), /*5.2*/
- HB_SCRIPT_TAI_THAM = HB_TAG ('L','a','n','a'), /*5.2*/
- HB_SCRIPT_TAI_VIET = HB_TAG ('T','a','v','t'), /*5.2*/
-
- HB_SCRIPT_BATAK = HB_TAG ('B','a','t','k'), /*6.0*/
- HB_SCRIPT_BRAHMI = HB_TAG ('B','r','a','h'), /*6.0*/
- HB_SCRIPT_MANDAIC = HB_TAG ('M','a','n','d'), /*6.0*/
-
- HB_SCRIPT_CHAKMA = HB_TAG ('C','a','k','m'), /*6.1*/
- HB_SCRIPT_MEROITIC_CURSIVE = HB_TAG ('M','e','r','c'), /*6.1*/
- HB_SCRIPT_MEROITIC_HIEROGLYPHS = HB_TAG ('M','e','r','o'), /*6.1*/
- HB_SCRIPT_MIAO = HB_TAG ('P','l','r','d'), /*6.1*/
- HB_SCRIPT_SHARADA = HB_TAG ('S','h','r','d'), /*6.1*/
- HB_SCRIPT_SORA_SOMPENG = HB_TAG ('S','o','r','a'), /*6.1*/
- HB_SCRIPT_TAKRI = HB_TAG ('T','a','k','r'), /*6.1*/
-
- /*
- * Since: 0.9.30
- */
- HB_SCRIPT_BASSA_VAH = HB_TAG ('B','a','s','s'), /*7.0*/
- HB_SCRIPT_CAUCASIAN_ALBANIAN = HB_TAG ('A','g','h','b'), /*7.0*/
- HB_SCRIPT_DUPLOYAN = HB_TAG ('D','u','p','l'), /*7.0*/
- HB_SCRIPT_ELBASAN = HB_TAG ('E','l','b','a'), /*7.0*/
- HB_SCRIPT_GRANTHA = HB_TAG ('G','r','a','n'), /*7.0*/
- HB_SCRIPT_KHOJKI = HB_TAG ('K','h','o','j'), /*7.0*/
- HB_SCRIPT_KHUDAWADI = HB_TAG ('S','i','n','d'), /*7.0*/
- HB_SCRIPT_LINEAR_A = HB_TAG ('L','i','n','a'), /*7.0*/
- HB_SCRIPT_MAHAJANI = HB_TAG ('M','a','h','j'), /*7.0*/
- HB_SCRIPT_MANICHAEAN = HB_TAG ('M','a','n','i'), /*7.0*/
- HB_SCRIPT_MENDE_KIKAKUI = HB_TAG ('M','e','n','d'), /*7.0*/
- HB_SCRIPT_MODI = HB_TAG ('M','o','d','i'), /*7.0*/
- HB_SCRIPT_MRO = HB_TAG ('M','r','o','o'), /*7.0*/
- HB_SCRIPT_NABATAEAN = HB_TAG ('N','b','a','t'), /*7.0*/
- HB_SCRIPT_OLD_NORTH_ARABIAN = HB_TAG ('N','a','r','b'), /*7.0*/
- HB_SCRIPT_OLD_PERMIC = HB_TAG ('P','e','r','m'), /*7.0*/
- HB_SCRIPT_PAHAWH_HMONG = HB_TAG ('H','m','n','g'), /*7.0*/
- HB_SCRIPT_PALMYRENE = HB_TAG ('P','a','l','m'), /*7.0*/
- HB_SCRIPT_PAU_CIN_HAU = HB_TAG ('P','a','u','c'), /*7.0*/
- HB_SCRIPT_PSALTER_PAHLAVI = HB_TAG ('P','h','l','p'), /*7.0*/
- HB_SCRIPT_SIDDHAM = HB_TAG ('S','i','d','d'), /*7.0*/
- HB_SCRIPT_TIRHUTA = HB_TAG ('T','i','r','h'), /*7.0*/
- HB_SCRIPT_WARANG_CITI = HB_TAG ('W','a','r','a'), /*7.0*/
-
- HB_SCRIPT_AHOM = HB_TAG ('A','h','o','m'), /*8.0*/
- HB_SCRIPT_ANATOLIAN_HIEROGLYPHS = HB_TAG ('H','l','u','w'), /*8.0*/
- HB_SCRIPT_HATRAN = HB_TAG ('H','a','t','r'), /*8.0*/
- HB_SCRIPT_MULTANI = HB_TAG ('M','u','l','t'), /*8.0*/
- HB_SCRIPT_OLD_HUNGARIAN = HB_TAG ('H','u','n','g'), /*8.0*/
- HB_SCRIPT_SIGNWRITING = HB_TAG ('S','g','n','w'), /*8.0*/
-
- /*
- * Since 1.3.0
- */
- HB_SCRIPT_ADLAM = HB_TAG ('A','d','l','m'), /*9.0*/
- HB_SCRIPT_BHAIKSUKI = HB_TAG ('B','h','k','s'), /*9.0*/
- HB_SCRIPT_MARCHEN = HB_TAG ('M','a','r','c'), /*9.0*/
- HB_SCRIPT_OSAGE = HB_TAG ('O','s','g','e'), /*9.0*/
- HB_SCRIPT_TANGUT = HB_TAG ('T','a','n','g'), /*9.0*/
- HB_SCRIPT_NEWA = HB_TAG ('N','e','w','a'), /*9.0*/
-
- /*
- * Since 1.6.0
- */
- HB_SCRIPT_MASARAM_GONDI = HB_TAG ('G','o','n','m'), /*10.0*/
- HB_SCRIPT_NUSHU = HB_TAG ('N','s','h','u'), /*10.0*/
- HB_SCRIPT_SOYOMBO = HB_TAG ('S','o','y','o'), /*10.0*/
- HB_SCRIPT_ZANABAZAR_SQUARE = HB_TAG ('Z','a','n','b'), /*10.0*/
-
- /*
- * Since 1.8.0
- */
- HB_SCRIPT_DOGRA = HB_TAG ('D','o','g','r'), /*11.0*/
- HB_SCRIPT_GUNJALA_GONDI = HB_TAG ('G','o','n','g'), /*11.0*/
- HB_SCRIPT_HANIFI_ROHINGYA = HB_TAG ('R','o','h','g'), /*11.0*/
- HB_SCRIPT_MAKASAR = HB_TAG ('M','a','k','a'), /*11.0*/
- HB_SCRIPT_MEDEFAIDRIN = HB_TAG ('M','e','d','f'), /*11.0*/
- HB_SCRIPT_OLD_SOGDIAN = HB_TAG ('S','o','g','o'), /*11.0*/
- HB_SCRIPT_SOGDIAN = HB_TAG ('S','o','g','d'), /*11.0*/
-
- /*
- * Since 2.4.0
- */
- HB_SCRIPT_ELYMAIC = HB_TAG ('E','l','y','m'), /*12.0*/
- HB_SCRIPT_NANDINAGARI = HB_TAG ('N','a','n','d'), /*12.0*/
- HB_SCRIPT_NYIAKENG_PUACHUE_HMONG = HB_TAG ('H','m','n','p'), /*12.0*/
- HB_SCRIPT_WANCHO = HB_TAG ('W','c','h','o'), /*12.0*/
-
- /*
- * Since 2.6.7
- */
- HB_SCRIPT_CHORASMIAN = HB_TAG ('C','h','r','s'), /*13.0*/
- HB_SCRIPT_DIVES_AKURU = HB_TAG ('D','i','a','k'), /*13.0*/
- HB_SCRIPT_KHITAN_SMALL_SCRIPT = HB_TAG ('K','i','t','s'), /*13.0*/
- HB_SCRIPT_YEZIDI = HB_TAG ('Y','e','z','i'), /*13.0*/
-
- /*
- * Since 3.0.0
- */
- HB_SCRIPT_CYPRO_MINOAN = HB_TAG ('C','p','m','n'), /*14.0*/
- HB_SCRIPT_OLD_UYGHUR = HB_TAG ('O','u','g','r'), /*14.0*/
- HB_SCRIPT_TANGSA = HB_TAG ('T','n','s','a'), /*14.0*/
- HB_SCRIPT_TOTO = HB_TAG ('T','o','t','o'), /*14.0*/
- HB_SCRIPT_VITHKUQI = HB_TAG ('V','i','t','h'), /*14.0*/
-
- /*
- * Since 3.4.0
- */
- HB_SCRIPT_MATH = HB_TAG ('Z','m','t','h'),
-
- /*
- * Since 5.2.0
- */
- HB_SCRIPT_KAWI = HB_TAG ('K','a','w','i'), /*15.0*/
- HB_SCRIPT_NAG_MUNDARI = HB_TAG ('N','a','g','m'), /*15.0*/
-
- /*
- * Since 10.0.0
- */
- HB_SCRIPT_GARAY = HB_TAG ('G','a','r','a'), /*16.0*/
- HB_SCRIPT_GURUNG_KHEMA = HB_TAG ('G','u','k','h'), /*16.0*/
- HB_SCRIPT_KIRAT_RAI = HB_TAG ('K','r','a','i'), /*16.0*/
- HB_SCRIPT_OL_ONAL = HB_TAG ('O','n','a','o'), /*16.0*/
- HB_SCRIPT_SUNUWAR = HB_TAG ('S','u','n','u'), /*16.0*/
- HB_SCRIPT_TODHRI = HB_TAG ('T','o','d','r'), /*16.0*/
- HB_SCRIPT_TULU_TIGALARI = HB_TAG ('T','u','t','g'), /*16.0*/
-
- /* No script set. */
- HB_SCRIPT_INVALID = HB_TAG_NONE,
-
- /*< private >*/
-
- /* Dummy values to ensure any hb_tag_t value can be passed/stored as hb_script_t
- * without risking undefined behavior. We have two, for historical reasons.
- * HB_TAG_MAX used to be unsigned, but that was invalid Ansi C, so was changed
- * to _HB_SCRIPT_MAX_VALUE to be equal to HB_TAG_MAX_SIGNED as well.
- *
- * See this thread for technicalities:
- *
- * https://lists.freedesktop.org/archives/harfbuzz/2014-March/004150.html
- */
- _HB_SCRIPT_MAX_VALUE = HB_TAG_MAX_SIGNED, /*< skip >*/
- _HB_SCRIPT_MAX_VALUE_SIGNED = HB_TAG_MAX_SIGNED /*< skip >*/
-
-} hb_script_t;
-
+#include "hb-script-list.h"
/* Script functions */
@@ -948,6 +519,16 @@ typedef struct hb_glyph_extents_t {
*/
typedef struct hb_font_t hb_font_t;
+/* Not of much use to clients. */
+HB_EXTERN void*
+hb_malloc (size_t size);
+HB_EXTERN void*
+hb_calloc (size_t nmemb, size_t size);
+HB_EXTERN void*
+hb_realloc (void *ptr, size_t size);
+HB_EXTERN void
+hb_free (void *ptr);
+
HB_END_DECLS
#endif /* HB_COMMON_H */
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-config.hh b/src/java.desktop/share/native/libharfbuzz/hb-config.hh
index 40cc2403c18..3956690da35 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-config.hh
+++ b/src/java.desktop/share/native/libharfbuzz/hb-config.hh
@@ -146,6 +146,7 @@
#ifdef HB_NO_DRAW
#define HB_NO_OUTLINE
+#define HB_NO_PAINT
#endif
#ifdef HB_NO_GETENV
@@ -191,7 +192,6 @@
#ifdef HB_MINIMIZE_MEMORY_USAGE
#define HB_NO_GDEF_CACHE
#define HB_NO_OT_LAYOUT_LOOKUP_CACHE
-#define HB_NO_OT_FONT_ADVANCE_CACHE
#define HB_NO_OT_FONT_CMAP_CACHE
#endif
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-debug.hh b/src/java.desktop/share/native/libharfbuzz/hb-debug.hh
index 341e61e57c6..1e9a18b9326 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-debug.hh
+++ b/src/java.desktop/share/native/libharfbuzz/hb-debug.hh
@@ -49,15 +49,15 @@ struct hb_options_t
};
union hb_options_union_t {
- int i;
+ unsigned i;
hb_options_t opts;
};
-static_assert ((sizeof (hb_atomic_int_t) >= sizeof (hb_options_union_t)), "");
+static_assert ((sizeof (hb_atomic_t) >= sizeof (hb_options_union_t)), "");
HB_INTERNAL void
_hb_options_init ();
-extern HB_INTERNAL hb_atomic_int_t _hb_options;
+extern HB_INTERNAL hb_atomic_t _hb_options;
static inline hb_options_t
hb_options ()
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-deprecated.h b/src/java.desktop/share/native/libharfbuzz/hb-deprecated.h
index d854a2b16f5..927563c4c40 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-deprecated.h
+++ b/src/java.desktop/share/native/libharfbuzz/hb-deprecated.h
@@ -275,6 +275,48 @@ typedef void (*hb_font_get_glyph_shape_func_t) (hb_font_t *font, void *font_data
hb_draw_funcs_t *draw_funcs, void *draw_data,
void *user_data);
+/**
+ * hb_font_draw_glyph_func_t:
+ * @font: #hb_font_t to work upon
+ * @font_data: @font user data pointer
+ * @glyph: The glyph ID to query
+ * @draw_funcs: The draw functions to send the shape data to
+ * @draw_data: The data accompanying the draw functions
+ * @user_data: User data pointer passed by the caller
+ *
+ * A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
+ *
+ * Since: 7.0.0
+ * XDeprecated: REPLACEME: Use hb_font_draw_glyph_func_or_fail_t instead.
+ **/
+typedef void (*hb_font_draw_glyph_func_t) (hb_font_t *font, void *font_data,
+ hb_codepoint_t glyph,
+ hb_draw_funcs_t *draw_funcs, void *draw_data,
+ void *user_data);
+
+/**
+ * hb_font_paint_glyph_func_t:
+ * @font: #hb_font_t to work upon
+ * @font_data: @font user data pointer
+ * @glyph: The glyph ID to query
+ * @paint_funcs: The paint functions to use
+ * @paint_data: The data accompanying the paint functions
+ * @palette_index: The color palette to use
+ * @foreground: The foreground color
+ * @user_data: User data pointer passed by the caller
+ *
+ * A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
+ *
+ * Since: 7.0.0
+ * XDeprecated: REPLACEME: Use hb_font_paint_glyph_or_fail_func_t instead.
+ */
+typedef hb_bool_t (*hb_font_paint_glyph_func_t) (hb_font_t *font, void *font_data,
+ hb_codepoint_t glyph,
+ hb_paint_funcs_t *paint_funcs, void *paint_data,
+ unsigned int palette_index,
+ hb_color_t foreground,
+ void *user_data);
+
/**
* hb_font_funcs_set_glyph_shape_func:
* @ffuncs: A font-function structure
@@ -288,13 +330,49 @@ typedef void (*hb_font_get_glyph_shape_func_t) (hb_font_t *font, void *font_data
* Since: 4.0.0
* Deprecated: 7.0.0: Use hb_font_funcs_set_draw_glyph_func() instead
**/
-HB_DEPRECATED_FOR (hb_font_funcs_set_draw_glyph_func)
+HB_DEPRECATED_FOR (hb_font_funcs_set_draw_glyph_or_fail_func)
HB_EXTERN void
hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs,
hb_font_get_glyph_shape_func_t func,
void *user_data, hb_destroy_func_t destroy);
-HB_DEPRECATED_FOR (hb_font_draw_glyph)
+/**
+ * hb_font_funcs_set_draw_glyph_func:
+ * @ffuncs: A font-function structure
+ * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
+ * @user_data: Data to pass to @func
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
+ *
+ * Sets the implementation function for #hb_font_draw_glyph_func_t.
+ *
+ * Since: 7.0.0
+ * XDeprecated: REPLACEME: Use hb_font_funcs_set_draw_glyph_or_fail_func instead.
+ **/
+HB_DEPRECATED_FOR (hb_font_funcs_set_draw_glyph_or_fail_func)
+HB_EXTERN void
+hb_font_funcs_set_draw_glyph_func (hb_font_funcs_t *ffuncs,
+ hb_font_draw_glyph_func_t func,
+ void *user_data, hb_destroy_func_t destroy);
+
+/**
+ * hb_font_funcs_set_paint_glyph_func:
+ * @ffuncs: A font-function structure
+ * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
+ * @user_data: Data to pass to @func
+ * @destroy: (nullable): The function to call when @user_data is no longer needed
+ *
+ * Sets the implementation function for #hb_font_paint_glyph_func_t.
+ *
+ * Since: 7.0.0
+ * XDeprecated: REPLACEME: Use hb_font_funcs_set_paint_glyph_or_fail_func() instead.
+ */
+HB_DEPRECATED_FOR (hb_font_funcs_set_paint_glyph_or_fail_func)
+HB_EXTERN void
+hb_font_funcs_set_paint_glyph_func (hb_font_funcs_t *ffuncs,
+ hb_font_paint_glyph_func_t func,
+ void *user_data, hb_destroy_func_t destroy);
+
+HB_DEPRECATED_FOR (hb_font_draw_glyph_or_fail)
HB_EXTERN void
hb_font_get_glyph_shape (hb_font_t *font,
hb_codepoint_t glyph,
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-draw.cc b/src/java.desktop/share/native/libharfbuzz/hb-draw.cc
index f2821578b65..8764ffe7129 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-draw.cc
+++ b/src/java.desktop/share/native/libharfbuzz/hb-draw.cc
@@ -28,6 +28,11 @@
#include "hb-draw.hh"
+#include "hb-geometry.hh"
+
+#include "hb-machinery.hh"
+
+
/**
* SECTION:hb-draw
* @title: hb-draw
@@ -455,4 +460,92 @@ hb_draw_close_path (hb_draw_funcs_t *dfuncs, void *draw_data,
}
+static void
+hb_draw_extents_move_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
+ void *data,
+ hb_draw_state_t *st,
+ float to_x, float to_y,
+ void *user_data HB_UNUSED)
+{
+ hb_extents_t *extents = (hb_extents_t *) data;
+
+ extents->add_point (to_x, to_y);
+}
+
+static void
+hb_draw_extents_line_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
+ void *data,
+ hb_draw_state_t *st,
+ float to_x, float to_y,
+ void *user_data HB_UNUSED)
+{
+ hb_extents_t *extents = (hb_extents_t *) data;
+
+ extents->add_point (to_x, to_y);
+}
+
+static void
+hb_draw_extents_quadratic_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
+ void *data,
+ hb_draw_state_t *st,
+ float control_x, float control_y,
+ float to_x, float to_y,
+ void *user_data HB_UNUSED)
+{
+ hb_extents_t *extents = (hb_extents_t *) data;
+
+ extents->add_point (control_x, control_y);
+ extents->add_point (to_x, to_y);
+}
+
+static void
+hb_draw_extents_cubic_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
+ void *data,
+ hb_draw_state_t *st,
+ float control1_x, float control1_y,
+ float control2_x, float control2_y,
+ float to_x, float to_y,
+ void *user_data HB_UNUSED)
+{
+ hb_extents_t *extents = (hb_extents_t *) data;
+
+ extents->add_point (control1_x, control1_y);
+ extents->add_point (control2_x, control2_y);
+ extents->add_point (to_x, to_y);
+}
+
+static inline void free_static_draw_extents_funcs ();
+
+static struct hb_draw_extents_funcs_lazy_loader_t : hb_draw_funcs_lazy_loader_t
+{
+ static hb_draw_funcs_t *create ()
+ {
+ hb_draw_funcs_t *funcs = hb_draw_funcs_create ();
+
+ hb_draw_funcs_set_move_to_func (funcs, hb_draw_extents_move_to, nullptr, nullptr);
+ hb_draw_funcs_set_line_to_func (funcs, hb_draw_extents_line_to, nullptr, nullptr);
+ hb_draw_funcs_set_quadratic_to_func (funcs, hb_draw_extents_quadratic_to, nullptr, nullptr);
+ hb_draw_funcs_set_cubic_to_func (funcs, hb_draw_extents_cubic_to, nullptr, nullptr);
+
+ hb_draw_funcs_make_immutable (funcs);
+
+ hb_atexit (free_static_draw_extents_funcs);
+
+ return funcs;
+ }
+} static_draw_extents_funcs;
+
+static inline
+void free_static_draw_extents_funcs ()
+{
+ static_draw_extents_funcs.free_instance ();
+}
+
+hb_draw_funcs_t *
+hb_draw_extents_get_funcs ()
+{
+ return static_draw_extents_funcs.get_unconst ();
+}
+
+
#endif
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-draw.h b/src/java.desktop/share/native/libharfbuzz/hb-draw.h
index 4556b082d60..06299e17a78 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-draw.h
+++ b/src/java.desktop/share/native/libharfbuzz/hb-draw.h
@@ -70,7 +70,7 @@ typedef struct hb_draw_state_t {
*
* The default #hb_draw_state_t at the start of glyph drawing.
*/
-#define HB_DRAW_STATE_DEFAULT {0, 0.f, 0.f, 0.f, 0.f, {0.}, {0.}, {0.}, {0.}, {0.}, {0.}, {0.}}
+#define HB_DRAW_STATE_DEFAULT {0, 0.f, 0.f, 0.f, 0.f, {0}, {0}, {0}, {0}, {0}, {0}, {0}}
/**
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-draw.hh b/src/java.desktop/share/native/libharfbuzz/hb-draw.hh
index 2c30843de64..224e10939fe 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-draw.hh
+++ b/src/java.desktop/share/native/libharfbuzz/hb-draw.hh
@@ -99,6 +99,7 @@ struct hb_draw_funcs_t
float to_x, float to_y)
{
if (unlikely (st.path_open)) close_path (draw_data, st);
+
st.current_x = to_x;
st.current_y = to_y;
}
@@ -109,7 +110,9 @@ struct hb_draw_funcs_t
float to_x, float to_y)
{
if (unlikely (!st.path_open)) start_path (draw_data, st);
+
emit_line_to (draw_data, st, to_x, to_y);
+
st.current_x = to_x;
st.current_y = to_y;
}
@@ -121,7 +124,9 @@ struct hb_draw_funcs_t
float to_x, float to_y)
{
if (unlikely (!st.path_open)) start_path (draw_data, st);
+
emit_quadratic_to (draw_data, st, control_x, control_y, to_x, to_y);
+
st.current_x = to_x;
st.current_y = to_y;
}
@@ -134,7 +139,9 @@ struct hb_draw_funcs_t
float to_x, float to_y)
{
if (unlikely (!st.path_open)) start_path (draw_data, st);
+
emit_cubic_to (draw_data, st, control1_x, control1_y, control2_x, control2_y, to_x, to_y);
+
st.current_x = to_x;
st.current_y = to_y;
}
@@ -168,9 +175,8 @@ DECLARE_NULL_INSTANCE (hb_draw_funcs_t);
struct hb_draw_session_t
{
- hb_draw_session_t (hb_draw_funcs_t *funcs_, void *draw_data_, float slant_ = 0.f)
- : slant {slant_}, not_slanted {slant == 0.f},
- funcs {funcs_}, draw_data {draw_data_}, st HB_DRAW_STATE_DEFAULT
+ hb_draw_session_t (hb_draw_funcs_t *funcs_, void *draw_data_)
+ : funcs {funcs_}, draw_data {draw_data_}, st HB_DRAW_STATE_DEFAULT
{}
~hb_draw_session_t () { close_path (); }
@@ -178,36 +184,23 @@ struct hb_draw_session_t
HB_ALWAYS_INLINE
void move_to (float to_x, float to_y)
{
- if (likely (not_slanted))
- funcs->move_to (draw_data, st,
- to_x, to_y);
- else
- funcs->move_to (draw_data, st,
- to_x + to_y * slant, to_y);
+ funcs->move_to (draw_data, st,
+ to_x, to_y);
}
HB_ALWAYS_INLINE
void line_to (float to_x, float to_y)
{
- if (likely (not_slanted))
- funcs->line_to (draw_data, st,
- to_x, to_y);
- else
- funcs->line_to (draw_data, st,
- to_x + to_y * slant, to_y);
+ funcs->line_to (draw_data, st,
+ to_x, to_y);
}
void
HB_ALWAYS_INLINE
quadratic_to (float control_x, float control_y,
float to_x, float to_y)
{
- if (likely (not_slanted))
- funcs->quadratic_to (draw_data, st,
- control_x, control_y,
- to_x, to_y);
- else
- funcs->quadratic_to (draw_data, st,
- control_x + control_y * slant, control_y,
- to_x + to_y * slant, to_y);
+ funcs->quadratic_to (draw_data, st,
+ control_x, control_y,
+ to_x, to_y);
}
void
HB_ALWAYS_INLINE
@@ -215,16 +208,10 @@ struct hb_draw_session_t
float control2_x, float control2_y,
float to_x, float to_y)
{
- if (likely (not_slanted))
- funcs->cubic_to (draw_data, st,
- control1_x, control1_y,
- control2_x, control2_y,
- to_x, to_y);
- else
- funcs->cubic_to (draw_data, st,
- control1_x + control1_y * slant, control1_y,
- control2_x + control2_y * slant, control2_y,
- to_x + to_y * slant, to_y);
+ funcs->cubic_to (draw_data, st,
+ control1_x, control1_y,
+ control2_x, control2_y,
+ to_x, to_y);
}
HB_ALWAYS_INLINE
void close_path ()
@@ -233,11 +220,14 @@ struct hb_draw_session_t
}
public:
- float slant;
- bool not_slanted;
hb_draw_funcs_t *funcs;
void *draw_data;
hb_draw_state_t st;
};
+
+HB_INTERNAL hb_draw_funcs_t *
+hb_draw_extents_get_funcs ();
+
+
#endif /* HB_DRAW_HH */
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-face.cc b/src/java.desktop/share/native/libharfbuzz/hb-face.cc
index 7967ae3241b..9d59d7c9468 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-face.cc
+++ b/src/java.desktop/share/native/libharfbuzz/hb-face.cc
@@ -34,6 +34,16 @@
#include "hb-ot-face.hh"
#include "hb-ot-cmap-table.hh"
+#ifdef HAVE_FREETYPE
+#include "hb-ft.h"
+#endif
+#ifdef HAVE_CORETEXT
+#include "hb-coretext.h"
+#endif
+#ifdef HAVE_DIRECTWRITE
+#include "hb-directwrite.h"
+#endif
+
/**
* SECTION:hb-face
@@ -72,14 +82,14 @@ hb_face_count (hb_blob_t *blob)
if (unlikely (!blob))
return 0;
- /* TODO We shouldn't be sanitizing blob. Port to run sanitizer and return if not sane. */
- /* Make API signature const after. */
- hb_blob_t *sanitized = hb_sanitize_context_t ().sanitize_blob (hb_blob_reference (blob));
- const OT::OpenTypeFontFile& ot = *sanitized->as ();
- unsigned int ret = ot.get_face_count ();
- hb_blob_destroy (sanitized);
+ hb_sanitize_context_t c (blob);
- return ret;
+ const char *start = hb_blob_get_data (blob, nullptr);
+ auto *ot = reinterpret_cast (const_cast (start));
+ if (unlikely (!ot->sanitize (&c)))
+ return 0;
+
+ return ot->get_face_count ();
}
/*
@@ -318,7 +328,209 @@ hb_face_create_from_file_or_fail (const char *file_name,
return face;
}
+
+static struct supported_face_loaders_t {
+ char name[16];
+ hb_face_t * (*from_file) (const char *font_file, unsigned face_index);
+ hb_face_t * (*from_blob) (hb_blob_t *blob, unsigned face_index);
+} supported_face_loaders[] =
+{
+ {"ot",
+#ifndef HB_NO_OPEN
+ hb_face_create_from_file_or_fail,
+#else
+ nullptr,
#endif
+ hb_face_create_or_fail
+ },
+#ifdef HAVE_FREETYPE
+ {"ft",
+ hb_ft_face_create_from_file_or_fail,
+ hb_ft_face_create_from_blob_or_fail
+ },
+#endif
+#ifdef HAVE_CORETEXT
+ {"coretext",
+ hb_coretext_face_create_from_file_or_fail,
+ hb_coretext_face_create_from_blob_or_fail
+ },
+#endif
+#ifdef HAVE_DIRECTWRITE
+ {"directwrite",
+ hb_directwrite_face_create_from_file_or_fail,
+ hb_directwrite_face_create_from_blob_or_fail
+ },
+#endif
+};
+
+static const char *get_default_loader_name ()
+{
+ static hb_atomic_t static_loader_name;
+ const char *loader_name = static_loader_name.get_acquire ();
+ if (!loader_name)
+ {
+ loader_name = getenv ("HB_FACE_LOADER");
+ if (!loader_name)
+ loader_name = "";
+ if (!static_loader_name.cmpexch (nullptr, loader_name))
+ loader_name = static_loader_name.get_acquire ();
+ }
+ return loader_name;
+}
+
+/**
+ * hb_face_create_from_file_or_fail_using:
+ * @file_name: A font filename
+ * @index: The index of the face within the file
+ * @loader_name: (nullable): The name of the loader to use, or `NULL`
+ *
+ * A thin wrapper around the face loader functions registered with HarfBuzz.
+ * If @loader_name is `NULL` or the empty string, the first available loader
+ * is used.
+ *
+ * For example, the FreeType ("ft") loader might be able to load
+ * WOFF and WOFF2 files if FreeType is built with those features,
+ * whereas the OpenType ("ot") loader will not.
+ *
+ * Return value: (transfer full): The new face object, or `NULL` if
+ * the file cannot be read or the loader fails to load the face.
+ *
+ * Since: 11.0.0
+ **/
+hb_face_t *
+hb_face_create_from_file_or_fail_using (const char *file_name,
+ unsigned int index,
+ const char *loader_name)
+{
+ // Duplicated in hb_face_create_or_fail_using
+ bool retry = false;
+ if (!loader_name || !*loader_name)
+ {
+ loader_name = get_default_loader_name ();
+ retry = true;
+ }
+ if (loader_name && !*loader_name) loader_name = nullptr;
+
+retry:
+ for (unsigned i = 0; i < ARRAY_LENGTH (supported_face_loaders); i++)
+ {
+ if (!loader_name || (supported_face_loaders[i].from_file && !strcmp (supported_face_loaders[i].name, loader_name)))
+ return supported_face_loaders[i].from_file (file_name, index);
+ }
+
+ if (retry)
+ {
+ retry = false;
+ loader_name = nullptr;
+ goto retry;
+ }
+
+ return nullptr;
+}
+
+/**
+ * hb_face_create_or_fail_using:
+ * @blob: #hb_blob_t to work upon
+ * @index: The index of the face within @blob
+ * @loader_name: (nullable): The name of the loader to use, or `NULL`
+ *
+ * A thin wrapper around the face loader functions registered with HarfBuzz.
+ * If @loader_name is `NULL` or the empty string, the first available loader
+ * is used.
+ *
+ * For example, the FreeType ("ft") loader might be able to load
+ * WOFF and WOFF2 files if FreeType is built with those features,
+ * whereas the OpenType ("ot") loader will not.
+ *
+ * Return value: (transfer full): The new face object, or `NULL` if
+ * the loader fails to load the face.
+ *
+ * Since: 11.0.0
+ **/
+hb_face_t *
+hb_face_create_or_fail_using (hb_blob_t *blob,
+ unsigned int index,
+ const char *loader_name)
+{
+ // Duplicated in hb_face_create_from_file_or_fail_using
+ bool retry = false;
+ if (!loader_name || !*loader_name)
+ {
+ loader_name = get_default_loader_name ();
+ retry = true;
+ }
+ if (loader_name && !*loader_name) loader_name = nullptr;
+
+retry:
+ for (unsigned i = 0; i < ARRAY_LENGTH (supported_face_loaders); i++)
+ {
+ if (!loader_name || (supported_face_loaders[i].from_blob && !strcmp (supported_face_loaders[i].name, loader_name)))
+ return supported_face_loaders[i].from_blob (blob, index);
+ }
+
+ if (retry)
+ {
+ retry = false;
+ loader_name = nullptr;
+ goto retry;
+ }
+
+ return nullptr;
+}
+
+static inline void free_static_face_loader_list ();
+
+static const char * const nil_face_loader_list[] = {nullptr};
+
+static struct hb_face_loader_list_lazy_loader_t : hb_lazy_loader_t
+{
+ static const char ** create ()
+ {
+ const char **face_loader_list = (const char **) hb_calloc (1 + ARRAY_LENGTH (supported_face_loaders), sizeof (const char *));
+ if (unlikely (!face_loader_list))
+ return nullptr;
+
+ unsigned i;
+ for (i = 0; i < ARRAY_LENGTH (supported_face_loaders); i++)
+ face_loader_list[i] = supported_face_loaders[i].name;
+ face_loader_list[i] = nullptr;
+
+ hb_atexit (free_static_face_loader_list);
+
+ return face_loader_list;
+ }
+ static void destroy (const char **l)
+ { hb_free (l); }
+ static const char * const * get_null ()
+ { return nil_face_loader_list; }
+} static_face_loader_list;
+
+static inline
+void free_static_face_loader_list ()
+{
+ static_face_loader_list.free_instance ();
+}
+
+/**
+ * hb_face_list_loaders:
+ *
+ * Retrieves the list of face loaders supported by HarfBuzz.
+ *
+ * Return value: (transfer none) (array zero-terminated=1): a
+ * `NULL`-terminated array of supported face loaders
+ * constant strings. The returned array is owned by HarfBuzz
+ * and should not be modified or freed.
+ *
+ * Since: 11.0.0
+ **/
+const char **
+hb_face_list_loaders ()
+{
+ return static_face_loader_list.get_unconst ();
+}
+#endif
+
/**
* hb_face_get_empty:
@@ -460,7 +672,7 @@ hb_face_make_immutable (hb_face_t *face)
* Since: 0.9.2
**/
hb_bool_t
-hb_face_is_immutable (const hb_face_t *face)
+hb_face_is_immutable (hb_face_t *face)
{
return hb_object_is_immutable (face);
}
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-face.h b/src/java.desktop/share/native/libharfbuzz/hb-face.h
index 953298fa50b..2c130f00fee 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-face.h
+++ b/src/java.desktop/share/native/libharfbuzz/hb-face.h
@@ -63,10 +63,24 @@ HB_EXTERN hb_face_t *
hb_face_create_or_fail (hb_blob_t *blob,
unsigned int index);
+HB_EXTERN hb_face_t *
+hb_face_create_or_fail_using (hb_blob_t *blob,
+ unsigned int index,
+ const char *loader_name);
+
HB_EXTERN hb_face_t *
hb_face_create_from_file_or_fail (const char *file_name,
unsigned int index);
+HB_EXTERN hb_face_t *
+hb_face_create_from_file_or_fail_using (const char *file_name,
+ unsigned int index,
+ const char *loader_name);
+
+HB_EXTERN const char **
+hb_face_list_loaders (void);
+
+
/**
* hb_reference_table_func_t:
* @face: an #hb_face_t to reference table for
@@ -117,7 +131,7 @@ HB_EXTERN void
hb_face_make_immutable (hb_face_t *face);
HB_EXTERN hb_bool_t
-hb_face_is_immutable (const hb_face_t *face);
+hb_face_is_immutable (hb_face_t *face);
HB_EXTERN hb_blob_t *
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-face.hh b/src/java.desktop/share/native/libharfbuzz/hb-face.hh
index 4d12030f187..e58e8f9b94c 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-face.hh
+++ b/src/java.desktop/share/native/libharfbuzz/hb-face.hh
@@ -49,8 +49,8 @@ struct hb_face_t
hb_object_header_t header;
unsigned int index; /* Face index in a collection, zero-based. */
- mutable hb_atomic_int_t upem; /* Units-per-EM. */
- mutable hb_atomic_int_t num_glyphs; /* Number of glyphs. */
+ mutable hb_atomic_t upem; /* Units-per-EM. */
+ mutable hb_atomic_t num_glyphs;/* Number of glyphs. */
hb_reference_table_func_t reference_table_func;
void *user_data;
@@ -70,7 +70,7 @@ struct hb_face_t
plan_node_t *next;
};
#ifndef HB_NO_SHAPER
- hb_atomic_ptr_t shape_plans;
+ hb_atomic_t shape_plans;
#endif
hb_blob_t *reference_table (hb_tag_t tag) const
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-font.cc b/src/java.desktop/share/native/libharfbuzz/hb-font.cc
index 0c9084c574f..849855e2c22 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-font.cc
+++ b/src/java.desktop/share/native/libharfbuzz/hb-font.cc
@@ -38,6 +38,22 @@
#include "hb-ot-var-avar-table.hh"
#include "hb-ot-var-fvar-table.hh"
+#ifndef HB_NO_OT_FONT
+#include "hb-ot.h"
+#endif
+#ifdef HAVE_FREETYPE
+#include "hb-ft.h"
+#endif
+#ifdef HAVE_FONTATIONS
+#include "hb-fontations.h"
+#endif
+#ifdef HAVE_CORETEXT
+#include "hb-coretext.h"
+#endif
+#ifdef HAVE_DIRECTWRITE
+#include "hb-directwrite.h"
+#endif
+
/**
* SECTION:hb-font
@@ -87,7 +103,7 @@ hb_font_get_font_h_extents_default (hb_font_t *font,
hb_font_extents_t *extents,
void *user_data HB_UNUSED)
{
- hb_bool_t ret = font->parent->get_font_h_extents (extents);
+ hb_bool_t ret = font->parent->get_font_h_extents (extents, false);
if (ret) {
extents->ascender = font->parent_scale_y_distance (extents->ascender);
extents->descender = font->parent_scale_y_distance (extents->descender);
@@ -112,7 +128,7 @@ hb_font_get_font_v_extents_default (hb_font_t *font,
hb_font_extents_t *extents,
void *user_data HB_UNUSED)
{
- hb_bool_t ret = font->parent->get_font_v_extents (extents);
+ hb_bool_t ret = font->parent->get_font_v_extents (extents, false);
if (ret) {
extents->ascender = font->parent_scale_x_distance (extents->ascender);
extents->descender = font->parent_scale_x_distance (extents->descender);
@@ -218,10 +234,10 @@ hb_font_get_glyph_h_advance_default (hb_font_t *font,
if (font->has_glyph_h_advances_func_set ())
{
hb_position_t ret;
- font->get_glyph_h_advances (1, &glyph, 0, &ret, 0);
+ font->get_glyph_h_advances (1, &glyph, 0, &ret, 0, false);
return ret;
}
- return font->parent_scale_x_distance (font->parent->get_glyph_h_advance (glyph));
+ return font->parent_scale_x_distance (font->parent->get_glyph_h_advance (glyph, false));
}
static hb_position_t
@@ -243,10 +259,10 @@ hb_font_get_glyph_v_advance_default (hb_font_t *font,
if (font->has_glyph_v_advances_func_set ())
{
hb_position_t ret;
- font->get_glyph_v_advances (1, &glyph, 0, &ret, 0);
+ font->get_glyph_v_advances (1, &glyph, 0, &ret, 0, false);
return ret;
}
- return font->parent_scale_y_distance (font->parent->get_glyph_v_advance (glyph));
+ return font->parent_scale_y_distance (font->parent->get_glyph_v_advance (glyph, false));
}
#define hb_font_get_glyph_h_advances_nil hb_font_get_glyph_h_advances_default
@@ -265,7 +281,7 @@ hb_font_get_glyph_h_advances_default (hb_font_t* font,
{
for (unsigned int i = 0; i < count; i++)
{
- *first_advance = font->get_glyph_h_advance (*first_glyph);
+ *first_advance = font->get_glyph_h_advance (*first_glyph, false);
first_glyph = &StructAtOffsetUnaligned (first_glyph, glyph_stride);
first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride);
}
@@ -274,7 +290,8 @@ hb_font_get_glyph_h_advances_default (hb_font_t* font,
font->parent->get_glyph_h_advances (count,
first_glyph, glyph_stride,
- first_advance, advance_stride);
+ first_advance, advance_stride,
+ false);
for (unsigned int i = 0; i < count; i++)
{
*first_advance = font->parent_scale_x_distance (*first_advance);
@@ -297,7 +314,7 @@ hb_font_get_glyph_v_advances_default (hb_font_t* font,
{
for (unsigned int i = 0; i < count; i++)
{
- *first_advance = font->get_glyph_v_advance (*first_glyph);
+ *first_advance = font->get_glyph_v_advance (*first_glyph, false);
first_glyph = &StructAtOffsetUnaligned (first_glyph, glyph_stride);
first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride);
}
@@ -306,7 +323,8 @@ hb_font_get_glyph_v_advances_default (hb_font_t* font,
font->parent->get_glyph_v_advances (count,
first_glyph, glyph_stride,
- first_advance, advance_stride);
+ first_advance, advance_stride,
+ false);
for (unsigned int i = 0; i < count; i++)
{
*first_advance = font->parent_scale_y_distance (*first_advance);
@@ -426,7 +444,7 @@ hb_font_get_glyph_extents_default (hb_font_t *font,
hb_glyph_extents_t *extents,
void *user_data HB_UNUSED)
{
- hb_bool_t ret = font->parent->get_glyph_extents (glyph, extents);
+ hb_bool_t ret = font->parent->get_glyph_extents (glyph, extents, false);
if (ret) {
font->parent_scale_position (&extents->x_bearing, &extents->y_bearing);
font->parent_scale_distance (&extents->width, &extents->height);
@@ -456,7 +474,7 @@ hb_font_get_glyph_contour_point_default (hb_font_t *font,
hb_position_t *y,
void *user_data HB_UNUSED)
{
- hb_bool_t ret = font->parent->get_glyph_contour_point (glyph, point_index, x, y);
+ hb_bool_t ret = font->parent->get_glyph_contour_point (glyph, point_index, x, y, false);
if (ret)
font->parent_scale_position (x, y);
return ret;
@@ -508,26 +526,28 @@ hb_font_get_glyph_from_name_default (hb_font_t *font,
return font->parent->get_glyph_from_name (name, len, glyph);
}
-static void
-hb_font_draw_glyph_nil (hb_font_t *font HB_UNUSED,
- void *font_data HB_UNUSED,
- hb_codepoint_t glyph,
- hb_draw_funcs_t *draw_funcs,
- void *draw_data,
- void *user_data HB_UNUSED)
+static hb_bool_t
+hb_font_draw_glyph_or_fail_nil (hb_font_t *font HB_UNUSED,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph,
+ hb_draw_funcs_t *draw_funcs,
+ void *draw_data,
+ void *user_data HB_UNUSED)
{
+ return false;
}
-static void
-hb_font_paint_glyph_nil (hb_font_t *font HB_UNUSED,
- void *font_data HB_UNUSED,
- hb_codepoint_t glyph HB_UNUSED,
- hb_paint_funcs_t *paint_funcs HB_UNUSED,
- void *paint_data HB_UNUSED,
- unsigned int palette HB_UNUSED,
- hb_color_t foreground HB_UNUSED,
- void *user_data HB_UNUSED)
+static hb_bool_t
+hb_font_paint_glyph_or_fail_nil (hb_font_t *font HB_UNUSED,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph HB_UNUSED,
+ hb_paint_funcs_t *paint_funcs HB_UNUSED,
+ void *paint_data HB_UNUSED,
+ unsigned int palette HB_UNUSED,
+ hb_color_t foreground HB_UNUSED,
+ void *user_data HB_UNUSED)
{
+ return false;
}
typedef struct hb_font_draw_glyph_default_adaptor_t {
@@ -535,7 +555,6 @@ typedef struct hb_font_draw_glyph_default_adaptor_t {
void *draw_data;
float x_scale;
float y_scale;
- float slant;
} hb_font_draw_glyph_default_adaptor_t;
static void
@@ -548,10 +567,9 @@ hb_draw_move_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED,
hb_font_draw_glyph_default_adaptor_t *adaptor = (hb_font_draw_glyph_default_adaptor_t *) draw_data;
float x_scale = adaptor->x_scale;
float y_scale = adaptor->y_scale;
- float slant = adaptor->slant;
adaptor->draw_funcs->emit_move_to (adaptor->draw_data, *st,
- x_scale * to_x + slant * to_y, y_scale * to_y);
+ x_scale * to_x, y_scale * to_y);
}
static void
@@ -563,13 +581,12 @@ hb_draw_line_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data,
hb_font_draw_glyph_default_adaptor_t *adaptor = (hb_font_draw_glyph_default_adaptor_t *) draw_data;
float x_scale = adaptor->x_scale;
float y_scale = adaptor->y_scale;
- float slant = adaptor->slant;
- st->current_x = st->current_x * x_scale + st->current_y * slant;
+ st->current_x = st->current_x * x_scale;
st->current_y = st->current_y * y_scale;
adaptor->draw_funcs->emit_line_to (adaptor->draw_data, *st,
- x_scale * to_x + slant * to_y, y_scale * to_y);
+ x_scale * to_x, y_scale * to_y);
}
static void
@@ -582,14 +599,13 @@ hb_draw_quadratic_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data
hb_font_draw_glyph_default_adaptor_t *adaptor = (hb_font_draw_glyph_default_adaptor_t *) draw_data;
float x_scale = adaptor->x_scale;
float y_scale = adaptor->y_scale;
- float slant = adaptor->slant;
- st->current_x = st->current_x * x_scale + st->current_y * slant;
+ st->current_x = st->current_x * x_scale;
st->current_y = st->current_y * y_scale;
adaptor->draw_funcs->emit_quadratic_to (adaptor->draw_data, *st,
- x_scale * control_x + slant * control_y, y_scale * control_y,
- x_scale * to_x + slant * to_y, y_scale * to_y);
+ x_scale * control_x, y_scale * control_y,
+ x_scale * to_x, y_scale * to_y);
}
static void
@@ -603,15 +619,14 @@ hb_draw_cubic_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data,
hb_font_draw_glyph_default_adaptor_t *adaptor = (hb_font_draw_glyph_default_adaptor_t *) draw_data;
float x_scale = adaptor->x_scale;
float y_scale = adaptor->y_scale;
- float slant = adaptor->slant;
- st->current_x = st->current_x * x_scale + st->current_y * slant;
+ st->current_x = st->current_x * x_scale;
st->current_y = st->current_y * y_scale;
adaptor->draw_funcs->emit_cubic_to (adaptor->draw_data, *st,
- x_scale * control1_x + slant * control1_y, y_scale * control1_y,
- x_scale * control2_x + slant * control2_y, y_scale * control2_y,
- x_scale * to_x + slant * to_y, y_scale * to_y);
+ x_scale * control1_x, y_scale * control1_y,
+ x_scale * control2_x, y_scale * control2_y,
+ x_scale * to_x, y_scale * to_y);
}
static void
@@ -634,49 +649,47 @@ static const hb_draw_funcs_t _hb_draw_funcs_default = {
}
};
-static void
-hb_font_draw_glyph_default (hb_font_t *font,
- void *font_data HB_UNUSED,
- hb_codepoint_t glyph,
- hb_draw_funcs_t *draw_funcs,
- void *draw_data,
- void *user_data HB_UNUSED)
+static hb_bool_t
+hb_font_draw_glyph_or_fail_default (hb_font_t *font,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph,
+ hb_draw_funcs_t *draw_funcs,
+ void *draw_data,
+ void *user_data HB_UNUSED)
{
hb_font_draw_glyph_default_adaptor_t adaptor = {
draw_funcs,
draw_data,
font->parent->x_scale ? (float) font->x_scale / (float) font->parent->x_scale : 0.f,
- font->parent->y_scale ? (float) font->y_scale / (float) font->parent->y_scale : 0.f,
- font->parent->y_scale ? (font->slant - font->parent->slant) *
- (float) font->x_scale / (float) font->parent->y_scale : 0.f
+ font->parent->y_scale ? (float) font->y_scale / (float) font->parent->y_scale : 0.f
};
- font->parent->draw_glyph (glyph,
- const_cast (&_hb_draw_funcs_default),
- &adaptor);
+ return font->parent->draw_glyph_or_fail (glyph,
+ const_cast (&_hb_draw_funcs_default),
+ &adaptor,
+ false);
}
-static void
-hb_font_paint_glyph_default (hb_font_t *font,
- void *font_data,
- hb_codepoint_t glyph,
- hb_paint_funcs_t *paint_funcs,
- void *paint_data,
- unsigned int palette,
- hb_color_t foreground,
- void *user_data)
+static hb_bool_t
+hb_font_paint_glyph_or_fail_default (hb_font_t *font,
+ void *font_data,
+ hb_codepoint_t glyph,
+ hb_paint_funcs_t *paint_funcs,
+ void *paint_data,
+ unsigned int palette,
+ hb_color_t foreground,
+ void *user_data)
{
paint_funcs->push_transform (paint_data,
- font->parent->x_scale ? (float) font->x_scale / (float) font->parent->x_scale : 0.f,
- font->parent->y_scale ? (font->slant - font->parent->slant) *
- (float) font->x_scale / (float) font->parent->y_scale : 0.f,
- 0.f,
- font->parent->y_scale ? (float) font->y_scale / (float) font->parent->y_scale : 0.f,
- 0.f, 0.f);
+ font->parent->x_scale ? (float) font->x_scale / (float) font->parent->x_scale : 0, 0,
+ 0, font->parent->y_scale ? (float) font->y_scale / (float) font->parent->y_scale : 0,
+ 0, 0);
- font->parent->paint_glyph (glyph, paint_funcs, paint_data, palette, foreground);
+ bool ret = font->parent->paint_glyph_or_fail (glyph, paint_funcs, paint_data, palette, foreground);
paint_funcs->pop_transform (paint_data);
+
+ return ret;
}
DEFINE_NULL_INSTANCE (hb_font_funcs_t) =
@@ -1413,6 +1426,92 @@ hb_font_get_glyph_shape (hb_font_t *font,
}
#endif
+/**
+ * hb_font_draw_glyph_or_fail:
+ * @font: #hb_font_t to work upon
+ * @glyph: The glyph ID
+ * @dfuncs: #hb_draw_funcs_t to draw to
+ * @draw_data: User data to pass to draw callbacks
+ *
+ * Draws the outline that corresponds to a glyph in the specified @font.
+ *
+ * This is a newer name for hb_font_draw_glyph(), that returns `false`
+ * if the font has no outlines for the glyph.
+ *
+ * The outline is returned by way of calls to the callbacks of the @dfuncs
+ * objects, with @draw_data passed to them.
+ *
+ * Return value: `true` if glyph was drawn, `false` otherwise
+ *
+ * XSince: REPLACEME
+ **/
+hb_bool_t
+hb_font_draw_glyph_or_fail (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_draw_funcs_t *dfuncs, void *draw_data)
+{
+ return font->draw_glyph_or_fail (glyph, dfuncs, draw_data);
+}
+
+/**
+ * hb_font_paint_glyph_or_fail:
+ * @font: #hb_font_t to work upon
+ * @glyph: The glyph ID
+ * @pfuncs: #hb_paint_funcs_t to paint with
+ * @paint_data: User data to pass to paint callbacks
+ * @palette_index: The index of the font's color palette to use
+ * @foreground: The foreground color, unpremultipled
+ *
+ * Paints a color glyph.
+ *
+ * This function is similar to, but lower-level than,
+ * hb_font_paint_glyph(). It is suitable for clients that
+ * need more control. If there are no color glyphs available,
+ * it will return `false`. The client can then fall back to
+ * hb_font_draw_glyph_or_fail() for the monochrome outline glyph.
+ *
+ * The painting instructions are returned by way of calls to
+ * the callbacks of the @funcs object, with @paint_data passed
+ * to them.
+ *
+ * If the font has color palettes (see hb_ot_color_has_palettes()),
+ * then @palette_index selects the palette to use. If the font only
+ * has one palette, this will be 0.
+ *
+ * Return value: `true` if glyph was painted, `false` otherwise
+ *
+ * XSince: REPLACEME
+ */
+hb_bool_t
+hb_font_paint_glyph_or_fail (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_paint_funcs_t *pfuncs, void *paint_data,
+ unsigned int palette_index,
+ hb_color_t foreground)
+{
+ return font->paint_glyph_or_fail (glyph, pfuncs, paint_data, palette_index, foreground);
+}
+
+/* A bit higher-level, and with fallback */
+
+void
+hb_font_t::paint_glyph (hb_codepoint_t glyph,
+ hb_paint_funcs_t *paint_funcs, void *paint_data,
+ unsigned int palette,
+ hb_color_t foreground)
+{
+ if (paint_glyph_or_fail (glyph,
+ paint_funcs, paint_data,
+ palette, foreground))
+ return;
+
+ /* Fallback for outline glyph. */
+ paint_funcs->push_clip_glyph (paint_data, glyph, this);
+ paint_funcs->color (paint_data, true, foreground);
+ paint_funcs->pop_clip (paint_data);
+}
+
+
/**
* hb_font_draw_glyph:
* @font: #hb_font_t to work upon
@@ -1422,6 +1521,9 @@ hb_font_get_glyph_shape (hb_font_t *font,
*
* Draws the outline that corresponds to a glyph in the specified @font.
*
+ * This is an older name for hb_font_draw_glyph_or_fail(), with no
+ * return value.
+ *
* The outline is returned by way of calls to the callbacks of the @dfuncs
* objects, with @draw_data passed to them.
*
@@ -1429,10 +1531,10 @@ hb_font_get_glyph_shape (hb_font_t *font,
**/
void
hb_font_draw_glyph (hb_font_t *font,
- hb_codepoint_t glyph,
- hb_draw_funcs_t *dfuncs, void *draw_data)
+ hb_codepoint_t glyph,
+ hb_draw_funcs_t *dfuncs, void *draw_data)
{
- font->draw_glyph (glyph, dfuncs, draw_data);
+ (void) hb_font_draw_glyph_or_fail (font, glyph, dfuncs, draw_data);
}
/**
@@ -1444,7 +1546,10 @@ hb_font_draw_glyph (hb_font_t *font,
* @palette_index: The index of the font's color palette to use
* @foreground: The foreground color, unpremultipled
*
- * Paints the glyph.
+ * Paints the glyph. This function is similar to
+ * hb_font_paint_glyph_or_fail(), but if painting a color glyph
+ * failed, it will fall back to painting an outline monochrome
+ * glyph.
*
* The painting instructions are returned by way of calls to
* the callbacks of the @funcs object, with @paint_data passed
@@ -1466,8 +1571,6 @@ hb_font_paint_glyph (hb_font_t *font,
font->paint_glyph (glyph, pfuncs, paint_data, palette_index, foreground);
}
-/* A bit higher-level, and with fallback */
-
/**
* hb_font_get_extents_for_direction:
* @font: #hb_font_t to work upon
@@ -1854,10 +1957,7 @@ hb_font_create (hb_face_t *face)
{
hb_font_t *font = _hb_font_create (face);
-#ifndef HB_NO_OT_FONT
- /* Install our in-house, very lightweight, funcs. */
- hb_ot_font_set_funcs (font);
-#endif
+ hb_font_set_funcs_using (font, nullptr);
#ifndef HB_NO_VAR
if (face && face->index >> 16)
@@ -1880,7 +1980,8 @@ _hb_font_adopt_var_coords (hb_font_t *font,
font->design_coords = design_coords;
font->num_coords = coords_length;
- font->mults_changed (); // Easiest to call this to drop cached data
+ font->changed ();
+ font->serial_coords = font->serial;
}
/**
@@ -1935,7 +2036,8 @@ hb_font_create_sub_font (hb_font_t *parent)
}
}
- font->mults_changed ();
+ font->changed ();
+ font->serial_coords = font->serial;
return font;
}
@@ -2023,7 +2125,7 @@ hb_font_set_user_data (hb_font_t *font,
hb_bool_t replace)
{
if (!hb_object_is_immutable (font))
- font->serial++;
+ font->changed ();
return hb_object_set_user_data (font, key, data, destroy, replace);
}
@@ -2098,7 +2200,7 @@ hb_font_is_immutable (hb_font_t *font)
unsigned int
hb_font_get_serial (hb_font_t *font)
{
- return font->serial;
+ return font->serial.get_acquire ();
}
/**
@@ -2117,9 +2219,7 @@ hb_font_changed (hb_font_t *font)
if (hb_object_is_immutable (font))
return;
- font->serial++;
-
- font->mults_changed ();
+ font->changed ();
}
/**
@@ -2141,8 +2241,6 @@ hb_font_set_parent (hb_font_t *font,
if (parent == font->parent)
return;
- font->serial++;
-
if (!parent)
parent = hb_font_get_empty ();
@@ -2151,6 +2249,8 @@ hb_font_set_parent (hb_font_t *font,
font->parent = hb_font_reference (parent);
hb_font_destroy (old);
+
+ font->changed ();
}
/**
@@ -2188,8 +2288,6 @@ hb_font_set_face (hb_font_t *font,
if (face == font->face)
return;
- font->serial++;
-
if (unlikely (!face))
face = hb_face_get_empty ();
@@ -2197,9 +2295,12 @@ hb_font_set_face (hb_font_t *font,
hb_face_make_immutable (face);
font->face = hb_face_reference (face);
- font->mults_changed ();
+ font->changed ();
hb_face_destroy (old);
+
+ font->changed ();
+ font->serial_coords = font->serial;
}
/**
@@ -2244,8 +2345,6 @@ hb_font_set_funcs (hb_font_t *font,
return;
}
- font->serial++;
-
if (font->destroy)
font->destroy (font->user_data);
@@ -2257,6 +2356,8 @@ hb_font_set_funcs (hb_font_t *font,
font->klass = klass;
font->user_data = font_data;
font->destroy = destroy;
+
+ font->changed ();
}
/**
@@ -2283,15 +2384,151 @@ hb_font_set_funcs_data (hb_font_t *font,
return;
}
- font->serial++;
-
if (font->destroy)
font->destroy (font->user_data);
font->user_data = font_data;
font->destroy = destroy;
+
+ font->changed ();
}
+static struct supported_font_funcs_t {
+ char name[16];
+ void (*func) (hb_font_t *);
+} supported_font_funcs[] =
+{
+#ifndef HB_NO_OT_FONT
+ {"ot", hb_ot_font_set_funcs},
+#endif
+#ifdef HAVE_FREETYPE
+ {"ft", hb_ft_font_set_funcs},
+#endif
+#ifdef HAVE_FONTATIONS
+ {"fontations",hb_fontations_font_set_funcs},
+#endif
+#ifdef HAVE_CORETEXT
+ {"coretext", hb_coretext_font_set_funcs},
+#endif
+#ifdef HAVE_DIRECTWRITE
+ {"directwrite",hb_directwrite_font_set_funcs},
+#endif
+};
+
+static const char *get_default_funcs_name ()
+{
+ static hb_atomic_t static_funcs_name;
+ const char *name = static_funcs_name.get_acquire ();
+ if (!name)
+ {
+ name = getenv ("HB_FONT_FUNCS");
+ if (!name)
+ name = "";
+ if (!static_funcs_name.cmpexch (nullptr, name))
+ name = static_funcs_name.get_acquire ();
+ }
+ return name;
+}
+
+/**
+ * hb_font_set_funcs_using:
+ * @font: #hb_font_t to work upon
+ * @name: The name of the font-functions structure to use, or `NULL`
+ *
+ * Sets the font-functions structure to use for a font, based on the
+ * specified name.
+ *
+ * If @name is `NULL` or the empty string, the default (first) functioning font-functions
+ * are used. This default can be changed by setting the `HB_FONT_FUNCS` environment
+ * variable to the name of the desired font-functions.
+ *
+ * Return value: `true` if the font-functions was found and set, `false` otherwise
+ *
+ * Since: 11.0.0
+ **/
+hb_bool_t
+hb_font_set_funcs_using (hb_font_t *font,
+ const char *name)
+{
+ bool retry = false;
+
+ if (!name || !*name)
+ {
+ name = get_default_funcs_name ();
+ retry = true;
+ }
+ if (name && !*name) name = nullptr;
+
+retry:
+ for (unsigned i = 0; i < ARRAY_LENGTH (supported_font_funcs); i++)
+ if (!name || strcmp (supported_font_funcs[i].name, name) == 0)
+ {
+ supported_font_funcs[i].func (font);
+ if (name || font->klass != hb_font_funcs_get_empty ())
+ return true;
+ }
+
+ if (retry)
+ {
+ retry = false;
+ name = nullptr;
+ goto retry;
+ }
+
+ return false;
+}
+
+static inline void free_static_font_funcs_list ();
+
+static const char * const nil_font_funcs_list[] = {nullptr};
+
+static struct hb_font_funcs_list_lazy_loader_t : hb_lazy_loader_t
+{
+ static const char ** create ()
+ {
+ const char **font_funcs_list = (const char **) hb_calloc (1 + ARRAY_LENGTH (supported_font_funcs), sizeof (const char *));
+ if (unlikely (!font_funcs_list))
+ return nullptr;
+
+ unsigned i;
+ for (i = 0; i < ARRAY_LENGTH (supported_font_funcs); i++)
+ font_funcs_list[i] = supported_font_funcs[i].name;
+ font_funcs_list[i] = nullptr;
+
+ hb_atexit (free_static_font_funcs_list);
+
+ return font_funcs_list;
+ }
+ static void destroy (const char **l)
+ { hb_free (l); }
+ static const char * const * get_null ()
+ { return nil_font_funcs_list; }
+} static_font_funcs_list;
+
+static inline
+void free_static_font_funcs_list ()
+{
+ static_font_funcs_list.free_instance ();
+}
+
+/**
+ * hb_font_list_funcs:
+ *
+ * Retrieves the list of font functions supported by HarfBuzz.
+ *
+ * Return value: (transfer none) (array zero-terminated=1): a
+ * `NULL`-terminated array of supported font functions
+ * constant strings. The returned array is owned by HarfBuzz
+ * and should not be modified or freed.
+ *
+ * Since: 11.0.0
+ **/
+const char **
+hb_font_list_funcs ()
+{
+ return static_font_funcs_list.get_unconst ();
+}
/**
* hb_font_set_scale:
@@ -2339,11 +2576,10 @@ hb_font_set_scale (hb_font_t *font,
if (font->x_scale == x_scale && font->y_scale == y_scale)
return;
- font->serial++;
-
font->x_scale = x_scale;
font->y_scale = y_scale;
- font->mults_changed ();
+
+ font->changed ();
}
/**
@@ -2390,10 +2626,10 @@ hb_font_set_ppem (hb_font_t *font,
if (font->x_ppem == x_ppem && font->y_ppem == y_ppem)
return;
- font->serial++;
-
font->x_ppem = x_ppem;
font->y_ppem = y_ppem;
+
+ font->changed ();
}
/**
@@ -2437,9 +2673,9 @@ hb_font_set_ptem (hb_font_t *font,
if (font->ptem == ptem)
return;
- font->serial++;
-
font->ptem = ptem;
+
+ font->changed ();
}
/**
@@ -2459,6 +2695,23 @@ hb_font_get_ptem (hb_font_t *font)
return font->ptem;
}
+/**
+ * hb_font_is_synthetic:
+ * @font: #hb_font_t to work upon
+ *
+ * Tests whether a font is synthetic. A synthetic font is one
+ * that has either synthetic slant or synthetic bold set on it.
+ *
+ * Return value: `true` if the font is synthetic, `false` otherwise.
+ *
+ * XSince: REPLACEME
+ */
+hb_bool_t
+hb_font_is_synthetic (hb_font_t *font)
+{
+ return font->is_synthetic ();
+}
+
/**
* hb_font_set_synthetic_bold:
* @font: #hb_font_t to work upon
@@ -2476,7 +2729,7 @@ hb_font_get_ptem (hb_font_t *font)
* points of the glyph shape.
*
* Synthetic boldness is applied when rendering a glyph via
- * hb_font_draw_glyph().
+ * hb_font_draw_glyph_or_fail().
*
* If @in_place is `false`, then glyph advance-widths are also
* adjusted, otherwise they are not. The in-place mode is
@@ -2499,12 +2752,11 @@ hb_font_set_synthetic_bold (hb_font_t *font,
font->embolden_in_place == (bool) in_place)
return;
- font->serial++;
-
font->x_embolden = x_embolden;
font->y_embolden = y_embolden;
font->embolden_in_place = in_place;
- font->mults_changed ();
+
+ font->changed ();
}
/**
@@ -2541,7 +2793,7 @@ hb_font_get_synthetic_bold (hb_font_t *font,
* HarfBuzz needs to know this value to adjust shaping results,
* metrics, and style values to match the slanted rendering.
*
- * Note: The glyph shape fetched via the hb_font_draw_glyph()
+ * Note: The glyph shape fetched via the hb_font_draw_glyph_or_fail()
* function is slanted to reflect this value as well.
*
* Note: The slant value is a ratio. For example, a
@@ -2558,10 +2810,9 @@ hb_font_set_synthetic_slant (hb_font_t *font, float slant)
if (font->slant == slant)
return;
- font->serial++;
-
font->slant = slant;
- font->mults_changed ();
+
+ font->changed ();
}
/**
@@ -2607,8 +2858,6 @@ hb_font_set_variations (hb_font_t *font,
if (hb_object_is_immutable (font))
return;
- font->serial_coords = ++font->serial;
-
if (!variations_length && font->instance_index == HB_FONT_NO_VAR_NAMED_INSTANCE)
{
hb_font_set_var_coords_normalized (font, nullptr, 0);
@@ -2677,8 +2926,6 @@ hb_font_set_variation (hb_font_t *font,
if (hb_object_is_immutable (font))
return;
- font->serial_coords = ++font->serial;
-
// TODO Share some of this code with set_variations()
const OT::fvar &fvar = *font->face->table.fvar;
@@ -2749,8 +2996,6 @@ hb_font_set_var_coords_design (hb_font_t *font,
if (hb_object_is_immutable (font))
return;
- font->serial_coords = ++font->serial;
-
int *normalized = coords_length ? (int *) hb_calloc (coords_length, sizeof (int)) : nullptr;
float *design_coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (float)) : nullptr;
@@ -2787,8 +3032,6 @@ hb_font_set_var_named_instance (hb_font_t *font,
if (font->instance_index == instance_index)
return;
- font->serial_coords = ++font->serial;
-
font->instance_index = instance_index;
hb_font_set_variations (font, nullptr, 0);
}
@@ -2834,8 +3077,6 @@ hb_font_set_var_coords_normalized (hb_font_t *font,
if (hb_object_is_immutable (font))
return;
- font->serial_coords = ++font->serial;
-
int *copy = coords_length ? (int *) hb_calloc (coords_length, sizeof (coords[0])) : nullptr;
int *unmapped = coords_length ? (int *) hb_calloc (coords_length, sizeof (coords[0])) : nullptr;
float *design_coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (design_coords[0])) : nullptr;
@@ -3058,12 +3299,134 @@ hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
#ifndef HB_DISABLE_DEPRECATED
+
+struct hb_draw_glyph_closure_t
+{
+ hb_font_draw_glyph_func_t func;
+ void *user_data;
+ hb_destroy_func_t destroy;
+};
+static hb_bool_t
+hb_font_draw_glyph_trampoline (hb_font_t *font,
+ void *font_data,
+ hb_codepoint_t glyph,
+ hb_draw_funcs_t *draw_funcs,
+ void *draw_data,
+ void *user_data)
+{
+ hb_draw_glyph_closure_t *closure = (hb_draw_glyph_closure_t *) user_data;
+ closure->func (font, font_data, glyph, draw_funcs, draw_data, closure->user_data);
+ return true;
+}
+static void
+hb_font_draw_glyph_closure_destroy (void *user_data)
+{
+ hb_draw_glyph_closure_t *closure = (hb_draw_glyph_closure_t *) user_data;
+
+ if (closure->destroy)
+ closure->destroy (closure->user_data);
+ hb_free (closure);
+}
+static void
+_hb_font_funcs_set_draw_glyph_func (hb_font_funcs_t *ffuncs,
+ hb_font_draw_glyph_func_t func,
+ void *user_data,
+ hb_destroy_func_t destroy /* May be NULL. */)
+{
+ if (hb_object_is_immutable (ffuncs))
+ {
+ if (destroy)
+ destroy (user_data);
+ return;
+ }
+ hb_draw_glyph_closure_t *closure = (hb_draw_glyph_closure_t *) hb_calloc (1, sizeof (hb_draw_glyph_closure_t));
+ if (unlikely (!closure))
+ {
+ if (destroy)
+ destroy (user_data);
+ return;
+ }
+ closure->func = func;
+ closure->user_data = user_data;
+ closure->destroy = destroy;
+
+ hb_font_funcs_set_draw_glyph_or_fail_func (ffuncs,
+ hb_font_draw_glyph_trampoline,
+ closure,
+ hb_font_draw_glyph_closure_destroy);
+}
+void
+hb_font_funcs_set_draw_glyph_func (hb_font_funcs_t *ffuncs,
+ hb_font_draw_glyph_func_t func,
+ void *user_data,
+ hb_destroy_func_t destroy /* May be NULL. */)
+{
+ _hb_font_funcs_set_draw_glyph_func (ffuncs, func, user_data, destroy);
+}
void
hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs,
hb_font_get_glyph_shape_func_t func,
void *user_data,
hb_destroy_func_t destroy /* May be NULL. */)
{
- hb_font_funcs_set_draw_glyph_func (ffuncs, func, user_data, destroy);
+ _hb_font_funcs_set_draw_glyph_func (ffuncs, func, user_data, destroy);
+}
+
+struct hb_paint_glyph_closure_t
+{
+ hb_font_paint_glyph_func_t func;
+ void *user_data;
+ hb_destroy_func_t destroy;
+};
+static hb_bool_t
+hb_font_paint_glyph_trampoline (hb_font_t *font,
+ void *font_data,
+ hb_codepoint_t glyph,
+ hb_paint_funcs_t *paint_funcs,
+ void *paint_data,
+ unsigned int palette,
+ hb_color_t foreground,
+ void *user_data)
+{
+ hb_paint_glyph_closure_t *closure = (hb_paint_glyph_closure_t *) user_data;
+ closure->func (font, font_data, glyph, paint_funcs, paint_data, palette, foreground, closure->user_data);
+ return true;
+}
+static void
+hb_font_paint_glyph_closure_destroy (void *user_data)
+{
+ hb_paint_glyph_closure_t *closure = (hb_paint_glyph_closure_t *) user_data;
+
+ if (closure->destroy)
+ closure->destroy (closure->user_data);
+ hb_free (closure);
+}
+void
+hb_font_funcs_set_paint_glyph_func (hb_font_funcs_t *ffuncs,
+ hb_font_paint_glyph_func_t func,
+ void *user_data,
+ hb_destroy_func_t destroy /* May be NULL. */)
+{
+ if (hb_object_is_immutable (ffuncs))
+ {
+ if (destroy)
+ destroy (user_data);
+ return;
+ }
+ hb_paint_glyph_closure_t *closure = (hb_paint_glyph_closure_t *) hb_calloc (1, sizeof (hb_paint_glyph_closure_t));
+ if (unlikely (!closure))
+ {
+ if (destroy)
+ destroy (user_data);
+ return;
+ }
+ closure->func = func;
+ closure->user_data = user_data;
+ closure->destroy = destroy;
+
+ hb_font_funcs_set_paint_glyph_or_fail_func (ffuncs,
+ hb_font_paint_glyph_trampoline,
+ closure,
+ hb_font_paint_glyph_closure_destroy);
}
#endif
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-font.h b/src/java.desktop/share/native/libharfbuzz/hb-font.h
index f16658d9d88..4e267ba6a80 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-font.h
+++ b/src/java.desktop/share/native/libharfbuzz/hb-font.h
@@ -486,7 +486,7 @@ typedef hb_bool_t (*hb_font_get_glyph_from_name_func_t) (hb_font_t *font, void *
void *user_data);
/**
- * hb_font_draw_glyph_func_t:
+ * hb_font_draw_glyph_or_fail_func_t:
* @font: #hb_font_t to work upon
* @font_data: @font user data pointer
* @glyph: The glyph ID to query
@@ -496,16 +496,17 @@ typedef hb_bool_t (*hb_font_get_glyph_from_name_func_t) (hb_font_t *font, void *
*
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
*
- * Since: 7.0.0
+ * Return value: `true` if glyph was drawn, `false` otherwise
*
+ * XSince: REPLACEME
**/
-typedef void (*hb_font_draw_glyph_func_t) (hb_font_t *font, void *font_data,
- hb_codepoint_t glyph,
- hb_draw_funcs_t *draw_funcs, void *draw_data,
- void *user_data);
+typedef hb_bool_t (*hb_font_draw_glyph_or_fail_func_t) (hb_font_t *font, void *font_data,
+ hb_codepoint_t glyph,
+ hb_draw_funcs_t *draw_funcs, void *draw_data,
+ void *user_data);
/**
- * hb_font_paint_glyph_func_t:
+ * hb_font_paint_glyph_or_fail_func_t:
* @font: #hb_font_t to work upon
* @font_data: @font user data pointer
* @glyph: The glyph ID to query
@@ -517,14 +518,16 @@ typedef void (*hb_font_draw_glyph_func_t) (hb_font_t *font, void *font_data,
*
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
*
- * Since: 7.0.0
+ * Return value: `true` if glyph was painted, `false` otherwise
+ *
+ * XSince: REPLACEME
*/
-typedef void (*hb_font_paint_glyph_func_t) (hb_font_t *font, void *font_data,
- hb_codepoint_t glyph,
- hb_paint_funcs_t *paint_funcs, void *paint_data,
- unsigned int palette_index,
- hb_color_t foreground,
- void *user_data);
+typedef hb_bool_t (*hb_font_paint_glyph_or_fail_func_t) (hb_font_t *font, void *font_data,
+ hb_codepoint_t glyph,
+ hb_paint_funcs_t *paint_funcs, void *paint_data,
+ unsigned int palette_index,
+ hb_color_t foreground,
+ void *user_data);
/* func setters */
@@ -785,36 +788,36 @@ hb_font_funcs_set_glyph_from_name_func (hb_font_funcs_t *ffuncs,
void *user_data, hb_destroy_func_t destroy);
/**
- * hb_font_funcs_set_draw_glyph_func:
+ * hb_font_funcs_set_draw_glyph_or_fail_func:
* @ffuncs: A font-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func
* @destroy: (nullable): The function to call when @user_data is not needed anymore
*
- * Sets the implementation function for #hb_font_draw_glyph_func_t.
+ * Sets the implementation function for #hb_font_draw_glyph_or_fail_func_t.
*
- * Since: 7.0.0
+ * XSince: REPLACEME
**/
HB_EXTERN void
-hb_font_funcs_set_draw_glyph_func (hb_font_funcs_t *ffuncs,
- hb_font_draw_glyph_func_t func,
- void *user_data, hb_destroy_func_t destroy);
+hb_font_funcs_set_draw_glyph_or_fail_func (hb_font_funcs_t *ffuncs,
+ hb_font_draw_glyph_or_fail_func_t func,
+ void *user_data, hb_destroy_func_t destroy);
/**
- * hb_font_funcs_set_paint_glyph_func:
+ * hb_font_funcs_set_paint_glyph_or_fail_func:
* @ffuncs: A font-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func
* @destroy: (nullable): The function to call when @user_data is no longer needed
*
- * Sets the implementation function for #hb_font_paint_glyph_func_t.
+ * Sets the implementation function for #hb_font_paint_glyph_or_fail_func_t.
*
- * Since: 7.0.0
+ * XSince: REPLACEME
*/
HB_EXTERN void
-hb_font_funcs_set_paint_glyph_func (hb_font_funcs_t *ffuncs,
- hb_font_paint_glyph_func_t func,
- void *user_data, hb_destroy_func_t destroy);
+hb_font_funcs_set_paint_glyph_or_fail_func (hb_font_funcs_t *ffuncs,
+ hb_font_paint_glyph_or_fail_func_t func,
+ void *user_data, hb_destroy_func_t destroy);
/* func dispatch */
@@ -896,17 +899,17 @@ hb_font_get_glyph_from_name (hb_font_t *font,
const char *name, int len, /* -1 means nul-terminated */
hb_codepoint_t *glyph);
-HB_EXTERN void
-hb_font_draw_glyph (hb_font_t *font,
- hb_codepoint_t glyph,
- hb_draw_funcs_t *dfuncs, void *draw_data);
+HB_EXTERN hb_bool_t
+hb_font_draw_glyph_or_fail (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_draw_funcs_t *dfuncs, void *draw_data);
-HB_EXTERN void
-hb_font_paint_glyph (hb_font_t *font,
- hb_codepoint_t glyph,
- hb_paint_funcs_t *pfuncs, void *paint_data,
- unsigned int palette_index,
- hb_color_t foreground);
+HB_EXTERN hb_bool_t
+hb_font_paint_glyph_or_fail (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_paint_funcs_t *pfuncs, void *paint_data,
+ unsigned int palette_index,
+ hb_color_t foreground);
/* high-level funcs, with fallback */
@@ -979,6 +982,19 @@ hb_font_glyph_from_string (hb_font_t *font,
const char *s, int len, /* -1 means nul-terminated */
hb_codepoint_t *glyph);
+/* Older alias for hb_font_draw_glyph_or_fail() with no return value. */
+HB_EXTERN void
+hb_font_draw_glyph (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_draw_funcs_t *dfuncs, void *draw_data);
+
+/* Paints color glyph; if failed, draws outline glyph. */
+HB_EXTERN void
+hb_font_paint_glyph (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_paint_funcs_t *pfuncs, void *paint_data,
+ unsigned int palette_index,
+ hb_color_t foreground);
/*
* hb_font_t
@@ -1052,6 +1068,12 @@ hb_font_set_funcs_data (hb_font_t *font,
void *font_data,
hb_destroy_func_t destroy);
+HB_EXTERN hb_bool_t
+hb_font_set_funcs_using (hb_font_t *font,
+ const char *name);
+
+HB_EXTERN const char **
+hb_font_list_funcs (void);
HB_EXTERN void
hb_font_set_scale (hb_font_t *font,
@@ -1086,6 +1108,9 @@ hb_font_set_ptem (hb_font_t *font, float ptem);
HB_EXTERN float
hb_font_get_ptem (hb_font_t *font);
+HB_EXTERN hb_bool_t
+hb_font_is_synthetic (hb_font_t *font);
+
HB_EXTERN void
hb_font_set_synthetic_bold (hb_font_t *font,
float x_embolden, float y_embolden,
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-font.hh b/src/java.desktop/share/native/libharfbuzz/hb-font.hh
index 8273f347562..69d8d4b09df 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-font.hh
+++ b/src/java.desktop/share/native/libharfbuzz/hb-font.hh
@@ -32,7 +32,11 @@
#include "hb.hh"
#include "hb-face.hh"
+#include "hb-atomic.hh"
+#include "hb-draw.hh"
+#include "hb-paint-extents.hh"
#include "hb-shaper.hh"
+#include "hb-outline.hh"
/*
@@ -57,8 +61,8 @@
HB_FONT_FUNC_IMPLEMENT (get_,glyph_contour_point) \
HB_FONT_FUNC_IMPLEMENT (get_,glyph_name) \
HB_FONT_FUNC_IMPLEMENT (get_,glyph_from_name) \
- HB_FONT_FUNC_IMPLEMENT (,draw_glyph) \
- HB_FONT_FUNC_IMPLEMENT (,paint_glyph) \
+ HB_FONT_FUNC_IMPLEMENT (,draw_glyph_or_fail) \
+ HB_FONT_FUNC_IMPLEMENT (,paint_glyph_or_fail) \
/* ^--- Add new callbacks here */
struct hb_font_funcs_t
@@ -105,8 +109,8 @@ DECLARE_NULL_INSTANCE (hb_font_funcs_t);
struct hb_font_t
{
hb_object_header_t header;
- unsigned int serial;
- unsigned int serial_coords;
+ hb_atomic_t serial;
+ hb_atomic_t serial_coords;
hb_font_t *parent;
hb_face_t *face;
@@ -191,23 +195,35 @@ struct hb_font_t
void scale_glyph_extents (hb_glyph_extents_t *extents)
{
- float x1 = em_fscale_x (extents->x_bearing);
- float y1 = em_fscale_y (extents->y_bearing);
- float x2 = em_fscale_x (extents->x_bearing + extents->width);
- float y2 = em_fscale_y (extents->y_bearing + extents->height);
+ float x1 = em_scale_x (extents->x_bearing);
+ float y1 = em_scale_y (extents->y_bearing);
+ float x2 = em_scale_x (extents->x_bearing + extents->width);
+ float y2 = em_scale_y (extents->y_bearing + extents->height);
- /* Apply slant. */
+ extents->x_bearing = roundf (x1);
+ extents->y_bearing = roundf (y1);
+ extents->width = roundf (x2) - extents->x_bearing;
+ extents->height = roundf (y2) - extents->y_bearing;
+ }
+
+ void synthetic_glyph_extents (hb_glyph_extents_t *extents)
+ {
+ /* Slant. */
if (slant_xy)
{
- x1 += hb_min (y1 * slant_xy, y2 * slant_xy);
- x2 += hb_max (y1 * slant_xy, y2 * slant_xy);
+ hb_position_t x1 = extents->x_bearing;
+ hb_position_t y1 = extents->y_bearing;
+ hb_position_t x2 = extents->x_bearing + extents->width;
+ hb_position_t y2 = extents->y_bearing + extents->height;
+
+ x1 += floorf (hb_min (y1 * slant_xy, y2 * slant_xy));
+ x2 += ceilf (hb_max (y1 * slant_xy, y2 * slant_xy));
+
+ extents->x_bearing = x1;
+ extents->width = x2 - extents->x_bearing;
}
- extents->x_bearing = floorf (x1);
- extents->y_bearing = floorf (y1);
- extents->width = ceilf (x2) - extents->x_bearing;
- extents->height = ceilf (y2) - extents->y_bearing;
-
+ /* Embolden. */
if (x_strength || y_strength)
{
/* Y */
@@ -250,19 +266,45 @@ struct hb_font_t
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_FONT_FUNC_IMPLEMENT
- hb_bool_t get_font_h_extents (hb_font_extents_t *extents)
+ hb_bool_t get_font_h_extents (hb_font_extents_t *extents,
+ bool synthetic = true)
{
hb_memset (extents, 0, sizeof (*extents));
- return klass->get.f.font_h_extents (this, user_data,
- extents,
- !klass->user_data ? nullptr : klass->user_data->font_h_extents);
+ bool ret = klass->get.f.font_h_extents (this, user_data,
+ extents,
+ !klass->user_data ? nullptr : klass->user_data->font_h_extents);
+
+ if (synthetic && ret)
+ {
+ /* Embolden */
+ int y_shift = y_scale < 0 ? -y_strength : y_strength;
+ extents->ascender += y_shift;
+ }
+
+ return ret;
}
- hb_bool_t get_font_v_extents (hb_font_extents_t *extents)
+ hb_bool_t get_font_v_extents (hb_font_extents_t *extents,
+ bool synthetic = true)
{
hb_memset (extents, 0, sizeof (*extents));
- return klass->get.f.font_v_extents (this, user_data,
- extents,
- !klass->user_data ? nullptr : klass->user_data->font_v_extents);
+ bool ret = klass->get.f.font_v_extents (this, user_data,
+ extents,
+ !klass->user_data ? nullptr : klass->user_data->font_v_extents);
+
+ if (synthetic && ret)
+ {
+ /* Embolden */
+ int x_shift = x_scale < 0 ? -x_strength : x_strength;
+ if (embolden_in_place)
+ {
+ extents->ascender += x_shift / 2;
+ extents->descender -= x_shift - x_shift / 2;
+ }
+ else
+ extents->ascender += x_shift;
+ }
+
+ return ret;
}
bool has_glyph (hb_codepoint_t unicode)
@@ -303,44 +345,88 @@ struct hb_font_t
!klass->user_data ? nullptr : klass->user_data->variation_glyph);
}
- hb_position_t get_glyph_h_advance (hb_codepoint_t glyph)
+ hb_position_t get_glyph_h_advance (hb_codepoint_t glyph,
+ bool synthetic = true)
{
- return klass->get.f.glyph_h_advance (this, user_data,
- glyph,
- !klass->user_data ? nullptr : klass->user_data->glyph_h_advance);
+ hb_position_t advance = klass->get.f.glyph_h_advance (this, user_data,
+ glyph,
+ !klass->user_data ? nullptr : klass->user_data->glyph_h_advance);
+
+ if (synthetic && x_strength && !embolden_in_place)
+ {
+ /* Embolden */
+ hb_position_t strength = x_scale >= 0 ? x_strength : -x_strength;
+ advance += advance ? strength : 0;
+ }
+
+ return advance;
}
- hb_position_t get_glyph_v_advance (hb_codepoint_t glyph)
+ hb_position_t get_glyph_v_advance (hb_codepoint_t glyph,
+ bool synthetic = true)
{
- return klass->get.f.glyph_v_advance (this, user_data,
- glyph,
- !klass->user_data ? nullptr : klass->user_data->glyph_v_advance);
+ hb_position_t advance = klass->get.f.glyph_v_advance (this, user_data,
+ glyph,
+ !klass->user_data ? nullptr : klass->user_data->glyph_v_advance);
+
+ if (synthetic && y_strength && !embolden_in_place)
+ {
+ /* Embolden */
+ hb_position_t strength = y_scale >= 0 ? y_strength : -y_strength;
+ advance += advance ? strength : 0;
+ }
+
+ return advance;
}
void get_glyph_h_advances (unsigned int count,
const hb_codepoint_t *first_glyph,
unsigned int glyph_stride,
hb_position_t *first_advance,
- unsigned int advance_stride)
+ unsigned int advance_stride,
+ bool synthetic = true)
{
- return klass->get.f.glyph_h_advances (this, user_data,
- count,
- first_glyph, glyph_stride,
- first_advance, advance_stride,
- !klass->user_data ? nullptr : klass->user_data->glyph_h_advances);
+ klass->get.f.glyph_h_advances (this, user_data,
+ count,
+ first_glyph, glyph_stride,
+ first_advance, advance_stride,
+ !klass->user_data ? nullptr : klass->user_data->glyph_h_advances);
+
+ if (synthetic && x_strength && !embolden_in_place)
+ {
+ /* Embolden */
+ hb_position_t strength = x_scale >= 0 ? x_strength : -x_strength;
+ for (unsigned int i = 0; i < count; i++)
+ {
+ *first_advance += *first_advance ? strength : 0;
+ first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride);
+ }
+ }
}
void get_glyph_v_advances (unsigned int count,
const hb_codepoint_t *first_glyph,
unsigned int glyph_stride,
hb_position_t *first_advance,
- unsigned int advance_stride)
+ unsigned int advance_stride,
+ bool synthetic = true)
{
- return klass->get.f.glyph_v_advances (this, user_data,
- count,
- first_glyph, glyph_stride,
- first_advance, advance_stride,
- !klass->user_data ? nullptr : klass->user_data->glyph_v_advances);
+ klass->get.f.glyph_v_advances (this, user_data,
+ count,
+ first_glyph, glyph_stride,
+ first_advance, advance_stride,
+ !klass->user_data ? nullptr : klass->user_data->glyph_v_advances);
+
+ if (synthetic && y_strength && !embolden_in_place)
+ {
+ /* Embolden */
+ hb_position_t strength = y_scale >= 0 ? y_strength : -y_strength;
+ for (unsigned int i = 0; i < count; i++)
+ {
+ *first_advance += *first_advance ? strength : 0;
+ first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride);
+ }
+ }
}
hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph,
@@ -386,23 +472,82 @@ struct hb_font_t
}
hb_bool_t get_glyph_extents (hb_codepoint_t glyph,
- hb_glyph_extents_t *extents)
+ hb_glyph_extents_t *extents,
+ bool synthetic = true)
{
hb_memset (extents, 0, sizeof (*extents));
- return klass->get.f.glyph_extents (this, user_data,
- glyph,
- extents,
- !klass->user_data ? nullptr : klass->user_data->glyph_extents);
+
+ /* This is rather messy, but necessary. */
+
+ if (!synthetic)
+ {
+ return klass->get.f.glyph_extents (this, user_data,
+ glyph,
+ extents,
+ !klass->user_data ? nullptr : klass->user_data->glyph_extents);
+ }
+ if (!is_synthetic () &&
+ klass->get.f.glyph_extents (this, user_data,
+ glyph,
+ extents,
+ !klass->user_data ? nullptr : klass->user_data->glyph_extents))
+ return true;
+
+ /* Try getting extents from paint(), then draw(), *then* get_extents()
+ * and apply synthetic settings in the last case. */
+
+ hb_paint_extents_context_t paint_extents;
+ if (paint_glyph_or_fail (glyph,
+ hb_paint_extents_get_funcs (), &paint_extents,
+ 0, 0))
+ {
+ *extents = paint_extents.get_extents ().to_glyph_extents ();
+ return true;
+ }
+
+ hb_extents_t draw_extents;
+ if (draw_glyph_or_fail (glyph,
+ hb_draw_extents_get_funcs (), &draw_extents))
+ {
+ *extents = draw_extents.to_glyph_extents ();
+ return true;
+ }
+
+ bool ret = klass->get.f.glyph_extents (this, user_data,
+ glyph,
+ extents,
+ !klass->user_data ? nullptr : klass->user_data->glyph_extents);
+ if (ret)
+ synthetic_glyph_extents (extents);
+
+ return ret;
}
hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index,
- hb_position_t *x, hb_position_t *y)
+ hb_position_t *x, hb_position_t *y,
+ bool synthetic = true)
{
*x = *y = 0;
- return klass->get.f.glyph_contour_point (this, user_data,
- glyph, point_index,
- x, y,
- !klass->user_data ? nullptr : klass->user_data->glyph_contour_point);
+ bool ret = klass->get.f.glyph_contour_point (this, user_data,
+ glyph, point_index,
+ x, y,
+ !klass->user_data ? nullptr : klass->user_data->glyph_contour_point);
+
+ if (synthetic && ret)
+ {
+ /* Slant */
+ if (slant_xy)
+ *x += roundf (*y * slant_xy);
+
+ /* Embolden */
+ if (!embolden_in_place)
+ {
+ int x_shift = x_scale < 0 ? -x_strength : x_strength;
+ *x += x_shift;
+ }
+ }
+
+ return ret;
}
hb_bool_t get_glyph_name (hb_codepoint_t glyph,
@@ -426,29 +571,88 @@ struct hb_font_t
!klass->user_data ? nullptr : klass->user_data->glyph_from_name);
}
- void draw_glyph (hb_codepoint_t glyph,
- hb_draw_funcs_t *draw_funcs, void *draw_data)
+ bool draw_glyph_or_fail (hb_codepoint_t glyph,
+ hb_draw_funcs_t *draw_funcs, void *draw_data,
+ bool synthetic = true)
{
- klass->get.f.draw_glyph (this, user_data,
- glyph,
- draw_funcs, draw_data,
- !klass->user_data ? nullptr : klass->user_data->draw_glyph);
+#ifndef HB_NO_OUTLINE
+ bool embolden = x_strength || y_strength;
+ bool slanted = slant_xy;
+ synthetic = synthetic && (embolden || slanted);
+#else
+ synthetic = false;
+#endif
+
+ if (!synthetic)
+ {
+ return klass->get.f.draw_glyph_or_fail (this, user_data,
+ glyph,
+ draw_funcs, draw_data,
+ !klass->user_data ? nullptr : klass->user_data->draw_glyph_or_fail);
+ }
+
+#ifndef HB_NO_OUTLINE
+
+ hb_outline_t outline;
+ if (!klass->get.f.draw_glyph_or_fail (this, user_data,
+ glyph,
+ hb_outline_recording_pen_get_funcs (), &outline,
+ !klass->user_data ? nullptr : klass->user_data->draw_glyph_or_fail))
+ return false;
+
+ // Slant before embolden; produces nicer results.
+
+ if (slanted)
+ outline.slant (slant_xy);
+
+ if (embolden)
+ {
+ float x_shift = embolden_in_place ? 0 : (float) x_strength / 2;
+ float y_shift = (float) y_strength / 2;
+ if (x_scale < 0) x_shift = -x_shift;
+ if (y_scale < 0) y_shift = -y_shift;
+ outline.embolden (x_strength, y_strength, x_shift, y_shift);
+ }
+
+ outline.replay (draw_funcs, draw_data);
+
+ return true;
+#endif
}
- void paint_glyph (hb_codepoint_t glyph,
- hb_paint_funcs_t *paint_funcs, void *paint_data,
- unsigned int palette,
- hb_color_t foreground)
+ bool paint_glyph_or_fail (hb_codepoint_t glyph,
+ hb_paint_funcs_t *paint_funcs, void *paint_data,
+ unsigned int palette,
+ hb_color_t foreground,
+ bool synthetic = true)
{
- klass->get.f.paint_glyph (this, user_data,
- glyph,
- paint_funcs, paint_data,
- palette, foreground,
- !klass->user_data ? nullptr : klass->user_data->paint_glyph);
+ /* Slant */
+ if (synthetic && slant_xy)
+ hb_paint_push_transform (paint_funcs, paint_data,
+ 1.f, 0.f,
+ slant_xy, 1.f,
+ 0.f, 0.f);
+
+ bool ret = klass->get.f.paint_glyph_or_fail (this, user_data,
+ glyph,
+ paint_funcs, paint_data,
+ palette, foreground,
+ !klass->user_data ? nullptr : klass->user_data->paint_glyph_or_fail);
+
+ if (synthetic && slant_xy)
+ hb_paint_pop_transform (paint_funcs, paint_data);
+
+ return ret;
}
/* A bit higher-level, and with fallback */
+ HB_INTERNAL
+ void paint_glyph (hb_codepoint_t glyph,
+ hb_paint_funcs_t *paint_funcs, void *paint_data,
+ unsigned int palette,
+ hb_color_t foreground);
+
void get_h_extents_with_fallback (hb_font_extents_t *extents)
{
if (!get_font_h_extents (extents))
@@ -686,7 +890,12 @@ struct hb_font_t
return false;
}
- void mults_changed ()
+ bool is_synthetic () const
+ {
+ return x_embolden || y_embolden || slant;
+ }
+
+ void changed ()
{
float upem = face->get_upem ();
@@ -697,12 +906,14 @@ struct hb_font_t
bool y_neg = y_scale < 0;
y_mult = (y_neg ? -((int64_t) -y_scale << 16) : ((int64_t) y_scale << 16)) / upem;
- x_strength = fabsf (roundf (x_scale * x_embolden));
- y_strength = fabsf (roundf (y_scale * y_embolden));
+ x_strength = roundf (abs (x_scale) * x_embolden);
+ y_strength = roundf (abs (y_scale) * y_embolden);
slant_xy = y_scale ? slant * x_scale / y_scale : 0.f;
data.fini ();
+
+ serial++;
}
hb_position_t em_mult (int16_t v, int64_t mult)
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ft.cc b/src/java.desktop/share/native/libharfbuzz/hb-ft.cc
index b126d2022d1..e9c0e734a53 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-ft.cc
+++ b/src/java.desktop/share/native/libharfbuzz/hb-ft.cc
@@ -37,11 +37,7 @@
#include "hb-draw.hh"
#include "hb-font.hh"
#include "hb-machinery.hh"
-#ifndef HB_NO_AAT
-#include "hb-aat-layout-trak-table.hh"
-#endif
#include "hb-ot-os2-table.hh"
-#include "hb-ot-stat-table.hh"
#include "hb-ot-shaper-arabic-pua.hh"
#include "hb-paint.hh"
@@ -101,7 +97,7 @@ struct hb_ft_font_t
mutable hb_mutex_t lock; /* Protects members below. */
FT_Face ft_face;
- mutable unsigned cached_serial;
+ mutable hb_atomic_t cached_serial;
mutable hb_ft_advance_cache_t advance_cache;
};
@@ -118,7 +114,7 @@ _hb_ft_font_create (FT_Face ft_face, bool symbol, bool unref)
ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
- ft_font->cached_serial = (unsigned) -1;
+ ft_font->cached_serial = UINT_MAX;
new (&ft_font->advance_cache) hb_ft_advance_cache_t;
return ft_font;
@@ -213,9 +209,10 @@ _hb_ft_hb_font_check_changed (hb_font_t *font,
{
if (font->serial != ft_font->cached_serial)
{
+ hb_lock_t lock (ft_font->lock);
_hb_ft_hb_font_changed (font, ft_font->ft_face);
ft_font->advance_cache.clear ();
- ft_font->cached_serial = font->serial;
+ ft_font->cached_serial.set_release (font->serial.get_acquire ());
return true;
}
return false;
@@ -478,7 +475,8 @@ hb_ft_get_glyph_h_advances (hb_font_t* font, void* font_data,
void *user_data HB_UNUSED)
{
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
- hb_position_t *orig_first_advance = first_advance;
+ _hb_ft_hb_font_check_changed (font, ft_font);
+
hb_lock_t lock (ft_font->lock);
FT_Face ft_face = ft_font->ft_face;
int load_flags = ft_font->load_flags;
@@ -519,38 +517,6 @@ hb_ft_get_glyph_h_advances (hb_font_t* font, void* font_data,
first_glyph = &StructAtOffsetUnaligned (first_glyph, glyph_stride);
first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride);
}
-
- if (font->x_strength && !font->embolden_in_place)
- {
- /* Emboldening. */
- hb_position_t x_strength = font->x_scale >= 0 ? font->x_strength : -font->x_strength;
- first_advance = orig_first_advance;
- for (unsigned int i = 0; i < count; i++)
- {
- *first_advance += *first_advance ? x_strength : 0;
- first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride);
- }
- }
-
-#ifndef HB_NO_AAT
- /* According to Ned, trak is applied by default for "modern fonts", as detected by presence of STAT table. */
-#ifndef HB_NO_STYLE
- bool apply_trak = font->face->table.STAT->has_data () && font->face->table.trak->has_data ();
-#else
- bool apply_trak = false;
-#endif
- if (apply_trak)
- {
- hb_position_t tracking = font->face->table.trak->get_h_tracking (font);
- first_advance = orig_first_advance;
- for (unsigned int i = 0; i < count; i++)
- {
- *first_advance += tracking;
- first_glyph = &StructAtOffsetUnaligned (first_glyph, glyph_stride);
- first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride);
- }
- }
-#endif
}
#ifndef HB_NO_VERTICAL
@@ -561,6 +527,8 @@ hb_ft_get_glyph_v_advance (hb_font_t *font,
void *user_data HB_UNUSED)
{
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+ _hb_ft_hb_font_check_changed (font, ft_font);
+
hb_lock_t lock (ft_font->lock);
FT_Fixed v;
float y_mult;
@@ -581,26 +549,11 @@ hb_ft_get_glyph_v_advance (hb_font_t *font,
if (unlikely (FT_Get_Advance (ft_font->ft_face, glyph, ft_font->load_flags | FT_LOAD_VERTICAL_LAYOUT, &v)))
return 0;
- v = (int) (y_mult * v);
-
/* Note: FreeType's vertical metrics grows downward while other FreeType coordinates
* have a Y growing upward. Hence the extra negation. */
+ v = ((-v + (1<<9)) >> 10);
- hb_position_t y_strength = font->y_scale >= 0 ? font->y_strength : -font->y_strength;
- v = ((-v + (1<<9)) >> 10) + (font->embolden_in_place ? 0 : y_strength);
-
-#ifndef HB_NO_AAT
- /* According to Ned, trak is applied by default for "modern fonts", as detected by presence of STAT table. */
-#ifndef HB_NO_STYLE
- bool apply_trak = font->face->table.STAT->has_data () && font->face->table.trak->has_data ();
-#else
- bool apply_trak = false;
-#endif
- if (apply_trak)
- v += font->face->table.trak->get_v_tracking (font);
-#endif
-
- return v;
+ return (hb_position_t) (y_mult * v);
}
#endif
@@ -614,6 +567,8 @@ hb_ft_get_glyph_v_origin (hb_font_t *font,
void *user_data HB_UNUSED)
{
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+ _hb_ft_hb_font_check_changed (font, ft_font);
+
hb_lock_t lock (ft_font->lock);
FT_Face ft_face = ft_font->ft_face;
float x_mult, y_mult;
@@ -658,6 +613,8 @@ hb_ft_get_glyph_h_kerning (hb_font_t *font,
void *user_data HB_UNUSED)
{
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+ _hb_ft_hb_font_check_changed (font, ft_font);
+
hb_lock_t lock (ft_font->lock);
FT_Vector kerningv;
@@ -669,6 +626,41 @@ hb_ft_get_glyph_h_kerning (hb_font_t *font,
}
#endif
+static bool
+hb_ft_is_colr_glyph (hb_font_t *font,
+ void *font_data,
+ hb_codepoint_t gid)
+{
+#ifndef HB_NO_PAINT
+#if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) >= 21300
+ const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+ FT_Face ft_face = ft_font->ft_face;
+
+
+ /* COLRv1 */
+ FT_OpaquePaint paint = {0};
+ if (FT_Get_Color_Glyph_Paint (ft_face, gid,
+ FT_COLOR_NO_ROOT_TRANSFORM,
+ &paint))
+ return true;
+
+ /* COLRv0 */
+ FT_LayerIterator iterator;
+ FT_UInt layer_glyph_index;
+ FT_UInt layer_color_index;
+ iterator.p = NULL;
+ if (FT_Get_Color_Glyph_Layer (ft_face,
+ gid,
+ &layer_glyph_index,
+ &layer_color_index,
+ &iterator))
+ return true;
+#endif
+#endif
+
+ return false;
+}
+
static hb_bool_t
hb_ft_get_glyph_extents (hb_font_t *font,
void *font_data,
@@ -676,11 +668,17 @@ hb_ft_get_glyph_extents (hb_font_t *font,
hb_glyph_extents_t *extents,
void *user_data HB_UNUSED)
{
+ // FreeType doesn't return COLR glyph extents.
+ if (hb_ft_is_colr_glyph (font, font_data, glyph))
+ return false;
+
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+ _hb_ft_hb_font_check_changed (font, ft_font);
+
hb_lock_t lock (ft_font->lock);
FT_Face ft_face = ft_font->ft_face;
float x_mult, y_mult;
- float slant_xy = font->slant_xy;
+
#ifdef HAVE_FT_GET_TRANSFORM
if (ft_font->transform)
{
@@ -708,33 +706,10 @@ hb_ft_get_glyph_extents (hb_font_t *font,
float x2 = x1 + x_mult * ft_face->glyph->metrics.width;
float y2 = y1 + y_mult * -ft_face->glyph->metrics.height;
- /* Apply slant. */
- if (slant_xy)
- {
- x1 += hb_min (y1 * slant_xy, y2 * slant_xy);
- x2 += hb_max (y1 * slant_xy, y2 * slant_xy);
- }
-
- extents->x_bearing = floorf (x1);
- extents->y_bearing = floorf (y1);
- extents->width = ceilf (x2) - extents->x_bearing;
- extents->height = ceilf (y2) - extents->y_bearing;
-
- if (font->x_strength || font->y_strength)
- {
- /* Y */
- int y_shift = font->y_strength;
- if (font->y_scale < 0) y_shift = -y_shift;
- extents->y_bearing += y_shift;
- extents->height -= y_shift;
-
- /* X */
- int x_shift = font->x_strength;
- if (font->x_scale < 0) x_shift = -x_shift;
- if (font->embolden_in_place)
- extents->x_bearing -= x_shift / 2;
- extents->width += x_shift;
- }
+ extents->x_bearing = roundf (x1);
+ extents->y_bearing = roundf (y1);
+ extents->width = roundf (x2) - extents->x_bearing;
+ extents->height = roundf (y2) - extents->y_bearing;
return true;
}
@@ -749,6 +724,8 @@ hb_ft_get_glyph_contour_point (hb_font_t *font HB_UNUSED,
void *user_data HB_UNUSED)
{
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+ _hb_ft_hb_font_check_changed (font, ft_font);
+
hb_lock_t lock (ft_font->lock);
FT_Face ft_face = ft_font->ft_face;
@@ -826,6 +803,8 @@ hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED,
void *user_data HB_UNUSED)
{
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+ _hb_ft_hb_font_check_changed (font, ft_font);
+
hb_lock_t lock (ft_font->lock);
FT_Face ft_face = ft_font->ft_face;
float y_mult;
@@ -857,7 +836,7 @@ hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED,
metrics->line_gap = ft_face->size->metrics.height - (metrics->ascender - metrics->descender);
}
- metrics->ascender = (hb_position_t) (y_mult * (metrics->ascender + font->y_strength));
+ metrics->ascender = (hb_position_t) (y_mult * metrics->ascender);
metrics->descender = (hb_position_t) (y_mult * metrics->descender);
metrics->line_gap = (hb_position_t) (y_mult * metrics->line_gap);
@@ -908,23 +887,25 @@ _hb_ft_cubic_to (const FT_Vector *control1,
return FT_Err_Ok;
}
-static void
-hb_ft_draw_glyph (hb_font_t *font,
- void *font_data,
- hb_codepoint_t glyph,
- hb_draw_funcs_t *draw_funcs, void *draw_data,
- void *user_data HB_UNUSED)
+static hb_bool_t
+hb_ft_draw_glyph_or_fail (hb_font_t *font,
+ void *font_data,
+ hb_codepoint_t glyph,
+ hb_draw_funcs_t *draw_funcs, void *draw_data,
+ void *user_data HB_UNUSED)
{
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+ _hb_ft_hb_font_check_changed (font, ft_font);
+
hb_lock_t lock (ft_font->lock);
FT_Face ft_face = ft_font->ft_face;
if (unlikely (FT_Load_Glyph (ft_face, glyph,
FT_LOAD_NO_BITMAP | ft_font->load_flags)))
- return;
+ return false;
if (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE)
- return;
+ return false;
const FT_Outline_Funcs outline_funcs = {
_hb_ft_move_to,
@@ -935,43 +916,13 @@ hb_ft_draw_glyph (hb_font_t *font,
0, /* delta */
};
- hb_draw_session_t draw_session (draw_funcs, draw_data, font->slant_xy);
-
- /* Embolden */
- if (font->x_strength || font->y_strength)
- {
- FT_Outline_EmboldenXY (&ft_face->glyph->outline, font->x_strength, font->y_strength);
-
- int x_shift = 0;
- int y_shift = 0;
- if (font->embolden_in_place)
- {
- /* Undo the FreeType shift. */
- x_shift = -font->x_strength / 2;
- y_shift = 0;
- if (font->y_scale < 0) y_shift = -font->y_strength;
- }
- else
- {
- /* FreeType applied things in the wrong direction for negative scale; fix up. */
- if (font->x_scale < 0) x_shift = -font->x_strength;
- if (font->y_scale < 0) y_shift = -font->y_strength;
- }
- if (x_shift || y_shift)
- {
- auto &outline = ft_face->glyph->outline;
- for (auto &point : hb_iter (outline.points, outline.contours[outline.n_contours - 1] + 1))
- {
- point.x += x_shift;
- point.y += y_shift;
- }
- }
- }
-
+ hb_draw_session_t draw_session {draw_funcs, draw_data};
FT_Outline_Decompose (&ft_face->glyph->outline,
&outline_funcs,
&draw_session);
+
+ return true;
}
#endif
@@ -980,20 +931,22 @@ hb_ft_draw_glyph (hb_font_t *font,
#include "hb-ft-colr.hh"
-static void
-hb_ft_paint_glyph (hb_font_t *font,
- void *font_data,
- hb_codepoint_t gid,
- hb_paint_funcs_t *paint_funcs, void *paint_data,
- unsigned int palette_index,
- hb_color_t foreground,
- void *user_data)
+static hb_bool_t
+hb_ft_paint_glyph_or_fail (hb_font_t *font,
+ void *font_data,
+ hb_codepoint_t gid,
+ hb_paint_funcs_t *paint_funcs, void *paint_data,
+ unsigned int palette_index,
+ hb_color_t foreground,
+ void *user_data)
{
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+ _hb_ft_hb_font_check_changed (font, ft_font);
+
hb_lock_t lock (ft_font->lock);
FT_Face ft_face = ft_font->ft_face;
- FT_Long load_flags = ft_font->load_flags | FT_LOAD_NO_BITMAP | FT_LOAD_COLOR;
+ FT_Long load_flags = ft_font->load_flags | FT_LOAD_COLOR;
#if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) >= 21301
load_flags |= FT_LOAD_NO_SVG;
#endif
@@ -1002,7 +955,7 @@ hb_ft_paint_glyph (hb_font_t *font,
* eg. draw API can call back into the face.*/
if (unlikely (FT_Load_Glyph (ft_face, gid, load_flags)))
- return;
+ return false;
if (ft_face->glyph->format == FT_GLYPH_FORMAT_OUTLINE)
{
@@ -1010,26 +963,21 @@ hb_ft_paint_glyph (hb_font_t *font,
paint_funcs, paint_data,
palette_index, foreground,
user_data))
- return;
+ return true;
- /* Simple outline. */
- ft_font->lock.unlock ();
- paint_funcs->push_clip_glyph (paint_data, gid, font);
- ft_font->lock.lock ();
- paint_funcs->color (paint_data, true, foreground);
- paint_funcs->pop_clip (paint_data);
-
- return;
+ // Outline glyph
+ return false;
}
auto *glyph = ft_face->glyph;
if (glyph->format == FT_GLYPH_FORMAT_BITMAP)
{
+ bool ret = false;
auto &bitmap = glyph->bitmap;
if (bitmap.pixel_mode == FT_PIXEL_MODE_BGRA)
{
if (bitmap.pitch != (signed) bitmap.width * 4)
- return;
+ return ret;
ft_font->lock.unlock ();
@@ -1039,27 +987,26 @@ hb_ft_paint_glyph (hb_font_t *font,
nullptr, nullptr);
hb_glyph_extents_t extents;
- if (!hb_font_get_glyph_extents (font, gid, &extents))
+ if (!font->get_glyph_extents (gid, &extents, false))
goto out;
- if (!paint_funcs->image (paint_data,
- blob,
- bitmap.width,
- bitmap.rows,
- HB_PAINT_IMAGE_FORMAT_BGRA,
- font->slant_xy,
- &extents))
- {
- /* TODO Try a forced outline load and paint? */
- }
+ if (paint_funcs->image (paint_data,
+ blob,
+ bitmap.width,
+ bitmap.rows,
+ HB_PAINT_IMAGE_FORMAT_BGRA,
+ 0.f,
+ &extents))
+ ret = true;
out:
hb_blob_destroy (blob);
ft_font->lock.lock ();
}
- return;
+ return ret;
}
+ return false;
}
#endif
#endif
@@ -1079,10 +1026,8 @@ static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t= 21300
- hb_font_funcs_set_paint_glyph_func (funcs, hb_ft_paint_glyph, nullptr, nullptr);
+ hb_font_funcs_set_paint_glyph_or_fail_func (funcs, hb_ft_paint_glyph_or_fail, nullptr, nullptr);
#endif
#endif
@@ -1456,6 +1400,10 @@ hb_ft_font_changed (hb_font_t *font)
* variation-axis settings on the @font.
* This call is fast if nothing has changed on @font.
*
+ * Note that as of version 11.0.0, calling this function is not necessary,
+ * as HarfBuzz will automatically detect changes to the font and update
+ * the underlying FT_Face as needed.
+ *
* Return value: true if changed, false otherwise
*
* Since: 4.4.0
@@ -1587,7 +1535,8 @@ destroy_ft_library (void *arg)
* font file and face index.
*
* This is similar in functionality to hb_face_create_from_file_or_fail(),
- * but uses the FreeType library for loading the font file.
+ * but uses the FreeType library for loading the font file. This can
+ * be useful, for example, to load WOFF and WOFF2 font data.
*
* Return value: (transfer full): The new face object, or `NULL` if
* no face is found at the specified index or the file cannot be read.
@@ -1624,6 +1573,75 @@ hb_ft_face_create_from_file_or_fail (const char *file_name,
return face;
}
+static hb_user_data_key_t ft_blob_key = {0};
+
+static void
+_destroy_blob (void *p)
+{
+ hb_blob_destroy ((hb_blob_t *) p);
+}
+
+/**
+ * hb_ft_face_create_from_blob_or_fail:
+ * @blob: A blob
+ * @index: The index of the face within the blob
+ *
+ * Creates an #hb_face_t face object from the specified
+ * font blob and face index.
+ *
+ * This is similar in functionality to hb_face_create_from_blob_or_fail(),
+ * but uses the FreeType library for loading the font blob. This can
+ * be useful, for example, to load WOFF and WOFF2 font data.
+ *
+ * Return value: (transfer full): The new face object, or `NULL` if
+ * loading fails (eg. blob does not contain valid font data).
+ *
+ * Since: 11.0.0
+ */
+hb_face_t *
+hb_ft_face_create_from_blob_or_fail (hb_blob_t *blob,
+ unsigned int index)
+{
+ FT_Library ft_library = reference_ft_library ();
+ if (unlikely (!ft_library))
+ {
+ DEBUG_MSG (FT, ft_library, "reference_ft_library failed");
+ return nullptr;
+ }
+
+ hb_blob_make_immutable (blob);
+ unsigned blob_size;
+ const char *blob_data = hb_blob_get_data (blob, &blob_size);
+
+ FT_Face ft_face;
+ if (unlikely (FT_New_Memory_Face (ft_library,
+ (const FT_Byte *) blob_data,
+ blob_size,
+ index,
+ &ft_face)))
+ return nullptr;
+
+ hb_face_t *face = hb_ft_face_create_referenced (ft_face);
+ FT_Done_Face (ft_face);
+
+ ft_face->generic.data = ft_library;
+ ft_face->generic.finalizer = finalize_ft_library;
+
+ if (hb_face_is_immutable (face))
+ return nullptr;
+
+ // Hook the blob to the hb_face_t, since FT_Face still needs it.
+ hb_blob_reference (blob);
+ if (!hb_face_set_user_data (face, &ft_blob_key, blob, _destroy_blob, true))
+ {
+ hb_blob_destroy (blob);
+ hb_face_destroy (face);
+ return nullptr;
+ }
+
+ return face;
+}
+
static void
_release_blob (void *arg)
{
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ft.h b/src/java.desktop/share/native/libharfbuzz/hb-ft.h
index 94952f48a05..9f83b91abb6 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-ft.h
+++ b/src/java.desktop/share/native/libharfbuzz/hb-ft.h
@@ -88,6 +88,10 @@ HB_EXTERN hb_face_t *
hb_ft_face_create_from_file_or_fail (const char *file_name,
unsigned int index);
+HB_EXTERN hb_face_t *
+hb_ft_face_create_from_blob_or_fail (hb_blob_t *blob,
+ unsigned int index);
+
/*
* hb-font from ft-face.
*/
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-geometry.hh b/src/java.desktop/share/native/libharfbuzz/hb-geometry.hh
index e91e371dc0c..795f29f6ab0 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-geometry.hh
+++ b/src/java.desktop/share/native/libharfbuzz/hb-geometry.hh
@@ -30,6 +30,11 @@
struct hb_extents_t
{
hb_extents_t () {}
+ hb_extents_t (const hb_glyph_extents_t &extents) :
+ xmin (hb_min (extents.x_bearing, extents.x_bearing + extents.width)),
+ ymin (hb_min (extents.y_bearing, extents.y_bearing + extents.height)),
+ xmax (hb_max (extents.x_bearing, extents.x_bearing + extents.width)),
+ ymax (hb_max (extents.y_bearing, extents.y_bearing + extents.height)) {}
hb_extents_t (float xmin, float ymin, float xmax, float ymax) :
xmin (xmin), ymin (ymin), xmax (xmax), ymax (ymax) {}
@@ -38,6 +43,12 @@ struct hb_extents_t
void union_ (const hb_extents_t &o)
{
+ if (o.is_empty ()) return;
+ if (is_empty ())
+ {
+ *this = o;
+ return;
+ }
xmin = hb_min (xmin, o.xmin);
ymin = hb_min (ymin, o.ymin);
xmax = hb_max (xmax, o.xmax);
@@ -46,6 +57,11 @@ struct hb_extents_t
void intersect (const hb_extents_t &o)
{
+ if (o.is_empty () || is_empty ())
+ {
+ *this = hb_extents_t {};
+ return;
+ }
xmin = hb_max (xmin, o.xmin);
ymin = hb_max (ymin, o.ymin);
xmax = hb_min (xmax, o.xmax);
@@ -69,6 +85,18 @@ struct hb_extents_t
}
}
+ hb_glyph_extents_t to_glyph_extents (bool xneg = false, bool yneg = false) const
+ {
+ hb_position_t x0 = (hb_position_t) roundf (xmin);
+ hb_position_t y0 = (hb_position_t) roundf (ymin);
+ hb_position_t x1 = (hb_position_t) roundf (xmax);
+ hb_position_t y1 = (hb_position_t) roundf (ymax);
+ return hb_glyph_extents_t {xneg ? x1 : x0,
+ yneg ? y0 : y1,
+ xneg ? x0 - x1 : x1 - x0,
+ yneg ? y1 - y0 : y0 - y1};
+ }
+
float xmin = 0.f;
float ymin = 0.f;
float xmax = -1.f;
@@ -218,7 +246,7 @@ struct hb_bounds_t
EMPTY,
};
- hb_bounds_t (status_t status) : status (status) {}
+ hb_bounds_t (status_t status = UNBOUNDED) : status (status) {}
hb_bounds_t (const hb_extents_t &extents) :
status (extents.is_empty () ? EMPTY : BOUNDED), extents (extents) {}
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-machinery.hh b/src/java.desktop/share/native/libharfbuzz/hb-machinery.hh
index 580c9f0c785..ffbb8f3d301 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-machinery.hh
+++ b/src/java.desktop/share/native/libharfbuzz/hb-machinery.hh
@@ -273,7 +273,7 @@ struct hb_lazy_loader_t : hb_data_wrapper_t
private:
/* Must only have one pointer. */
- hb_atomic_ptr_t instance;
+ mutable hb_atomic_t instance;
};
/* Specializations. */
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-mutex.hh b/src/java.desktop/share/native/libharfbuzz/hb-mutex.hh
index 72012bd2e64..4b6c5a118ae 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-mutex.hh
+++ b/src/java.desktop/share/native/libharfbuzz/hb-mutex.hh
@@ -99,6 +99,8 @@ struct hb_mutex_t
hb_mutex_t () { init (); }
~hb_mutex_t () { fini (); }
+ hb_mutex_t (const hb_mutex_t &) = delete;
+ hb_mutex_t &operator= (const hb_mutex_t &) = delete;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-align"
@@ -114,6 +116,10 @@ struct hb_lock_t
hb_lock_t (hb_mutex_t &mutex_) : mutex (&mutex_) { mutex->lock (); }
hb_lock_t (hb_mutex_t *mutex_) : mutex (mutex_) { if (mutex) mutex->lock (); }
~hb_lock_t () { if (mutex) mutex->unlock (); }
+
+ hb_lock_t (const hb_lock_t &) = delete;
+ hb_lock_t &operator= (const hb_lock_t &) = delete;
+
private:
hb_mutex_t *mutex;
};
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-object.hh b/src/java.desktop/share/native/libharfbuzz/hb-object.hh
index c02ec8bfacf..fa9a249b2e2 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-object.hh
+++ b/src/java.desktop/share/native/libharfbuzz/hb-object.hh
@@ -142,7 +142,7 @@ struct hb_lockable_set_t
struct hb_reference_count_t
{
- mutable hb_atomic_int_t ref_count;
+ mutable hb_atomic_t ref_count;
void init (int v = 1) { ref_count = v; }
int get_relaxed () const { return ref_count; }
@@ -213,8 +213,8 @@ struct hb_user_data_array_t
struct hb_object_header_t
{
hb_reference_count_t ref_count;
- mutable hb_atomic_int_t writable = 0;
- hb_atomic_ptr_t user_data;
+ mutable hb_atomic_t writable = false;
+ hb_atomic_t user_data;
bool is_inert () const { return !ref_count.get_relaxed (); }
};
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-open-type.hh b/src/java.desktop/share/native/libharfbuzz/hb-open-type.hh
index 89da9c7bc95..75d87f11ea5 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-open-type.hh
+++ b/src/java.desktop/share/native/libharfbuzz/hb-open-type.hh
@@ -1888,7 +1888,7 @@ struct TupleValues
bool ensure_run ()
{
- if (likely (run_count > 0)) return true;
+ if (run_count > 0) return true;
if (unlikely (p >= end))
{
@@ -1943,6 +1943,11 @@ struct TupleValues
unsigned count = hb_min (n - i, (unsigned) run_count);
switch (width)
{
+ case 0:
+ {
+ arrayZ += count;
+ break;
+ }
case 1:
{
const auto *pp = (const HBINT8 *) p;
@@ -1958,6 +1963,8 @@ struct TupleValues
#endif
for (; j < count; j++)
*arrayZ++ += scaled ? *pp++ * scale : *pp++;
+
+ p = (const unsigned char *) pp;
}
break;
case 2:
@@ -1975,6 +1982,8 @@ struct TupleValues
#endif
for (; j < count; j++)
*arrayZ++ += scaled ? *pp++ * scale : *pp++;
+
+ p = (const unsigned char *) pp;
}
break;
case 4:
@@ -1982,10 +1991,11 @@ struct TupleValues
const auto *pp = (const HBINT32 *) p;
for (unsigned j = 0; j < count; j++)
*arrayZ++ += scaled ? *pp++ * scale : *pp++;
+
+ p = (const unsigned char *) pp;
}
break;
}
- p += count * width;
run_count -= count;
i += count;
}
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-cff1-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-cff1-table.hh
index 0116a0c9192..27c4d31b9ce 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-cff1-table.hh
+++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-cff1-table.hh
@@ -1073,7 +1073,7 @@ struct cff1
this->blob = sc.reference_table (face);
- /* setup for run-time santization */
+ /* setup for run-time sanitization */
sc.init (this->blob);
sc.start_processing ();
@@ -1176,7 +1176,8 @@ struct cff1
if (unlikely (!font_interp.interpret (*font))) goto fail;
PRIVDICTVAL *priv = &privateDicts[i];
const hb_ubytes_t privDictStr = StructAtOffsetOrNull (cff, font->privateDictInfo.offset, sc, font->privateDictInfo.size).as_ubytes (font->privateDictInfo.size);
- if (unlikely (privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail;
+ if (unlikely (font->privateDictInfo.size &&
+ privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail;
num_interp_env_t env2 (privDictStr);
dict_interpreter_t priv_interp (env2);
priv->init ();
@@ -1191,7 +1192,8 @@ struct cff1
PRIVDICTVAL *priv = &privateDicts[0];
const hb_ubytes_t privDictStr = StructAtOffsetOrNull (cff, font->privateDictInfo.offset, sc, font->privateDictInfo.size).as_ubytes (font->privateDictInfo.size);
- if (unlikely (privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail;
+ if (font->privateDictInfo.size &&
+ unlikely (privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail;
num_interp_env_t env (privDictStr);
dict_interpreter_t priv_interp (env);
priv->init ();
@@ -1483,7 +1485,7 @@ struct cff1
int cmp (const gname_t &a) const { return cmp (&a, this); }
};
- mutable hb_atomic_ptr_t> glyph_names;
+ mutable hb_atomic_t *> glyph_names;
typedef accelerator_templ_t SUPER;
};
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.cc b/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.cc
index fce39da21ce..b2702106ecc 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.cc
+++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.cc
@@ -102,6 +102,14 @@ struct cff2_cs_opset_extents_t : cff2_cs_opset_tcoords, font->num_coords));
+}
+
+bool OT::cff2::accelerator_t::get_extents_at (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_glyph_extents_t *extents,
+ hb_array_t coords) const
{
#ifdef HB_NO_OT_FONT_CFF
/* XXX Remove check when this code moves to .hh file. */
@@ -112,7 +120,7 @@ bool OT::cff2::accelerator_t::get_extents (hb_font_t *font,
unsigned int fd = fdSelect->get_fd (glyph);
const hb_ubytes_t str = (*charStrings)[glyph];
- cff2_cs_interp_env_t env (str, *this, fd, font->coords, font->num_coords);
+ cff2_cs_interp_env_t env (str, *this, fd, coords.arrayZ, coords.length);
cff2_cs_interpreter_t interp (env);
cff2_extents_param_t param;
if (unlikely (!interp.interpret (param))) return false;
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.hh
index 81d30f57a28..7e94e38e115 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.hh
+++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.hh
@@ -405,7 +405,7 @@ struct cff2
this->blob = sc.reference_table (face);
- /* setup for run-time santization */
+ /* setup for run-time sanitization */
sc.init (this->blob);
sc.start_processing ();
@@ -458,7 +458,8 @@ struct cff2
if (unlikely (!font_interp.interpret (*font))) goto fail;
const hb_ubytes_t privDictStr = StructAtOffsetOrNull (cff2, font->privateDictInfo.offset, sc, font->privateDictInfo.size).as_ubytes (font->privateDictInfo.size);
- if (unlikely (privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail;
+ if (unlikely (font->privateDictInfo.size &&
+ privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail;
cff2_priv_dict_interp_env_t env2 (privDictStr);
dict_interpreter_t priv_interp (env2);
privateDicts[i].init ();
@@ -481,6 +482,13 @@ struct cff2
privateDicts.fini ();
hb_blob_destroy (blob);
blob = nullptr;
+
+ auto *scalars = cached_scalars_vector.get_acquire ();
+ if (scalars && cached_scalars_vector.cmpexch (scalars, nullptr))
+ {
+ scalars->fini ();
+ hb_free (scalars);
+ }
}
hb_vector_t *create_glyph_to_sid_map () const
@@ -508,6 +516,8 @@ struct cff2
hb_vector_t fontDicts;
hb_vector_t privateDicts;
+ mutable hb_atomic_t *> cached_scalars_vector;
+
unsigned int num_glyphs = 0;
};
@@ -518,6 +528,10 @@ struct cff2
HB_INTERNAL bool get_extents (hb_font_t *font,
hb_codepoint_t glyph,
hb_glyph_extents_t *extents) const;
+ HB_INTERNAL bool get_extents_at (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_glyph_extents_t *extents,
+ hb_array_t coords) const;
HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const;
HB_INTERNAL bool get_path_at (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session, hb_array_t coords) const;
};
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-cmap-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-cmap-table.hh
index 249d4cac5db..6bf37c062fc 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-cmap-table.hh
+++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-cmap-table.hh
@@ -2014,7 +2014,8 @@ struct cmap
struct accelerator_t
{
- using cache_t = hb_cache_t<21, 16, 8, true>;
+ using cache_t = hb_cache_t<21, 19>;
+ static_assert (sizeof (cache_t) == 1024, "");
accelerator_t (hb_face_t *face)
{
@@ -2028,6 +2029,14 @@ struct cmap
subtable_uvs = &st->u.format14;
}
+#ifndef HB_NO_OT_FONT_CMAP_CACHE
+ cache = (cache_t *) hb_malloc (sizeof (cache_t));
+ if (cache)
+ new (cache) cache_t ();
+ else
+ return; // Such that get_glyph_funcZ remains null.
+#endif
+
this->get_glyph_data = subtable;
#ifndef HB_NO_CMAP_LEGACY_SUBTABLES
if (unlikely (symbol))
@@ -2061,62 +2070,71 @@ struct cmap
#endif
{
switch (subtable->u.format) {
- /* Accelerate format 4 and format 12. */
- default:
- this->get_glyph_funcZ = get_glyph_from;
- break;
- case 12:
- this->get_glyph_funcZ = get_glyph_from;
- break;
- case 4:
- {
- this->format4_accel.init (&subtable->u.format4);
- this->get_glyph_data = &this->format4_accel;
- this->get_glyph_funcZ = this->format4_accel.get_glyph_func;
- break;
- }
+ /* Accelerate format 4 and format 12. */
+ default:
+ this->get_glyph_funcZ = get_glyph_from;
+ break;
+ case 12:
+ this->get_glyph_funcZ = get_glyph_from;
+ break;
+ case 4:
+ {
+ this->format4_accel.init (&subtable->u.format4);
+ this->get_glyph_data = &this->format4_accel;
+ this->get_glyph_funcZ = this->format4_accel.get_glyph_func;
+ break;
+ }
}
}
}
- ~accelerator_t () { this->table.destroy (); }
+ ~accelerator_t ()
+ {
+#ifndef HB_NO_OT_FONT_CMAP_CACHE
+ hb_free (cache);
+#endif
+ table.destroy ();
+ }
inline bool _cached_get (hb_codepoint_t unicode,
- hb_codepoint_t *glyph,
- cache_t *cache) const
+ hb_codepoint_t *glyph) const
{
+#ifndef HB_NO_OT_FONT_CMAP_CACHE
+ // cache is always non-null if we have a get_glyph_funcZ
unsigned v;
- if (cache && cache->get (unicode, &v))
+ if (cache->get (unicode, &v))
{
*glyph = v;
return true;
}
+#endif
bool ret = this->get_glyph_funcZ (this->get_glyph_data, unicode, glyph);
- if (cache && ret)
+#ifndef HB_NO_OT_FONT_CMAP_CACHE
+ if (ret)
cache->set (unicode, *glyph);
+#endif
+
return ret;
}
bool get_nominal_glyph (hb_codepoint_t unicode,
- hb_codepoint_t *glyph,
- cache_t *cache = nullptr) const
+ hb_codepoint_t *glyph) const
{
if (unlikely (!this->get_glyph_funcZ)) return false;
- return _cached_get (unicode, glyph, cache);
+ return _cached_get (unicode, glyph);
}
unsigned int get_nominal_glyphs (unsigned int count,
const hb_codepoint_t *first_unicode,
unsigned int unicode_stride,
hb_codepoint_t *first_glyph,
- unsigned int glyph_stride,
- cache_t *cache = nullptr) const
+ unsigned int glyph_stride) const
{
if (unlikely (!this->get_glyph_funcZ)) return 0;
unsigned int done;
for (done = 0;
- done < count && _cached_get (*first_unicode, first_glyph, cache);
+ done < count && _cached_get (*first_unicode, first_glyph);
done++)
{
first_unicode = &StructAtOffsetUnaligned (first_unicode, unicode_stride);
@@ -2127,8 +2145,7 @@ struct cmap
bool get_variation_glyph (hb_codepoint_t unicode,
hb_codepoint_t variation_selector,
- hb_codepoint_t *glyph,
- cache_t *cache = nullptr) const
+ hb_codepoint_t *glyph) const
{
switch (this->subtable_uvs->get_glyph_variant (unicode,
variation_selector,
@@ -2139,7 +2156,7 @@ struct cmap
case GLYPH_VARIANT_USE_DEFAULT: break;
}
- return get_nominal_glyph (unicode, glyph, cache);
+ return get_nominal_glyph (unicode, glyph);
}
void collect_unicodes (hb_set_t *out, unsigned int num_glyphs) const
@@ -2209,11 +2226,15 @@ struct cmap
hb_nonnull_ptr_t subtable;
hb_nonnull_ptr_t subtable_uvs;
- hb_cmap_get_glyph_func_t get_glyph_funcZ;
- const void *get_glyph_data;
+ hb_cmap_get_glyph_func_t get_glyph_funcZ = nullptr;
+ const void *get_glyph_data = nullptr;
CmapSubtableFormat4::accelerator_t format4_accel;
+#ifndef HB_NO_OT_FONT_CMAP_CACHE
+ cache_t *cache = nullptr;
+#endif
+
public:
hb_blob_ptr_t table;
};
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-color.cc b/src/java.desktop/share/native/libharfbuzz/hb-ot-color.cc
index ef46fe5429a..2d9b8e7cad2 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-color.cc
+++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-color.cc
@@ -204,7 +204,7 @@ hb_ot_color_palette_get_colors (hb_face_t *face,
hb_bool_t
hb_ot_color_has_layers (hb_face_t *face)
{
- return face->table.COLR->has_v0_data ();
+ return face->table.COLR->colr->has_v0_data ();
}
/**
@@ -221,7 +221,7 @@ hb_ot_color_has_layers (hb_face_t *face)
hb_bool_t
hb_ot_color_has_paint (hb_face_t *face)
{
- return face->table.COLR->has_v1_data ();
+ return face->table.COLR->colr->has_v1_data ();
}
/**
@@ -240,7 +240,7 @@ hb_bool_t
hb_ot_color_glyph_has_paint (hb_face_t *face,
hb_codepoint_t glyph)
{
- return face->table.COLR->has_paint_for_glyph (glyph);
+ return face->table.COLR->colr->has_paint_for_glyph (glyph);
}
/**
@@ -266,7 +266,7 @@ hb_ot_color_glyph_get_layers (hb_face_t *face,
unsigned int *layer_count, /* IN/OUT. May be NULL. */
hb_ot_color_layer_t *layers /* OUT. May be NULL. */)
{
- return face->table.COLR->get_glyph_layers (glyph, start_offset, layer_count, layers);
+ return face->table.COLR->colr->get_glyph_layers (glyph, start_offset, layer_count, layers);
}
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-face-table-list.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-face-table-list.hh
index 97825f4d19c..afc8aa476e2 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-face-table-list.hh
+++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-face-table-list.hh
@@ -136,7 +136,7 @@ HB_OT_TABLE (AAT, feat)
/* OpenType color fonts. */
#ifndef HB_NO_COLOR
-HB_OT_CORE_TABLE (OT, COLR)
+HB_OT_ACCELERATOR (OT, COLR)
HB_OT_CORE_TABLE (OT, CPAL)
HB_OT_ACCELERATOR (OT, CBDT)
HB_OT_ACCELERATOR (OT, sbix)
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-face.cc b/src/java.desktop/share/native/libharfbuzz/hb-ot-face.cc
index 1cf14f3ebc6..d17f088073c 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-face.cc
+++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-face.cc
@@ -36,6 +36,7 @@
#include "hb-ot-name-table.hh"
#include "hb-ot-post-table.hh"
#include "OT/Color/CBDT/CBDT.hh"
+#include "OT/Color/COLR/COLR.hh"
#include "OT/Color/sbix/sbix.hh"
#include "OT/Color/svg/svg.hh"
#include "hb-ot-layout-gdef-table.hh"
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-font.cc b/src/java.desktop/share/native/libharfbuzz/hb-ot-font.cc
index 2a633c77816..0238bb346a9 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-font.cc
+++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-font.cc
@@ -34,11 +34,7 @@
#include "hb-font.hh"
#include "hb-machinery.hh"
#include "hb-ot-face.hh"
-#include "hb-outline.hh"
-#ifndef HB_NO_AAT
-#include "hb-aat-layout-trak-table.hh"
-#endif
#include "hb-ot-cmap-table.hh"
#include "hb-ot-glyf-table.hh"
#include "hb-ot-cff2-table.hh"
@@ -65,28 +61,111 @@
* never need to call these functions directly.
**/
-using hb_ot_font_cmap_cache_t = hb_cache_t<21, 16, 8, true>;
-using hb_ot_font_advance_cache_t = hb_cache_t<24, 16, 8, true>;
-
-#ifndef HB_NO_OT_FONT_CMAP_CACHE
-static hb_user_data_key_t hb_ot_font_cmap_cache_user_data_key;
-#endif
+using hb_ot_font_advance_cache_t = hb_cache_t<24, 16>;
+static_assert (sizeof (hb_ot_font_advance_cache_t) == 1024, "");
struct hb_ot_font_t
{
const hb_ot_face_t *ot_face;
-#ifndef HB_NO_AAT
- bool apply_trak;
-#endif
-
-#ifndef HB_NO_OT_FONT_CMAP_CACHE
- hb_ot_font_cmap_cache_t *cmap_cache;
-#endif
-
/* h_advance caching */
- mutable hb_atomic_int_t cached_coords_serial;
- mutable hb_atomic_ptr_t advance_cache;
+ mutable hb_atomic_t cached_coords_serial;
+ struct advance_cache_t
+ {
+ mutable hb_atomic_t advance_cache;
+ mutable hb_atomic_t varStore_cache;
+
+ ~advance_cache_t ()
+ {
+ clear ();
+ }
+
+ hb_ot_font_advance_cache_t *acquire_advance_cache () const
+ {
+ retry:
+ auto *cache = advance_cache.get_acquire ();
+ if (!cache)
+ {
+ cache = (hb_ot_font_advance_cache_t *) hb_malloc (sizeof (hb_ot_font_advance_cache_t));
+ if (!cache)
+ return nullptr;
+ new (cache) hb_ot_font_advance_cache_t;
+ return cache;
+ }
+ if (advance_cache.cmpexch (cache, nullptr))
+ return cache;
+ else
+ goto retry;
+ }
+ void release_advance_cache (hb_ot_font_advance_cache_t *cache) const
+ {
+ if (!cache)
+ return;
+ if (!advance_cache.cmpexch (nullptr, cache))
+ hb_free (cache);
+ }
+ void clear_advance_cache () const
+ {
+ retry:
+ auto *cache = advance_cache.get_acquire ();
+ if (!cache)
+ return;
+ if (advance_cache.cmpexch (cache, nullptr))
+ hb_free (cache);
+ else
+ goto retry;
+ }
+
+ OT::ItemVariationStore::cache_t *acquire_varStore_cache (const OT::ItemVariationStore &varStore) const
+ {
+ retry:
+ auto *cache = varStore_cache.get_acquire ();
+ if (!cache)
+ return varStore.create_cache ();
+ if (varStore_cache.cmpexch (cache, nullptr))
+ return cache;
+ else
+ goto retry;
+ }
+ void release_varStore_cache (OT::ItemVariationStore::cache_t *cache) const
+ {
+ if (!cache)
+ return;
+ if (!varStore_cache.cmpexch (nullptr, cache))
+ OT::ItemVariationStore::destroy_cache (cache);
+ }
+ void clear_varStore_cache () const
+ {
+ retry:
+ auto *cache = varStore_cache.get_acquire ();
+ if (!cache)
+ return;
+ if (varStore_cache.cmpexch (cache, nullptr))
+ OT::ItemVariationStore::destroy_cache (cache);
+ else
+ goto retry;
+ }
+
+ void clear () const
+ {
+ clear_advance_cache ();
+ clear_varStore_cache ();
+ }
+
+ } h, v;
+
+ void check_serial (hb_font_t *font) const
+ {
+ int font_serial = font->serial_coords.get_acquire ();
+
+ if (cached_coords_serial.get_acquire () == font_serial)
+ return;
+
+ h.clear ();
+ v.clear ();
+
+ cached_coords_serial.set_release (font_serial);
+ }
};
static hb_ot_font_t *
@@ -98,44 +177,6 @@ _hb_ot_font_create (hb_font_t *font)
ot_font->ot_face = &font->face->table;
-#ifndef HB_NO_AAT
- /* According to Ned, trak is applied by default for "modern fonts", as detected by presence of STAT table. */
-#ifndef HB_NO_STYLE
- ot_font->apply_trak = font->face->table.STAT->has_data () && font->face->table.trak->has_data ();
-#else
- ot_font->apply_trak = false;
-#endif
-#endif
-
-#ifndef HB_NO_OT_FONT_CMAP_CACHE
- // retry:
- auto *cmap_cache = (hb_ot_font_cmap_cache_t *) hb_face_get_user_data (font->face,
- &hb_ot_font_cmap_cache_user_data_key);
- if (!cmap_cache)
- {
- cmap_cache = (hb_ot_font_cmap_cache_t *) hb_malloc (sizeof (hb_ot_font_cmap_cache_t));
- if (unlikely (!cmap_cache)) goto out;
- new (cmap_cache) hb_ot_font_cmap_cache_t ();
- if (unlikely (!hb_face_set_user_data (font->face,
- &hb_ot_font_cmap_cache_user_data_key,
- cmap_cache,
- hb_free,
- false)))
- {
- hb_free (cmap_cache);
- cmap_cache = nullptr;
- /* Normally we would retry here, but that would
- * infinite-loop if the face is the empty-face.
- * Just let it go and this font will be uncached if it
- * happened to collide with another thread creating the
- * cache at the same time. */
- // goto retry;
- }
- }
- out:
- ot_font->cmap_cache = cmap_cache;
-#endif
-
return ot_font;
}
@@ -144,8 +185,7 @@ _hb_ot_font_destroy (void *font_data)
{
hb_ot_font_t *ot_font = (hb_ot_font_t *) font_data;
- auto *cache = ot_font->advance_cache.get_relaxed ();
- hb_free (cache);
+ ot_font->~hb_ot_font_t ();
hb_free (ot_font);
}
@@ -159,11 +199,7 @@ hb_ot_get_nominal_glyph (hb_font_t *font HB_UNUSED,
{
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
const hb_ot_face_t *ot_face = ot_font->ot_face;
- hb_ot_font_cmap_cache_t *cmap_cache = nullptr;
-#ifndef HB_NO_OT_FONT_CMAP_CACHE
- cmap_cache = ot_font->cmap_cache;
-#endif
- return ot_face->cmap->get_nominal_glyph (unicode, glyph, cmap_cache);
+ return ot_face->cmap->get_nominal_glyph (unicode, glyph);
}
static unsigned int
@@ -178,14 +214,9 @@ hb_ot_get_nominal_glyphs (hb_font_t *font HB_UNUSED,
{
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
const hb_ot_face_t *ot_face = ot_font->ot_face;
- hb_ot_font_cmap_cache_t *cmap_cache = nullptr;
-#ifndef HB_NO_OT_FONT_CMAP_CACHE
- cmap_cache = ot_font->cmap_cache;
-#endif
return ot_face->cmap->get_nominal_glyphs (count,
first_unicode, unicode_stride,
- first_glyph, glyph_stride,
- cmap_cache);
+ first_glyph, glyph_stride);
}
static hb_bool_t
@@ -198,13 +229,8 @@ hb_ot_get_variation_glyph (hb_font_t *font HB_UNUSED,
{
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
const hb_ot_face_t *ot_face = ot_font->ot_face;
- hb_ot_font_cmap_cache_t *cmap_cache = nullptr;
-#ifndef HB_NO_OT_FONT_CMAP_CACHE
- cmap_cache = ot_font->cmap_cache;
-#endif
return ot_face->cmap->get_variation_glyph (unicode,
- variation_selector, glyph,
- cmap_cache);
+ variation_selector, glyph);
}
static void
@@ -216,47 +242,25 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data,
unsigned advance_stride,
void *user_data HB_UNUSED)
{
+
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
const hb_ot_face_t *ot_face = ot_font->ot_face;
const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx;
- hb_position_t *orig_first_advance = first_advance;
-
-#if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE)
+ ot_font->check_serial (font);
const OT::HVAR &HVAR = *hmtx.var_table;
const OT::ItemVariationStore &varStore = &HVAR + HVAR.varStore;
- OT::ItemVariationStore::cache_t *varStore_cache = font->num_coords * count >= 128 ? varStore.create_cache () : nullptr;
+ OT::ItemVariationStore::cache_t *varStore_cache = ot_font->h.acquire_varStore_cache (varStore);
+
+ hb_ot_font_advance_cache_t *advance_cache = nullptr;
bool use_cache = font->num_coords;
-#else
- OT::ItemVariationStore::cache_t *varStore_cache = nullptr;
- bool use_cache = false;
-#endif
-
- hb_ot_font_advance_cache_t *cache = nullptr;
if (use_cache)
{
- retry:
- cache = ot_font->advance_cache.get_acquire ();
- if (unlikely (!cache))
- {
- cache = (hb_ot_font_advance_cache_t *) hb_malloc (sizeof (hb_ot_font_advance_cache_t));
- if (unlikely (!cache))
- {
- use_cache = false;
- goto out;
- }
- new (cache) hb_ot_font_advance_cache_t;
-
- if (unlikely (!ot_font->advance_cache.cmpexch (nullptr, cache)))
- {
- hb_free (cache);
- goto retry;
- }
- ot_font->cached_coords_serial.set_release (font->serial_coords);
- }
+ advance_cache = ot_font->h.acquire_advance_cache ();
+ if (!advance_cache)
+ use_cache = false;
}
- out:
if (!use_cache)
{
@@ -269,58 +273,26 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data,
}
else
{ /* Use cache. */
- if (ot_font->cached_coords_serial.get_acquire () != (int) font->serial_coords)
- {
- ot_font->advance_cache->clear ();
- ot_font->cached_coords_serial.set_release (font->serial_coords);
- }
-
for (unsigned int i = 0; i < count; i++)
{
hb_position_t v;
unsigned cv;
- if (ot_font->advance_cache->get (*first_glyph, &cv))
+ if (advance_cache->get (*first_glyph, &cv))
v = cv;
else
{
v = hmtx.get_advance_with_var_unscaled (*first_glyph, font, varStore_cache);
- ot_font->advance_cache->set (*first_glyph, v);
+ advance_cache->set (*first_glyph, v);
}
*first_advance = font->em_scale_x (v);
first_glyph = &StructAtOffsetUnaligned (first_glyph, glyph_stride);
first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride);
}
+
+ ot_font->h.release_advance_cache (advance_cache);
}
-#if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE)
- OT::ItemVariationStore::destroy_cache (varStore_cache);
-#endif
-
- if (font->x_strength && !font->embolden_in_place)
- {
- /* Emboldening. */
- hb_position_t x_strength = font->x_scale >= 0 ? font->x_strength : -font->x_strength;
- first_advance = orig_first_advance;
- for (unsigned int i = 0; i < count; i++)
- {
- *first_advance += *first_advance ? x_strength : 0;
- first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride);
- }
- }
-
-#ifndef HB_NO_AAT
- if (ot_font->apply_trak)
- {
- hb_position_t tracking = font->face->table.trak->get_h_tracking (font);
- first_advance = orig_first_advance;
- for (unsigned int i = 0; i < count; i++)
- {
- *first_advance += tracking;
- first_glyph = &StructAtOffsetUnaligned (first_glyph, glyph_stride);
- first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride);
- }
- }
-#endif
+ ot_font->h.release_varStore_cache (varStore_cache);
}
#ifndef HB_NO_VERTICAL
@@ -337,17 +309,13 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data,
const hb_ot_face_t *ot_face = ot_font->ot_face;
const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
- hb_position_t *orig_first_advance = first_advance;
-
if (vmtx.has_data ())
{
-#if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE)
+ ot_font->check_serial (font);
const OT::VVAR &VVAR = *vmtx.var_table;
const OT::ItemVariationStore &varStore = &VVAR + VVAR.varStore;
- OT::ItemVariationStore::cache_t *varStore_cache = font->num_coords ? varStore.create_cache () : nullptr;
-#else
- OT::ItemVariationStore::cache_t *varStore_cache = nullptr;
-#endif
+ OT::ItemVariationStore::cache_t *varStore_cache = ot_font->v.acquire_varStore_cache (varStore);
+ // TODO Use advance_cache.
for (unsigned int i = 0; i < count; i++)
{
@@ -356,9 +324,7 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data,
first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride);
}
-#if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE)
- OT::ItemVariationStore::destroy_cache (varStore_cache);
-#endif
+ ot_font->v.release_varStore_cache (varStore_cache);
}
else
{
@@ -373,32 +339,6 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data,
first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride);
}
}
-
- if (font->y_strength && !font->embolden_in_place)
- {
- /* Emboldening. */
- hb_position_t y_strength = font->y_scale >= 0 ? font->y_strength : -font->y_strength;
- first_advance = orig_first_advance;
- for (unsigned int i = 0; i < count; i++)
- {
- *first_advance += *first_advance ? y_strength : 0;
- first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride);
- }
- }
-
-#ifndef HB_NO_AAT
- if (ot_font->apply_trak)
- {
- hb_position_t tracking = font->face->table.trak->get_v_tracking (font);
- first_advance = orig_first_advance;
- for (unsigned int i = 0; i < count; i++)
- {
- *first_advance += tracking;
- first_glyph = &StructAtOffsetUnaligned (first_glyph, glyph_stride);
- first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride);
- }
- }
-#endif
}
#endif
@@ -435,7 +375,8 @@ hb_ot_get_glyph_v_origin (hb_font_t *font,
}
hb_glyph_extents_t extents = {0};
- if (ot_face->glyf->get_extents (font, glyph, &extents))
+
+ if (hb_font_get_glyph_extents (font, glyph, &extents))
{
const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
int tsb = 0;
@@ -448,7 +389,7 @@ hb_ot_get_glyph_v_origin (hb_font_t *font,
hb_font_extents_t font_extents;
font->get_h_extents_with_fallback (&font_extents);
hb_position_t advance = font_extents.ascender - font_extents.descender;
- int diff = advance - -extents.height;
+ hb_position_t diff = advance - -extents.height;
*y = extents.y_bearing + (diff >> 1);
return true;
}
@@ -477,6 +418,9 @@ hb_ot_get_glyph_extents (hb_font_t *font,
#endif
#if !defined(HB_NO_COLOR) && !defined(HB_NO_PAINT)
if (ot_face->COLR->get_extents (font, glyph, extents)) return true;
+#endif
+#ifndef HB_NO_VAR_COMPOSITES
+ if (ot_face->VARC->get_extents (font, glyph, extents)) return true;
#endif
if (ot_face->glyf->get_extents (font, glyph, extents)) return true;
#ifndef HB_NO_OT_FONT_CFF
@@ -528,16 +472,9 @@ hb_ot_get_font_h_extents (hb_font_t *font,
hb_font_extents_t *metrics,
void *user_data HB_UNUSED)
{
- bool ret = _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER, &metrics->ascender) &&
- _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER, &metrics->descender) &&
- _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP, &metrics->line_gap);
-
- /* Embolden */
- int y_shift = font->y_strength;
- if (font->y_scale < 0) y_shift = -y_shift;
- metrics->ascender += y_shift;
-
- return ret;
+ return _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER, &metrics->ascender) &&
+ _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER, &metrics->descender) &&
+ _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP, &metrics->line_gap);
}
#ifndef HB_NO_VERTICAL
@@ -554,68 +491,46 @@ hb_ot_get_font_v_extents (hb_font_t *font,
#endif
#ifndef HB_NO_DRAW
-static void
-hb_ot_draw_glyph (hb_font_t *font,
- void *font_data HB_UNUSED,
- hb_codepoint_t glyph,
- hb_draw_funcs_t *draw_funcs, void *draw_data,
- void *user_data)
+static hb_bool_t
+hb_ot_draw_glyph_or_fail (hb_font_t *font,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph,
+ hb_draw_funcs_t *draw_funcs, void *draw_data,
+ void *user_data)
{
- bool embolden = font->x_strength || font->y_strength;
- hb_outline_t outline;
-
- { // Need draw_session to be destructed before emboldening.
- hb_draw_session_t draw_session (embolden ? hb_outline_recording_pen_get_funcs () : draw_funcs,
- embolden ? &outline : draw_data, font->slant_xy);
+ hb_draw_session_t draw_session {draw_funcs, draw_data};
#ifndef HB_NO_VAR_COMPOSITES
- if (!font->face->table.VARC->get_path (font, glyph, draw_session))
+ if (font->face->table.VARC->get_path (font, glyph, draw_session)) return true;
#endif
- // Keep the following in synch with VARC::get_path_at()
- if (!font->face->table.glyf->get_path (font, glyph, draw_session))
+ // Keep the following in synch with VARC::get_path_at()
+ if (font->face->table.glyf->get_path (font, glyph, draw_session)) return true;
#ifndef HB_NO_CFF
- if (!font->face->table.cff2->get_path (font, glyph, draw_session))
- if (!font->face->table.cff1->get_path (font, glyph, draw_session))
+ if (font->face->table.cff2->get_path (font, glyph, draw_session)) return true;
+ if (font->face->table.cff1->get_path (font, glyph, draw_session)) return true;
#endif
- {}
- }
-
- if (embolden)
- {
- float x_shift = font->embolden_in_place ? 0 : (float) font->x_strength / 2;
- float y_shift = (float) font->y_strength / 2;
- if (font->x_scale < 0) x_shift = -x_shift;
- if (font->y_scale < 0) y_shift = -y_shift;
- outline.embolden (font->x_strength, font->y_strength,
- x_shift, y_shift);
-
- outline.replay (draw_funcs, draw_data);
- }
+ return false;
}
#endif
#ifndef HB_NO_PAINT
-static void
-hb_ot_paint_glyph (hb_font_t *font,
- void *font_data,
- hb_codepoint_t glyph,
- hb_paint_funcs_t *paint_funcs, void *paint_data,
- unsigned int palette,
- hb_color_t foreground,
- void *user_data)
+static hb_bool_t
+hb_ot_paint_glyph_or_fail (hb_font_t *font,
+ void *font_data,
+ hb_codepoint_t glyph,
+ hb_paint_funcs_t *paint_funcs, void *paint_data,
+ unsigned int palette,
+ hb_color_t foreground,
+ void *user_data)
{
#ifndef HB_NO_COLOR
- if (font->face->table.COLR->paint_glyph (font, glyph, paint_funcs, paint_data, palette, foreground)) return;
- if (font->face->table.SVG->paint_glyph (font, glyph, paint_funcs, paint_data)) return;
+ if (font->face->table.COLR->paint_glyph (font, glyph, paint_funcs, paint_data, palette, foreground)) return true;
+ if (font->face->table.SVG->paint_glyph (font, glyph, paint_funcs, paint_data)) return true;
#ifndef HB_NO_OT_FONT_BITMAP
- if (font->face->table.CBDT->paint_glyph (font, glyph, paint_funcs, paint_data)) return;
- if (font->face->table.sbix->paint_glyph (font, glyph, paint_funcs, paint_data)) return;
+ if (font->face->table.CBDT->paint_glyph (font, glyph, paint_funcs, paint_data)) return true;
+ if (font->face->table.sbix->paint_glyph (font, glyph, paint_funcs, paint_data)) return true;
#endif
#endif
-
- // Outline glyph
- paint_funcs->push_clip_glyph (paint_data, glyph, font);
- paint_funcs->color (paint_data, true, foreground);
- paint_funcs->pop_clip (paint_data);
+ return false;
}
#endif
@@ -642,11 +557,11 @@ static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t table;
AAT::kern_accelerator_data_t accel_data;
+ AAT::hb_aat_scratch_t scratch;
};
protected:
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-base-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-base-table.hh
index 5a3679e4bfa..04a79a93a89 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-base-table.hh
+++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-base-table.hh
@@ -182,7 +182,7 @@ struct BaseCoord
void collect_variation_indices (hb_set_t& varidx_set /* OUT */) const
{
switch (u.format) {
- case 3: hb_barrier (); u.format3.collect_variation_indices (varidx_set);
+ case 3: hb_barrier (); u.format3.collect_variation_indices (varidx_set); return;
default:return;
}
}
diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-common.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-common.hh
index f14675295f6..7ee34185575 100644
--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-common.hh
+++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-common.hh
@@ -1850,7 +1850,7 @@ struct ClassDefFormat2_4
hb_sorted_vector_t glyph_and_klass;
hb_set_t orig_klasses;
- if (glyph_set.get_population () * hb_bit_storage ((unsigned) rangeRecord.len) / 2
+ if (glyph_set.get_population () * hb_bit_storage ((unsigned) rangeRecord.len)
< get_population ())
{
for (hb_codepoint_t g : glyph_set)
@@ -1931,7 +1931,7 @@ struct ClassDefFormat2_4
bool intersects (const hb_set_t *glyphs) const
{
- if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len) / 2)
+ if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len))
{
for (auto g : *glyphs)
if (get_class (g))
@@ -2000,7 +2000,7 @@ struct ClassDefFormat2_4
}
unsigned count = rangeRecord.len;
- if (count > glyphs->get_population () * hb_bit_storage (count) * 8)
+ if (count > glyphs->get_population () * hb_bit_storage (count))
{
for (auto g : *glyphs)
{
@@ -2548,11 +2548,13 @@ struct SparseVarRegionAxis
DEFINE_SIZE_STATIC (8);
};
-#define REGION_CACHE_ITEM_CACHE_INVALID 2.f
+#define REGION_CACHE_ITEM_CACHE_INVALID INT_MIN
+#define REGION_CACHE_ITEM_MULTIPLIER (float (1 << ((sizeof (int) * 8) - 2)))
+#define REGION_CACHE_ITEM_DIVISOR (1.f / float (1 << ((sizeof (int) * 8) - 2)))
struct VarRegionList
{
- using cache_t = float;
+ using cache_t = hb_atomic_t;
float evaluate (unsigned int region_index,
const int *coords, unsigned int coord_len,
@@ -2561,12 +2563,12 @@ struct VarRegionList
if (unlikely (region_index >= regionCount))
return 0.;
- float *cached_value = nullptr;
+ cache_t *cached_value = nullptr;
if (cache)
{
cached_value = &(cache[region_index]);
- if (likely (*cached_value != REGION_CACHE_ITEM_CACHE_INVALID))
- return *cached_value;
+ if (*cached_value != REGION_CACHE_ITEM_CACHE_INVALID)
+ return *cached_value * REGION_CACHE_ITEM_DIVISOR;
}
const VarRegionAxis *axes = axesZ.arrayZ + (region_index * axisCount);
@@ -2587,7 +2589,7 @@ struct VarRegionList
}
if (cache)
- *cached_value = v;
+ *cached_value = v * REGION_CACHE_ITEM_MULTIPLIER;
return v;
}
@@ -2730,7 +2732,7 @@ struct SparseVariationRegion : Array16Of
struct SparseVarRegionList
{
- using cache_t = float;
+ using cache_t = hb_atomic_t;
float evaluate (unsigned int region_index,
const int *coords, unsigned int coord_len,
@@ -2739,12 +2741,12 @@ struct SparseVarRegionList
if (unlikely (region_index >= regions.len))
return 0.;
- float *cached_value = nullptr;
+ cache_t *cached_value = nullptr;
if (cache)
{
cached_value = &(cache[region_index]);
- if (likely (*cached_value != REGION_CACHE_ITEM_CACHE_INVALID))
- return *cached_value;
+ if (*cached_value != REGION_CACHE_ITEM_CACHE_INVALID)
+ return *cached_value * REGION_CACHE_ITEM_DIVISOR;
}
const SparseVariationRegion ®ion = this+regions[region_index];
@@ -2752,7 +2754,7 @@ struct SparseVarRegionList
float v = region.evaluate (coords, coord_len);
if (cache)
- *cached_value = v;
+ *cached_value = v * REGION_CACHE_ITEM_MULTIPLIER;
return v;
}
@@ -2861,8 +2863,13 @@ struct VarData
const hb_vector_t*>& rows)
{
TRACE_SERIALIZE (this);
- if (unlikely (!c->extend_min (this))) return_trace (false);
unsigned row_count = rows.length;
+ if (!row_count) {
+ // Nothing to serialize, will be empty.
+ return false;
+ }
+
+ if (unlikely (!c->extend_min (this))) return_trace (false);
itemCount = row_count;
int min_threshold = has_long ? -65536 : -128;
@@ -3187,10 +3194,10 @@ struct ItemVariationStore
#ifdef HB_NO_VAR
return nullptr;
#endif
- auto &r = this+regions;
- unsigned count = r.regionCount;
+ unsigned count = (this+regions).regionCount;
+ if (!count) return nullptr;
- float *cache = (float *) hb_malloc (sizeof (float) * count);
+ cache_t *cache = (cache_t *) hb_malloc (sizeof (float) * count);
if (unlikely (!cache)) return nullptr;
for (unsigned i = 0; i < count; i++)
@@ -3440,7 +3447,7 @@ struct MultiItemVariationStore
{
using cache_t = SparseVarRegionList::cache_t;
- cache_t *create_cache (hb_array_t static_cache = hb_array_t ()) const
+ cache_t *create_cache (hb_array_t